Merge "New CLI option to get/set manifest"

This commit is contained in:
Zuul 2020-06-29 15:18:39 +00:00 committed by Gerrit Code Review
commit 901c314f02
27 changed files with 995 additions and 6 deletions

View File

@ -51,5 +51,8 @@ func NewConfigCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Comma
configRootCmd.AddCommand(NewInitCommand(rootSettings))
configRootCmd.AddCommand(NewUseContextCommand(rootSettings))
configRootCmd.AddCommand(NewGetManifestCommand(rootSettings))
configRootCmd.AddCommand(NewSetManifestCommand(rootSettings))
return configRootCmd
}

View File

@ -0,0 +1,76 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package config
import (
"fmt"
"github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/environment"
)
const (
getManifestsLong = `
Display a specific manifest information, or all defined manifests if no name is provided.
`
getManifestsExample = `
# List all the manifests airshipctl knows about
airshipctl config get-manifests
# Display a specific manifest
airshipctl config get-manifest e2e
`
)
// NewGetManifestCommand creates a command for viewing the manifest information
// defined in the airshipctl config file.
func NewGetManifestCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
o := &config.ManifestOptions{}
cmd := &cobra.Command{
Use: "get-manifest NAME",
Short: "Get a manifest information from the airshipctl config",
Long: getManifestsLong[1:],
Example: getManifestsExample,
Args: cobra.MaximumNArgs(1),
Aliases: []string{"get-manifests"},
RunE: func(cmd *cobra.Command, args []string) error {
airconfig := rootSettings.Config
if len(args) == 1 {
o.Name = args[0]
manifest, exists := airconfig.Manifests[o.Name]
if !exists {
return config.ErrMissingConfig{
What: fmt.Sprintf("Manifest with name '%s'", o.Name),
}
}
fmt.Fprintln(cmd.OutOrStdout(), manifest)
} else {
manifests := airconfig.GetManifests()
if len(manifests) == 0 {
fmt.Fprintln(cmd.OutOrStdout(), "No Manifest found in the configuration.")
}
for _, manifest := range manifests {
fmt.Fprintln(cmd.OutOrStdout(), manifest)
}
}
return nil
},
}
return cmd
}

View File

@ -0,0 +1,75 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package config_test
import (
"fmt"
"testing"
cmd "opendev.org/airship/airshipctl/cmd/config"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/environment"
"opendev.org/airship/airshipctl/testutil"
)
func TestGetManifestConfigCmd(t *testing.T) {
settings := &environment.AirshipCTLSettings{
Config: &config.Config{
Manifests: map[string]*config.Manifest{
"fooManifestConfig": getTestManifest("foo"),
"barManifestConfig": getTestManifest("bar"),
"bazManifestConfig": getTestManifest("baz"),
},
},
}
noConfigSettings := &environment.AirshipCTLSettings{Config: new(config.Config)}
cmdTests := []*testutil.CmdTest{
{
Name: "get-manifest",
CmdLine: "fooManifestConfig",
Cmd: cmd.NewGetManifestCommand(settings),
},
{
Name: "get-all-manifests",
CmdLine: "",
Cmd: cmd.NewGetManifestCommand(settings),
},
{
Name: "missing",
CmdLine: "manifestMissing",
Cmd: cmd.NewGetManifestCommand(settings),
Error: fmt.Errorf("Missing configuration: Manifest with name 'manifestMissing'"),
},
{
Name: "no-manifests",
CmdLine: "",
Cmd: cmd.NewGetManifestCommand(noConfigSettings),
},
}
for _, tt := range cmdTests {
testutil.RunTest(t, tt)
}
}
func getTestManifest(name string) *config.Manifest {
manifests := &config.Manifest{
PrimaryRepositoryName: name + "_primary_repo",
TargetPath: name + "_target_path",
}
return manifests
}

148
cmd/config/set_manifest.go Normal file
View File

