grim/convey

Bump the version for release
v0.14.0-alpha3
2018-02-20, Gary Kramlich
166a6d1979fa
Bump the version for release
// Convey
// Copyright 2016-2018 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 docker
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/aphistic/gomol"
"bitbucket.org/rw_grim/convey/environment"
"bitbucket.org/rw_grim/convey/state"
"bitbucket.org/rw_grim/convey/tasks"
"bitbucket.org/rw_grim/convey/yaml"
)
// Environment contains options for loading environment variables from a file
// in the workspace.
type Environment struct {
File string `yaml:"from-file"`
Files yaml.StringOrSlice `yaml:"from-files"`
Prefix string `yaml:"prefix"`
}
// Execute runs the environment plan.
func (e *Environment) Execute(name string, logger *gomol.LogAdapter, env []string, st *state.State) error {
fullEnv := environment.Merge(env, st.GetEnv())
prefix, err := environment.Mapper(e.Prefix, fullEnv)
if err != nil {
return err
}
files, err := st.MapSlice(e.Files, fullEnv)
if err != nil {
return err
}
// create a directory in our state for the task
envDir := filepath.Join(st.Directory, name)
err = os.MkdirAll(envDir, 0700)
if err != nil {
return err
}
for _, file := range files {
// Export the file into the temp directory and maintain the
// structure of the file (for ease of error messages, so we
// get the file a/b/c/env instead of env).
e := Export{
Files: []string{file},
Path: envDir,
}
err = e.Execute(name, logger, env, st)
if err != nil {
return err
}
// Process the entries of the file and apply them to the
// state's base environment immediately.
dest := filepath.Clean(filepath.Join(envDir, file))
entries, err := processFile(dest, file, prefix)
if err != nil {
return err
}
st.MergeEnv(entries)
}
return nil
}
func processFile(path, name, prefix string) ([]string, error) {
data, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read environment file '%s'", name)
}
entries := []string{}
for _, line := range strings.Split(string(data), "\n") {
// Allow blank lines
if len(strings.TrimSpace(line)) == 0 {
continue
}
// Each non-empty line requires the form key=val. Split the
// key and the val, then uppercase the key and add the prefix.
// We don't care what form val takes, it will be treated as a
// string (does not need to be quoted).
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("malformed entry in environments file '%s'", line)
}
var (
key = strings.TrimSpace(parts[0])
val = strings.TrimSpace(parts[1])
)
if len(key) == 0 {
return nil, fmt.Errorf("malformed entry in environments file '%s'", line)
}
entries = append(entries, fmt.Sprintf("%s%s=%s", prefix, strings.ToUpper(key), val))
}
return entries, nil
}
// New creates a new environment command.
func (e *Environment) New() tasks.Task {
return &Environment{}
}
// Valid validate the environment command.
func (e *Environment) Valid() error {
if e.File != "" {
e.Files = append([]string{e.File}, e.Files...)
}
if len(e.Files) == 0 {
return errNoFilesEnvironment
}
return nil
}