mirror of https://github.com/databricks/cli.git
Added support for bundle.Seq, simplified Mutator.Apply interface (#403)
## Changes Added support for `bundle.Seq`, simplified `Mutator.Apply` interface by removing list of mutators from return values/ ## Tests 1. Ran `cli bundle deploy` and interrupted it with Cmd + C mid execution so lock is not released 2. Ran `cli bundle deploy` top make sure that CLI is not trying to release lock when it fail to acquire it ``` andrew.nester@HFW9Y94129 multiples-tasks % cli bundle deploy Starting upload of bundle files Uploaded bundle files at /Users/andrew.nester@databricks.com/.bundle/simple-task/development/files! ^C andrew.nester@HFW9Y94129 multiples-tasks % cli bundle deploy Error: deploy lock acquired by andrew.nester@databricks.com at 2023-05-24 12:10:23.050343 +0200 CEST. Use --force to override ```
This commit is contained in:
parent
273271bc59
commit
6141476ca2
|
@ -20,7 +20,7 @@ func (m *all) Name() string {
|
||||||
return fmt.Sprintf("artifacts.%sAll", m.name)
|
return fmt.Sprintf("artifacts.%sAll", m.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *all) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *all) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
var out []bundle.Mutator
|
var out []bundle.Mutator
|
||||||
|
|
||||||
// Iterate with stable ordering.
|
// Iterate with stable ordering.
|
||||||
|
@ -30,12 +30,12 @@ func (m *all) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, er
|
||||||
for _, name := range keys {
|
for _, name := range keys {
|
||||||
m, err := m.fn(name)
|
m, err := m.fn(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
if m != nil {
|
if m != nil {
|
||||||
out = append(out, m)
|
out = append(out, m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out, nil
|
return bundle.Apply(ctx, b, bundle.Seq(out...))
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,15 +27,15 @@ func (m *build) Name() string {
|
||||||
return fmt.Sprintf("artifacts.Build(%s)", m.name)
|
return fmt.Sprintf("artifacts.Build(%s)", m.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *build) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *build) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
artifact, ok := b.Config.Artifacts[m.name]
|
artifact, ok := b.Config.Artifacts[m.name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("artifact doesn't exist: %s", m.name)
|
return fmt.Errorf("artifact doesn't exist: %s", m.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if artifact.Notebook != nil {
|
if artifact.Notebook != nil {
|
||||||
return []bundle.Mutator{notebook.Build(m.name)}, nil
|
return bundle.Apply(ctx, b, notebook.Build(m.name))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@ func (m *build) Name() string {
|
||||||
return fmt.Sprintf("notebook.Build(%s)", m.name)
|
return fmt.Sprintf("notebook.Build(%s)", m.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *build) Apply(_ context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *build) Apply(_ context.Context, b *bundle.Bundle) error {
|
||||||
a, ok := b.Config.Artifacts[m.name]
|
a, ok := b.Config.Artifacts[m.name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("artifact doesn't exist: %s", m.name)
|
return fmt.Errorf("artifact doesn't exist: %s", m.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
artifact := a.Notebook
|
artifact := a.Notebook
|
||||||
|
@ -44,35 +44,35 @@ func (m *build) Apply(_ context.Context, b *bundle.Bundle) ([]bundle.Mutator, er
|
||||||
case ".sql":
|
case ".sql":
|
||||||
artifact.Language = workspace.LanguageSql
|
artifact.Language = workspace.LanguageSql
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid notebook extension: %s", ext)
|
return fmt.Errorf("invalid notebook extension: %s", ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open underlying file.
|
// Open underlying file.
|
||||||
f, err := os.Open(filepath.Join(b.Config.Path, artifact.Path))
|
f, err := os.Open(filepath.Join(b.Config.Path, artifact.Path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to open artifact file %s: %w", artifact.Path, errors.Unwrap(err))
|
return fmt.Errorf("unable to open artifact file %s: %w", artifact.Path, errors.Unwrap(err))
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
// Check that the file contains the notebook marker on its first line.
|
// Check that the file contains the notebook marker on its first line.
|
||||||
ok, err = hasMarker(artifact.Language, f)
|
ok, err = hasMarker(artifact.Language, f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to read artifact file %s: %s", artifact.Path, errors.Unwrap(err))
|
return fmt.Errorf("unable to read artifact file %s: %s", artifact.Path, errors.Unwrap(err))
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("notebook marker not found in %s", artifact.Path)
|
return fmt.Errorf("notebook marker not found in %s", artifact.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that an artifact path is defined.
|
// Check that an artifact path is defined.
|
||||||
remotePath := b.Config.Workspace.ArtifactsPath
|
remotePath := b.Config.Workspace.ArtifactsPath
|
||||||
if remotePath == "" {
|
if remotePath == "" {
|
||||||
return nil, fmt.Errorf("remote artifact path not configured")
|
return fmt.Errorf("remote artifact path not configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store absolute paths.
|
// Store absolute paths.
|
||||||
artifact.LocalPath = filepath.Join(b.Config.Path, artifact.Path)
|
artifact.LocalPath = filepath.Join(b.Config.Path, artifact.Path)
|
||||||
artifact.RemotePath = path.Join(remotePath, stripExtension(artifact.Path))
|
artifact.RemotePath = path.Join(remotePath, stripExtension(artifact.Path))
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func stripExtension(path string) string {
|
func stripExtension(path string) string {
|
||||||
|
|
|
@ -26,22 +26,22 @@ func (m *upload) Name() string {
|
||||||
return fmt.Sprintf("notebook.Upload(%s)", m.name)
|
return fmt.Sprintf("notebook.Upload(%s)", m.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *upload) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *upload) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
a, ok := b.Config.Artifacts[m.name]
|
a, ok := b.Config.Artifacts[m.name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("artifact doesn't exist: %s", m.name)
|
return fmt.Errorf("artifact doesn't exist: %s", m.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
artifact := a.Notebook
|
artifact := a.Notebook
|
||||||
raw, err := os.ReadFile(artifact.LocalPath)
|
raw, err := os.ReadFile(artifact.LocalPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to read %s: %w", m.name, errors.Unwrap(err))
|
return fmt.Errorf("unable to read %s: %w", m.name, errors.Unwrap(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure target directory exists.
|
// Make sure target directory exists.
|
||||||
err = b.WorkspaceClient().Workspace.MkdirsByPath(ctx, path.Dir(artifact.RemotePath))
|
err = b.WorkspaceClient().Workspace.MkdirsByPath(ctx, path.Dir(artifact.RemotePath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to create directory for %s: %w", m.name, err)
|
return fmt.Errorf("unable to create directory for %s: %w", m.name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import to workspace.
|
// Import to workspace.
|
||||||
|
@ -53,8 +53,8 @@ func (m *upload) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator,
|
||||||
Content: base64.StdEncoding.EncodeToString(raw),
|
Content: base64.StdEncoding.EncodeToString(raw),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to import %s: %w", m.name, err)
|
return fmt.Errorf("unable to import %s: %w", m.name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,15 +27,15 @@ func (m *upload) Name() string {
|
||||||
return fmt.Sprintf("artifacts.Upload(%s)", m.name)
|
return fmt.Sprintf("artifacts.Upload(%s)", m.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *upload) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *upload) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
artifact, ok := b.Config.Artifacts[m.name]
|
artifact, ok := b.Config.Artifacts[m.name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("artifact doesn't exist: %s", m.name)
|
return fmt.Errorf("artifact doesn't exist: %s", m.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if artifact.Notebook != nil {
|
if artifact.Notebook != nil {
|
||||||
return []bundle.Mutator{notebook.Upload(m.name)}, nil
|
return bundle.Apply(ctx, b, notebook.Upload(m.name))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,6 +247,6 @@ func (m *interpolate) Name() string {
|
||||||
return "Interpolate"
|
return "Interpolate"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *interpolate) Apply(_ context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *interpolate) Apply(_ context.Context, b *bundle.Bundle) error {
|
||||||
return nil, m.expand(&b.Config)
|
return m.expand(&b.Config)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,14 +24,14 @@ func (m *defineDefaultEnvironment) Name() string {
|
||||||
return fmt.Sprintf("DefineDefaultEnvironment(%s)", m.name)
|
return fmt.Sprintf("DefineDefaultEnvironment(%s)", m.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *defineDefaultEnvironment) Apply(_ context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *defineDefaultEnvironment) Apply(_ context.Context, b *bundle.Bundle) error {
|
||||||
// Nothing to do if the configuration has at least 1 environment.
|
// Nothing to do if the configuration has at least 1 environment.
|
||||||
if len(b.Config.Environments) > 0 {
|
if len(b.Config.Environments) > 0 {
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define default environment.
|
// Define default environment.
|
||||||
b.Config.Environments = make(map[string]*config.Environment)
|
b.Config.Environments = make(map[string]*config.Environment)
|
||||||
b.Config.Environments[m.name] = &config.Environment{}
|
b.Config.Environments[m.name] = &config.Environment{}
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
|
|
||||||
func TestDefaultEnvironment(t *testing.T) {
|
func TestDefaultEnvironment(t *testing.T) {
|
||||||
bundle := &bundle.Bundle{}
|
bundle := &bundle.Bundle{}
|
||||||
_, err := mutator.DefineDefaultEnvironment().Apply(context.Background(), bundle)
|
err := mutator.DefineDefaultEnvironment().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
env, ok := bundle.Config.Environments["default"]
|
env, ok := bundle.Config.Environments["default"]
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
|
@ -28,7 +28,7 @@ func TestDefaultEnvironmentAlreadySpecified(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.DefineDefaultEnvironment().Apply(context.Background(), bundle)
|
err := mutator.DefineDefaultEnvironment().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, ok := bundle.Config.Environments["default"]
|
_, ok := bundle.Config.Environments["default"]
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
|
|
|
@ -28,9 +28,9 @@ func (m *defineDefaultInclude) Name() string {
|
||||||
return "DefineDefaultInclude"
|
return "DefineDefaultInclude"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *defineDefaultInclude) Apply(_ context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *defineDefaultInclude) Apply(_ context.Context, b *bundle.Bundle) error {
|
||||||
if len(b.Config.Include) == 0 {
|
if len(b.Config.Include) == 0 {
|
||||||
b.Config.Include = slices.Clone(m.include)
|
b.Config.Include = slices.Clone(m.include)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
|
|
||||||
func TestDefaultInclude(t *testing.T) {
|
func TestDefaultInclude(t *testing.T) {
|
||||||
bundle := &bundle.Bundle{}
|
bundle := &bundle.Bundle{}
|
||||||
_, err := mutator.DefineDefaultInclude().Apply(context.Background(), bundle)
|
err := mutator.DefineDefaultInclude().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, []string{"*.yml", "*/*.yml"}, bundle.Config.Include)
|
assert.Equal(t, []string{"*.yml", "*/*.yml"}, bundle.Config.Include)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,10 @@ func (m *defineDefaultWorkspacePaths) Name() string {
|
||||||
return "DefaultWorkspacePaths"
|
return "DefaultWorkspacePaths"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *defineDefaultWorkspacePaths) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *defineDefaultWorkspacePaths) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
root := b.Config.Workspace.RootPath
|
root := b.Config.Workspace.RootPath
|
||||||
if root == "" {
|
if root == "" {
|
||||||
return nil, fmt.Errorf("unable to define default workspace paths: workspace root not defined")
|
return fmt.Errorf("unable to define default workspace paths: workspace root not defined")
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.Config.Workspace.FilesPath == "" {
|
if b.Config.Workspace.FilesPath == "" {
|
||||||
|
@ -37,5 +37,5 @@ func (m *defineDefaultWorkspacePaths) Apply(ctx context.Context, b *bundle.Bundl
|
||||||
b.Config.Workspace.StatePath = path.Join(root, "state")
|
b.Config.Workspace.StatePath = path.Join(root, "state")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ func TestDefineDefaultWorkspacePaths(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.DefineDefaultWorkspacePaths().Apply(context.Background(), bundle)
|
err := mutator.DefineDefaultWorkspacePaths().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "/files", bundle.Config.Workspace.FilesPath)
|
assert.Equal(t, "/files", bundle.Config.Workspace.FilesPath)
|
||||||
assert.Equal(t, "/artifacts", bundle.Config.Workspace.ArtifactsPath)
|
assert.Equal(t, "/artifacts", bundle.Config.Workspace.ArtifactsPath)
|
||||||
|
@ -37,7 +37,7 @@ func TestDefineDefaultWorkspacePathsAlreadySet(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.DefineDefaultWorkspacePaths().Apply(context.Background(), bundle)
|
err := mutator.DefineDefaultWorkspacePaths().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "/foo/bar", bundle.Config.Workspace.FilesPath)
|
assert.Equal(t, "/foo/bar", bundle.Config.Workspace.FilesPath)
|
||||||
assert.Equal(t, "/foo/bar", bundle.Config.Workspace.ArtifactsPath)
|
assert.Equal(t, "/foo/bar", bundle.Config.Workspace.ArtifactsPath)
|
||||||
|
|
|
@ -18,17 +18,17 @@ func (m *defineDefaultWorkspaceRoot) Name() string {
|
||||||
return "DefineDefaultWorkspaceRoot"
|
return "DefineDefaultWorkspaceRoot"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *defineDefaultWorkspaceRoot) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *defineDefaultWorkspaceRoot) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
if b.Config.Workspace.RootPath != "" {
|
if b.Config.Workspace.RootPath != "" {
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.Config.Bundle.Name == "" {
|
if b.Config.Bundle.Name == "" {
|
||||||
return nil, fmt.Errorf("unable to define default workspace root: bundle name not defined")
|
return fmt.Errorf("unable to define default workspace root: bundle name not defined")
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.Config.Bundle.Environment == "" {
|
if b.Config.Bundle.Environment == "" {
|
||||||
return nil, fmt.Errorf("unable to define default workspace root: bundle environment not selected")
|
return fmt.Errorf("unable to define default workspace root: bundle environment not selected")
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Config.Workspace.RootPath = fmt.Sprintf(
|
b.Config.Workspace.RootPath = fmt.Sprintf(
|
||||||
|
@ -36,5 +36,5 @@ func (m *defineDefaultWorkspaceRoot) Apply(ctx context.Context, b *bundle.Bundle
|
||||||
b.Config.Bundle.Name,
|
b.Config.Bundle.Name,
|
||||||
b.Config.Bundle.Environment,
|
b.Config.Bundle.Environment,
|
||||||
)
|
)
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ func TestDefaultWorkspaceRoot(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.DefineDefaultWorkspaceRoot().Apply(context.Background(), bundle)
|
err := mutator.DefineDefaultWorkspaceRoot().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "~/.bundle/name/environment", bundle.Config.Workspace.RootPath)
|
assert.Equal(t, "~/.bundle/name/environment", bundle.Config.Workspace.RootPath)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,15 +20,15 @@ func (m *expandWorkspaceRoot) Name() string {
|
||||||
return "ExpandWorkspaceRoot"
|
return "ExpandWorkspaceRoot"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *expandWorkspaceRoot) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *expandWorkspaceRoot) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
root := b.Config.Workspace.RootPath
|
root := b.Config.Workspace.RootPath
|
||||||
if root == "" {
|
if root == "" {
|
||||||
return nil, fmt.Errorf("unable to expand workspace root: workspace root not defined")
|
return fmt.Errorf("unable to expand workspace root: workspace root not defined")
|
||||||
}
|
}
|
||||||
|
|
||||||
currentUser := b.Config.Workspace.CurrentUser
|
currentUser := b.Config.Workspace.CurrentUser
|
||||||
if currentUser == nil || currentUser.UserName == "" {
|
if currentUser == nil || currentUser.UserName == "" {
|
||||||
return nil, fmt.Errorf("unable to expand workspace root: current user not set")
|
return fmt.Errorf("unable to expand workspace root: current user not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(root, "~/") {
|
if strings.HasPrefix(root, "~/") {
|
||||||
|
@ -36,5 +36,5 @@ func (m *expandWorkspaceRoot) Apply(ctx context.Context, b *bundle.Bundle) ([]bu
|
||||||
b.Config.Workspace.RootPath = path.Join(home, root[2:])
|
b.Config.Workspace.RootPath = path.Join(home, root[2:])
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ func TestExpandWorkspaceRoot(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.ExpandWorkspaceRoot().Apply(context.Background(), bundle)
|
err := mutator.ExpandWorkspaceRoot().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "/Users/jane@doe.com/foo", bundle.Config.Workspace.RootPath)
|
assert.Equal(t, "/Users/jane@doe.com/foo", bundle.Config.Workspace.RootPath)
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ func TestExpandWorkspaceRootDoesNothing(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.ExpandWorkspaceRoot().Apply(context.Background(), bundle)
|
err := mutator.ExpandWorkspaceRoot().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "/Users/charly@doe.com/foo", bundle.Config.Workspace.RootPath)
|
assert.Equal(t, "/Users/charly@doe.com/foo", bundle.Config.Workspace.RootPath)
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ func TestExpandWorkspaceRootWithoutRoot(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.ExpandWorkspaceRoot().Apply(context.Background(), bundle)
|
err := mutator.ExpandWorkspaceRoot().Apply(context.Background(), bundle)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +66,6 @@ func TestExpandWorkspaceRootWithoutCurrentUser(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.ExpandWorkspaceRoot().Apply(context.Background(), bundle)
|
err := mutator.ExpandWorkspaceRoot().Apply(context.Background(), bundle)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,11 @@ func (m *loadGitDetails) Name() string {
|
||||||
return "LoadGitDetails"
|
return "LoadGitDetails"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *loadGitDetails) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *loadGitDetails) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
// Load relevant git repository
|
// Load relevant git repository
|
||||||
repo, err := git.NewRepository(b.Config.Path)
|
repo, err := git.NewRepository(b.Config.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
// load branch name if undefined
|
// load branch name if undefined
|
||||||
if b.Config.Bundle.Git.Branch == "" {
|
if b.Config.Bundle.Git.Branch == "" {
|
||||||
|
@ -47,5 +47,5 @@ func (m *loadGitDetails) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.
|
||||||
remoteUrl := repo.OriginUrl()
|
remoteUrl := repo.OriginUrl()
|
||||||
b.Config.Bundle.Git.OriginURL = remoteUrl
|
b.Config.Bundle.Git.OriginURL = remoteUrl
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,13 @@ func (m *populateCurrentUser) Name() string {
|
||||||
return "PopulateCurrentUser"
|
return "PopulateCurrentUser"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *populateCurrentUser) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *populateCurrentUser) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
w := b.WorkspaceClient()
|
w := b.WorkspaceClient()
|
||||||
me, err := w.CurrentUser.Me(ctx)
|
me, err := w.CurrentUser.Me(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Config.Workspace.CurrentUser = me
|
b.Config.Workspace.CurrentUser = me
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,10 @@ func (m *processInclude) Name() string {
|
||||||
return fmt.Sprintf("ProcessInclude(%s)", m.relPath)
|
return fmt.Sprintf("ProcessInclude(%s)", m.relPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *processInclude) Apply(_ context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *processInclude) Apply(_ context.Context, b *bundle.Bundle) error {
|
||||||
this, err := config.Load(m.fullPath)
|
this, err := config.Load(m.fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
return nil, b.Config.Merge(this)
|
return b.Config.Merge(this)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ func TestProcessInclude(t *testing.T) {
|
||||||
f.Close()
|
f.Close()
|
||||||
|
|
||||||
assert.Equal(t, "foo", bundle.Config.Workspace.Host)
|
assert.Equal(t, "foo", bundle.Config.Workspace.Host)
|
||||||
_, err = mutator.ProcessInclude(fullPath, relPath).Apply(context.Background(), bundle)
|
err = mutator.ProcessInclude(fullPath, relPath).Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "bar", bundle.Config.Workspace.Host)
|
assert.Equal(t, "bar", bundle.Config.Workspace.Host)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ func (m *processRootIncludes) Name() string {
|
||||||
return "ProcessRootIncludes"
|
return "ProcessRootIncludes"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *processRootIncludes) Apply(_ context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *processRootIncludes) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
var out []bundle.Mutator
|
var out []bundle.Mutator
|
||||||
|
|
||||||
// Map with files we've already seen to avoid loading them twice.
|
// Map with files we've already seen to avoid loading them twice.
|
||||||
|
@ -40,13 +40,13 @@ func (m *processRootIncludes) Apply(_ context.Context, b *bundle.Bundle) ([]bund
|
||||||
for _, entry := range b.Config.Include {
|
for _, entry := range b.Config.Include {
|
||||||
// Include paths must be relative.
|
// Include paths must be relative.
|
||||||
if filepath.IsAbs(entry) {
|
if filepath.IsAbs(entry) {
|
||||||
return nil, fmt.Errorf("%s: includes must be relative paths", entry)
|
return fmt.Errorf("%s: includes must be relative paths", entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Anchor includes to the bundle root path.
|
// Anchor includes to the bundle root path.
|
||||||
matches, err := filepath.Glob(filepath.Join(b.Config.Path, entry))
|
matches, err := filepath.Glob(filepath.Join(b.Config.Path, entry))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter matches to ones we haven't seen yet.
|
// Filter matches to ones we haven't seen yet.
|
||||||
|
@ -54,7 +54,7 @@ func (m *processRootIncludes) Apply(_ context.Context, b *bundle.Bundle) ([]bund
|
||||||
for _, match := range matches {
|
for _, match := range matches {
|
||||||
rel, err := filepath.Rel(b.Config.Path, match)
|
rel, err := filepath.Rel(b.Config.Path, match)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
if _, ok := seen[rel]; ok {
|
if _, ok := seen[rel]; ok {
|
||||||
continue
|
continue
|
||||||
|
@ -74,5 +74,5 @@ func (m *processRootIncludes) Apply(_ context.Context, b *bundle.Bundle) ([]bund
|
||||||
// Swap out the original includes list with the expanded globs.
|
// Swap out the original includes list with the expanded globs.
|
||||||
b.Config.Include = files
|
b.Config.Include = files
|
||||||
|
|
||||||
return out, nil
|
return bundle.Apply(ctx, b, bundle.Seq(out...))
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ func TestProcessRootIncludesEmpty(t *testing.T) {
|
||||||
Path: ".",
|
Path: ".",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.ProcessRootIncludes().Apply(context.Background(), bundle)
|
err := mutator.ProcessRootIncludes().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ func TestProcessRootIncludesAbs(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.ProcessRootIncludes().Apply(context.Background(), bundle)
|
err := mutator.ProcessRootIncludes().Apply(context.Background(), bundle)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), "must be relative paths")
|
assert.Contains(t, err.Error(), "must be relative paths")
|
||||||
}
|
}
|
||||||
|
@ -65,17 +65,9 @@ func TestProcessRootIncludesSingleGlob(t *testing.T) {
|
||||||
touch(t, bundle.Config.Path, "a.yml")
|
touch(t, bundle.Config.Path, "a.yml")
|
||||||
touch(t, bundle.Config.Path, "b.yml")
|
touch(t, bundle.Config.Path, "b.yml")
|
||||||
|
|
||||||
ms, err := mutator.ProcessRootIncludes().Apply(context.Background(), bundle)
|
err := mutator.ProcessRootIncludes().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
var names []string
|
|
||||||
for _, m := range ms {
|
|
||||||
names = append(names, m.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.NotContains(t, names, "ProcessInclude(bundle.yml)")
|
|
||||||
assert.Contains(t, names, "ProcessInclude(a.yml)")
|
|
||||||
assert.Contains(t, names, "ProcessInclude(b.yml)")
|
|
||||||
assert.Equal(t, []string{"a.yml", "b.yml"}, bundle.Config.Include)
|
assert.Equal(t, []string{"a.yml", "b.yml"}, bundle.Config.Include)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,16 +85,9 @@ func TestProcessRootIncludesMultiGlob(t *testing.T) {
|
||||||
touch(t, bundle.Config.Path, "a1.yml")
|
touch(t, bundle.Config.Path, "a1.yml")
|
||||||
touch(t, bundle.Config.Path, "b1.yml")
|
touch(t, bundle.Config.Path, "b1.yml")
|
||||||
|
|
||||||
ms, err := mutator.ProcessRootIncludes().Apply(context.Background(), bundle)
|
err := mutator.ProcessRootIncludes().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
var names []string
|
|
||||||
for _, m := range ms {
|
|
||||||
names = append(names, m.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Contains(t, names, "ProcessInclude(a1.yml)")
|
|
||||||
assert.Contains(t, names, "ProcessInclude(b1.yml)")
|
|
||||||
assert.Equal(t, []string{"a1.yml", "b1.yml"}, bundle.Config.Include)
|
assert.Equal(t, []string{"a1.yml", "b1.yml"}, bundle.Config.Include)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,9 +104,7 @@ func TestProcessRootIncludesRemoveDups(t *testing.T) {
|
||||||
|
|
||||||
touch(t, bundle.Config.Path, "a.yml")
|
touch(t, bundle.Config.Path, "a.yml")
|
||||||
|
|
||||||
ms, err := mutator.ProcessRootIncludes().Apply(context.Background(), bundle)
|
err := mutator.ProcessRootIncludes().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, ms, 1)
|
|
||||||
assert.Equal(t, "ProcessInclude(a.yml)", ms[0].Name())
|
|
||||||
assert.Equal(t, []string{"a.yml"}, bundle.Config.Include)
|
assert.Equal(t, []string{"a.yml"}, bundle.Config.Include)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,15 +20,15 @@ func (m *selectDefaultEnvironment) Name() string {
|
||||||
return "SelectDefaultEnvironment"
|
return "SelectDefaultEnvironment"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *selectDefaultEnvironment) Apply(_ context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *selectDefaultEnvironment) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
if len(b.Config.Environments) == 0 {
|
if len(b.Config.Environments) == 0 {
|
||||||
return nil, fmt.Errorf("no environments defined")
|
return fmt.Errorf("no environments defined")
|
||||||
}
|
}
|
||||||
|
|
||||||
// One environment means there's only one default.
|
// One environment means there's only one default.
|
||||||
names := maps.Keys(b.Config.Environments)
|
names := maps.Keys(b.Config.Environments)
|
||||||
if len(names) == 1 {
|
if len(names) == 1 {
|
||||||
return []bundle.Mutator{SelectEnvironment(names[0])}, nil
|
return SelectEnvironment(names[0]).Apply(ctx, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiple environments means we look for the `default` flag.
|
// Multiple environments means we look for the `default` flag.
|
||||||
|
@ -41,14 +41,14 @@ func (m *selectDefaultEnvironment) Apply(_ context.Context, b *bundle.Bundle) ([
|
||||||
|
|
||||||
// It is invalid to have multiple environments with the `default` flag set.
|
// It is invalid to have multiple environments with the `default` flag set.
|
||||||
if len(defaults) > 1 {
|
if len(defaults) > 1 {
|
||||||
return nil, fmt.Errorf("multiple environments are marked as default (%s)", strings.Join(defaults, ", "))
|
return fmt.Errorf("multiple environments are marked as default (%s)", strings.Join(defaults, ", "))
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no environment has the `default` flag set, ask the user to specify one.
|
// If no environment has the `default` flag set, ask the user to specify one.
|
||||||
if len(defaults) == 0 {
|
if len(defaults) == 0 {
|
||||||
return nil, fmt.Errorf("please specify environment")
|
return fmt.Errorf("please specify environment")
|
||||||
}
|
}
|
||||||
|
|
||||||
// One default remaining.
|
// One default remaining.
|
||||||
return []bundle.Mutator{SelectEnvironment(defaults[0])}, nil
|
return SelectEnvironment(defaults[0]).Apply(ctx, b)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ func TestSelectDefaultEnvironmentNoEnvironments(t *testing.T) {
|
||||||
Environments: map[string]*config.Environment{},
|
Environments: map[string]*config.Environment{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.SelectDefaultEnvironment().Apply(context.Background(), bundle)
|
err := mutator.SelectDefaultEnvironment().Apply(context.Background(), bundle)
|
||||||
assert.ErrorContains(t, err, "no environments defined")
|
assert.ErrorContains(t, err, "no environments defined")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,10 +28,9 @@ func TestSelectDefaultEnvironmentSingleEnvironments(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
ms, err := mutator.SelectDefaultEnvironment().Apply(context.Background(), bundle)
|
err := mutator.SelectDefaultEnvironment().Apply(context.Background(), bundle)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, ms, 1)
|
assert.Equal(t, "foo", bundle.Config.Bundle.Environment)
|
||||||
assert.Equal(t, "SelectEnvironment(foo)", ms[0].Name())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSelectDefaultEnvironmentNoDefaults(t *testing.T) {
|
func TestSelectDefaultEnvironmentNoDefaults(t *testing.T) {
|
||||||
|
@ -44,7 +43,7 @@ func TestSelectDefaultEnvironmentNoDefaults(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.SelectDefaultEnvironment().Apply(context.Background(), bundle)
|
err := mutator.SelectDefaultEnvironment().Apply(context.Background(), bundle)
|
||||||
assert.ErrorContains(t, err, "please specify environment")
|
assert.ErrorContains(t, err, "please specify environment")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +56,7 @@ func TestSelectDefaultEnvironmentNoDefaultsWithNil(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.SelectDefaultEnvironment().Apply(context.Background(), bundle)
|
err := mutator.SelectDefaultEnvironment().Apply(context.Background(), bundle)
|
||||||
assert.ErrorContains(t, err, "please specify environment")
|
assert.ErrorContains(t, err, "please specify environment")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +70,7 @@ func TestSelectDefaultEnvironmentMultipleDefaults(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.SelectDefaultEnvironment().Apply(context.Background(), bundle)
|
err := mutator.SelectDefaultEnvironment().Apply(context.Background(), bundle)
|
||||||
assert.ErrorContains(t, err, "multiple environments are marked as default")
|
assert.ErrorContains(t, err, "multiple environments are marked as default")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,8 +84,7 @@ func TestSelectDefaultEnvironmentSingleDefault(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
ms, err := mutator.SelectDefaultEnvironment().Apply(context.Background(), bundle)
|
err := mutator.SelectDefaultEnvironment().Apply(context.Background(), bundle)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, ms, 1)
|
assert.Equal(t, "bar", bundle.Config.Bundle.Environment)
|
||||||
assert.Equal(t, "SelectEnvironment(bar)", ms[0].Name())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,21 +22,21 @@ func (m *selectEnvironment) Name() string {
|
||||||
return fmt.Sprintf("SelectEnvironment(%s)", m.name)
|
return fmt.Sprintf("SelectEnvironment(%s)", m.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *selectEnvironment) Apply(_ context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *selectEnvironment) Apply(_ context.Context, b *bundle.Bundle) error {
|
||||||
if b.Config.Environments == nil {
|
if b.Config.Environments == nil {
|
||||||
return nil, fmt.Errorf("no environments defined")
|
return fmt.Errorf("no environments defined")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get specified environment
|
// Get specified environment
|
||||||
env, ok := b.Config.Environments[m.name]
|
env, ok := b.Config.Environments[m.name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("%s: no such environment", m.name)
|
return fmt.Errorf("%s: no such environment", m.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge specified environment into root configuration structure.
|
// Merge specified environment into root configuration structure.
|
||||||
err := b.Config.MergeEnvironment(env)
|
err := b.Config.MergeEnvironment(env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store specified environment in configuration for reference.
|
// Store specified environment in configuration for reference.
|
||||||
|
@ -44,5 +44,5 @@ func (m *selectEnvironment) Apply(_ context.Context, b *bundle.Bundle) ([]bundle
|
||||||
|
|
||||||
// Clear environments after loading.
|
// Clear environments after loading.
|
||||||
b.Config.Environments = nil
|
b.Config.Environments = nil
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ func TestSelectEnvironment(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.SelectEnvironment("default").Apply(context.Background(), bundle)
|
err := mutator.SelectEnvironment("default").Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "bar", bundle.Config.Workspace.Host)
|
assert.Equal(t, "bar", bundle.Config.Workspace.Host)
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,6 @@ func TestSelectEnvironmentNotFound(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := mutator.SelectEnvironment("doesnt-exist").Apply(context.Background(), bundle)
|
err := mutator.SelectEnvironment("doesnt-exist").Apply(context.Background(), bundle)
|
||||||
require.Error(t, err, "no environments defined")
|
require.Error(t, err, "no environments defined")
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,12 +52,12 @@ func setVariable(v *variable.Variable, name string) error {
|
||||||
return fmt.Errorf(`no value assigned to required variable %s. Assignment can be done through the "--var" flag or by setting the %s environment variable`, name, bundleVarPrefix+name)
|
return fmt.Errorf(`no value assigned to required variable %s. Assignment can be done through the "--var" flag or by setting the %s environment variable`, name, bundleVarPrefix+name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *setVariables) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *setVariables) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
for name, variable := range b.Config.Variables {
|
for name, variable := range b.Config.Variables {
|
||||||
err := setVariable(variable, name)
|
err := setVariable(variable, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ func TestSetVariablesMutator(t *testing.T) {
|
||||||
|
|
||||||
t.Setenv("BUNDLE_VAR_b", "env-var-b")
|
t.Setenv("BUNDLE_VAR_b", "env-var-b")
|
||||||
|
|
||||||
_, err := SetVariables().Apply(context.Background(), bundle)
|
err := SetVariables().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "default-a", *bundle.Config.Variables["a"].Value)
|
assert.Equal(t, "default-a", *bundle.Config.Variables["a"].Value)
|
||||||
assert.Equal(t, "env-var-b", *bundle.Config.Variables["b"].Value)
|
assert.Equal(t, "env-var-b", *bundle.Config.Variables["b"].Value)
|
||||||
|
|
|
@ -145,19 +145,19 @@ func (m *translatePaths) translatePipelineLibrary(dir string, b *bundle.Bundle,
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *translatePaths) Apply(_ context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *translatePaths) Apply(_ context.Context, b *bundle.Bundle) error {
|
||||||
m.seen = make(map[string]string)
|
m.seen = make(map[string]string)
|
||||||
|
|
||||||
for key, job := range b.Config.Resources.Jobs {
|
for key, job := range b.Config.Resources.Jobs {
|
||||||
dir, err := job.ConfigFileDirectory()
|
dir, err := job.ConfigFileDirectory()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to determine directory for job %s: %w", key, err)
|
return fmt.Errorf("unable to determine directory for job %s: %w", key, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(job.Tasks); i++ {
|
for i := 0; i < len(job.Tasks); i++ {
|
||||||
err := m.translateJobTask(dir, b, &job.Tasks[i])
|
err := m.translateJobTask(dir, b, &job.Tasks[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,16 +165,16 @@ func (m *translatePaths) Apply(_ context.Context, b *bundle.Bundle) ([]bundle.Mu
|
||||||
for key, pipeline := range b.Config.Resources.Pipelines {
|
for key, pipeline := range b.Config.Resources.Pipelines {
|
||||||
dir, err := pipeline.ConfigFileDirectory()
|
dir, err := pipeline.ConfigFileDirectory()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to determine directory for pipeline %s: %w", key, err)
|
return fmt.Errorf("unable to determine directory for pipeline %s: %w", key, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(pipeline.Libraries); i++ {
|
for i := 0; i < len(pipeline.Libraries); i++ {
|
||||||
err := m.translatePipelineLibrary(dir, b, &pipeline.Libraries[i])
|
err := m.translatePipelineLibrary(dir, b, &pipeline.Libraries[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ func TestTranslatePaths(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := mutator.TranslatePaths().Apply(context.Background(), bundle)
|
err := mutator.TranslatePaths().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Assert that the path in the tasks now refer to the artifact.
|
// Assert that the path in the tasks now refer to the artifact.
|
||||||
|
@ -215,7 +215,7 @@ func TestTranslatePathsInSubdirectories(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := mutator.TranslatePaths().Apply(context.Background(), bundle)
|
err := mutator.TranslatePaths().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(
|
assert.Equal(
|
||||||
|
@ -261,7 +261,7 @@ func TestTranslatePathsOutsideBundleRoot(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := mutator.TranslatePaths().Apply(context.Background(), bundle)
|
err := mutator.TranslatePaths().Apply(context.Background(), bundle)
|
||||||
assert.ErrorContains(t, err, "is not contained in bundle root")
|
assert.ErrorContains(t, err, "is not contained in bundle root")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ func TestJobNotebookDoesNotExistError(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := mutator.TranslatePaths().Apply(context.Background(), bundle)
|
err := mutator.TranslatePaths().Apply(context.Background(), bundle)
|
||||||
assert.EqualError(t, err, "notebook ./doesnt_exist.py not found")
|
assert.EqualError(t, err, "notebook ./doesnt_exist.py not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +323,7 @@ func TestJobFileDoesNotExistError(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := mutator.TranslatePaths().Apply(context.Background(), bundle)
|
err := mutator.TranslatePaths().Apply(context.Background(), bundle)
|
||||||
assert.EqualError(t, err, "file ./doesnt_exist.py not found")
|
assert.EqualError(t, err, "file ./doesnt_exist.py not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,7 +354,7 @@ func TestPipelineNotebookDoesNotExistError(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := mutator.TranslatePaths().Apply(context.Background(), bundle)
|
err := mutator.TranslatePaths().Apply(context.Background(), bundle)
|
||||||
assert.EqualError(t, err, "notebook ./doesnt_exist.py not found")
|
assert.EqualError(t, err, "notebook ./doesnt_exist.py not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,6 +385,6 @@ func TestPipelineFileDoesNotExistError(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := mutator.TranslatePaths().Apply(context.Background(), bundle)
|
err := mutator.TranslatePaths().Apply(context.Background(), bundle)
|
||||||
assert.EqualError(t, err, "file ./doesnt_exist.py not found")
|
assert.EqualError(t, err, "file ./doesnt_exist.py not found")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,29 +7,27 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type DeferredMutator struct {
|
type DeferredMutator struct {
|
||||||
mutators []Mutator
|
mutator Mutator
|
||||||
finally []Mutator
|
finally Mutator
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DeferredMutator) Name() string {
|
func (d *DeferredMutator) Name() string {
|
||||||
return "deferred"
|
return "deferred"
|
||||||
}
|
}
|
||||||
|
|
||||||
func Defer(mutators []Mutator, finally []Mutator) []Mutator {
|
func Defer(mutator Mutator, finally Mutator) Mutator {
|
||||||
return []Mutator{
|
return &DeferredMutator{
|
||||||
&DeferredMutator{
|
mutator: mutator,
|
||||||
mutators: mutators,
|
|
||||||
finally: finally,
|
finally: finally,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DeferredMutator) Apply(ctx context.Context, b *Bundle) ([]Mutator, error) {
|
func (d *DeferredMutator) Apply(ctx context.Context, b *Bundle) error {
|
||||||
mainErr := Apply(ctx, b, d.mutators)
|
mainErr := Apply(ctx, b, d.mutator)
|
||||||
errOnFinish := Apply(ctx, b, d.finally)
|
errOnFinish := Apply(ctx, b, d.finally)
|
||||||
if mainErr != nil || errOnFinish != nil {
|
if mainErr != nil || errOnFinish != nil {
|
||||||
return nil, errs.FromMany(mainErr, errOnFinish)
|
return errs.FromMany(mainErr, errOnFinish)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,9 @@ func (t *mutatorWithError) Name() string {
|
||||||
return "mutatorWithError"
|
return "mutatorWithError"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *mutatorWithError) Apply(_ context.Context, b *Bundle) ([]Mutator, error) {
|
func (t *mutatorWithError) Apply(_ context.Context, b *Bundle) error {
|
||||||
t.applyCalled++
|
t.applyCalled++
|
||||||
return nil, fmt.Errorf(t.errorMsg)
|
return fmt.Errorf(t.errorMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeferredMutatorWhenAllMutatorsSucceed(t *testing.T) {
|
func TestDeferredMutatorWhenAllMutatorsSucceed(t *testing.T) {
|
||||||
|
@ -27,7 +27,7 @@ func TestDeferredMutatorWhenAllMutatorsSucceed(t *testing.T) {
|
||||||
m2 := &testMutator{}
|
m2 := &testMutator{}
|
||||||
m3 := &testMutator{}
|
m3 := &testMutator{}
|
||||||
cleanup := &testMutator{}
|
cleanup := &testMutator{}
|
||||||
deferredMutator := Defer([]Mutator{m1, m2, m3}, []Mutator{cleanup})
|
deferredMutator := Defer(Seq(m1, m2, m3), cleanup)
|
||||||
|
|
||||||
bundle := &Bundle{}
|
bundle := &Bundle{}
|
||||||
err := Apply(context.Background(), bundle, deferredMutator)
|
err := Apply(context.Background(), bundle, deferredMutator)
|
||||||
|
@ -44,7 +44,7 @@ func TestDeferredMutatorWhenFirstFails(t *testing.T) {
|
||||||
m2 := &testMutator{}
|
m2 := &testMutator{}
|
||||||
mErr := &mutatorWithError{errorMsg: "mutator error occurred"}
|
mErr := &mutatorWithError{errorMsg: "mutator error occurred"}
|
||||||
cleanup := &testMutator{}
|
cleanup := &testMutator{}
|
||||||
deferredMutator := Defer([]Mutator{mErr, m1, m2}, []Mutator{cleanup})
|
deferredMutator := Defer(Seq(mErr, m1, m2), cleanup)
|
||||||
|
|
||||||
bundle := &Bundle{}
|
bundle := &Bundle{}
|
||||||
err := Apply(context.Background(), bundle, deferredMutator)
|
err := Apply(context.Background(), bundle, deferredMutator)
|
||||||
|
@ -61,7 +61,7 @@ func TestDeferredMutatorWhenMiddleOneFails(t *testing.T) {
|
||||||
m2 := &testMutator{}
|
m2 := &testMutator{}
|
||||||
mErr := &mutatorWithError{errorMsg: "mutator error occurred"}
|
mErr := &mutatorWithError{errorMsg: "mutator error occurred"}
|
||||||
cleanup := &testMutator{}
|
cleanup := &testMutator{}
|
||||||
deferredMutator := Defer([]Mutator{m1, mErr, m2}, []Mutator{cleanup})
|
deferredMutator := Defer(Seq(m1, mErr, m2), cleanup)
|
||||||
|
|
||||||
bundle := &Bundle{}
|
bundle := &Bundle{}
|
||||||
err := Apply(context.Background(), bundle, deferredMutator)
|
err := Apply(context.Background(), bundle, deferredMutator)
|
||||||
|
@ -78,7 +78,7 @@ func TestDeferredMutatorWhenLastOneFails(t *testing.T) {
|
||||||
m2 := &testMutator{}
|
m2 := &testMutator{}
|
||||||
mErr := &mutatorWithError{errorMsg: "mutator error occurred"}
|
mErr := &mutatorWithError{errorMsg: "mutator error occurred"}
|
||||||
cleanup := &testMutator{}
|
cleanup := &testMutator{}
|
||||||
deferredMutator := Defer([]Mutator{m1, m2, mErr}, []Mutator{cleanup})
|
deferredMutator := Defer(Seq(m1, m2, mErr), cleanup)
|
||||||
|
|
||||||
bundle := &Bundle{}
|
bundle := &Bundle{}
|
||||||
err := Apply(context.Background(), bundle, deferredMutator)
|
err := Apply(context.Background(), bundle, deferredMutator)
|
||||||
|
@ -95,7 +95,7 @@ func TestDeferredMutatorCombinesErrorMessages(t *testing.T) {
|
||||||
m2 := &testMutator{}
|
m2 := &testMutator{}
|
||||||
mErr := &mutatorWithError{errorMsg: "mutator error occurred"}
|
mErr := &mutatorWithError{errorMsg: "mutator error occurred"}
|
||||||
cleanupErr := &mutatorWithError{errorMsg: "cleanup error occurred"}
|
cleanupErr := &mutatorWithError{errorMsg: "cleanup error occurred"}
|
||||||
deferredMutator := Defer([]Mutator{m1, m2, mErr}, []Mutator{cleanupErr})
|
deferredMutator := Defer(Seq(m1, m2, mErr), cleanupErr)
|
||||||
|
|
||||||
bundle := &Bundle{}
|
bundle := &Bundle{}
|
||||||
err := Apply(context.Background(), bundle, deferredMutator)
|
err := Apply(context.Background(), bundle, deferredMutator)
|
||||||
|
|
|
@ -16,10 +16,10 @@ func (m *delete) Name() string {
|
||||||
return "files.Delete"
|
return "files.Delete"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *delete) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *delete) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
// Do not delete files if terraform destroy was not consented
|
// Do not delete files if terraform destroy was not consented
|
||||||
if !b.Plan.IsEmpty && !b.Plan.ConfirmApply {
|
if !b.Plan.IsEmpty && !b.Plan.ConfirmApply {
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdio.LogString(ctx, "Starting deletion of remote bundle files")
|
cmdio.LogString(ctx, "Starting deletion of remote bundle files")
|
||||||
|
@ -29,10 +29,10 @@ func (m *delete) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator,
|
||||||
if !b.AutoApprove {
|
if !b.AutoApprove {
|
||||||
proceed, err := cmdio.Ask(ctx, fmt.Sprintf("\n%s and all files in it will be %s Proceed?: ", b.Config.Workspace.RootPath, red("deleted permanently!")))
|
proceed, err := cmdio.Ask(ctx, fmt.Sprintf("\n%s and all files in it will be %s Proceed?: ", b.Config.Workspace.RootPath, red("deleted permanently!")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
if !proceed {
|
if !proceed {
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,22 +41,22 @@ func (m *delete) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator,
|
||||||
Recursive: true,
|
Recursive: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up sync snapshot file
|
// Clean up sync snapshot file
|
||||||
sync, err := getSync(ctx, b)
|
sync, err := getSync(ctx, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
err = sync.DestroySnapshot(ctx)
|
err = sync.DestroySnapshot(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdio.LogString(ctx, fmt.Sprintf("Deleted snapshot file at %s", sync.SnapshotPath()))
|
cmdio.LogString(ctx, fmt.Sprintf("Deleted snapshot file at %s", sync.SnapshotPath()))
|
||||||
cmdio.LogString(ctx, "Successfully deleted files!")
|
cmdio.LogString(ctx, "Successfully deleted files!")
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Delete() bundle.Mutator {
|
func Delete() bundle.Mutator {
|
||||||
|
|
|
@ -14,20 +14,20 @@ func (m *upload) Name() string {
|
||||||
return "files.Upload"
|
return "files.Upload"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *upload) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *upload) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
cmdio.LogString(ctx, "Starting upload of bundle files")
|
cmdio.LogString(ctx, "Starting upload of bundle files")
|
||||||
sync, err := getSync(ctx, b)
|
sync, err := getSync(ctx, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sync.RunOnce(ctx)
|
err = sync.RunOnce(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdio.LogString(ctx, fmt.Sprintf("Uploaded bundle files at %s!\n", b.Config.Workspace.FilesPath))
|
cmdio.LogString(ctx, fmt.Sprintf("Uploaded bundle files at %s!\n", b.Config.Workspace.FilesPath))
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Upload() bundle.Mutator {
|
func Upload() bundle.Mutator {
|
||||||
|
|
|
@ -30,16 +30,16 @@ func (m *acquire) init(b *bundle.Bundle) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *acquire) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *acquire) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
// Return early if locking is disabled.
|
// Return early if locking is disabled.
|
||||||
if !b.Config.Bundle.Lock.IsEnabled() {
|
if !b.Config.Bundle.Lock.IsEnabled() {
|
||||||
log.Infof(ctx, "Skipping; locking is disabled")
|
log.Infof(ctx, "Skipping; locking is disabled")
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err := m.init(b)
|
err := m.init(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
force := b.Config.Bundle.Lock.Force
|
force := b.Config.Bundle.Lock.Force
|
||||||
|
@ -47,8 +47,8 @@ func (m *acquire) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator
|
||||||
err = b.Locker.Lock(ctx, force)
|
err = b.Locker.Lock(ctx, force)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf(ctx, "Failed to acquire deployment lock: %v", err)
|
log.Errorf(ctx, "Failed to acquire deployment lock: %v", err)
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,26 +17,26 @@ func (m *release) Name() string {
|
||||||
return "lock:release"
|
return "lock:release"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *release) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *release) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
// Return early if locking is disabled.
|
// Return early if locking is disabled.
|
||||||
if !b.Config.Bundle.Lock.IsEnabled() {
|
if !b.Config.Bundle.Lock.IsEnabled() {
|
||||||
log.Infof(ctx, "Skipping; locking is disabled")
|
log.Infof(ctx, "Skipping; locking is disabled")
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return early if the locker is not set.
|
// Return early if the locker is not set.
|
||||||
// It is likely an error occurred prior to initialization of the locker instance.
|
// It is likely an error occurred prior to initialization of the locker instance.
|
||||||
if b.Locker == nil {
|
if b.Locker == nil {
|
||||||
log.Warnf(ctx, "Unable to release lock if locker is not configured")
|
log.Warnf(ctx, "Unable to release lock if locker is not configured")
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof(ctx, "Releasing deployment lock")
|
log.Infof(ctx, "Releasing deployment lock")
|
||||||
err := b.Locker.Unlock(ctx)
|
err := b.Locker.Unlock(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf(ctx, "Failed to release deployment lock: %v", err)
|
log.Errorf(ctx, "Failed to release deployment lock: %v", err)
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,26 +15,26 @@ func (w *apply) Name() string {
|
||||||
return "terraform.Apply"
|
return "terraform.Apply"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *apply) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (w *apply) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
tf := b.Terraform
|
tf := b.Terraform
|
||||||
if tf == nil {
|
if tf == nil {
|
||||||
return nil, fmt.Errorf("terraform not initialized")
|
return fmt.Errorf("terraform not initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdio.LogString(ctx, "Starting resource deployment")
|
cmdio.LogString(ctx, "Starting resource deployment")
|
||||||
|
|
||||||
err := tf.Init(ctx, tfexec.Upgrade(true))
|
err := tf.Init(ctx, tfexec.Upgrade(true))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("terraform init: %w", err)
|
return fmt.Errorf("terraform init: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = tf.Apply(ctx)
|
err = tf.Apply(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("terraform apply: %w", err)
|
return fmt.Errorf("terraform apply: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdio.LogString(ctx, "Resource deployment completed!")
|
cmdio.LogString(ctx, "Resource deployment completed!")
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply returns a [bundle.Mutator] that runs the equivalent of `terraform apply`
|
// Apply returns a [bundle.Mutator] that runs the equivalent of `terraform apply`
|
||||||
|
|
|
@ -62,28 +62,28 @@ func (w *destroy) Name() string {
|
||||||
return "terraform.Destroy"
|
return "terraform.Destroy"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *destroy) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (w *destroy) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
// return early if plan is empty
|
// return early if plan is empty
|
||||||
if b.Plan.IsEmpty {
|
if b.Plan.IsEmpty {
|
||||||
cmdio.LogString(ctx, "No resources to destroy in plan. Skipping destroy!")
|
cmdio.LogString(ctx, "No resources to destroy in plan. Skipping destroy!")
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
tf := b.Terraform
|
tf := b.Terraform
|
||||||
if tf == nil {
|
if tf == nil {
|
||||||
return nil, fmt.Errorf("terraform not initialized")
|
return fmt.Errorf("terraform not initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// read plan file
|
// read plan file
|
||||||
plan, err := tf.ShowPlanFile(ctx, b.Plan.Path)
|
plan, err := tf.ShowPlanFile(ctx, b.Plan.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// print the resources that will be destroyed
|
// print the resources that will be destroyed
|
||||||
err = logDestroyPlan(ctx, plan.ResourceChanges)
|
err = logDestroyPlan(ctx, plan.ResourceChanges)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask for confirmation, if needed
|
// Ask for confirmation, if needed
|
||||||
|
@ -91,17 +91,17 @@ func (w *destroy) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator
|
||||||
red := color.New(color.FgRed).SprintFunc()
|
red := color.New(color.FgRed).SprintFunc()
|
||||||
b.Plan.ConfirmApply, err = cmdio.Ask(ctx, fmt.Sprintf("\nThis will permanently %s resources! Proceed? [y/n]: ", red("destroy")))
|
b.Plan.ConfirmApply, err = cmdio.Ask(ctx, fmt.Sprintf("\nThis will permanently %s resources! Proceed? [y/n]: ", red("destroy")))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return if confirmation was not provided
|
// return if confirmation was not provided
|
||||||
if !b.Plan.ConfirmApply {
|
if !b.Plan.ConfirmApply {
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.Plan.Path == "" {
|
if b.Plan.Path == "" {
|
||||||
return nil, fmt.Errorf("no plan found")
|
return fmt.Errorf("no plan found")
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdio.LogString(ctx, "Starting to destroy resources")
|
cmdio.LogString(ctx, "Starting to destroy resources")
|
||||||
|
@ -109,11 +109,11 @@ func (w *destroy) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator
|
||||||
// Apply terraform according to the computed destroy plan
|
// Apply terraform according to the computed destroy plan
|
||||||
err = tf.Apply(ctx, tfexec.DirOrPlan(b.Plan.Path))
|
err = tf.Apply(ctx, tfexec.DirOrPlan(b.Plan.Path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("terraform destroy: %w", err)
|
return fmt.Errorf("terraform destroy: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdio.LogString(ctx, "Successfully destroyed resources!")
|
cmdio.LogString(ctx, "Successfully destroyed resources!")
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy returns a [bundle.Mutator] that runs the conceptual equivalent of
|
// Destroy returns a [bundle.Mutator] that runs the conceptual equivalent of
|
||||||
|
|
|
@ -108,7 +108,7 @@ func setTempDirEnvVars(env map[string]string, b *bundle.Bundle) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *initialize) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (m *initialize) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
tfConfig := b.Config.Bundle.Terraform
|
tfConfig := b.Config.Bundle.Terraform
|
||||||
if tfConfig == nil {
|
if tfConfig == nil {
|
||||||
tfConfig = &config.Terraform{}
|
tfConfig = &config.Terraform{}
|
||||||
|
@ -117,22 +117,22 @@ func (m *initialize) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Muta
|
||||||
|
|
||||||
execPath, err := m.findExecPath(ctx, b, tfConfig)
|
execPath, err := m.findExecPath(ctx, b, tfConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
workingDir, err := Dir(b)
|
workingDir, err := Dir(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
tf, err := tfexec.NewTerraform(workingDir, execPath)
|
tf, err := tfexec.NewTerraform(workingDir, execPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
env, err := b.AuthEnv()
|
env, err := b.AuthEnv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include $HOME in set of environment variables to pass along.
|
// Include $HOME in set of environment variables to pass along.
|
||||||
|
@ -144,18 +144,18 @@ func (m *initialize) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Muta
|
||||||
// Set the temporary directory environment variables
|
// Set the temporary directory environment variables
|
||||||
err = setTempDirEnvVars(env, b)
|
err = setTempDirEnvVars(env, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure environment variables for auth for Terraform to use.
|
// Configure environment variables for auth for Terraform to use.
|
||||||
log.Debugf(ctx, "Environment variables for Terraform: %s", strings.Join(maps.Keys(env), ", "))
|
log.Debugf(ctx, "Environment variables for Terraform: %s", strings.Join(maps.Keys(env), ", "))
|
||||||
err = tf.SetEnv(env)
|
err = tf.SetEnv(env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Terraform = tf
|
b.Terraform = tf
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Initialize() bundle.Mutator {
|
func Initialize() bundle.Mutator {
|
||||||
|
|
|
@ -43,7 +43,7 @@ func TestInitEnvironmentVariables(t *testing.T) {
|
||||||
t.Setenv("DATABRICKS_TOKEN", "foobar")
|
t.Setenv("DATABRICKS_TOKEN", "foobar")
|
||||||
bundle.WorkspaceClient()
|
bundle.WorkspaceClient()
|
||||||
|
|
||||||
_, err = Initialize().Apply(context.Background(), bundle)
|
err = Initialize().Apply(context.Background(), bundle)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,34 +15,34 @@ func (l *load) Name() string {
|
||||||
return "terraform.Load"
|
return "terraform.Load"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *load) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (l *load) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
tf := b.Terraform
|
tf := b.Terraform
|
||||||
if tf == nil {
|
if tf == nil {
|
||||||
return nil, fmt.Errorf("terraform not initialized")
|
return fmt.Errorf("terraform not initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := tf.Init(ctx, tfexec.Upgrade(true))
|
err := tf.Init(ctx, tfexec.Upgrade(true))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("terraform init: %w", err)
|
return fmt.Errorf("terraform init: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
state, err := b.Terraform.Show(ctx)
|
state, err := b.Terraform.Show(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ValidateState(state)
|
err = ValidateState(state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge state into configuration.
|
// Merge state into configuration.
|
||||||
err = TerraformToBundle(state, &b.Config)
|
err = TerraformToBundle(state, &b.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateState(state *tfjson.State) error {
|
func ValidateState(state *tfjson.State) error {
|
||||||
|
|
|
@ -32,10 +32,10 @@ func TestLoadWithNoState(t *testing.T) {
|
||||||
t.Setenv("DATABRICKS_TOKEN", "foobar")
|
t.Setenv("DATABRICKS_TOKEN", "foobar")
|
||||||
b.WorkspaceClient()
|
b.WorkspaceClient()
|
||||||
|
|
||||||
err = bundle.Apply(context.Background(), b, []bundle.Mutator{
|
err = bundle.Apply(context.Background(), b, bundle.Seq(
|
||||||
Initialize(),
|
Initialize(),
|
||||||
Load(),
|
Load(),
|
||||||
})
|
))
|
||||||
|
|
||||||
require.ErrorContains(t, err, "Did you forget to run 'databricks bundle deploy'")
|
require.ErrorContains(t, err, "Did you forget to run 'databricks bundle deploy'")
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,30 +26,30 @@ func (p *plan) Name() string {
|
||||||
return "terraform.Plan"
|
return "terraform.Plan"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *plan) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (p *plan) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
tf := b.Terraform
|
tf := b.Terraform
|
||||||
if tf == nil {
|
if tf == nil {
|
||||||
return nil, fmt.Errorf("terraform not initialized")
|
return fmt.Errorf("terraform not initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdio.LogString(ctx, "Starting plan computation")
|
cmdio.LogString(ctx, "Starting plan computation")
|
||||||
|
|
||||||
err := tf.Init(ctx, tfexec.Upgrade(true))
|
err := tf.Init(ctx, tfexec.Upgrade(true))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("terraform init: %w", err)
|
return fmt.Errorf("terraform init: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Persist computed plan
|
// Persist computed plan
|
||||||
tfDir, err := Dir(b)
|
tfDir, err := Dir(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
planPath := filepath.Join(tfDir, "plan")
|
planPath := filepath.Join(tfDir, "plan")
|
||||||
destroy := p.goal == PlanDestroy
|
destroy := p.goal == PlanDestroy
|
||||||
|
|
||||||
notEmpty, err := tf.Plan(ctx, tfexec.Destroy(destroy), tfexec.Out(planPath))
|
notEmpty, err := tf.Plan(ctx, tfexec.Destroy(destroy), tfexec.Out(planPath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set plan in main bundle struct for downstream mutators
|
// Set plan in main bundle struct for downstream mutators
|
||||||
|
@ -60,7 +60,7 @@ func (p *plan) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, e
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdio.LogString(ctx, fmt.Sprintf("Planning complete and persisted at %s\n", planPath))
|
cmdio.LogString(ctx, fmt.Sprintf("Planning complete and persisted at %s\n", planPath))
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plan returns a [bundle.Mutator] that runs the equivalent of `terraform plan -out ./plan`
|
// Plan returns a [bundle.Mutator] that runs the equivalent of `terraform plan -out ./plan`
|
||||||
|
|
|
@ -18,15 +18,15 @@ func (l *statePull) Name() string {
|
||||||
return "terraform:state-pull"
|
return "terraform:state-pull"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *statePull) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (l *statePull) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
f, err := filer.NewWorkspaceFilesClient(b.WorkspaceClient(), b.Config.Workspace.StatePath)
|
f, err := filer.NewWorkspaceFilesClient(b.WorkspaceClient(), b.Config.Workspace.StatePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
dir, err := Dir(b)
|
dir, err := Dir(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download state file from filer to local cache directory.
|
// Download state file from filer to local cache directory.
|
||||||
|
@ -36,21 +36,21 @@ func (l *statePull) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutat
|
||||||
// On first deploy this state file doesn't yet exist.
|
// On first deploy this state file doesn't yet exist.
|
||||||
if apierr.IsMissing(err) {
|
if apierr.IsMissing(err) {
|
||||||
log.Infof(ctx, "Remote state file does not exist")
|
log.Infof(ctx, "Remote state file does not exist")
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expect the state file to live under dir.
|
// Expect the state file to live under dir.
|
||||||
local, err := os.OpenFile(filepath.Join(dir, TerraformStateFileName), os.O_CREATE|os.O_RDWR, 0600)
|
local, err := os.OpenFile(filepath.Join(dir, TerraformStateFileName), os.O_CREATE|os.O_RDWR, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
defer local.Close()
|
defer local.Close()
|
||||||
|
|
||||||
if !IsLocalStateStale(local, remote) {
|
if !IsLocalStateStale(local, remote) {
|
||||||
log.Infof(ctx, "Local state is the same or newer, ignoring remote state")
|
log.Infof(ctx, "Local state is the same or newer, ignoring remote state")
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncating the file before writing
|
// Truncating the file before writing
|
||||||
|
@ -61,10 +61,10 @@ func (l *statePull) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutat
|
||||||
log.Infof(ctx, "Writing remote state file to local cache directory")
|
log.Infof(ctx, "Writing remote state file to local cache directory")
|
||||||
_, err = io.Copy(local, remote)
|
_, err = io.Copy(local, remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func StatePull() bundle.Mutator {
|
func StatePull() bundle.Mutator {
|
||||||
|
|
|
@ -16,31 +16,31 @@ func (l *statePush) Name() string {
|
||||||
return "terraform:state-push"
|
return "terraform:state-push"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *statePush) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (l *statePush) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
f, err := filer.NewWorkspaceFilesClient(b.WorkspaceClient(), b.Config.Workspace.StatePath)
|
f, err := filer.NewWorkspaceFilesClient(b.WorkspaceClient(), b.Config.Workspace.StatePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
dir, err := Dir(b)
|
dir, err := Dir(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expect the state file to live under dir.
|
// Expect the state file to live under dir.
|
||||||
local, err := os.Open(filepath.Join(dir, TerraformStateFileName))
|
local, err := os.Open(filepath.Join(dir, TerraformStateFileName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upload state file from local cache directory to filer.
|
// Upload state file from local cache directory to filer.
|
||||||
log.Infof(ctx, "Writing local state file to remote state directory")
|
log.Infof(ctx, "Writing local state file to remote state directory")
|
||||||
err = f.Write(ctx, TerraformStateFileName, local, filer.CreateParentDirectories, filer.OverwriteIfExists)
|
err = f.Write(ctx, TerraformStateFileName, local, filer.CreateParentDirectories, filer.OverwriteIfExists)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func StatePush() bundle.Mutator {
|
func StatePush() bundle.Mutator {
|
||||||
|
|
|
@ -15,16 +15,16 @@ func (w *write) Name() string {
|
||||||
return "terraform.Write"
|
return "terraform.Write"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *write) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (w *write) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
dir, err := Dir(b)
|
dir, err := Dir(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
root := BundleToTerraform(&b.Config)
|
root := BundleToTerraform(&b.Config)
|
||||||
f, err := os.Create(filepath.Join(dir, "bundle.tf.json"))
|
f, err := os.Create(filepath.Join(dir, "bundle.tf.json"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
@ -33,10 +33,10 @@ func (w *write) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator,
|
||||||
enc.SetIndent("", " ")
|
enc.SetIndent("", " ")
|
||||||
err = enc.Encode(root)
|
err = enc.Encode(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write returns a [bundle.Mutator] that converts resources in a bundle configuration
|
// Write returns a [bundle.Mutator] that converts resources in a bundle configuration
|
||||||
|
|
|
@ -13,42 +13,18 @@ type Mutator interface {
|
||||||
Name() string
|
Name() string
|
||||||
|
|
||||||
// Apply mutates the specified bundle object.
|
// Apply mutates the specified bundle object.
|
||||||
// It may return a list of mutators to apply immediately after this mutator.
|
Apply(context.Context, *Bundle) error
|
||||||
// For example: when processing all configuration files in the tree; each file gets
|
|
||||||
// its own mutator instance.
|
|
||||||
Apply(context.Context, *Bundle) ([]Mutator, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyMutator calls apply on the specified mutator given a bundle.
|
func Apply(ctx context.Context, b *Bundle, m Mutator) error {
|
||||||
// Any mutators this call returns are applied recursively.
|
|
||||||
func applyMutator(ctx context.Context, b *Bundle, m Mutator) error {
|
|
||||||
ctx = log.NewContext(ctx, log.GetLogger(ctx).With("mutator", m.Name()))
|
ctx = log.NewContext(ctx, log.GetLogger(ctx).With("mutator", m.Name()))
|
||||||
|
|
||||||
log.Debugf(ctx, "Apply")
|
log.Debugf(ctx, "Apply")
|
||||||
ms, err := m.Apply(ctx, b)
|
err := m.Apply(ctx, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf(ctx, "Error: %s", err)
|
log.Errorf(ctx, "Error: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply recursively.
|
|
||||||
err = Apply(ctx, b, ms)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Apply(ctx context.Context, b *Bundle, ms []Mutator) error {
|
|
||||||
if len(ms) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
for _, m := range ms {
|
|
||||||
err := applyMutator(ctx, b, m)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@ func (t *testMutator) Name() string {
|
||||||
return "test"
|
return "test"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *testMutator) Apply(_ context.Context, b *Bundle) ([]Mutator, error) {
|
func (t *testMutator) Apply(ctx context.Context, b *Bundle) error {
|
||||||
t.applyCalled++
|
t.applyCalled++
|
||||||
return t.nestedMutators, nil
|
return Apply(ctx, b, Seq(t.nestedMutators...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMutator(t *testing.T) {
|
func TestMutator(t *testing.T) {
|
||||||
|
@ -35,7 +35,7 @@ func TestMutator(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bundle := &Bundle{}
|
bundle := &Bundle{}
|
||||||
err := Apply(context.Background(), bundle, []Mutator{m})
|
err := Apply(context.Background(), bundle, m)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, 1, m.applyCalled)
|
assert.Equal(t, 1, m.applyCalled)
|
||||||
|
|
|
@ -10,8 +10,10 @@ import (
|
||||||
|
|
||||||
// The deploy phase deploys artifacts and resources.
|
// The deploy phase deploys artifacts and resources.
|
||||||
func Deploy() bundle.Mutator {
|
func Deploy() bundle.Mutator {
|
||||||
deployPhase := bundle.Defer([]bundle.Mutator{
|
deployMutator := bundle.Seq(
|
||||||
lock.Acquire(),
|
lock.Acquire(),
|
||||||
|
bundle.Defer(
|
||||||
|
bundle.Seq(
|
||||||
files.Upload(),
|
files.Upload(),
|
||||||
artifacts.UploadAll(),
|
artifacts.UploadAll(),
|
||||||
terraform.Interpolate(),
|
terraform.Interpolate(),
|
||||||
|
@ -19,12 +21,13 @@ func Deploy() bundle.Mutator {
|
||||||
terraform.StatePull(),
|
terraform.StatePull(),
|
||||||
terraform.Apply(),
|
terraform.Apply(),
|
||||||
terraform.StatePush(),
|
terraform.StatePush(),
|
||||||
}, []bundle.Mutator{
|
),
|
||||||
lock.Release(),
|
lock.Release(),
|
||||||
})
|
),
|
||||||
|
)
|
||||||
|
|
||||||
return newPhase(
|
return newPhase(
|
||||||
"deploy",
|
"deploy",
|
||||||
deployPhase,
|
[]bundle.Mutator{deployMutator},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,19 +9,23 @@ import (
|
||||||
|
|
||||||
// The destroy phase deletes artifacts and resources.
|
// The destroy phase deletes artifacts and resources.
|
||||||
func Destroy() bundle.Mutator {
|
func Destroy() bundle.Mutator {
|
||||||
destroyPhase := bundle.Defer([]bundle.Mutator{
|
|
||||||
|
destroyMutator := bundle.Seq(
|
||||||
lock.Acquire(),
|
lock.Acquire(),
|
||||||
|
bundle.Defer(
|
||||||
|
bundle.Seq(
|
||||||
terraform.StatePull(),
|
terraform.StatePull(),
|
||||||
terraform.Plan(terraform.PlanGoal("destroy")),
|
terraform.Plan(terraform.PlanGoal("destroy")),
|
||||||
terraform.Destroy(),
|
terraform.Destroy(),
|
||||||
terraform.StatePush(),
|
terraform.StatePush(),
|
||||||
files.Delete(),
|
files.Delete(),
|
||||||
}, []bundle.Mutator{
|
),
|
||||||
lock.Release(),
|
lock.Release(),
|
||||||
})
|
),
|
||||||
|
)
|
||||||
|
|
||||||
return newPhase(
|
return newPhase(
|
||||||
"destroy",
|
"destroy",
|
||||||
destroyPhase,
|
[]bundle.Mutator{destroyMutator},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ func (p *phase) Name() string {
|
||||||
return p.name
|
return p.name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *phase) Apply(ctx context.Context, b *bundle.Bundle) ([]bundle.Mutator, error) {
|
func (p *phase) Apply(ctx context.Context, b *bundle.Bundle) error {
|
||||||
log.Infof(ctx, "Phase: %s", p.Name())
|
log.Infof(ctx, "Phase: %s", p.Name())
|
||||||
return p.mutators, nil
|
return bundle.Apply(ctx, b, bundle.Seq(p.mutators...))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package bundle
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
type seqMutator struct {
|
||||||
|
mutators []Mutator
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *seqMutator) Name() string {
|
||||||
|
return "seq"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *seqMutator) Apply(ctx context.Context, b *Bundle) error {
|
||||||
|
for _, m := range s.mutators {
|
||||||
|
err := Apply(ctx, b, m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Seq(ms ...Mutator) Mutator {
|
||||||
|
return &seqMutator{mutators: ms}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package bundle
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSeqMutator(t *testing.T) {
|
||||||
|
m1 := &testMutator{}
|
||||||
|
m2 := &testMutator{}
|
||||||
|
m3 := &testMutator{}
|
||||||
|
seqMutator := Seq(m1, m2, m3)
|
||||||
|
|
||||||
|
bundle := &Bundle{}
|
||||||
|
err := Apply(context.Background(), bundle, seqMutator)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, 1, m1.applyCalled)
|
||||||
|
assert.Equal(t, 1, m2.applyCalled)
|
||||||
|
assert.Equal(t, 1, m3.applyCalled)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSeqWithDeferredMutator(t *testing.T) {
|
||||||
|
m1 := &testMutator{}
|
||||||
|
m2 := &testMutator{}
|
||||||
|
m3 := &testMutator{}
|
||||||
|
m4 := &testMutator{}
|
||||||
|
seqMutator := Seq(m1, Defer(m2, m3), m4)
|
||||||
|
|
||||||
|
bundle := &Bundle{}
|
||||||
|
err := Apply(context.Background(), bundle, seqMutator)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, 1, m1.applyCalled)
|
||||||
|
assert.Equal(t, 1, m2.applyCalled)
|
||||||
|
assert.Equal(t, 1, m3.applyCalled)
|
||||||
|
assert.Equal(t, 1, m4.applyCalled)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSeqWithErrorAndDeferredMutator(t *testing.T) {
|
||||||
|
errorMut := &mutatorWithError{errorMsg: "error msg"}
|
||||||
|
m1 := &testMutator{}
|
||||||
|
m2 := &testMutator{}
|
||||||
|
m3 := &testMutator{}
|
||||||
|
seqMutator := Seq(errorMut, Defer(m1, m2), m3)
|
||||||
|
|
||||||
|
bundle := &Bundle{}
|
||||||
|
err := Apply(context.Background(), bundle, seqMutator)
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, 1, errorMut.applyCalled)
|
||||||
|
assert.Equal(t, 0, m1.applyCalled)
|
||||||
|
assert.Equal(t, 0, m2.applyCalled)
|
||||||
|
assert.Equal(t, 0, m3.applyCalled)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSeqWithErrorInsideDeferredMutator(t *testing.T) {
|
||||||
|
errorMut := &mutatorWithError{errorMsg: "error msg"}
|
||||||
|
m1 := &testMutator{}
|
||||||
|
m2 := &testMutator{}
|
||||||
|
m3 := &testMutator{}
|
||||||
|
seqMutator := Seq(m1, Defer(errorMut, m2), m3)
|
||||||
|
|
||||||
|
bundle := &Bundle{}
|
||||||
|
err := Apply(context.Background(), bundle, seqMutator)
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, 1, m1.applyCalled)
|
||||||
|
assert.Equal(t, 1, errorMut.applyCalled)
|
||||||
|
assert.Equal(t, 1, m2.applyCalled)
|
||||||
|
assert.Equal(t, 0, m3.applyCalled)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSeqWithErrorInsideFinallyStage(t *testing.T) {
|
||||||
|
errorMut := &mutatorWithError{errorMsg: "error msg"}
|
||||||
|
m1 := &testMutator{}
|
||||||
|
m2 := &testMutator{}
|
||||||
|
m3 := &testMutator{}
|
||||||
|
seqMutator := Seq(m1, Defer(m2, errorMut), m3)
|
||||||
|
|
||||||
|
bundle := &Bundle{}
|
||||||
|
err := Apply(context.Background(), bundle, seqMutator)
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, 1, m1.applyCalled)
|
||||||
|
assert.Equal(t, 1, m2.applyCalled)
|
||||||
|
assert.Equal(t, 1, errorMut.applyCalled)
|
||||||
|
assert.Equal(t, 0, m3.applyCalled)
|
||||||
|
}
|
|
@ -21,7 +21,7 @@ func TestConflictingResourceIdsNoSubconfig(t *testing.T) {
|
||||||
func TestConflictingResourceIdsOneSubconfig(t *testing.T) {
|
func TestConflictingResourceIdsOneSubconfig(t *testing.T) {
|
||||||
b, err := bundle.Load("./conflicting_resource_ids/one_subconfiguration")
|
b, err := bundle.Load("./conflicting_resource_ids/one_subconfiguration")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = bundle.Apply(context.Background(), b, mutator.DefaultMutators())
|
err = bundle.Apply(context.Background(), b, bundle.Seq(mutator.DefaultMutators()...))
|
||||||
bundleConfigPath := filepath.FromSlash("conflicting_resource_ids/one_subconfiguration/bundle.yml")
|
bundleConfigPath := filepath.FromSlash("conflicting_resource_ids/one_subconfiguration/bundle.yml")
|
||||||
resourcesConfigPath := filepath.FromSlash("conflicting_resource_ids/one_subconfiguration/resources.yml")
|
resourcesConfigPath := filepath.FromSlash("conflicting_resource_ids/one_subconfiguration/resources.yml")
|
||||||
assert.ErrorContains(t, err, fmt.Sprintf("multiple resources named foo (job at %s, pipeline at %s)", bundleConfigPath, resourcesConfigPath))
|
assert.ErrorContains(t, err, fmt.Sprintf("multiple resources named foo (job at %s, pipeline at %s)", bundleConfigPath, resourcesConfigPath))
|
||||||
|
@ -30,7 +30,7 @@ func TestConflictingResourceIdsOneSubconfig(t *testing.T) {
|
||||||
func TestConflictingResourceIdsTwoSubconfigs(t *testing.T) {
|
func TestConflictingResourceIdsTwoSubconfigs(t *testing.T) {
|
||||||
b, err := bundle.Load("./conflicting_resource_ids/two_subconfigurations")
|
b, err := bundle.Load("./conflicting_resource_ids/two_subconfigurations")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = bundle.Apply(context.Background(), b, mutator.DefaultMutators())
|
err = bundle.Apply(context.Background(), b, bundle.Seq(mutator.DefaultMutators()...))
|
||||||
resources1ConfigPath := filepath.FromSlash("conflicting_resource_ids/two_subconfigurations/resources1.yml")
|
resources1ConfigPath := filepath.FromSlash("conflicting_resource_ids/two_subconfigurations/resources1.yml")
|
||||||
resources2ConfigPath := filepath.FromSlash("conflicting_resource_ids/two_subconfigurations/resources2.yml")
|
resources2ConfigPath := filepath.FromSlash("conflicting_resource_ids/two_subconfigurations/resources2.yml")
|
||||||
assert.ErrorContains(t, err, fmt.Sprintf("multiple resources named foo (job at %s, pipeline at %s)", resources1ConfigPath, resources2ConfigPath))
|
assert.ErrorContains(t, err, fmt.Sprintf("multiple resources named foo (job at %s, pipeline at %s)", resources1ConfigPath, resources2ConfigPath))
|
||||||
|
|
|
@ -12,11 +12,10 @@ import (
|
||||||
|
|
||||||
func TestInterpolation(t *testing.T) {
|
func TestInterpolation(t *testing.T) {
|
||||||
b := load(t, "./interpolation")
|
b := load(t, "./interpolation")
|
||||||
err := bundle.Apply(context.Background(), b, []bundle.Mutator{
|
err := bundle.Apply(context.Background(), b, interpolation.Interpolate(
|
||||||
interpolation.Interpolate(
|
|
||||||
interpolation.IncludeLookupsInPath("bundle"),
|
interpolation.IncludeLookupsInPath("bundle"),
|
||||||
interpolation.IncludeLookupsInPath("workspace"),
|
interpolation.IncludeLookupsInPath("workspace"),
|
||||||
)})
|
))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "foo bar", b.Config.Bundle.Name)
|
assert.Equal(t, "foo bar", b.Config.Bundle.Name)
|
||||||
assert.Equal(t, "foo bar | bar", b.Config.Resources.Jobs["my_job"].Name)
|
assert.Equal(t, "foo bar | bar", b.Config.Resources.Jobs["my_job"].Name)
|
||||||
|
|
|
@ -12,14 +12,14 @@ import (
|
||||||
func load(t *testing.T, path string) *bundle.Bundle {
|
func load(t *testing.T, path string) *bundle.Bundle {
|
||||||
b, err := bundle.Load(path)
|
b, err := bundle.Load(path)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = bundle.Apply(context.Background(), b, mutator.DefaultMutators())
|
err = bundle.Apply(context.Background(), b, bundle.Seq(mutator.DefaultMutators()...))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadEnvironment(t *testing.T, path, env string) *bundle.Bundle {
|
func loadEnvironment(t *testing.T, path, env string) *bundle.Bundle {
|
||||||
b := load(t, path)
|
b := load(t, path)
|
||||||
err := bundle.Apply(context.Background(), b, []bundle.Mutator{mutator.SelectEnvironment(env)})
|
err := bundle.Apply(context.Background(), b, mutator.SelectEnvironment(env))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,45 +15,45 @@ import (
|
||||||
func TestVariables(t *testing.T) {
|
func TestVariables(t *testing.T) {
|
||||||
t.Setenv("BUNDLE_VAR_b", "def")
|
t.Setenv("BUNDLE_VAR_b", "def")
|
||||||
b := load(t, "./variables/vanilla")
|
b := load(t, "./variables/vanilla")
|
||||||
err := bundle.Apply(context.Background(), b, []bundle.Mutator{
|
err := bundle.Apply(context.Background(), b, bundle.Seq(
|
||||||
mutator.SetVariables(),
|
mutator.SetVariables(),
|
||||||
interpolation.Interpolate(
|
interpolation.Interpolate(
|
||||||
interpolation.IncludeLookupsInPath(variable.VariableReferencePrefix),
|
interpolation.IncludeLookupsInPath(variable.VariableReferencePrefix),
|
||||||
)})
|
)))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "abc def", b.Config.Bundle.Name)
|
assert.Equal(t, "abc def", b.Config.Bundle.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVariablesLoadingFailsWhenRequiredVariableIsNotSpecified(t *testing.T) {
|
func TestVariablesLoadingFailsWhenRequiredVariableIsNotSpecified(t *testing.T) {
|
||||||
b := load(t, "./variables/vanilla")
|
b := load(t, "./variables/vanilla")
|
||||||
err := bundle.Apply(context.Background(), b, []bundle.Mutator{
|
err := bundle.Apply(context.Background(), b, bundle.Seq(
|
||||||
mutator.SetVariables(),
|
mutator.SetVariables(),
|
||||||
interpolation.Interpolate(
|
interpolation.Interpolate(
|
||||||
interpolation.IncludeLookupsInPath(variable.VariableReferencePrefix),
|
interpolation.IncludeLookupsInPath(variable.VariableReferencePrefix),
|
||||||
)})
|
)))
|
||||||
assert.ErrorContains(t, err, "no value assigned to required variable b. Assignment can be done through the \"--var\" flag or by setting the BUNDLE_VAR_b environment variable")
|
assert.ErrorContains(t, err, "no value assigned to required variable b. Assignment can be done through the \"--var\" flag or by setting the BUNDLE_VAR_b environment variable")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVariablesEnvironmentsBlockOverride(t *testing.T) {
|
func TestVariablesEnvironmentsBlockOverride(t *testing.T) {
|
||||||
b := load(t, "./variables/env_overrides")
|
b := load(t, "./variables/env_overrides")
|
||||||
err := bundle.Apply(context.Background(), b, []bundle.Mutator{
|
err := bundle.Apply(context.Background(), b, bundle.Seq(
|
||||||
mutator.SelectEnvironment("env-with-single-variable-override"),
|
mutator.SelectEnvironment("env-with-single-variable-override"),
|
||||||
mutator.SetVariables(),
|
mutator.SetVariables(),
|
||||||
interpolation.Interpolate(
|
interpolation.Interpolate(
|
||||||
interpolation.IncludeLookupsInPath(variable.VariableReferencePrefix),
|
interpolation.IncludeLookupsInPath(variable.VariableReferencePrefix),
|
||||||
)})
|
)))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "default-a dev-b", b.Config.Workspace.Profile)
|
assert.Equal(t, "default-a dev-b", b.Config.Workspace.Profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVariablesEnvironmentsBlockOverrideForMultipleVariables(t *testing.T) {
|
func TestVariablesEnvironmentsBlockOverrideForMultipleVariables(t *testing.T) {
|
||||||
b := load(t, "./variables/env_overrides")
|
b := load(t, "./variables/env_overrides")
|
||||||
err := bundle.Apply(context.Background(), b, []bundle.Mutator{
|
err := bundle.Apply(context.Background(), b, bundle.Seq(
|
||||||
mutator.SelectEnvironment("env-with-two-variable-overrides"),
|
mutator.SelectEnvironment("env-with-two-variable-overrides"),
|
||||||
mutator.SetVariables(),
|
mutator.SetVariables(),
|
||||||
interpolation.Interpolate(
|
interpolation.Interpolate(
|
||||||
interpolation.IncludeLookupsInPath(variable.VariableReferencePrefix),
|
interpolation.IncludeLookupsInPath(variable.VariableReferencePrefix),
|
||||||
)})
|
)))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "prod-a prod-b", b.Config.Workspace.Profile)
|
assert.Equal(t, "prod-a prod-b", b.Config.Workspace.Profile)
|
||||||
}
|
}
|
||||||
|
@ -61,34 +61,34 @@ func TestVariablesEnvironmentsBlockOverrideForMultipleVariables(t *testing.T) {
|
||||||
func TestVariablesEnvironmentsBlockOverrideWithProcessEnvVars(t *testing.T) {
|
func TestVariablesEnvironmentsBlockOverrideWithProcessEnvVars(t *testing.T) {
|
||||||
t.Setenv("BUNDLE_VAR_b", "env-var-b")
|
t.Setenv("BUNDLE_VAR_b", "env-var-b")
|
||||||
b := load(t, "./variables/env_overrides")
|
b := load(t, "./variables/env_overrides")
|
||||||
err := bundle.Apply(context.Background(), b, []bundle.Mutator{
|
err := bundle.Apply(context.Background(), b, bundle.Seq(
|
||||||
mutator.SelectEnvironment("env-with-two-variable-overrides"),
|
mutator.SelectEnvironment("env-with-two-variable-overrides"),
|
||||||
mutator.SetVariables(),
|
mutator.SetVariables(),
|
||||||
interpolation.Interpolate(
|
interpolation.Interpolate(
|
||||||
interpolation.IncludeLookupsInPath(variable.VariableReferencePrefix),
|
interpolation.IncludeLookupsInPath(variable.VariableReferencePrefix),
|
||||||
)})
|
)))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "prod-a env-var-b", b.Config.Workspace.Profile)
|
assert.Equal(t, "prod-a env-var-b", b.Config.Workspace.Profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVariablesEnvironmentsBlockOverrideWithMissingVariables(t *testing.T) {
|
func TestVariablesEnvironmentsBlockOverrideWithMissingVariables(t *testing.T) {
|
||||||
b := load(t, "./variables/env_overrides")
|
b := load(t, "./variables/env_overrides")
|
||||||
err := bundle.Apply(context.Background(), b, []bundle.Mutator{
|
err := bundle.Apply(context.Background(), b, bundle.Seq(
|
||||||
mutator.SelectEnvironment("env-missing-a-required-variable-assignment"),
|
mutator.SelectEnvironment("env-missing-a-required-variable-assignment"),
|
||||||
mutator.SetVariables(),
|
mutator.SetVariables(),
|
||||||
interpolation.Interpolate(
|
interpolation.Interpolate(
|
||||||
interpolation.IncludeLookupsInPath(variable.VariableReferencePrefix),
|
interpolation.IncludeLookupsInPath(variable.VariableReferencePrefix),
|
||||||
)})
|
)))
|
||||||
assert.ErrorContains(t, err, "no value assigned to required variable b. Assignment can be done through the \"--var\" flag or by setting the BUNDLE_VAR_b environment variable")
|
assert.ErrorContains(t, err, "no value assigned to required variable b. Assignment can be done through the \"--var\" flag or by setting the BUNDLE_VAR_b environment variable")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVariablesEnvironmentsBlockOverrideWithUndefinedVariables(t *testing.T) {
|
func TestVariablesEnvironmentsBlockOverrideWithUndefinedVariables(t *testing.T) {
|
||||||
b := load(t, "./variables/env_overrides")
|
b := load(t, "./variables/env_overrides")
|
||||||
err := bundle.Apply(context.Background(), b, []bundle.Mutator{
|
err := bundle.Apply(context.Background(), b, bundle.Seq(
|
||||||
mutator.SelectEnvironment("env-using-an-undefined-variable"),
|
mutator.SelectEnvironment("env-using-an-undefined-variable"),
|
||||||
mutator.SetVariables(),
|
mutator.SetVariables(),
|
||||||
interpolation.Interpolate(
|
interpolation.Interpolate(
|
||||||
interpolation.IncludeLookupsInPath(variable.VariableReferencePrefix),
|
interpolation.IncludeLookupsInPath(variable.VariableReferencePrefix),
|
||||||
)})
|
)))
|
||||||
assert.ErrorContains(t, err, "variable c is not defined but is assigned a value")
|
assert.ErrorContains(t, err, "variable c is not defined but is assigned a value")
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,11 @@ var deployCmd = &cobra.Command{
|
||||||
// If `--force` is specified, force acquisition of the deployment lock.
|
// If `--force` is specified, force acquisition of the deployment lock.
|
||||||
b.Config.Bundle.Lock.Force = force
|
b.Config.Bundle.Lock.Force = force
|
||||||
|
|
||||||
return bundle.Apply(cmd.Context(), b, []bundle.Mutator{
|
return bundle.Apply(cmd.Context(), b, bundle.Seq(
|
||||||
phases.Initialize(),
|
phases.Initialize(),
|
||||||
phases.Build(),
|
phases.Build(),
|
||||||
phases.Deploy(),
|
phases.Deploy(),
|
||||||
})
|
))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,11 +42,11 @@ var destroyCmd = &cobra.Command{
|
||||||
return fmt.Errorf("please specify --auto-approve since selected logging format is json")
|
return fmt.Errorf("please specify --auto-approve since selected logging format is json")
|
||||||
}
|
}
|
||||||
|
|
||||||
return bundle.Apply(ctx, b, []bundle.Mutator{
|
return bundle.Apply(ctx, b, bundle.Seq(
|
||||||
phases.Initialize(),
|
phases.Initialize(),
|
||||||
phases.Build(),
|
phases.Build(),
|
||||||
phases.Destroy(),
|
phases.Destroy(),
|
||||||
})
|
))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,13 +23,13 @@ var runCmd = &cobra.Command{
|
||||||
PreRunE: ConfigureBundleWithVariables,
|
PreRunE: ConfigureBundleWithVariables,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
b := bundle.Get(cmd.Context())
|
b := bundle.Get(cmd.Context())
|
||||||
err := bundle.Apply(cmd.Context(), b, []bundle.Mutator{
|
err := bundle.Apply(cmd.Context(), b, bundle.Seq(
|
||||||
phases.Initialize(),
|
phases.Initialize(),
|
||||||
terraform.Interpolate(),
|
terraform.Interpolate(),
|
||||||
terraform.Write(),
|
terraform.Write(),
|
||||||
terraform.StatePull(),
|
terraform.StatePull(),
|
||||||
terraform.Load(),
|
terraform.Load(),
|
||||||
})
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,9 +39,7 @@ var syncCmd = &cobra.Command{
|
||||||
b := bundle.Get(cmd.Context())
|
b := bundle.Get(cmd.Context())
|
||||||
|
|
||||||
// Run initialize phase to make sure paths are set.
|
// Run initialize phase to make sure paths are set.
|
||||||
err := bundle.Apply(cmd.Context(), b, []bundle.Mutator{
|
err := bundle.Apply(cmd.Context(), b, phases.Initialize())
|
||||||
phases.Initialize(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,7 @@ var validateCmd = &cobra.Command{
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
b := bundle.Get(cmd.Context())
|
b := bundle.Get(cmd.Context())
|
||||||
|
|
||||||
err := bundle.Apply(cmd.Context(), b, []bundle.Mutator{
|
err := bundle.Apply(cmd.Context(), b, phases.Initialize())
|
||||||
phases.Initialize(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ func loadBundle(cmd *cobra.Command, args []string, load func() (*bundle.Bundle,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
err = bundle.Apply(ctx, b, mutator.DefaultMutators())
|
err = bundle.Apply(ctx, b, bundle.Seq(mutator.DefaultMutators()...))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ func configureBundle(cmd *cobra.Command, args []string, load func() (*bundle.Bun
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
err = bundle.Apply(ctx, b, []bundle.Mutator{m})
|
err = bundle.Apply(ctx, b, m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,9 +78,7 @@ var syncCmd = &cobra.Command{
|
||||||
// b := bundle.GetOrNil(cmd.Context())
|
// b := bundle.GetOrNil(cmd.Context())
|
||||||
// if b != nil {
|
// if b != nil {
|
||||||
// // Run initialize phase to make sure paths are set.
|
// // Run initialize phase to make sure paths are set.
|
||||||
// err = bundle.Apply(cmd.Context(), b, []bundle.Mutator{
|
// err = bundle.Apply(cmd.Context(), b, phases.Initialize())
|
||||||
// phases.Initialize(),
|
|
||||||
// })
|
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return err
|
// return err
|
||||||
// }
|
// }
|
||||||
|
|
Loading…
Reference in New Issue