@ -0,0 +1,148 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package config
import (
"fmt"
"github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/environment"
"opendev.org/airship/airshipctl/pkg/log"
)
const (
setManifestsLong = `
Create or modify a manifests in the airshipctl config file.
`
setManifestsExample = `
# Create a new manifest
airshipctl config set-manifest exampleManifest \
--repo exampleRepo \
--url https://github.com/site \
--branch master \
--primary \
--sub-path exampleSubpath \
--target-path exampleTargetpath
# Change the primary repo for manifest
airshipctl config set-manifest e2e \
--repo exampleRepo \
--primary
# Change the sub-path for manifest
airshipctl config set-manifest e2e \
--sub-path treasuremap/manifests/e2e
# Change the target-path for manifest
airshipctl config set-manifest e2e \
--target-path /tmp/e2e
`
)
// NewSetManifestCommand creates a command for creating and modifying manifests
// in the airshipctl config file.
func NewSetManifestCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
o := &config.ManifestOptions{}
cmd := &cobra.Command{
Use: "set-manifest NAME",
Short: "Manage manifests in airship config",
Long: setManifestsLong[1:],
Example: setManifestsExample,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
o.Name = args[0]
modified, err := config.RunSetManifest(o, rootSettings.Config, true)
// Check if URL flag is passed with empty value
if cmd.Flags().Changed("url") && o.URL == "" {
log.Fatal("Repository URL cannot be empty.")
}
if err != nil {
return err
}
if modified {
fmt.Fprintf(cmd.OutOrStdout(), "Manifest %q modified.\n", o.Name)
} else {
fmt.Fprintf(cmd.OutOrStdout(), "Manifest %q created.\n", o.Name)
}
return nil
},
}
addSetManifestFlags(o, cmd)
return cmd
}
func addSetManifestFlags(o *config.ManifestOptions, cmd *cobra.Command) {
flags := cmd.Flags()
flags.StringVar(
&o.RepoName,
"repo",
"",
"the name of the repository to be associated with this manifest")
flags.StringVar(
&o.URL,
"url",
"",
"the repository url to be associated with this manifest")
flags.StringVar(
&o.Branch,
"branch",
"",
"the branch to be associated with repository in this manifest")
flags.StringVar(
&o.CommitHash,
"commithash",
"",
"the commit hash to be associated with repository in this manifest")
flags.StringVar(
&o.Tag,
"tag",
"",
"the tag to be associated with repository in this manifest")
flags.BoolVar(
&o.Force,
"force",
false,
"if set, enable force checkout in repository with this manifest")
flags.BoolVar(
&o.IsPrimary,
"primary",
false,
"if set, enable this repository as primary repository to be used with this manifest")
flags.StringVar(
&o.SubPath,
"sub-path",
"",
"the sub path to be set for this manifest")
flags.StringVar(
&o.TargetPath,
"target-path",
"",
"the target path for to be set for this manifest")
}

View File

@ -0,0 +1,137 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package config_test
import (
"fmt"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
cmd "opendev.org/airship/airshipctl/cmd/config"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/environment"
"opendev.org/airship/airshipctl/testutil"
)
const (
mName = "dummymanifest"
mRepoName = "treasuremap"
mURL = "https://github.com/airshipit/treasuremap"
mBranch = "master"
mSubPath = "manifests/test-site"
mTargetPath = "/tmp/airship"
testTargetPath = "/tmp/e2e"
)
type setManifestTest struct {
inputConfig *config.Config
cmdTest *testutil.CmdTest
manifestName string
manifestTargetPath string
}
func TestConfigSetManifest(t *testing.T) {
cmdTests := []*testutil.CmdTest{
{
Name: "config-cmd-set-manifest-with-help",
CmdLine: "--help",
Cmd: cmd.NewSetManifestCommand(nil),
},
{
Name: "config-cmd-set-manifest-too-many-args",
CmdLine: "arg1 arg2",
Cmd: cmd.NewSetManifestCommand(nil),
Error: fmt.Errorf("accepts %d arg(s), received %d", 1, 2),
},
{
Name: "config-cmd-set-manifest-too-few-args",
CmdLine: "",
Cmd: cmd.NewSetManifestCommand(nil),
Error: fmt.Errorf("accepts %d arg(s), received %d", 1, 0),
},
}
for _, tt := range cmdTests {
testutil.RunTest(t, tt)
}
}
func TestSetManifest(t *testing.T) {
given, cleanupGiven := testutil.InitConfig(t)
defer cleanupGiven(t)
tests := []struct {
testName string
manifestName string
flags []string
givenConfig *config.Config
targetPath string
}{
{
testName: "set-manifest",
manifestName: mName,
flags: []string{
"--repo " + mRepoName,
"--url " + mURL,
"--branch " + mBranch,
"--primary",
"--sub-path " + mSubPath,
"--target-path " + mTargetPath,
},
givenConfig: given,
targetPath: mTargetPath,
},
{
testName: "modify-manifest",
manifestName: mName,
flags: []string{
"--target-path " + testTargetPath,
},
givenConfig: given,
targetPath: testTargetPath,
},
}
for _, tt := range tests {
tt := tt
cmd := &testutil.CmdTest{
Name: tt.testName,
CmdLine: fmt.Sprintf("%s %s", tt.manifestName, strings.Join(tt.flags, " ")),
}
test := setManifestTest{
inputConfig: tt.givenConfig,
cmdTest: cmd,
manifestName: tt.manifestName,
manifestTargetPath: tt.targetPath,
}
test.run(t)
}
}
func (test setManifestTest) run(t *testing.T) {
settings := &environment.AirshipCTLSettings{Config: test.inputConfig}
test.cmdTest.Cmd = cmd.NewSetManifestCommand(settings)
testutil.RunTest(t, test.cmdTest)
afterRunConf := settings.Config
// Find the Manifest Created or Modified
afterRunManifest, _ := afterRunConf.Manifests[test.manifestName]
require.NotNil(t, afterRunManifest)
assert.EqualValues(t, afterRunManifest.TargetPath, test.manifestTargetPath)
}

