grim/convey
Clone
Summary
Browse
Changes
Graph
Added tag v0.10.1 for changeset 6fcf770a1b72
2017-09-26, Gary Kramlich
7fd7299d950f
Added tag v0.10.1 for changeset 6fcf770a1b72
/*
* Convey
* Copyright 2016-2017 Gary Kramlich <grim@reaperworld.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package
state
import
(
"errors"
"fmt"
"os"
"strings"
"time"
"bitbucket.org/rw_grim/convey/environment"
"bitbucket.org/rw_grim/convey/network"
"bitbucket.org/rw_grim/convey/workspace"
)
type
State
struct
{
Network
network
.
Network
Workspace
workspace
.
Workspace
KeepWorkspace
bool
ForceSequential
bool
EnableSSHAgent
bool
TaskTimeout
time
.
Duration
Environment
[]
string
ExtendFrames
[]
extendFrame
DockerConfig
string
CPUShares
string
Memory
string
DetachedContainers
[]
string
}
type
extendFrame
struct
{
expandable
[]
string
delimiter
string
stashedEnv
[]
string
}
var
errEmptyExtendStack
=
errors
.
New
(
"empty extend stack"
)
func
(
st
*
State
)
Valid
()
error
{
if
st
.
EnableSSHAgent
{
if
val
:=
os
.
Getenv
(
"SSH_AUTH_SOCK"
);
val
==
""
{
return
fmt
.
Errorf
(
"ssh-agent forwarding requested, but agent not running"
)
}
}
return
nil
}
// MapSlice calls SliceMapper on the given environment, but also checks to
// see if the variable could be expanded into a list.
func
(
st
*
State
)
MapSlice
(
env
,
fullEnv
[]
string
)
([]
string
,
error
)
{
if
len
(
env
)
==
1
{
// If we only have one thing and it looks like $VAR or ${VAR}, then
// see if we have it in the list of things we can expand on the stack.
if
delimiter
,
ok
:=
st
.
getDelimiter
(
getName
(
env
[
0
]));
ok
{
mapped
,
err
:=
environment
.
Mapper
(
env
[
0
],
fullEnv
)
if
err
!=
nil
{
return
nil
,
err
}
// Split it!
return
strings
.
SplitN
(
mapped
,
delimiter
,
-
1
),
nil
}
}
return
environment
.
SliceMapper
(
env
,
fullEnv
)
}
// GetDelimiter returns the highest (outermost extend task) delimiter registered
// with a given expandable environment variable. Returns true if found by name.
func
(
st
*
State
)
getDelimiter
(
name
string
)
(
string
,
bool
)
{
for
i
:=
len
(
st
.
ExtendFrames
)
-
1
;
i
>=
0
;
i
--
{
frame
:=
st
.
ExtendFrames
[
i
]
for
_
,
expandable
:=
range
frame
.
expandable
{
if
expandable
==
name
{
return
frame
.
delimiter
,
true
}
}
}
return
""
,
false
}
// PushExtendFrame will store the set of expandable environment variables
// and the current set of environments which are restored on pop. These frames
// are used to map a slice within an extended task.
func
(
st
*
State
)
PushExtendFrame
(
env
,
expandable
[]
string
,
delimiter
string
)
{
st
.
ExtendFrames
=
append
(
st
.
ExtendFrames
,
extendFrame
{
expandable
:
expandable
,
delimiter
:
delimiter
,
stashedEnv
:
st
.
Environment
,
})
// Merge the environment into this map, but do NOT override anything that
// is currently in the state's enviornment - this has higher precedence.
st
.
Environment
=
environment
.
Merge
(
env
,
st
.
Environment
)
}
// PopExtendFrame will remove one frame from the top of the stack.
func
(
st
*
State
)
PopExtendFrame
()
error
{
idx
:=
len
(
st
.
ExtendFrames
)
-
1
if
idx
<
0
{
return
errEmptyExtendStack
}
last
:=
st
.
ExtendFrames
[
idx
]
st
.
ExtendFrames
=
st
.
ExtendFrames
[:
idx
]
st
.
Environment
=
last
.
stashedEnv
return
nil
}
// getName returns the name of the variable `var` if the string is of the
// form $var or ${var}.
func
getName
(
env
string
)
string
{
env
=
strings
.
TrimSpace
(
env
)
if
strings
.
HasPrefix
(
env
,
"$"
)
{
return
strings
.
Trim
(
env
[
1
:],
"{}"
)
}
return
""
}