grim/convey

Move docker/import to convey/import.

2019-03-30, Gary Kramlich
1e90226dcdbd
Parents 268356681abb
Children fbdbcf89b3e3
Move docker/import to convey/import.
--- a/convey.yml Sat Mar 30 00:40:25 2019 -0500
+++ b/convey.yml Sat Mar 30 16:28:57 2019 -0500
@@ -6,7 +6,7 @@
tasks:
# tasks for the default plan
import:
- type: docker/import
+ type: convey/import
files:
- ./
export:
@@ -65,7 +65,7 @@
# tasks for the deploy plan
import-release:
- type: docker/import
+ type: convey/import
files:
- convey-${CONVEY_VERSION}-freebsd-amd64
- convey-${CONVEY_VERSION}-darwin-amd64
@@ -87,7 +87,7 @@
# tasks for creating images
import-images:
- type: docker/import
+ type: convey/import
files:
- images
build-image-bitbucket-upload:
--- a/docker/docker.go Sat Mar 30 00:40:25 2019 -0500
+++ b/docker/docker.go Sat Mar 30 16:28:57 2019 -0500
@@ -27,7 +27,6 @@
// Tasks is a map of all docker tasks.
Tasks = map[string]tasks.Task{
"build": &Build{},
- "import": &Import{},
"login": &Login{},
"logout": &Logout{},
"pull": &Pull{},
--- a/path/path.go Sat Mar 30 00:40:25 2019 -0500
+++ b/path/path.go Sat Mar 30 16:28:57 2019 -0500
@@ -34,7 +34,7 @@
return parts[0], trimBase(base, parts[1])
}
- return parts[0], trimBase(base, DestFromSrc(parts[0]))
+ return parts[0], trimBase(base, parts[0])
}
func trimBase(base, path string) string {
@@ -48,16 +48,3 @@
return strings.TrimPrefix(path, base)
}
-
-// DestFromSrc returns "." if the given filename does not reference a
-// file or directory outside of the current working directory and the
-// input otherwise.
-func DestFromSrc(file string) string {
- clean := strings.TrimRight(file, string(os.PathSeparator))
-
- if !strings.ContainsRune(clean, os.PathSeparator) {
- return "."
- }
-
- return file
-}
--- a/path/path_test.go Sat Mar 30 00:40:25 2019 -0500
+++ b/path/path_test.go Sat Mar 30 16:28:57 2019 -0500
@@ -41,8 +41,8 @@
"foo:bar": {"foo", "bar"},
"foo:bar:baz": {"foo", "bar:baz"},
"foo/bar:baz": {"foo/bar", "baz"},
- "file": {"file", "."},
- "dir/": {"dir/", "."},
+ "file": {"file", "file"},
+ "dir/": {"dir/", "dir/"},
"nested/file": {"nested/file", "nested/file"},
}
--- a/runtime/runtime.go Sat Mar 30 00:40:25 2019 -0500
+++ b/runtime/runtime.go Sat Mar 30 16:28:57 2019 -0500
@@ -17,6 +17,8 @@
package runtime
import (
+ "github.com/aphistic/gomol"
+
"bitbucket.org/rw_grim/convey/environment"
"bitbucket.org/rw_grim/convey/state"
)
@@ -40,6 +42,10 @@
Containers: NewContainers(),
}
+ rt.cleanupList.Add(func(*gomol.LogAdapter) {
+ st.Destroy()
+ })
+
rt.cleanupOnSignal()
return rt
--- a/state/state.go Sat Mar 30 00:40:25 2019 -0500
+++ b/state/state.go Sat Mar 30 16:28:57 2019 -0500
@@ -26,6 +26,7 @@
"bitbucket.org/rw_grim/convey/logging"
"bitbucket.org/rw_grim/convey/network"
+ "bitbucket.org/rw_grim/convey/workspace"
)
// State holds all of the runtime data during a run.
@@ -35,7 +36,7 @@
CfgPath string
Network network.Network
- Workspace *Workspace
+ Workspace *workspace.Workspace
KeepWorkspace bool
DisableDeprecated bool
@@ -55,7 +56,7 @@
panic(err)
}
- ws, err := newWorkspace(pwd)
+ ws, err := workspace.New(pwd)
if err != nil {
panic(err)
}
--- a/state/workspace.go Sat Mar 30 00:40:25 2019 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-// 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 state
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
-)
-
-type Workspace struct {
- path string
-}
-
-func newWorkspace(root string) (*Workspace, error) {
- parent := filepath.Join(root, ".convey")
- err := os.MkdirAll(parent, 0700)
- if err != nil {
- return nil, err
- }
-
- path, err := ioutil.TempDir(parent, "")
- if err != nil {
- return nil, err
- }
-
- workspace := &Workspace{
- path: path,
- }
-
- return workspace, nil
-}
-
-func (ws *Workspace) Destroy() {
- if err := os.RemoveAll(ws.path); err != nil {
- fmt.Printf("error removing worksace: %s\n", err)
- }
-
- // try to remove the .convey directory. This will only succeed when
- // our state is the only one and that's intentional.
- dir := filepath.Dir(ws.path)
- if err := os.Remove(dir); err != nil {
- fmt.Printf("error removing .convey: %s\n", err)
- }
-}
-
-func (ws *Workspace) TaskDirectory(name string) (string, error) {
- dir := filepath.Join(ws.path, name)
-
- err := os.MkdirAll(dir, 0700)
-
- return dir, err
-}
-
-func (ws *Workspace) Path() string {
- return ws.path
-}
--- a/tasks/export.go Sat Mar 30 00:40:25 2019 -0500
+++ b/tasks/export.go Sat Mar 30 16:28:57 2019 -0500
@@ -17,12 +17,12 @@
package tasks
import (
- "errors"
"path/filepath"
"github.com/aphistic/gomol"
"bitbucket.org/rw_grim/convey/environment"
+ "bitbucket.org/rw_grim/convey/path"
"bitbucket.org/rw_grim/convey/runtime"
)
@@ -45,21 +45,18 @@
return nil
}
-// Copies a file
-func (e *Export) copyFile(filename string) error {
- return errors.New("Not implemented")
-}
-
// Executes the task
func (e *Export) Execute(name string, logger *gomol.LogAdapter, env *environment.Environment, rt *runtime.Runtime) error {
- for _, patterns := range e.Files {
- matches, err := filepath.Glob(filepath.Join(rt.State.CfgPath, patterns))
+ for _, pattern := range e.Files {
+ src, dst := path.ParseFilePath("", pattern)
+
+ matches, err := filepath.Glob(filepath.Join(rt.State.Workspace.Path(), src))
if err != nil {
return err
}
for _, match := range matches {
- err = e.copyFile(match)
+ err = rt.State.Workspace.Export(match, dst)
if err != nil {
return nil
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tasks/import.go Sat Mar 30 16:28:57 2019 -0500
@@ -0,0 +1,71 @@
+// Convey
+// Copyright 2016-2019 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 tasks
+
+import (
+ "fmt"
+ "path/filepath"
+
+ "github.com/aphistic/gomol"
+
+ "bitbucket.org/rw_grim/convey/environment"
+ "bitbucket.org/rw_grim/convey/path"
+ "bitbucket.org/rw_grim/convey/runtime"
+)
+
+type Import struct {
+ Files []string `yaml:"files"`
+ Path string `yaml:"path"`
+}
+
+// New creates a new Import task.
+func (i *Import) New() Task {
+ return &Import{}
+}
+
+// Valid validates the export task.
+func (i *Import) Valid() error {
+ if len(i.Files) == 0 {
+ return errNoFiles
+ }
+
+ return nil
+}
+
+// Executes the task
+func (i *Import) Execute(name string, logger *gomol.LogAdapter, env *environment.Environment, rt *runtime.Runtime) error {
+ for _, pattern := range i.Files {
+ src, dst := path.ParseFilePath(rt.State.CfgPath, pattern)
+
+ matches, err := filepath.Glob(filepath.Join(rt.State.CfgPath, src))
+ if err != nil {
+ return err
+ }
+ if len(matches) == 0 {
+ return fmt.Errorf("no matches found for %s", src)
+ }
+
+ for _, match := range matches {
+ err = rt.State.Workspace.Import(match, dst)
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return nil
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tasks/import_test.go Sat Mar 30 16:28:57 2019 -0500
@@ -0,0 +1,84 @@
+// Convey
+// Copyright 2016-2019 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 tasks
+
+import (
+ "os"
+ "path/filepath"
+ "testing"
+
+ . "github.com/onsi/gomega"
+
+ "bitbucket.org/rw_grim/convey/environment"
+ "bitbucket.org/rw_grim/convey/logging"
+ "bitbucket.org/rw_grim/convey/path"
+ "bitbucket.org/rw_grim/convey/runtime"
+ "bitbucket.org/rw_grim/convey/state"
+)
+
+func testImport(t *testing.T, files []string) {
+ g := NewGomegaWithT(t)
+
+ pwd, err := os.Getwd()
+ g.Expect(err).To(BeNil())
+
+ // setup our state
+ st := state.New()
+ st.CfgPath = pwd
+
+ env := environment.New()
+
+ // create our runtime
+ rt := runtime.NewWithEnvironment(st, env)
+ defer rt.Shutdown()
+
+ // create our task and runn it.
+ importTask := &Import{Files: files}
+
+ err = importTask.Execute("", logging.NewAdapter("test"), env, rt)
+
+ g.Expect(err).To(BeNil())
+
+ for _, file := range files {
+ _, dst := path.ParseFilePath(st.CfgPath, file)
+
+ _, err = os.Stat(filepath.Join(st.Workspace.Volume(), dst))
+ Expect(err).ToNot(Equal(os.IsNotExist(err)))
+ }
+}
+
+// TestImportSingleSourceOnly tests that the following yaml functions
+// correctly:
+//
+// single-source-only:
+// type: convey/import
+// files:
+// - import_test.go
+func TestImportSingleSourceOnly(t *testing.T) {
+ testImport(t, []string{"import_test.go"})
+}
+
+// TestImportSingleSourceWithDestination tests that the following yaml
+// functions correctly:
+//
+// single-source-with-destination:
+// type: convey/import
+// files:
+// - import_test.go:imported.go
+func TestImportSingleSourceWithDestination(t *testing.T) {
+ testImport(t, []string{"import_test.go:imported.go"})
+}
--- a/tasks/tasks.go Sat Mar 30 00:40:25 2019 -0500
+++ b/tasks/tasks.go Sat Mar 30 16:28:57 2019 -0500
@@ -30,6 +30,7 @@
"clean": &Clean{},
"export": &Export{},
"extend": &Extend{},
+ "import": &Import{},
"noop": &Noop{},
}
)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/workspace/fileio.go Sat Mar 30 16:28:57 2019 -0500
@@ -0,0 +1,74 @@
+// Convey
+// Copyright 2016-2019 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 workspace
+
+import (
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+)
+
+func (ws *Workspace) TaskDirectory(name string) (string, error) {
+ dir := filepath.Join(ws.path, name)
+
+ err := os.MkdirAll(dir, 0700)
+
+ return dir, err
+}
+
+// CopyFile copies the contents from src to dst atomically.
+// If dst does not exist, CopyFile creates it with permissions perm.
+// If the copy fails, CopyFile aborts and dst is preserved.
+func (ws *Workspace) copyFile(src, dst string, perm os.FileMode) error {
+ in, err := os.Open(src)
+ if err != nil {
+ return err
+ }
+ defer in.Close()
+ tmp, err := ioutil.TempFile(filepath.Dir(dst), "")
+ if err != nil {
+ return err
+ }
+ _, err = io.Copy(tmp, in)
+ if err != nil {
+ tmp.Close()
+ os.Remove(tmp.Name())
+ return err
+ }
+ if err = tmp.Close(); err != nil {
+ os.Remove(tmp.Name())
+ return err
+ }
+ if err = os.Chmod(tmp.Name(), perm); err != nil {
+ os.Remove(tmp.Name())
+ return err
+ }
+ return os.Rename(tmp.Name(), dst)
+}
+
+func (ws *Workspace) Import(src, dst string) error {
+ realDst := filepath.Join(ws.volumePath, dst)
+
+ return ws.copyFile(src, realDst, 0644)
+}
+
+func (ws *Workspace) Export(src, dst string) error {
+ realSrc := filepath.Join(ws.volumePath, src)
+
+ return ws.copyFile(realSrc, dst, 0644)
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/workspace/workspace.go Sat Mar 30 16:28:57 2019 -0500
@@ -0,0 +1,76 @@
+// Convey
+// Copyright 2016-2019 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 workspace
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+)
+
+type Workspace struct {
+ path string
+ volumePath string
+}
+
+func New(root string) (*Workspace, error) {
+ parent := filepath.Join(root, ".convey")
+ err := os.MkdirAll(parent, 0700)
+ if err != nil {
+ return nil, err
+ }
+
+ path, err := ioutil.TempDir(parent, "")
+ if err != nil {
+ return nil, err
+ }
+
+ volumePath := filepath.Join(path, "volume")
+ err = os.Mkdir(volumePath, 0700)
+ if err != nil {
+ return nil, err
+ }
+
+ workspace := &Workspace{
+ path: path,
+ volumePath: volumePath,
+ }
+
+ return workspace, nil
+}
+
+func (ws *Workspace) Destroy() {
+ if err := os.RemoveAll(ws.path); err != nil {
+ fmt.Printf("error removing worksace: %s\n", err)
+ }
+
+ // try to remove the .convey directory. This will only succeed when
+ // our state is the only one and that's intentional.
+ dir := filepath.Dir(ws.path)
+ if err := os.Remove(dir); err != nil {
+ fmt.Printf("error removing .convey: %s\n", err)
+ }
+}
+
+func (ws *Workspace) Path() string {
+ return ws.path
+}
+
+func (ws *Workspace) Volume() string {
+ return ws.volumePath
+}