View File

@ -8,6 +8,7 @@ Available Commands:
get-context Get context information from the airshipctl config
get-credential Get user credentials from the airshipctl config
get-management-config View a management config or all management configs defined in the airshipctl config
get-manifest Get a manifest information from the airshipctl config
help Help about any command
import Merge information from a kubernetes config file
init Generate initial configuration files for airshipctl
@ -15,6 +16,7 @@ Available Commands:
set-context Manage contexts
set-credentials Manage user credentials
set-management-config Modify an out-of-band management configuration
set-manifest Manage manifests in airship config
use-context Switch to a different context
Flags:

View File

@ -0,0 +1,41 @@
Error: accepts 1 arg(s), received 0
Usage:
set-manifest NAME [flags]
Examples:
# Create a new manifest
airshipctl config set-manifest exampleManifest \
--repo exampleRepo \
--url https://github.com/site \
--branch master \
--primary \
--sub-path exampleSubpath \
--target-path exampleTargetpath
# Change the primary repo for manifest
airshipctl config set-manifest e2e \
--repo exampleRepo \
--primary
# Change the sub-path for manifest
airshipctl config set-manifest e2e \
--sub-path treasuremap/manifests/e2e
# Change the target-path for manifest
airshipctl config set-manifest e2e \
--target-path /tmp/e2e
Flags:
--branch string the branch to be associated with repository in this manifest
--commithash string the commit hash to be associated with repository in this manifest
--force if set, enable force checkout in repository with this manifest
-h, --help help for set-manifest
--primary if set, enable this repository as primary repository to be used with this manifest
--repo string the name of the repository to be associated with this manifest
--sub-path string the sub path to be set for this manifest
--tag string the tag to be associated with repository in this manifest
--target-path string the target path for to be set for this manifest
--url string the repository url to be associated with this manifest

View File

@ -0,0 +1,41 @@
Error: accepts 1 arg(s), received 2
Usage:
set-manifest NAME [flags]
Examples:
# Create a new manifest
airshipctl config set-manifest exampleManifest \
--repo exampleRepo \
--url https://github.com/site \
--branch master \
--primary \
--sub-path exampleSubpath \
--target-path exampleTargetpath
# Change the primary repo for manifest
airshipctl config set-manifest e2e \
--repo exampleRepo \
--primary
# Change the sub-path for manifest
airshipctl config set-manifest e2e \
--sub-path treasuremap/manifests/e2e
# Change the target-path for manifest
airshipctl config set-manifest e2e \
--target-path /tmp/e2e
Flags:
--branch string the branch to be associated with repository in this manifest
--commithash string the commit hash to be associated with repository in this manifest
--force if set, enable force checkout in repository with this manifest
-h, --help help for set-manifest
--primary if set, enable this repository as primary repository to be used with this manifest
--repo string the name of the repository to be associated with this manifest
--sub-path string the sub path to be set for this manifest
--tag string the tag to be associated with repository in this manifest
--target-path string the target path for to be set for this manifest
--url string the repository url to be associated with this manifest

View File

@ -0,0 +1,41 @@
Create or modify a manifests in the airshipctl config file.
Usage:
set-manifest NAME [flags]
Examples:
# Create a new manifest
airshipctl config set-manifest exampleManifest \
--repo exampleRepo \
--url https://github.com/site \
--branch master \
--primary \
--sub-path exampleSubpath \
--target-path exampleTargetpath
# Change the primary repo for manifest
airshipctl config set-manifest e2e \
--repo exampleRepo \
--primary
# Change the sub-path for manifest
airshipctl config set-manifest e2e \
--sub-path treasuremap/manifests/e2e
# Change the target-path for manifest
airshipctl config set-manifest e2e \
--target-path /tmp/e2e
Flags:
--branch string the branch to be associated with repository in this manifest
--commithash string the commit hash to be associated with repository in this manifest
--force if set, enable force checkout in repository with this manifest
-h, --help help for set-manifest
--primary if set, enable this repository as primary repository to be used with this manifest
--repo string the name of the repository to be associated with this manifest
--sub-path string the sub path to be set for this manifest
--tag string the tag to be associated with repository in this manifest
--target-path string the target path for to be set for this manifest
--url string the repository url to be associated with this manifest

View File

@ -0,0 +1,12 @@
primaryRepositoryName: bar_primary_repo
subPath: ""
targetPath: bar_target_path
primaryRepositoryName: baz_primary_repo
subPath: ""
targetPath: baz_target_path
primaryRepositoryName: foo_primary_repo
subPath: ""
targetPath: foo_target_path

View File

@ -0,0 +1,4 @@
primaryRepositoryName: foo_primary_repo
subPath: ""
targetPath: foo_target_path

View File

@ -0,0 +1,19 @@
Error: Missing configuration: Manifest with name 'manifestMissing'
Usage:
get-manifest NAME [flags]
Aliases:
get-manifest, get-manifests
Examples:
# List all the manifests airshipctl knows about
airshipctl config get-manifests
# Display a specific manifest
airshipctl config get-manifest e2e
Flags:
-h, --help help for get-manifest

View File

@ -0,0 +1 @@
No Manifest found in the configuration.

View File

@ -0,0 +1 @@
Manifest "dummymanifest" modified.

View File

@ -0,0 +1 @@
Manifest "dummymanifest" created.

View File

@ -27,11 +27,13 @@ Manage the airshipctl config file
* [airshipctl config get-context](airshipctl_config_get-context.md) - Get context information from the airshipctl config
* [airshipctl config get-credential](airshipctl_config_get-credential.md) - Get user credentials from the airshipctl config
* [airshipctl config get-management-config](airshipctl_config_get-management-config.md) - View a management config or all management configs defined in the airshipctl config
* [airshipctl config get-manifest](airshipctl_config_get-manifest.md) - Get a manifest information from the airshipctl config
* [airshipctl config import](airshipctl_config_import.md) - Merge information from a kubernetes config file
* [airshipctl config init](airshipctl_config_init.md) - Generate initial configuration files for airshipctl
* [airshipctl config set-cluster](airshipctl_config_set-cluster.md) - Manage clusters
* [airshipctl config set-context](airshipctl_config_set-context.md) - Manage contexts
* [airshipctl config set-credentials](airshipctl_config_set-credentials.md) - Manage user credentials
* [airshipctl config set-management-config](airshipctl_config_set-management-config.md) - Modify an out-of-band management configuration
* [airshipctl config set-manifest](airshipctl_config_set-manifest.md) - Manage manifests in airship config
* [airshipctl config use-context](airshipctl_config_use-context.md) - Switch to a different context

View File

@ -0,0 +1,43 @@
## airshipctl config get-manifest
Get a manifest information from the airshipctl config
### Synopsis
Display a specific manifest information, or all defined manifests if no name is provided.
```
airshipctl config get-manifest NAME [flags]
```
### Examples
```
# List all the manifests airshipctl knows about
airshipctl config get-manifests
# Display a specific manifest
airshipctl config get-manifest e2e
```
### Options
```
-h, --help help for get-manifest
```
### Options inherited from parent commands
```
--airshipconf string Path to file for airshipctl configuration. (default "$HOME/.airship/config")
--debug enable verbose output
--kubeconfig string Path to kubeconfig associated with airshipctl configuration. (default "$HOME/.airship/kubeconfig")
```
### SEE ALSO
* [airshipctl config](airshipctl_config.md) - Manage the airshipctl config file

View File

@ -0,0 +1,68 @@
## airshipctl config set-manifest
Manage manifests in airship config
### Synopsis
Create or modify a manifests in the airshipctl config file.
```
airshipctl config set-manifest NAME [flags]
```
### Examples
```
# Create a new manifest
airshipctl config set-manifest exampleManifest \
--repo exampleRepo \
--url https://github.com/site \
--branch master \
--primary \
--sub-path exampleSubpath \
--target-path exampleTargetpath
# Change the primary repo for manifest
airshipctl config set-manifest e2e \
--repo exampleRepo \
--primary
# Change the sub-path for manifest
airshipctl config set-manifest e2e \
--sub-path treasuremap/manifests/e2e
# Change the target-path for manifest
airshipctl config set-manifest e2e \
--target-path /tmp/e2e
```
### Options
```
--branch string the branch to be associated with repository in this manifest
--commithash string the commit hash to be associated with repository in this manifest
--force if set, enable force checkout in repository with this manifest
-h, --help help for set-manifest
--primary if set, enable this repository as primary repository to be used with this manifest
--repo string the name of the repository to be associated with this manifest
--sub-path string the sub path to be set for this manifest
--tag string the tag to be associated with repository in this manifest
--target-path string the target path for to be set for this manifest
--url string the repository url to be associated with this manifest
```
### Options inherited from parent commands
```
--airshipconf string Path to file for airshipctl configuration. (default "$HOME/.airship/config")
--debug enable verbose output
--kubeconfig string Path to kubeconfig associated with airshipctl configuration. (default "$HOME/.airship/kubeconfig")
```
### SEE ALSO
* [airshipctl config](airshipctl_config.md) - Manage the airshipctl config file

View File

@ -947,6 +947,112 @@ func (c *Config) CurrentContextBootstrapInfo() (*Bootstrap, error) {
return bootstrap, nil
}
// GetManifests returns all of the Manifests associated with the Config sorted by name
func (c *Config) GetManifests() []*Manifest {
keys := make([]string, 0, len(c.Manifests))
for name := range c.Manifests {
keys = append(keys, name)
}
sort.Strings(keys)
manifests := make([]*Manifest, 0, len(c.Manifests))
for _, name := range keys {
manifests = append(manifests, c.Manifests[name])
}
return manifests
}
// AddManifest creates new Manifest
func (c *Config) AddManifest(theManifest *ManifestOptions) *Manifest {
nManifest := NewManifest()
c.Manifests[theManifest.Name] = nManifest
err := c.ModifyManifest(nManifest, theManifest)
if err != nil {
return nil
}
return nManifest
}
// ModifyManifest set actual values to manifests
func (c *Config) ModifyManifest(manifest *Manifest, theManifest *ManifestOptions) error {
if theManifest.IsPrimary {
manifest.PrimaryRepositoryName = theManifest.RepoName
}
if theManifest.SubPath != "" {
manifest.SubPath = theManifest.SubPath
}
if theManifest.TargetPath != "" {
manifest.TargetPath = theManifest.TargetPath
}
// There is no repository details to be updated
if theManifest.RepoName == "" {
return nil
}
//when setting an existing repository as primary, verify whether the repository exists
//and user is also not passing any repository URL
if theManifest.IsPrimary && theManifest.URL == "" && (manifest.Repositories[theManifest.RepoName] == nil) {
return ErrRepositoryNotFound{theManifest.RepoName}
}
repository, exists := manifest.Repositories[theManifest.RepoName]
if !exists {
_, err := c.AddRepository(manifest, theManifest)
if err != nil {
return err
}
} else {
err := c.ModifyRepository(repository, theManifest)
if err != nil {
return err
}
}
return nil
}
// AddRepository creates new Repository
func (c *Config) AddRepository(manifest *Manifest, theManifest *ManifestOptions) (*Repository, error) {
nRepository := NewRepository()
manifest.Repositories[theManifest.RepoName] = nRepository
err := c.ModifyRepository(nRepository, theManifest)
if err != nil {
return nil, err
}
return nRepository, nil
}
// ModifyRepository set actual values to repository
func (c *Config) ModifyRepository(repository *Repository, theManifest *ManifestOptions) error {
if theManifest.URL != "" {
repository.URLString = theManifest.URL
}
if theManifest.Branch != "" {
repository.CheckoutOptions.Branch = theManifest.Branch
}
if theManifest.CommitHash != "" {
repository.CheckoutOptions.CommitHash = theManifest.CommitHash
}
if theManifest.Tag != "" {
repository.CheckoutOptions.Tag = theManifest.Tag
}
if theManifest.Force {
repository.CheckoutOptions.ForceCheckout = theManifest.Force
}
possibleValues := [3]string{repository.CheckoutOptions.CommitHash,
repository.CheckoutOptions.Branch, repository.CheckoutOptions.Tag}
var count int
for _, val := range possibleValues {
if val != "" {
count++
}
}
if count > 1 {
return ErrMutuallyExclusiveCheckout{}
}
if count == 0 {
return ErrMissingRepoCheckoutOptions{}
}
return nil
}
// CurrentContextManagementConfig returns the management options for the current context
func (c *Config) CurrentContextManagementConfig() (*ManagementConfiguration, error) {
currentCluster, err := c.CurrentContextCluster()

View File

@ -165,3 +165,35 @@ func RunUseContext(desiredContext string, airconfig *Config) error {
}
return nil
}
// RunSetManifest validates the given command line options and invokes AddManifest/ModifyManifest
func RunSetManifest(o *ManifestOptions, airconfig *Config, writeToStorage bool) (bool, error) {
modified := false
err := o.Validate()
if err != nil {
return modified, err
}
manifest, exists := airconfig.Manifests[o.Name]
if !exists {
// manifest didn't exist, create it
// ignoring the returned added manifest
airconfig.AddManifest(o)
} else {
// manifest exists, lets update
err = airconfig.ModifyManifest(manifest, o)
if err != nil {
return modified, err
}
modified = true
}
// Update configuration file just in time persistence approach
if writeToStorage {
if err := airconfig.PersistConfig(); err != nil {
// Error that it didnt persist the changes
return modified, ErrConfigFailed{}
}
}
return modified, nil
}

View File

@ -117,3 +117,26 @@ func TestRunUseContext(t *testing.T) {
assert.Error(t, err)
})
}
func TestRunSetManifest(t *testing.T) {
t.Run("testAddManifest", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyManifestOptions := testutil.DummyManifestOptions()
dummyManifestOptions.Name = "test_manifest"
modified, err := config.RunSetManifest(dummyManifestOptions, conf, false)
assert.NoError(t, err)
assert.False(t, modified)
})
t.Run("testModifyManifest", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyManifestOptions := testutil.DummyManifestOptions()
dummyManifestOptions.TargetPath = "/tmp/default"
modified, err := config.RunSetManifest(dummyManifestOptions, conf, false)
assert.NoError(t, err)
assert.True(t, modified)
assert.Equal(t, "/tmp/default", conf.Manifests["dummy_manifest"].TargetPath)
})
}

View File

@ -748,3 +748,13 @@ func TestManagementConfigurationByNameDoesNotExist(t *testing.T) {
_, err := conf.GetManagementConfiguration(fmt.Sprintf("%s-test", config.AirshipDefaultContext))
assert.Error(t, err)
}
func TestGetManifests(t *testing.T) {
conf, cleanup := testutil.InitConfig(t)
defer cleanup(t)
manifests := conf.GetManifests()
require.NotNil(t, manifests)
assert.EqualValues(t, manifests[0].PrimaryRepositoryName, "primary")
}

View File

@ -65,3 +65,13 @@ const (
DefaultSystemActionRetries = 30
DefaultSystemRebootDelay = 30
)
// Default Value for manifest
const (
// DefaultTestPrimaryRepo holds default repo name
DefaultTestPrimaryRepo = "primary"
// DefaultTargetPath holds default target path
DefaultTargetPath = "/tmp/default"
// DefaultSubPath holds default sub path
DefaultSubPath = "manifest/default"
)

View File

@ -70,6 +70,43 @@ func (e ErrMutuallyExclusiveCheckout) Error() string {
return "Checkout mutually exclusive, use either: commit-hash, branch or tag."
}
// ErrRepositoryNotFound is returned if repository is empty
// when using in set-manifest
type ErrRepositoryNotFound struct {
Name string
}
func (e ErrRepositoryNotFound) Error() string {
return fmt.Sprintf("Repository %q not found.", e.Name)
}
// ErrMissingRepositoryName is returned if repository name is empty
// when using in set-manifest
type ErrMissingRepositoryName struct {
}
func (e ErrMissingRepositoryName) Error() string {
return "Missing repository name."
}
// ErrMissingRepoURL is returned if repository is empty
// when using --primary in set-manifest
type ErrMissingRepoURL struct {
}
func (e ErrMissingRepoURL) Error() string {
return "A valid URL should be specified."
}
// ErrMissingRepoCheckoutOptions is returned if repository checkout
// options is empty in set-manifest
type ErrMissingRepoCheckoutOptions struct {
}
func (e ErrMissingRepoCheckoutOptions) Error() string {
return "Missing repository checkout options."
}
// ErrBootstrapInfoNotFound returned if bootstrap
// information is not found for cluster
type ErrBootstrapInfoNotFound struct {

View File

@ -19,6 +19,8 @@ package config
import (
"fmt"
"os"
"opendev.org/airship/airshipctl/pkg/errors"
)
// AuthInfoOptions holds all configurable options for
@ -55,6 +57,21 @@ type ClusterOptions struct {
EmbedCAData bool
}
// ManifestOptions holds all configurable options for manifest configuration
type ManifestOptions struct {
Name string
RepoName string
URL string
Branch string
CommitHash string
Tag string
RemoteRef string
Force bool
IsPrimary bool
SubPath string
TargetPath string
}
// TODO(howell): The following functions are tightly coupled with flags passed
// on the command line. We should find a way to remove this coupling, since it
// is possible to create (and validate) these objects without using the command
@ -152,3 +169,28 @@ func checkExists(flagName, path string) error {
}
return nil
}
// Validate checks for the possible manifest option values and returns
// Error when invalid value or incompatible choice of values given
func (o *ManifestOptions) Validate() error {
if o.Name == "" {
return fmt.Errorf("you must specify a non-empty Manifest name")
}
if o.RemoteRef != "" {
return fmt.Errorf("Repository checkout by RemoteRef is not yet implemented\n%w", errors.ErrNotImplemented{})
}
if o.IsPrimary && o.RepoName == "" {
return ErrMissingRepositoryName{}
}
possibleValues := [3]string{o.CommitHash, o.Branch, o.Tag}
var count int
for _, val := range possibleValues {
if val != "" {
count++
}
}
if count > 1 {
return ErrMutuallyExclusiveCheckout{}
}
return nil
}

View File

@ -20,11 +20,6 @@ import (
"encoding/base64"
)
const (
// DefaultTestPrimaryRepo holds default repo name
DefaultTestPrimaryRepo = "primary"
)
// NewConfig returns a newly initialized Config object
func NewConfig() *Config {
return &Config{
@ -95,13 +90,17 @@ func NewCluster() *Cluster {
func NewManifest() *Manifest {
return &Manifest{
PrimaryRepositoryName: DefaultTestPrimaryRepo,
TargetPath: DefaultTargetPath,
SubPath: DefaultSubPath,
Repositories: map[string]*Repository{DefaultTestPrimaryRepo: NewRepository()},
}
}
// NewRepository is a convenience function that returns a new Repository
func NewRepository() *Repository {
return &Repository{}
return &Repository{
CheckoutOptions: &RepoCheckout{},
}
}
// NewAuthInfo is a convenience function that returns a new AuthInfo

View File

@ -264,6 +264,21 @@ func DummyManagementConfiguration() *config.ManagementConfiguration {
}
}
// DummyManifestOptions creates ManifestOptions config object
// for unit testing
func DummyManifestOptions() *config.ManifestOptions {
return &config.ManifestOptions{
Name: "dummy_manifest",
SubPath: "manifests/dummy_site",
TargetPath: "/tmp/dummy_site",
IsPrimary: true,
RepoName: "dummy_repo",
URL: "https://github.com/treasuremap/dummy_site",
Branch: "master",
Force: true,
}
}
const (
testConfigYAML = `apiVersion: airshipit.org/v1alpha1
bootstrapInfo: