Remove clusters, users, reconcilation and config import
All of these entities are no longer required and should be deleted. Change-Id: Id4776efe668265df6961a38ce984b8ac37b27097 Signed-off-by: Ruslan Aliev <raliev@mirantis.com> Relates-To: #327
This commit is contained in:
parent
d87eea6544
commit
5d52339bd6
@ -82,8 +82,6 @@ func TestNewClusterStatusCmd(t *testing.T) {
|
|||||||
func clusterStatusTestSettings() config.Factory {
|
func clusterStatusTestSettings() config.Factory {
|
||||||
return func() (*config.Config, error) {
|
return func() (*config.Config, error) {
|
||||||
return &config.Config{
|
return &config.Config{
|
||||||
Clusters: map[string]*config.ClusterPurpose{"testCluster": nil},
|
|
||||||
AuthInfos: map[string]*config.AuthInfo{"testAuthInfo": nil},
|
|
||||||
Contexts: map[string]*config.Context{
|
Contexts: map[string]*config.Context{
|
||||||
"testContext": {Manifest: "testManifest"},
|
"testContext": {Manifest: "testManifest"},
|
||||||
},
|
},
|
||||||
|
@ -34,7 +34,6 @@ func NewConfigCommand(cfgFactory config.Factory) *cobra.Command {
|
|||||||
configRootCmd.AddCommand(NewGetManagementConfigCommand(cfgFactory))
|
configRootCmd.AddCommand(NewGetManagementConfigCommand(cfgFactory))
|
||||||
configRootCmd.AddCommand(NewSetManagementConfigCommand(cfgFactory))
|
configRootCmd.AddCommand(NewSetManagementConfigCommand(cfgFactory))
|
||||||
|
|
||||||
configRootCmd.AddCommand(NewImportCommand(cfgFactory))
|
|
||||||
configRootCmd.AddCommand(NewUseContextCommand(cfgFactory))
|
configRootCmd.AddCommand(NewUseContextCommand(cfgFactory))
|
||||||
|
|
||||||
configRootCmd.AddCommand(NewGetManifestCommand(cfgFactory))
|
configRootCmd.AddCommand(NewGetManifestCommand(cfgFactory))
|
||||||
|
@ -20,8 +20,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
kubeconfig "k8s.io/client-go/tools/clientcmd/api"
|
|
||||||
|
|
||||||
cmd "opendev.org/airship/airshipctl/cmd/config"
|
cmd "opendev.org/airship/airshipctl/cmd/config"
|
||||||
"opendev.org/airship/airshipctl/pkg/config"
|
"opendev.org/airship/airshipctl/pkg/config"
|
||||||
"opendev.org/airship/airshipctl/testutil"
|
"opendev.org/airship/airshipctl/testutil"
|
||||||
@ -94,17 +92,10 @@ func TestNoContextsGetContextCmd(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getNamedTestContext(contextName string) *config.Context {
|
func getNamedTestContext(contextName string) *config.Context {
|
||||||
kContext := &kubeconfig.Context{
|
|
||||||
Namespace: "dummy_namespace",
|
|
||||||
AuthInfo: "dummy_user",
|
|
||||||
Cluster: fmt.Sprintf("dummycluster_%s", config.Ephemeral),
|
|
||||||
}
|
|
||||||
|
|
||||||
newContext := &config.Context{
|
newContext := &config.Context{
|
||||||
NameInKubeconf: fmt.Sprintf("%s_%s", contextName, config.Ephemeral),
|
NameInKubeconf: fmt.Sprintf("%s_%s", contextName, config.Ephemeral),
|
||||||
Manifest: fmt.Sprintf("Manifest_%s", contextName),
|
Manifest: fmt.Sprintf("Manifest_%s", contextName),
|
||||||
}
|
}
|
||||||
newContext.SetKubeContext(kContext)
|
|
||||||
|
|
||||||
return newContext
|
return newContext
|
||||||
}
|
}
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
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"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
useImportLong = `
|
|
||||||
Merge the clusters, contexts, and users from an existing kubeConfig file into the airshipctl config file.
|
|
||||||
`
|
|
||||||
|
|
||||||
useImportExample = `
|
|
||||||
# Import from a kubeConfig file"
|
|
||||||
airshipctl config import $HOME/.kube/config
|
|
||||||
`
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewImportCommand creates a command that merges clusters, contexts, and
|
|
||||||
// users from a kubeConfig file into the airshipctl config file.
|
|
||||||
func NewImportCommand(cfgFactory config.Factory) *cobra.Command {
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "import <kubeConfig>",
|
|
||||||
Short: "Merge information from a kubernetes config file",
|
|
||||||
Long: useImportLong[1:],
|
|
||||||
Example: useImportExample,
|
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
cfg, err := cfgFactory()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
kubeConfigPath := args[0]
|
|
||||||
err = cfg.ImportFromKubeConfig(kubeConfigPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(cmd.OutOrStdout(), "Updated airship config with content imported from %q.\n", kubeConfigPath)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
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_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
cmd "opendev.org/airship/airshipctl/cmd/config"
|
|
||||||
"opendev.org/airship/airshipctl/pkg/config"
|
|
||||||
"opendev.org/airship/airshipctl/testutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestConfigImport(t *testing.T) {
|
|
||||||
settings := func() (*config.Config, error) {
|
|
||||||
return testutil.DummyConfig(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdTests := []*testutil.CmdTest{
|
|
||||||
{
|
|
||||||
Name: "config-import-with-help",
|
|
||||||
CmdLine: "--help",
|
|
||||||
Cmd: cmd.NewImportCommand(nil),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "config-import-no-args",
|
|
||||||
CmdLine: "",
|
|
||||||
Cmd: cmd.NewImportCommand(settings),
|
|
||||||
Error: errors.New("accepts 1 arg(s), received 0"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "config-import-file-does-not-exist",
|
|
||||||
CmdLine: "foo",
|
|
||||||
Cmd: cmd.NewImportCommand(settings),
|
|
||||||
Error: errors.New("stat foo: no such file or directory"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range cmdTests {
|
|
||||||
testutil.RunTest(t, tt)
|
|
||||||
}
|
|
||||||
}
|
|
@ -32,10 +32,7 @@ Create or modify a context in the airshipctl config files.
|
|||||||
setContextExample = `
|
setContextExample = `
|
||||||
# Create a new context named "exampleContext"
|
# Create a new context named "exampleContext"
|
||||||
airshipctl config set-context exampleContext \
|
airshipctl config set-context exampleContext \
|
||||||
--namespace=kube-system \
|
|
||||||
--manifest=exampleManifest \
|
--manifest=exampleManifest \
|
||||||
--user=exampleUser
|
|
||||||
--cluster-type=target
|
|
||||||
--encryption-config=exampleEncryptionConfig
|
--encryption-config=exampleEncryptionConfig
|
||||||
|
|
||||||
# Update the manifest of the current-context
|
# Update the manifest of the current-context
|
||||||
@ -91,18 +88,6 @@ func NewSetContextCommand(cfgFactory config.Factory) *cobra.Command {
|
|||||||
func addSetContextFlags(o *config.ContextOptions, cmd *cobra.Command) {
|
func addSetContextFlags(o *config.ContextOptions, cmd *cobra.Command) {
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
|
|
||||||
flags.StringVar(
|
|
||||||
&o.Cluster,
|
|
||||||
"cluster",
|
|
||||||
"",
|
|
||||||
"set the cluster for the specified context")
|
|
||||||
|
|
||||||
flags.StringVar(
|
|
||||||
&o.AuthInfo,
|
|
||||||
"user",
|
|
||||||
"",
|
|
||||||
"set the user for the specified context")
|
|
||||||
|
|
||||||
flags.StringVar(
|
flags.StringVar(
|
||||||
&o.Manifest,
|
&o.Manifest,
|
||||||
"manifest",
|
"manifest",
|
||||||
@ -115,12 +100,6 @@ func addSetContextFlags(o *config.ContextOptions, cmd *cobra.Command) {
|
|||||||
"",
|
"",
|
||||||
"set the encryption config for the specified context")
|
"set the encryption config for the specified context")
|
||||||
|
|
||||||
flags.StringVar(
|
|
||||||
&o.Namespace,
|
|
||||||
"namespace",
|
|
||||||
"",
|
|
||||||
"set the namespace for the specified context")
|
|
||||||
|
|
||||||
flags.StringVar(
|
flags.StringVar(
|
||||||
&o.ClusterType,
|
&o.ClusterType,
|
||||||
"cluster-type",
|
"cluster-type",
|
||||||
|
@ -30,11 +30,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
testUser = "admin@kubernetes"
|
|
||||||
defaultManifest = "edge_cloud"
|
|
||||||
defaultNamespace = "kube-system"
|
|
||||||
testManifest = "test_manifest"
|
|
||||||
testEncryptionConfig = "test_encryption_config"
|
testEncryptionConfig = "test_encryption_config"
|
||||||
|
defaultManifest = "edge_cloud"
|
||||||
|
testManifest = "test_manifest"
|
||||||
)
|
)
|
||||||
|
|
||||||
type setContextTest struct {
|
type setContextTest struct {
|
||||||
@ -86,9 +84,7 @@ func TestSetContext(t *testing.T) {
|
|||||||
contextName: "dummycontext",
|
contextName: "dummycontext",
|
||||||
flags: []string{
|
flags: []string{
|
||||||
"--cluster-type=target",
|
"--cluster-type=target",
|
||||||
"--user=" + testUser,
|
|
||||||
"--manifest=" + defaultManifest,
|
"--manifest=" + defaultManifest,
|
||||||
"--namespace=" + defaultNamespace,
|
|
||||||
"--encryption-config=" + testEncryptionConfig,
|
"--encryption-config=" + testEncryptionConfig,
|
||||||
},
|
},
|
||||||
givenConfig: given,
|
givenConfig: given,
|
||||||
@ -153,9 +149,6 @@ func (test setContextTest) run(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, afterRunContext)
|
require.NotNil(t, afterRunContext)
|
||||||
|
|
||||||
afterKcontext := afterRunContext.KubeContext()
|
|
||||||
require.NotNil(t, afterKcontext)
|
|
||||||
|
|
||||||
if test.manifest != "" {
|
if test.manifest != "" {
|
||||||
assert.EqualValues(t, afterRunContext.Manifest, test.manifest)
|
assert.EqualValues(t, afterRunContext.Manifest, test.manifest)
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ Available Commands:
|
|||||||
get-management-config View a management config or all management configs defined in 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
|
get-manifest Get a manifest information from the airshipctl config
|
||||||
help Help about any command
|
help Help about any command
|
||||||
import Merge information from a kubernetes config file
|
|
||||||
init Generate initial configuration files for airshipctl
|
init Generate initial configuration files for airshipctl
|
||||||
set-context Manage contexts
|
set-context Manage contexts
|
||||||
set-encryption-config Manage encryption configs in airship config
|
set-encryption-config Manage encryption configs in airship config
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
Error: stat foo: no such file or directory
|
|
||||||
Usage:
|
|
||||||
import <kubeConfig> [flags]
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
# Import from a kubeConfig file"
|
|
||||||
airshipctl config import $HOME/.kube/config
|
|
||||||
|
|
||||||
|
|
||||||
Flags:
|
|
||||||
-h, --help help for import
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
|||||||
Error: accepts 1 arg(s), received 0
|
|
||||||
Usage:
|
|
||||||
import <kubeConfig> [flags]
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
# Import from a kubeConfig file"
|
|
||||||
airshipctl config import $HOME/.kube/config
|
|
||||||
|
|
||||||
|
|
||||||
Flags:
|
|
||||||
-h, --help help for import
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
|||||||
Merge the clusters, contexts, and users from an existing kubeConfig file into the airshipctl config file.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
import <kubeConfig> [flags]
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
# Import from a kubeConfig file"
|
|
||||||
airshipctl config import $HOME/.kube/config
|
|
||||||
|
|
||||||
|
|
||||||
Flags:
|
|
||||||
-h, --help help for import
|
|
@ -6,10 +6,7 @@ Examples:
|
|||||||
|
|
||||||
# Create a new context named "exampleContext"
|
# Create a new context named "exampleContext"
|
||||||
airshipctl config set-context exampleContext \
|
airshipctl config set-context exampleContext \
|
||||||
--namespace=kube-system \
|
|
||||||
--manifest=exampleManifest \
|
--manifest=exampleManifest \
|
||||||
--user=exampleUser
|
|
||||||
--cluster-type=target
|
|
||||||
--encryption-config=exampleEncryptionConfig
|
--encryption-config=exampleEncryptionConfig
|
||||||
|
|
||||||
# Update the manifest of the current-context
|
# Update the manifest of the current-context
|
||||||
@ -19,12 +16,9 @@ airshipctl config set-context \
|
|||||||
|
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
--cluster string set the cluster for the specified context
|
|
||||||
--cluster-type string set the cluster-type for the specified context
|
--cluster-type string set the cluster-type for the specified context
|
||||||
--current update the current context
|
--current update the current context
|
||||||
--encryption-config string set the encryption config for the specified context
|
--encryption-config string set the encryption config for the specified context
|
||||||
-h, --help help for set-context
|
-h, --help help for set-context
|
||||||
--manifest string set the manifest for the specified context
|
--manifest string set the manifest for the specified context
|
||||||
--namespace string set the namespace for the specified context
|
|
||||||
--user string set the user for the specified context
|
|
||||||
|
|
||||||
|
@ -7,10 +7,7 @@ Examples:
|
|||||||
|
|
||||||
# Create a new context named "exampleContext"
|
# Create a new context named "exampleContext"
|
||||||
airshipctl config set-context exampleContext \
|
airshipctl config set-context exampleContext \
|
||||||
--namespace=kube-system \
|
|
||||||
--manifest=exampleManifest \
|
--manifest=exampleManifest \
|
||||||
--user=exampleUser
|
|
||||||
--cluster-type=target
|
|
||||||
--encryption-config=exampleEncryptionConfig
|
--encryption-config=exampleEncryptionConfig
|
||||||
|
|
||||||
# Update the manifest of the current-context
|
# Update the manifest of the current-context
|
||||||
@ -20,11 +17,8 @@ airshipctl config set-context \
|
|||||||
|
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
--cluster string set the cluster for the specified context
|
|
||||||
--cluster-type string set the cluster-type for the specified context
|
--cluster-type string set the cluster-type for the specified context
|
||||||
--current update the current context
|
--current update the current context
|
||||||
--encryption-config string set the encryption config for the specified context
|
--encryption-config string set the encryption config for the specified context
|
||||||
-h, --help help for set-context
|
-h, --help help for set-context
|
||||||
--manifest string set the manifest for the specified context
|
--manifest string set the manifest for the specified context
|
||||||
--namespace string set the namespace for the specified context
|
|
||||||
--user string set the user for the specified context
|
|
||||||
|
@ -1,30 +1,18 @@
|
|||||||
Context: ContextBar
|
Context: ContextBar
|
||||||
contextKubeconf: ContextBar_ephemeral
|
contextKubeconf: ContextBar_ephemeral
|
||||||
|
managementConfiguration: ""
|
||||||
manifest: Manifest_ContextBar
|
manifest: Manifest_ContextBar
|
||||||
|
|
||||||
LocationOfOrigin: ""
|
|
||||||
cluster: dummycluster_ephemeral
|
|
||||||
namespace: dummy_namespace
|
|
||||||
user: dummy_user
|
|
||||||
|
|
||||||
|
|
||||||
Context: ContextBaz
|
Context: ContextBaz
|
||||||
contextKubeconf: ContextBaz_ephemeral
|
contextKubeconf: ContextBaz_ephemeral
|
||||||
|
managementConfiguration: ""
|
||||||
manifest: Manifest_ContextBaz
|
manifest: Manifest_ContextBaz
|
||||||
|
|
||||||
LocationOfOrigin: ""
|
|
||||||
cluster: dummycluster_ephemeral
|
|
||||||
namespace: dummy_namespace
|
|
||||||
user: dummy_user
|
|
||||||
|
|
||||||
|
|
||||||
Context: ContextFoo
|
Context: ContextFoo
|
||||||
contextKubeconf: ContextFoo_ephemeral
|
contextKubeconf: ContextFoo_ephemeral
|
||||||
|
managementConfiguration: ""
|
||||||
manifest: Manifest_ContextFoo
|
manifest: Manifest_ContextFoo
|
||||||
|
|
||||||
LocationOfOrigin: ""
|
|
||||||
cluster: dummycluster_ephemeral
|
|
||||||
namespace: dummy_namespace
|
|
||||||
user: dummy_user
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
Context: ContextFoo
|
Context: ContextFoo
|
||||||
contextKubeconf: ContextFoo_ephemeral
|
contextKubeconf: ContextFoo_ephemeral
|
||||||
|
managementConfiguration: ""
|
||||||
manifest: Manifest_ContextFoo
|
manifest: Manifest_ContextFoo
|
||||||
|
|
||||||
LocationOfOrigin: ""
|
|
||||||
cluster: dummycluster_ephemeral
|
|
||||||
namespace: dummy_namespace
|
|
||||||
user: dummy_user
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
Context: ContextBaz
|
Context: ContextBaz
|
||||||
contextKubeconf: ContextBaz_ephemeral
|
contextKubeconf: ContextBaz_ephemeral
|
||||||
|
managementConfiguration: ""
|
||||||
manifest: Manifest_ContextBaz
|
manifest: Manifest_ContextBaz
|
||||||
|
|
||||||
LocationOfOrigin: ""
|
|
||||||
cluster: dummycluster_ephemeral
|
|
||||||
namespace: dummy_namespace
|
|
||||||
user: dummy_user
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,30 +1,18 @@
|
|||||||
Context: ContextBar
|
Context: ContextBar
|
||||||
contextKubeconf: ContextBar_ephemeral
|
contextKubeconf: ContextBar_ephemeral
|
||||||
|
managementConfiguration: ""
|
||||||
manifest: Manifest_ContextBar
|
manifest: Manifest_ContextBar
|
||||||
|
|
||||||
LocationOfOrigin: ""
|
|
||||||
cluster: dummycluster_ephemeral
|
|
||||||
namespace: dummy_namespace
|
|
||||||
user: dummy_user
|
|
||||||
|
|
||||||
|
|
||||||
Context: ContextBaz
|
Context: ContextBaz
|
||||||
contextKubeconf: ContextBaz_ephemeral
|
contextKubeconf: ContextBaz_ephemeral
|
||||||
|
managementConfiguration: ""
|
||||||
manifest: Manifest_ContextBaz
|
manifest: Manifest_ContextBaz
|
||||||
|
|
||||||
LocationOfOrigin: ""
|
|
||||||
cluster: dummycluster_ephemeral
|
|
||||||
namespace: dummy_namespace
|
|
||||||
user: dummy_user
|
|
||||||
|
|
||||||
|
|
||||||
Context: ContextFoo
|
Context: ContextFoo
|
||||||
contextKubeconf: ContextFoo_ephemeral
|
contextKubeconf: ContextFoo_ephemeral
|
||||||
|
managementConfiguration: ""
|
||||||
manifest: Manifest_ContextFoo
|
manifest: Manifest_ContextFoo
|
||||||
|
|
||||||
LocationOfOrigin: ""
|
|
||||||
cluster: dummycluster_ephemeral
|
|
||||||
namespace: dummy_namespace
|
|
||||||
user: dummy_user
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@ Manage the airshipctl config file
|
|||||||
* [airshipctl config get-encryption-config](airshipctl_config_get-encryption-config.md) - Get an encryption config information from the airshipctl config
|
* [airshipctl config get-encryption-config](airshipctl_config_get-encryption-config.md) - Get an encryption config information 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-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 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 init](airshipctl_config_init.md) - Generate initial configuration files for airshipctl
|
||||||
* [airshipctl config set-context](airshipctl_config_set-context.md) - Manage contexts
|
* [airshipctl config set-context](airshipctl_config_set-context.md) - Manage contexts
|
||||||
* [airshipctl config set-encryption-config](airshipctl_config_set-encryption-config.md) - Manage encryption configs in airship config
|
* [airshipctl config set-encryption-config](airshipctl_config_set-encryption-config.md) - Manage encryption configs in airship config
|
||||||
|
@ -17,10 +17,7 @@ airshipctl config set-context NAME [flags]
|
|||||||
|
|
||||||
# Create a new context named "exampleContext"
|
# Create a new context named "exampleContext"
|
||||||
airshipctl config set-context exampleContext \
|
airshipctl config set-context exampleContext \
|
||||||
--namespace=kube-system \
|
|
||||||
--manifest=exampleManifest \
|
--manifest=exampleManifest \
|
||||||
--user=exampleUser
|
|
||||||
--cluster-type=target
|
|
||||||
--encryption-config=exampleEncryptionConfig
|
--encryption-config=exampleEncryptionConfig
|
||||||
|
|
||||||
# Update the manifest of the current-context
|
# Update the manifest of the current-context
|
||||||
@ -33,14 +30,11 @@ airshipctl config set-context \
|
|||||||
### Options
|
### Options
|
||||||
|
|
||||||
```
|
```
|
||||||
--cluster string set the cluster for the specified context
|
|
||||||
--cluster-type string set the cluster-type for the specified context
|
--cluster-type string set the cluster-type for the specified context
|
||||||
--current update the current context
|
--current update the current context
|
||||||
--encryption-config string set the encryption config for the specified context
|
--encryption-config string set the encryption config for the specified context
|
||||||
-h, --help help for set-context
|
-h, --help help for set-context
|
||||||
--manifest string set the manifest for the specified context
|
--manifest string set the manifest for the specified context
|
||||||
--namespace string set the namespace for the specified context
|
|
||||||
--user string set the user for the specified context
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options inherited from parent commands
|
### Options inherited from parent commands
|
||||||
|
@ -66,6 +66,7 @@ func NewCommand(cfgFactory config.Factory) (*Command, error) {
|
|||||||
|
|
||||||
// Init runs clusterctl init
|
// Init runs clusterctl init
|
||||||
func (c *Command) Init() error {
|
func (c *Command) Init() error {
|
||||||
|
log.Printf("config %s \n context %s", c.kubeconfigPath, c.kubeconfigContext)
|
||||||
return c.client.Init(c.kubeconfigPath, c.kubeconfigContext)
|
return c.client.Init(c.kubeconfigPath, c.kubeconfigContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
pkg/clusterctl/cmd/testdata/airshipconfig.yaml
vendored
22
pkg/clusterctl/cmd/testdata/airshipconfig.yaml
vendored
@ -1,25 +1,7 @@
|
|||||||
apiVersion: airshipit.org/v1alpha1
|
apiVersion: airshipit.org/v1alpha1
|
||||||
bootstrapInfo:
|
|
||||||
dummy_bootstrap_config:
|
|
||||||
container:
|
|
||||||
volume: /tmp/airship:/config
|
|
||||||
image: quay.io/airshipit/isogen:latest-ubuntu_focal
|
|
||||||
containerRuntime: docker
|
|
||||||
builder:
|
|
||||||
userDataFileName: user-data
|
|
||||||
networkConfigFileName: network-config
|
|
||||||
outputMetadataFileName: output-metadata.yaml
|
|
||||||
remoteDirect:
|
|
||||||
isoUrl: http://localhost:8099/ubuntu-focal.iso
|
|
||||||
clusters:
|
|
||||||
dummycluster:
|
|
||||||
clusterType:
|
|
||||||
ephemeral:
|
|
||||||
bootstrapInfo: dummy_bootstrap_config
|
|
||||||
clusterKubeconf: dummycluster_ephemeral
|
|
||||||
contexts:
|
contexts:
|
||||||
dummy_cluster:
|
dummy_cluster:
|
||||||
contextKubeconf: dummy_cluster
|
contextKubeconf: dummycluster_ephemeral
|
||||||
manifest: dummy_manifest
|
manifest: dummy_manifest
|
||||||
currentContext: dummy_cluster
|
currentContext: dummy_cluster
|
||||||
kind: Config
|
kind: Config
|
||||||
@ -39,5 +21,3 @@ manifests:
|
|||||||
url: http://dummy.url.com/primary.git
|
url: http://dummy.url.com/primary.git
|
||||||
subPath: site
|
subPath: site
|
||||||
targetPath: testdata
|
targetPath: testdata
|
||||||
users:
|
|
||||||
dummy_user: {}
|
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 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 (
|
|
||||||
"k8s.io/client-go/tools/clientcmd/api"
|
|
||||||
"sigs.k8s.io/yaml"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AuthInfo contains kubeConfig AuthInfo Object
|
|
||||||
type AuthInfo struct {
|
|
||||||
// KubeConfig AuthInfo Object
|
|
||||||
authInfo *api.AuthInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// AuthInfo functions
|
|
||||||
func (c *AuthInfo) String() string {
|
|
||||||
kauthinfo := c.KubeAuthInfo()
|
|
||||||
kyaml, err := yaml.Marshal(&kauthinfo)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(kyaml)
|
|
||||||
}
|
|
||||||
|
|
||||||
// KubeAuthInfo returns kubeConfig AuthInfo Object
|
|
||||||
func (c *AuthInfo) KubeAuthInfo() *api.AuthInfo {
|
|
||||||
return c.authInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetKubeAuthInfo sets kubeConfig in AuthInfo
|
|
||||||
func (c *AuthInfo) SetKubeAuthInfo(kc *api.AuthInfo) {
|
|
||||||
c.authInfo = kc
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 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_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"opendev.org/airship/airshipctl/testutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetAuthInfos(t *testing.T) {
|
|
||||||
conf, cleanup := testutil.InitConfig(t)
|
|
||||||
defer cleanup(t)
|
|
||||||
|
|
||||||
authinfos, err := conf.GetAuthInfos()
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Len(t, authinfos, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetAuthInfo(t *testing.T) {
|
|
||||||
conf, cleanup := testutil.InitConfig(t)
|
|
||||||
defer cleanup(t)
|
|
||||||
|
|
||||||
authinfo, err := conf.GetAuthInfo("def-user")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Test Positives
|
|
||||||
assert.EqualValues(t, authinfo.KubeAuthInfo().Username, "dummy_username")
|
|
||||||
|
|
||||||
// Test Wrong Cluster
|
|
||||||
_, err = conf.GetAuthInfo("unknown")
|
|
||||||
assert.Error(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddAuthInfo(t *testing.T) {
|
|
||||||
conf, cleanup := testutil.InitConfig(t)
|
|
||||||
defer cleanup(t)
|
|
||||||
|
|
||||||
co := testutil.DummyAuthInfoOptions()
|
|
||||||
authinfo := conf.AddAuthInfo(co)
|
|
||||||
assert.EqualValues(t, conf.AuthInfos[co.Name], authinfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestModifyAuthInfo(t *testing.T) {
|
|
||||||
conf, cleanup := testutil.InitConfig(t)
|
|
||||||
defer cleanup(t)
|
|
||||||
|
|
||||||
co := testutil.DummyAuthInfoOptions()
|
|
||||||
authinfo := conf.AddAuthInfo(co)
|
|
||||||
|
|
||||||
co.Username += stringDelta
|
|
||||||
co.Password = newPassword
|
|
||||||
co.ClientCertificate = newCertificate
|
|
||||||
co.ClientKey = newKey
|
|
||||||
co.Token = newToken
|
|
||||||
conf.ModifyAuthInfo(authinfo, co)
|
|
||||||
modifiedAuthinfo, err := conf.GetAuthInfo(co.Name)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.EqualValues(t, modifiedAuthinfo.KubeAuthInfo().Username, co.Username)
|
|
||||||
assert.EqualValues(t, modifiedAuthinfo.KubeAuthInfo().Password, co.Password)
|
|
||||||
assert.EqualValues(t, modifiedAuthinfo.KubeAuthInfo().ClientCertificate, co.ClientCertificate)
|
|
||||||
assert.EqualValues(t, modifiedAuthinfo.KubeAuthInfo().ClientKey, co.ClientKey)
|
|
||||||
assert.EqualValues(t, modifiedAuthinfo.KubeAuthInfo().Token, co.Token)
|
|
||||||
assert.EqualValues(t, modifiedAuthinfo, authinfo)
|
|
||||||
}
|
|
@ -1,141 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 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"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"k8s.io/client-go/tools/clientcmd/api"
|
|
||||||
"sigs.k8s.io/yaml"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Cluster contains information about how to communicate with a kubernetes cluster
|
|
||||||
type Cluster struct {
|
|
||||||
// Complex cluster name defined by the using <cluster name>_<cluster type>)
|
|
||||||
NameInKubeconf string `json:"clusterKubeconf"`
|
|
||||||
|
|
||||||
// KubeConfig Cluster Object
|
|
||||||
cluster *api.Cluster
|
|
||||||
|
|
||||||
// Management configuration which will be used for all hosts in the cluster
|
|
||||||
ManagementConfiguration string `json:"managementConfiguration"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClusterPurpose encapsulates the Cluster Type as an enumeration
|
|
||||||
type ClusterPurpose struct {
|
|
||||||
// Cluster map of referenceable names to cluster configs
|
|
||||||
ClusterTypes map[string]*Cluster `json:"clusterType"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClusterComplexName holds the complex cluster name information
|
|
||||||
// Encapsulates the different operations around using it.
|
|
||||||
type ClusterComplexName struct {
|
|
||||||
Name string
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Cluster) String() string {
|
|
||||||
cyaml, err := yaml.Marshal(&c)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
kcluster := c.KubeCluster()
|
|
||||||
kyaml, err := yaml.Marshal(&kcluster)
|
|
||||||
if err != nil {
|
|
||||||
return string(cyaml)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("%s\n%s", string(cyaml), string(kyaml))
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrettyString returns cluster information in a formatted string
|
|
||||||
func (c *Cluster) PrettyString() string {
|
|
||||||
clusterName := NewClusterComplexNameFromKubeClusterName(c.NameInKubeconf)
|
|
||||||
return fmt.Sprintf("Cluster: %s\n%s:\n%s", clusterName.Name, clusterName.Type, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
// KubeCluster returns KubeConfig Cluster Object
|
|
||||||
func (c *Cluster) KubeCluster() *api.Cluster {
|
|
||||||
return c.cluster
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetKubeCluster sets cluster in KubeConfig
|
|
||||||
func (c *Cluster) SetKubeCluster(kc *api.Cluster) {
|
|
||||||
c.cluster = kc
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns cluster's complex name, formed by combining name and type with a delimiter('_')
|
|
||||||
func (c *ClusterComplexName) String() string {
|
|
||||||
return strings.Join([]string{c.Name, c.Type}, AirshipClusterNameSeparator)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidClusterType checks for the possible options for cluster type
|
|
||||||
// Returns error when invalid cluster type is given
|
|
||||||
func ValidClusterType(clusterType string) error {
|
|
||||||
for _, validType := range AllClusterTypes {
|
|
||||||
if clusterType == validType {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fmt.Errorf("cluster type must be one of %v", AllClusterTypes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClusterPurpose is a convenience function that returns a new ClusterPurpose
|
|
||||||
func NewClusterPurpose() *ClusterPurpose {
|
|
||||||
return &ClusterPurpose{
|
|
||||||
ClusterTypes: make(map[string]*Cluster),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClusterComplexName returns a ClusterComplexName with the given name and type.
|
|
||||||
func NewClusterComplexName(clusterName, clusterType string) ClusterComplexName {
|
|
||||||
return ClusterComplexName{
|
|
||||||
Name: clusterName,
|
|
||||||
Type: clusterType,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClusterComplexNameFromKubeClusterName takes the name of a cluster in a
|
|
||||||
// format which might be found in a kubeconfig file. This may be a simple
|
|
||||||
// string (e.g. myCluster), or it may be prepended with the type of the cluster
|
|
||||||
// (e.g. myCluster_target)
|
|
||||||
//
|
|
||||||
// If a valid cluster type was appended, the returned ClusterComplexName will
|
|
||||||
// have that type. If no cluster type is provided, the
|
|
||||||
// AirshipDefaultClusterType will be used.
|
|
||||||
func NewClusterComplexNameFromKubeClusterName(kubeClusterName string) ClusterComplexName {
|
|
||||||
parts := strings.Split(kubeClusterName, AirshipClusterNameSeparator)
|
|
||||||
|
|
||||||
if len(parts) == 1 {
|
|
||||||
return NewClusterComplexName(kubeClusterName, AirshipDefaultClusterType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// kubeClusterName matches the format myCluster_something.
|
|
||||||
// Let's check if "something" is a clusterType.
|
|
||||||
potentialType := parts[len(parts)-1]
|
|
||||||
for _, ct := range AllClusterTypes {
|
|
||||||
if potentialType == ct {
|
|
||||||
// Rejoin the parts in the case of "my_cluster_etc_etc_<clusterType>"
|
|
||||||
name := strings.Join(parts[:len(parts)-1], AirshipClusterNameSeparator)
|
|
||||||
return NewClusterComplexName(name, potentialType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// "something" is not a valid clusterType, so just use the default
|
|
||||||
return NewClusterComplexName(kubeClusterName, AirshipDefaultClusterType)
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 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_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"opendev.org/airship/airshipctl/pkg/config"
|
|
||||||
"opendev.org/airship/airshipctl/testutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPrettyString(t *testing.T) {
|
|
||||||
fSys := testutil.SetupTestFs(t, "testdata")
|
|
||||||
data, err := fSys.ReadFile("/prettycluster-string.yaml")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
cluster := testutil.DummyCluster()
|
|
||||||
assert.EqualValues(t, cluster.PrettyString(), string(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidClusterTypeFail(t *testing.T) {
|
|
||||||
err := config.ValidClusterType("Fake")
|
|
||||||
assert.Error(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetCluster(t *testing.T) {
|
|
||||||
conf, cleanup := testutil.InitConfig(t)
|
|
||||||
defer cleanup(t)
|
|
||||||
|
|
||||||
cluster, err := conf.GetCluster("def", config.Ephemeral)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Test Positives
|
|
||||||
assert.EqualValues(t, cluster.NameInKubeconf, "def_ephemeral")
|
|
||||||
assert.EqualValues(t, cluster.KubeCluster().Server, "http://5.6.7.8")
|
|
||||||
|
|
||||||
// Test Wrong Cluster
|
|
||||||
_, err = conf.GetCluster("unknown", config.Ephemeral)
|
|
||||||
assert.Error(t, err)
|
|
||||||
|
|
||||||
// Test Wrong Cluster Type
|
|
||||||
_, err = conf.GetCluster("def", "Unknown")
|
|
||||||
assert.Error(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddCluster(t *testing.T) {
|
|
||||||
conf, cleanup := testutil.InitConfig(t)
|
|
||||||
defer cleanup(t)
|
|
||||||
|
|
||||||
co := testutil.DummyClusterOptions()
|
|
||||||
cluster, err := conf.AddCluster(co)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
assert.EqualValues(t, conf.Clusters[co.Name].ClusterTypes[co.ClusterType], cluster)
|
|
||||||
}
|
|
@ -1,6 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2014 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
@ -47,12 +45,6 @@ type Config struct {
|
|||||||
// +optional
|
// +optional
|
||||||
APIVersion string `json:"apiVersion,omitempty"`
|
APIVersion string `json:"apiVersion,omitempty"`
|
||||||
|
|
||||||
// Clusters is a map of referenceable names to cluster configs
|
|
||||||
Clusters map[string]*ClusterPurpose `json:"clusters"`
|
|
||||||
|
|
||||||
// AuthInfos is a map of referenceable names to user configs
|
|
||||||
AuthInfos map[string]*AuthInfo `json:"users"`
|
|
||||||
|
|
||||||
// Permissions is a struct of permissions for file and directory
|
// Permissions is a struct of permissions for file and directory
|
||||||
Permissions Permissions `json:"permissions,omitempty"`
|
Permissions Permissions `json:"permissions,omitempty"`
|
||||||
|
|
||||||
@ -124,9 +116,6 @@ func CreateConfig(airshipConfigPath string, kubeConfigPath string) error {
|
|||||||
cfg := NewConfig()
|
cfg := NewConfig()
|
||||||
cfg.kubeConfig = NewKubeConfig()
|
cfg.kubeConfig = NewKubeConfig()
|
||||||
cfg.initConfigPath(airshipConfigPath, kubeConfigPath)
|
cfg.initConfigPath(airshipConfigPath, kubeConfigPath)
|
||||||
if err := cfg.reconcileConfig(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return cfg.PersistConfig(true)
|
return cfg.PersistConfig(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,8 +159,7 @@ func (c *Config) LoadConfig(airshipConfigPath, kubeConfigPath string, create boo
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lets navigate through the kubeconfig to populate the references in airship config
|
return nil
|
||||||
return c.reconcileConfig()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadFromAirConfig populates the Config from the file found at airshipConfigPath.
|
// loadFromAirConfig populates the Config from the file found at airshipConfigPath.
|
||||||
@ -217,220 +205,14 @@ func (c *Config) loadKubeConfig(kubeConfigPath string, create bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// reconcileConfig serves two functions:
|
|
||||||
// 1 - it will consume from kubeconfig and update airship config
|
|
||||||
// For cluster that do not comply with the airship cluster type expectations a default
|
|
||||||
// behavior will be implemented. Such as ,by default they will be tar or ephemeral
|
|
||||||
// 2 - it will update kubeconfig cluster objects with the appropriate <clustername>_<clustertype> convention
|
|
||||||
func (c *Config) reconcileConfig() error {
|
|
||||||
updatedClusterNames, persistIt := c.reconcileClusters()
|
|
||||||
c.reconcileContexts(updatedClusterNames)
|
|
||||||
c.reconcileAuthInfos()
|
|
||||||
c.reconcileCurrentContext()
|
|
||||||
|
|
||||||
// I changed things during the reconciliation
|
|
||||||
// Lets reflect them in the config files
|
|
||||||
// Specially useful if the config is loaded during a get operation
|
|
||||||
// If it was a Set this would have happened eventually any way
|
|
||||||
if persistIt {
|
|
||||||
return c.PersistConfig(true)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// reconcileClusters synchronizes the airshipconfig file with the kubeconfig file.
|
|
||||||
//
|
|
||||||
// It iterates over the clusters listed in the kubeconfig. If any cluster in
|
|
||||||
// the kubeconfig does not meet the <name>_<type> convention, the name is
|
|
||||||
// first changed to the airship default.
|
|
||||||
//
|
|
||||||
// It then updates the airshipconfig's names of those clusters, as well as the
|
|
||||||
// pointer to the clusters.
|
|
||||||
// If the cluster wasn't referenced prior to the call, it is created; otherwise
|
|
||||||
// it is modified.
|
|
||||||
//
|
|
||||||
// Finally, any clusters listed in the airshipconfig that are no longer
|
|
||||||
// referenced in the kubeconfig are deleted
|
|
||||||
//
|
|
||||||
// The function returns a mapping of changed names in the kubeconfig, as well
|
|
||||||
// as a boolean denoting that the config files need to be written to file
|
|
||||||
func (c *Config) reconcileClusters() (map[string]string, bool) {
|
|
||||||
// updatedClusterNames is a mapping from OLD cluster names to NEW
|
|
||||||
// cluster names. This will be used later when we update contexts
|
|
||||||
updatedClusterNames := map[string]string{}
|
|
||||||
|
|
||||||
persistIt := false
|
|
||||||
for clusterName, cluster := range c.kubeConfig.Clusters {
|
|
||||||
clusterComplexName := NewClusterComplexNameFromKubeClusterName(clusterName)
|
|
||||||
// Check if the cluster from the kubeconfig file complies with
|
|
||||||
// the airship naming convention
|
|
||||||
if clusterName != clusterComplexName.String() {
|
|
||||||
// Update the kubeconfig with proper airship name
|
|
||||||
c.kubeConfig.Clusters[clusterComplexName.String()] = cluster
|
|
||||||
delete(c.kubeConfig.Clusters, clusterName)
|
|
||||||
|
|
||||||
// We also need to save the mapping from the old name
|
|
||||||
// so we can update the context in the kubeconfig later
|
|
||||||
updatedClusterNames[clusterName] = clusterComplexName.String()
|
|
||||||
|
|
||||||
// Since we've modified the kubeconfig object, we'll
|
|
||||||
// need to let the caller know that the kubeconfig file
|
|
||||||
// needs to be updated
|
|
||||||
persistIt = true
|
|
||||||
|
|
||||||
// Otherwise this is a cluster that didnt have an
|
|
||||||
// airship cluster type, however when you added the
|
|
||||||
// cluster type
|
|
||||||
// Probable should just add a number _<COUNTER to it
|
|
||||||
}
|
|
||||||
|
|
||||||
// The cluster in the kubeconfig is not present in the airship config. Create it.
|
|
||||||
if c.Clusters[clusterComplexName.Name] == nil {
|
|
||||||
c.Clusters[clusterComplexName.Name] = NewClusterPurpose()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE(drewwalters96): This is a user error because a cluster is defined in name but incomplete. We
|
|
||||||
// need to fail sooner than this function; add up-front validation for this later.
|
|
||||||
if c.Clusters[clusterComplexName.Name].ClusterTypes == nil {
|
|
||||||
c.Clusters[clusterComplexName.Name].ClusterTypes = make(map[string]*Cluster)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The cluster is defined, but the type is not. Define the type.
|
|
||||||
if c.Clusters[clusterComplexName.Name].ClusterTypes[clusterComplexName.Type] == nil {
|
|
||||||
c.Clusters[clusterComplexName.Name].ClusterTypes[clusterComplexName.Type] = NewCluster()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Point cluster at kubeconfig
|
|
||||||
configCluster := c.Clusters[clusterComplexName.Name].ClusterTypes[clusterComplexName.Type]
|
|
||||||
configCluster.NameInKubeconf = clusterComplexName.String()
|
|
||||||
|
|
||||||
// Store the reference to the KubeConfig Cluster in the Airship Config
|
|
||||||
configCluster.SetKubeCluster(cluster)
|
|
||||||
}
|
|
||||||
|
|
||||||
persistIt = c.rmConfigClusterStragglers(persistIt)
|
|
||||||
|
|
||||||
return updatedClusterNames, persistIt
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes Cluster configuration that exist in Airship Config and do not have
|
|
||||||
// any kubeconfig appropriate <clustername>_<clustertype> entries
|
|
||||||
func (c *Config) rmConfigClusterStragglers(persistIt bool) bool {
|
|
||||||
rccs := persistIt
|
|
||||||
// Checking if there is any Cluster reference in airship config that does not match
|
|
||||||
// an actual Cluster struct in kubeconfig
|
|
||||||
for clusterName := range c.Clusters {
|
|
||||||
for cType, cluster := range c.Clusters[clusterName].ClusterTypes {
|
|
||||||
if _, found := c.kubeConfig.Clusters[cluster.NameInKubeconf]; !found {
|
|
||||||
// Instead of removing it , I could add a empty entry in kubeconfig as well
|
|
||||||
// Will see what is more appropriate with use of Modules configuration
|
|
||||||
delete(c.Clusters[clusterName].ClusterTypes, cType)
|
|
||||||
|
|
||||||
// If that was the last cluster type, then we
|
|
||||||
// should delete the cluster entry
|
|
||||||
if len(c.Clusters[clusterName].ClusterTypes) == 0 {
|
|
||||||
delete(c.Clusters, clusterName)
|
|
||||||
}
|
|
||||||
rccs = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rccs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) reconcileContexts(updatedClusterNames map[string]string) {
|
|
||||||
for key, context := range c.kubeConfig.Contexts {
|
|
||||||
// Check if the Cluster name referred to by the context
|
|
||||||
// was updated during the cluster reconcile
|
|
||||||
if newName, ok := updatedClusterNames[context.Cluster]; ok {
|
|
||||||
context.Cluster = newName
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Contexts[key] == nil {
|
|
||||||
c.Contexts[key] = NewContext()
|
|
||||||
}
|
|
||||||
// Make sure the name matches
|
|
||||||
c.Contexts[key].NameInKubeconf = context.Cluster
|
|
||||||
c.Contexts[key].SetKubeContext(context)
|
|
||||||
|
|
||||||
// What about if a Context refers to a cluster that does not
|
|
||||||
// exist in airship config
|
|
||||||
clusterName := NewClusterComplexNameFromKubeClusterName(context.Cluster)
|
|
||||||
if c.Clusters[clusterName.Name] == nil {
|
|
||||||
// I cannot create this cluster, it will have empty information
|
|
||||||
// Best course of action is to delete it I think
|
|
||||||
delete(c.kubeConfig.Contexts, key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Checking if there is any Context reference in airship config that does not match
|
|
||||||
// an actual Context struct in kubeconfig, if they do not exists I will delete
|
|
||||||
// Since context in airship config are only references mainly.
|
|
||||||
for key := range c.Contexts {
|
|
||||||
if c.kubeConfig.Contexts[key] == nil {
|
|
||||||
delete(c.Contexts, key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) reconcileAuthInfos() {
|
|
||||||
for key, authinfo := range c.kubeConfig.AuthInfos {
|
|
||||||
// Simple check if the AuthInfo name is referenced in airship config
|
|
||||||
if c.AuthInfos[key] == nil && authinfo != nil {
|
|
||||||
// Add the reference
|
|
||||||
c.AuthInfos[key] = NewAuthInfo()
|
|
||||||
}
|
|
||||||
c.AuthInfos[key].authInfo = authinfo
|
|
||||||
}
|
|
||||||
// Checking if there is any AuthInfo reference in airship config that does not match
|
|
||||||
// an actual Auth Info struct in kubeconfig
|
|
||||||
for key := range c.AuthInfos {
|
|
||||||
if c.kubeConfig.AuthInfos[key] == nil {
|
|
||||||
delete(c.AuthInfos, key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) reconcileCurrentContext() {
|
|
||||||
// If the Airship current context is different that the current context in the kubeconfig
|
|
||||||
// then
|
|
||||||
// - if the airship current context is valid, then updated kubeconfig CC
|
|
||||||
// - if the airship currentcontext is invalid, and the kubeconfig CC is valid, then create the reference
|
|
||||||
// - otherwise , they are both empty. Make sure
|
|
||||||
|
|
||||||
if c.Contexts[c.CurrentContext] == nil { // Its not valid
|
|
||||||
if c.Contexts[c.kubeConfig.CurrentContext] != nil {
|
|
||||||
c.CurrentContext = c.kubeConfig.CurrentContext
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Overpowers kubeConfig CurrentContext
|
|
||||||
if c.kubeConfig.CurrentContext != c.CurrentContext {
|
|
||||||
c.kubeConfig.CurrentContext = c.CurrentContext
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnsureComplete verifies that a Config object is ready to use.
|
// EnsureComplete verifies that a Config object is ready to use.
|
||||||
// A complete Config object meets the following criteria:
|
// A complete Config object meets the following criteria:
|
||||||
// * At least 1 Cluster is defined
|
|
||||||
// * At least 1 AuthInfo (user) is defined
|
|
||||||
// * At least 1 Context is defined
|
// * At least 1 Context is defined
|
||||||
// * At least 1 Manifest is defined
|
// * At least 1 Manifest is defined
|
||||||
// * The CurrentContext is set
|
// * The CurrentContext is set
|
||||||
// * The CurrentContext identifies an existing Context
|
// * The CurrentContext identifies an existing Context
|
||||||
// * The CurrentContext identifies an existing Manifest
|
// * The CurrentContext identifies an existing Manifest
|
||||||
func (c *Config) EnsureComplete() error {
|
func (c *Config) EnsureComplete() error {
|
||||||
if len(c.Clusters) == 0 {
|
|
||||||
return ErrMissingConfig{
|
|
||||||
What: "At least one cluster needs to be defined",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.AuthInfos) == 0 {
|
|
||||||
return ErrMissingConfig{
|
|
||||||
What: "At least one Authentication Information (User) needs to be defined",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.Contexts) == 0 {
|
if len(c.Contexts) == 0 {
|
||||||
return ErrMissingConfig{
|
return ErrMissingConfig{
|
||||||
What: "At least one Context needs to be defined",
|
What: "At least one Context needs to be defined",
|
||||||
@ -560,113 +342,6 @@ func (c *Config) SetKubeConfig(kubeConfig *clientcmdapi.Config) {
|
|||||||
c.kubeConfig = kubeConfig
|
c.kubeConfig = kubeConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCluster returns a cluster instance
|
|
||||||
func (c *Config) GetCluster(cName, cType string) (*Cluster, error) {
|
|
||||||
_, exists := c.Clusters[cName]
|
|
||||||
if !exists {
|
|
||||||
return nil, ErrMissingConfig{What: fmt.Sprintf("Cluster with name '%s' of type '%s'", cName, cType)}
|
|
||||||
}
|
|
||||||
// Alternative to this would be enhance Cluster.String() to embed the appropriate kubeconfig cluster information
|
|
||||||
cluster, exists := c.Clusters[cName].ClusterTypes[cType]
|
|
||||||
if !exists {
|
|
||||||
return nil, ErrMissingConfig{What: fmt.Sprintf("Cluster with name '%s' of type '%s'", cName, cType)}
|
|
||||||
}
|
|
||||||
return cluster, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddCluster creates a new cluster and returns the
|
|
||||||
// newly created cluster object
|
|
||||||
func (c *Config) AddCluster(theCluster *ClusterOptions) (*Cluster, error) {
|
|
||||||
// Need to create new cluster placeholder
|
|
||||||
// Get list of ClusterPurposes that match the theCluster.name
|
|
||||||
// Cluster might exists, but ClusterPurpose should not
|
|
||||||
_, exists := c.Clusters[theCluster.Name]
|
|
||||||
if !exists {
|
|
||||||
c.Clusters[theCluster.Name] = NewClusterPurpose()
|
|
||||||
}
|
|
||||||
// Create the new Airship config Cluster
|
|
||||||
nCluster := NewCluster()
|
|
||||||
c.Clusters[theCluster.Name].ClusterTypes[theCluster.ClusterType] = nCluster
|
|
||||||
// Create a new KubeConfig Cluster object as well
|
|
||||||
kcluster := clientcmdapi.NewCluster()
|
|
||||||
clusterName := NewClusterComplexName(theCluster.Name, theCluster.ClusterType)
|
|
||||||
nCluster.NameInKubeconf = clusterName.String()
|
|
||||||
nCluster.SetKubeCluster(kcluster)
|
|
||||||
|
|
||||||
c.KubeConfig().Clusters[clusterName.String()] = kcluster
|
|
||||||
|
|
||||||
// Ok , I have initialized structs for the Cluster information
|
|
||||||
// We can use Modify to populate the correct information
|
|
||||||
return c.ModifyCluster(nCluster, theCluster)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ModifyCluster updates cluster object with given cluster options
|
|
||||||
func (c *Config) ModifyCluster(cluster *Cluster, theCluster *ClusterOptions) (*Cluster, error) {
|
|
||||||
kcluster := cluster.KubeCluster()
|
|
||||||
if kcluster == nil {
|
|
||||||
return cluster, nil
|
|
||||||
}
|
|
||||||
if theCluster.Server != "" {
|
|
||||||
kcluster.Server = theCluster.Server
|
|
||||||
}
|
|
||||||
if theCluster.InsecureSkipTLSVerify {
|
|
||||||
kcluster.InsecureSkipTLSVerify = theCluster.InsecureSkipTLSVerify
|
|
||||||
// Specifying insecur mode clears any certificate authority
|
|
||||||
if kcluster.InsecureSkipTLSVerify {
|
|
||||||
kcluster.CertificateAuthority = ""
|
|
||||||
kcluster.CertificateAuthorityData = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if theCluster.CertificateAuthority == "" {
|
|
||||||
return cluster, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if theCluster.EmbedCAData {
|
|
||||||
readData, err := ioutil.ReadFile(theCluster.CertificateAuthority)
|
|
||||||
kcluster.CertificateAuthorityData = readData
|
|
||||||
if err != nil {
|
|
||||||
return cluster, err
|
|
||||||
}
|
|
||||||
kcluster.InsecureSkipTLSVerify = false
|
|
||||||
kcluster.CertificateAuthority = ""
|
|
||||||
} else {
|
|
||||||
caPath, err := filepath.Abs(theCluster.CertificateAuthority)
|
|
||||||
if err != nil {
|
|
||||||
return cluster, err
|
|
||||||
}
|
|
||||||
kcluster.CertificateAuthority = caPath
|
|
||||||
// Specifying a certificate authority file clears certificate authority data and insecure mode
|
|
||||||
if caPath != "" {
|
|
||||||
kcluster.InsecureSkipTLSVerify = false
|
|
||||||
kcluster.CertificateAuthorityData = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cluster, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetClusters returns all of the clusters associated with the Config sorted by name
|
|
||||||
func (c *Config) GetClusters() []*Cluster {
|
|
||||||
keys := make([]string, 0, len(c.Clusters))
|
|
||||||
for name := range c.Clusters {
|
|
||||||
keys = append(keys, name)
|
|
||||||
}
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
clusters := make([]*Cluster, 0, len(c.Clusters))
|
|
||||||
for _, name := range keys {
|
|
||||||
for _, clusterType := range AllClusterTypes {
|
|
||||||
cluster, exists := c.Clusters[name].ClusterTypes[clusterType]
|
|
||||||
if exists {
|
|
||||||
// If it doesn't exist, then there must not be
|
|
||||||
// a cluster with this name/type combination.
|
|
||||||
// This is expected behavior
|
|
||||||
clusters = append(clusters, cluster)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return clusters
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetContext returns a context instance
|
// GetContext returns a context instance
|
||||||
func (c *Config) GetContext(cName string) (*Context, error) {
|
func (c *Config) GetContext(cName string) (*Context, error) {
|
||||||
context, exists := c.Contexts[cName]
|
context, exists := c.Contexts[cName]
|
||||||
@ -707,30 +382,19 @@ func (c *Config) AddContext(theContext *ContextOptions) *Context {
|
|||||||
// Create the new Airship config context
|
// Create the new Airship config context
|
||||||
nContext := NewContext()
|
nContext := NewContext()
|
||||||
c.Contexts[theContext.Name] = nContext
|
c.Contexts[theContext.Name] = nContext
|
||||||
// Create a new KubeConfig Context object as well
|
|
||||||
context := clientcmdapi.NewContext()
|
|
||||||
nContext.NameInKubeconf = theContext.Name
|
nContext.NameInKubeconf = theContext.Name
|
||||||
|
|
||||||
nContext.SetKubeContext(context)
|
|
||||||
c.KubeConfig().Contexts[theContext.Name] = context
|
|
||||||
|
|
||||||
// Ok , I have initialized structs for the Context information
|
// Ok , I have initialized structs for the Context information
|
||||||
// We can use Modify to populate the correct information
|
// We can use Modify to populate the correct information
|
||||||
c.ModifyContext(nContext, theContext)
|
c.ModifyContext(nContext, theContext)
|
||||||
|
nContext.ClusterType()
|
||||||
return nContext
|
return nContext
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModifyContext updates Context object with given given context options
|
// ModifyContext updates Context object with given given context options
|
||||||
func (c *Config) ModifyContext(context *Context, theContext *ContextOptions) {
|
func (c *Config) ModifyContext(context *Context, theContext *ContextOptions) {
|
||||||
kubeContext := context.KubeContext()
|
if theContext.ManagementConfiguration != "" {
|
||||||
if kubeContext == nil {
|
context.ManagementConfiguration = theContext.ManagementConfiguration
|
||||||
return
|
|
||||||
}
|
|
||||||
if theContext.Cluster != "" {
|
|
||||||
kubeContext.Cluster = theContext.Cluster
|
|
||||||
}
|
|
||||||
if theContext.AuthInfo != "" {
|
|
||||||
kubeContext.AuthInfo = theContext.AuthInfo
|
|
||||||
}
|
}
|
||||||
if theContext.Manifest != "" {
|
if theContext.Manifest != "" {
|
||||||
context.Manifest = theContext.Manifest
|
context.Manifest = theContext.Manifest
|
||||||
@ -738,16 +402,11 @@ func (c *Config) ModifyContext(context *Context, theContext *ContextOptions) {
|
|||||||
if theContext.EncryptionConfig != "" {
|
if theContext.EncryptionConfig != "" {
|
||||||
context.EncryptionConfig = theContext.EncryptionConfig
|
context.EncryptionConfig = theContext.EncryptionConfig
|
||||||
}
|
}
|
||||||
if theContext.Namespace != "" {
|
|
||||||
kubeContext.Namespace = theContext.Namespace
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentContext methods Returns the appropriate information for the current context
|
// GetCurrentContext methods Returns the appropriate information for the current context
|
||||||
// Current Context holds labels for the approriate config objects
|
// Current Context holds labels for the approriate config objects
|
||||||
// Cluster is the name of the cluster for this context
|
|
||||||
// ClusterType is the name of the clustertype for this context, it should be a flag we pass to it??
|
// ClusterType is the name of the clustertype for this context, it should be a flag we pass to it??
|
||||||
// AuthInfo is the name of the authInfo for this context
|
|
||||||
// Manifest is the default manifest to be use with this context
|
// Manifest is the default manifest to be use with this context
|
||||||
// Purpose for this method is simplifying the current context information
|
// Purpose for this method is simplifying the current context information
|
||||||
func (c *Config) GetCurrentContext() (*Context, error) {
|
func (c *Config) GetCurrentContext() (*Context, error) {
|
||||||
@ -759,27 +418,6 @@ func (c *Config) GetCurrentContext() (*Context, error) {
|
|||||||
return currentContext, nil
|
return currentContext, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CurrentContextCluster returns the Cluster for the current context
|
|
||||||
func (c *Config) CurrentContextCluster() (*Cluster, error) {
|
|
||||||
currentContext, err := c.GetCurrentContext()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
clusterName := NewClusterComplexNameFromKubeClusterName(currentContext.KubeContext().Cluster)
|
|
||||||
|
|
||||||
return c.Clusters[clusterName.Name].ClusterTypes[currentContext.ClusterType()], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CurrentContextAuthInfo returns the AuthInfo for the current context
|
|
||||||
func (c *Config) CurrentContextAuthInfo() (*AuthInfo, error) {
|
|
||||||
currentContext, err := c.GetCurrentContext()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.AuthInfos[currentContext.KubeContext().AuthInfo], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CurrentContextManifest returns the manifest for the current context
|
// CurrentContextManifest returns the manifest for the current context
|
||||||
func (c *Config) CurrentContextManifest() (*Manifest, error) {
|
func (c *Config) CurrentContextManifest() (*Manifest, error) {
|
||||||
currentContext, err := c.GetCurrentContext()
|
currentContext, err := c.GetCurrentContext()
|
||||||
@ -798,10 +436,6 @@ func (c *Config) CurrentContextEntryPoint(phase string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ValidClusterType(clusterType)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
ccm, err := c.CurrentContextManifest()
|
ccm, err := c.CurrentContextManifest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -844,167 +478,6 @@ func (c *Config) CurrentContextClusterName() (string, error) {
|
|||||||
return context.ClusterName(), nil
|
return context.ClusterName(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAuthInfo returns an instance of authino
|
|
||||||
// Credential or AuthInfo related methods
|
|
||||||
func (c *Config) GetAuthInfo(aiName string) (*AuthInfo, error) {
|
|
||||||
authinfo, exists := c.AuthInfos[aiName]
|
|
||||||
if !exists {
|
|
||||||
return nil, ErrMissingConfig{What: fmt.Sprintf("User credentials with name '%s'", aiName)}
|
|
||||||
}
|
|
||||||
decodedAuthInfo, err := DecodeAuthInfo(authinfo.authInfo)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
authinfo.authInfo = decodedAuthInfo
|
|
||||||
return authinfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAuthInfos returns a slice containing all the AuthInfos associated with
|
|
||||||
// the Config sorted by name
|
|
||||||
func (c *Config) GetAuthInfos() ([]*AuthInfo, error) {
|
|
||||||
keys := make([]string, 0, len(c.AuthInfos))
|
|
||||||
for name := range c.AuthInfos {
|
|
||||||
keys = append(keys, name)
|
|
||||||
}
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
authInfos := make([]*AuthInfo, 0, len(c.AuthInfos))
|
|
||||||
for _, name := range keys {
|
|
||||||
decodedAuthInfo, err := DecodeAuthInfo(c.AuthInfos[name].authInfo)
|
|
||||||
if err != nil {
|
|
||||||
return []*AuthInfo{}, err
|
|
||||||
}
|
|
||||||
c.AuthInfos[name].authInfo = decodedAuthInfo
|
|
||||||
authInfos = append(authInfos, c.AuthInfos[name])
|
|
||||||
}
|
|
||||||
return authInfos, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddAuthInfo creates new AuthInfo with context details updated
|
|
||||||
// in the airship config and kube config
|
|
||||||
func (c *Config) AddAuthInfo(theAuthInfo *AuthInfoOptions) *AuthInfo {
|
|
||||||
// Create the new Airship config context
|
|
||||||
nAuthInfo := NewAuthInfo()
|
|
||||||
c.AuthInfos[theAuthInfo.Name] = nAuthInfo
|
|
||||||
// Create a new KubeConfig AuthInfo object as well
|
|
||||||
authInfo := clientcmdapi.NewAuthInfo()
|
|
||||||
nAuthInfo.authInfo = authInfo
|
|
||||||
c.KubeConfig().AuthInfos[theAuthInfo.Name] = authInfo
|
|
||||||
|
|
||||||
c.ModifyAuthInfo(nAuthInfo, theAuthInfo)
|
|
||||||
return nAuthInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// ModifyAuthInfo updates the AuthInfo in the Config object
|
|
||||||
func (c *Config) ModifyAuthInfo(authinfo *AuthInfo, theAuthInfo *AuthInfoOptions) {
|
|
||||||
kubeAuthInfo := EncodeAuthInfo(authinfo.KubeAuthInfo())
|
|
||||||
if kubeAuthInfo == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if theAuthInfo.ClientCertificate != "" {
|
|
||||||
kubeAuthInfo.ClientCertificate = EncodeString(theAuthInfo.ClientCertificate)
|
|
||||||
}
|
|
||||||
if theAuthInfo.Token != "" {
|
|
||||||
kubeAuthInfo.Token = EncodeString(theAuthInfo.Token)
|
|
||||||
}
|
|
||||||
if theAuthInfo.Username != "" {
|
|
||||||
kubeAuthInfo.Username = theAuthInfo.Username
|
|
||||||
}
|
|
||||||
if theAuthInfo.Password != "" {
|
|
||||||
kubeAuthInfo.Password = EncodeString(theAuthInfo.Password)
|
|
||||||
}
|
|
||||||
if theAuthInfo.ClientKey != "" {
|
|
||||||
kubeAuthInfo.ClientKey = EncodeString(theAuthInfo.ClientKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ImportFromKubeConfig absorbs the clusters, contexts and credentials from the
|
|
||||||
// given kubeConfig
|
|
||||||
func (c *Config) ImportFromKubeConfig(kubeConfigPath string) error {
|
|
||||||
_, err := os.Stat(kubeConfigPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
kubeConfig, err := clientcmd.LoadFromFile(kubeConfigPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.importClusters(kubeConfig)
|
|
||||||
c.importContexts(kubeConfig)
|
|
||||||
c.importAuthInfos(kubeConfig)
|
|
||||||
return c.PersistConfig(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) importClusters(importKubeConfig *clientcmdapi.Config) {
|
|
||||||
for clusterName, cluster := range importKubeConfig.Clusters {
|
|
||||||
clusterComplexName := NewClusterComplexNameFromKubeClusterName(clusterName)
|
|
||||||
if _, err := c.GetCluster(clusterComplexName.Name, clusterComplexName.Type); err == nil {
|
|
||||||
// err == nil implies that we were successfully able to
|
|
||||||
// get the cluster from the existing configuration.
|
|
||||||
// Since existing clusters takes precedence, skip this cluster
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the new cluster for the airship configuration
|
|
||||||
airshipCluster := NewCluster()
|
|
||||||
airshipCluster.NameInKubeconf = clusterComplexName.String()
|
|
||||||
// Store the reference to the KubeConfig Cluster in the Airship Config
|
|
||||||
airshipCluster.SetKubeCluster(cluster)
|
|
||||||
|
|
||||||
// Update the airship configuration
|
|
||||||
if _, ok := c.Clusters[clusterComplexName.Name]; !ok {
|
|
||||||
c.Clusters[clusterComplexName.Name] = NewClusterPurpose()
|
|
||||||
}
|
|
||||||
c.Clusters[clusterComplexName.Name].ClusterTypes[clusterComplexName.Type] = airshipCluster
|
|
||||||
c.kubeConfig.Clusters[clusterComplexName.String()] = cluster
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) importContexts(importKubeConfig *clientcmdapi.Config) {
|
|
||||||
// TODO(howell): This function doesn't handle the case when an incoming
|
|
||||||
// context refers to a cluster that doesn't exist in the airship
|
|
||||||
// configuration.
|
|
||||||
for kubeContextName, kubeContext := range importKubeConfig.Contexts {
|
|
||||||
if _, ok := c.kubeConfig.Contexts[kubeContextName]; ok {
|
|
||||||
// Since existing contexts take precedence, skip this context
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
clusterComplexName := NewClusterComplexNameFromKubeClusterName(kubeContext.Cluster)
|
|
||||||
if kubeContext.Cluster != clusterComplexName.String() {
|
|
||||||
// If the name of cluster from the kubeConfig doesn't
|
|
||||||
// match the clusterComplexName, it needs to be updated
|
|
||||||
kubeContext.Cluster = clusterComplexName.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
airshipContext, ok := c.Contexts[kubeContextName]
|
|
||||||
if !ok {
|
|
||||||
airshipContext = NewContext()
|
|
||||||
}
|
|
||||||
airshipContext.NameInKubeconf = kubeContext.Cluster
|
|
||||||
airshipContext.Manifest = AirshipDefaultManifest
|
|
||||||
airshipContext.SetKubeContext(kubeContext)
|
|
||||||
|
|
||||||
// Store the contexts in the airship configuration
|
|
||||||
c.Contexts[kubeContextName] = airshipContext
|
|
||||||
c.kubeConfig.Contexts[kubeContextName] = kubeContext
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) importAuthInfos(importKubeConfig *clientcmdapi.Config) {
|
|
||||||
for key, authinfo := range importKubeConfig.AuthInfos {
|
|
||||||
if _, ok := c.AuthInfos[key]; ok {
|
|
||||||
// Since existing credentials take precedence, skip this credential
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
c.AuthInfos[key] = NewAuthInfo()
|
|
||||||
c.AuthInfos[key].SetKubeAuthInfo(authinfo)
|
|
||||||
c.kubeConfig.AuthInfos[key] = authinfo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetManifests returns all of the Manifests associated with the Config sorted by name
|
// GetManifests returns all of the Manifests associated with the Config sorted by name
|
||||||
func (c *Config) GetManifests() []*Manifest {
|
func (c *Config) GetManifests() []*Manifest {
|
||||||
keys := make([]string, 0, len(c.Manifests))
|
keys := make([]string, 0, len(c.Manifests))
|
||||||
@ -1164,20 +637,20 @@ func (c *Config) ModifyEncryptionConfig(encryptionConfig *EncryptionConfig, opti
|
|||||||
|
|
||||||
// CurrentContextManagementConfig returns the management options for the current context
|
// CurrentContextManagementConfig returns the management options for the current context
|
||||||
func (c *Config) CurrentContextManagementConfig() (*ManagementConfiguration, error) {
|
func (c *Config) CurrentContextManagementConfig() (*ManagementConfiguration, error) {
|
||||||
currentCluster, err := c.CurrentContextCluster()
|
currentContext, err := c.GetCurrentContext()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if currentCluster.ManagementConfiguration == "" {
|
if currentContext.ManagementConfiguration == "" {
|
||||||
return nil, ErrMissingConfig{
|
return nil, ErrMissingConfig{
|
||||||
What: fmt.Sprintf("No management config listed for cluster %s", currentCluster.NameInKubeconf),
|
What: fmt.Sprintf("No management config listed for cluster %s", currentContext.NameInKubeconf),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
managementCfg, exists := c.ManagementConfiguration[currentCluster.ManagementConfiguration]
|
managementCfg, exists := c.ManagementConfiguration[currentContext.ManagementConfiguration]
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, ErrMissingManagementConfiguration{cluster: currentCluster}
|
return nil, ErrMissingManagementConfiguration{context: currentContext}
|
||||||
}
|
}
|
||||||
|
|
||||||
return managementCfg, nil
|
return managementCfg, nil
|
||||||
@ -1205,44 +678,3 @@ func (c *Config) CurrentContextManifestMetadata() (*Metadata, error) {
|
|||||||
}
|
}
|
||||||
return meta, nil
|
return meta, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeAuthInfo returns authInfo with credentials decoded
|
|
||||||
func DecodeAuthInfo(authinfo *clientcmdapi.AuthInfo) (*clientcmdapi.AuthInfo, error) {
|
|
||||||
password := authinfo.Password
|
|
||||||
decodedPassword, err := DecodeString(password)
|
|
||||||
if err != nil {
|
|
||||||
return nil, ErrDecodingCredentials{Given: password}
|
|
||||||
}
|
|
||||||
authinfo.Password = decodedPassword
|
|
||||||
|
|
||||||
token := authinfo.Token
|
|
||||||
decodedToken, err := DecodeString(token)
|
|
||||||
if err != nil {
|
|
||||||
return nil, ErrDecodingCredentials{Given: token}
|
|
||||||
}
|
|
||||||
authinfo.Token = decodedToken
|
|
||||||
|
|
||||||
clientCert := authinfo.ClientCertificate
|
|
||||||
decodedClientCertificate, err := DecodeString(clientCert)
|
|
||||||
if err != nil {
|
|
||||||
return nil, ErrDecodingCredentials{Given: clientCert}
|
|
||||||
}
|
|
||||||
authinfo.ClientCertificate = decodedClientCertificate
|
|
||||||
|
|
||||||
clientKey := authinfo.ClientKey
|
|
||||||
decodedClientKey, err := DecodeString(clientKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, ErrDecodingCredentials{Given: clientKey}
|
|
||||||
}
|
|
||||||
authinfo.ClientKey = decodedClientKey
|
|
||||||
return authinfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeAuthInfo returns authInfo with credentials base64 encoded
|
|
||||||
func EncodeAuthInfo(authinfo *clientcmdapi.AuthInfo) *clientcmdapi.AuthInfo {
|
|
||||||
authinfo.Password = EncodeString(authinfo.Password)
|
|
||||||
authinfo.Token = EncodeString(authinfo.Token)
|
|
||||||
authinfo.ClientCertificate = EncodeString(authinfo.ClientCertificate)
|
|
||||||
authinfo.ClientKey = EncodeString(authinfo.ClientKey)
|
|
||||||
return authinfo
|
|
||||||
}
|
|
||||||
|
@ -20,86 +20,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RunSetAuthInfo validates the given command line options and invokes AddAuthInfo/ModifyAuthInfo
|
|
||||||
func RunSetAuthInfo(o *AuthInfoOptions, airconfig *Config, writeToStorage bool) (bool, error) {
|
|
||||||
modified := false
|
|
||||||
err := o.Validate()
|
|
||||||
if err != nil {
|
|
||||||
return modified, err
|
|
||||||
}
|
|
||||||
|
|
||||||
authinfo, err := airconfig.GetAuthInfo(o.Name)
|
|
||||||
if err != nil {
|
|
||||||
var cerr ErrMissingConfig
|
|
||||||
if !errors.As(err, &cerr) {
|
|
||||||
// An error occurred, but it wasn't a "missing" config error.
|
|
||||||
return modified, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// authinfo didn't exist, create it
|
|
||||||
// ignoring the returned added authinfo
|
|
||||||
airconfig.AddAuthInfo(o)
|
|
||||||
} else {
|
|
||||||
// AuthInfo exists, lets update
|
|
||||||
airconfig.ModifyAuthInfo(authinfo, o)
|
|
||||||
modified = true
|
|
||||||
}
|
|
||||||
// Update configuration file just in time persistence approach
|
|
||||||
if writeToStorage {
|
|
||||||
if err := airconfig.PersistConfig(true); err != nil {
|
|
||||||
// Error that it didnt persist the changes
|
|
||||||
return modified, ErrConfigFailed{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return modified, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunSetCluster validates the given command line options and invokes AddCluster/ModifyCluster
|
|
||||||
func RunSetCluster(o *ClusterOptions, airconfig *Config, writeToStorage bool) (bool, error) {
|
|
||||||
modified := false
|
|
||||||
err := o.Validate()
|
|
||||||
if err != nil {
|
|
||||||
return modified, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cluster, err := airconfig.GetCluster(o.Name, o.ClusterType)
|
|
||||||
if err != nil {
|
|
||||||
var cerr ErrMissingConfig
|
|
||||||
if !errors.As(err, &cerr) {
|
|
||||||
// An error occurred, but it wasn't a "missing" config error.
|
|
||||||
return modified, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cluster didn't exist, create it
|
|
||||||
_, err := airconfig.AddCluster(o)
|
|
||||||
if err != nil {
|
|
||||||
return modified, err
|
|
||||||
}
|
|
||||||
modified = false
|
|
||||||
} else {
|
|
||||||
// Cluster exists, lets update
|
|
||||||
_, err := airconfig.ModifyCluster(cluster, o)
|
|
||||||
if err != nil {
|
|
||||||
return modified, err
|
|
||||||
}
|
|
||||||
modified = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update configuration file
|
|
||||||
// Just in time persistence approach
|
|
||||||
if writeToStorage {
|
|
||||||
if err := airconfig.PersistConfig(true); err != nil {
|
|
||||||
// Some warning here , that it didnt persist the changes because of this
|
|
||||||
// Or should we float this up
|
|
||||||
// What would it mean? No value.
|
|
||||||
return modified, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return modified, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunSetContext validates the given command line options and invokes AddContext/ModifyContext
|
// RunSetContext validates the given command line options and invokes AddContext/ModifyContext
|
||||||
func RunSetContext(o *ContextOptions, airconfig *Config, writeToStorage bool) (bool, error) {
|
func RunSetContext(o *ContextOptions, airconfig *Config, writeToStorage bool) (bool, error) {
|
||||||
modified := false
|
modified := false
|
||||||
|
@ -25,61 +25,6 @@ import (
|
|||||||
"opendev.org/airship/airshipctl/testutil"
|
"opendev.org/airship/airshipctl/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRunSetAuthInfo(t *testing.T) {
|
|
||||||
t.Run("testAddAuthInfo", func(t *testing.T) {
|
|
||||||
conf := testutil.DummyConfig()
|
|
||||||
dummyAuthInfoOptions := testutil.DummyAuthInfoOptions()
|
|
||||||
dummyAuthInfoOptions.Name = "second_user"
|
|
||||||
dummyAuthInfoOptions.Token = ""
|
|
||||||
|
|
||||||
modified, err := config.RunSetAuthInfo(dummyAuthInfoOptions, conf, false)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.False(t, modified)
|
|
||||||
assert.Contains(t, conf.AuthInfos, "second_user")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("testModifyAuthInfo", func(t *testing.T) {
|
|
||||||
conf := testutil.DummyConfig()
|
|
||||||
dummyAuthInfoOptions := testutil.DummyAuthInfoOptions()
|
|
||||||
dummyAuthInfoOptions.Name = "dummy_user"
|
|
||||||
dummyAuthInfoOptions.Password = "testpassword123"
|
|
||||||
dummyAuthInfoOptions.Token = ""
|
|
||||||
|
|
||||||
modified, err := config.RunSetAuthInfo(dummyAuthInfoOptions, conf, false)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.True(t, modified)
|
|
||||||
authInfo, err := conf.GetAuthInfo("dummy_user")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, dummyAuthInfoOptions.Password, authInfo.KubeAuthInfo().Password)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRunSetCluster(t *testing.T) {
|
|
||||||
t.Run("testAddCluster", func(t *testing.T) {
|
|
||||||
conf := testutil.DummyConfig()
|
|
||||||
dummyClusterOptions := testutil.DummyClusterOptions()
|
|
||||||
dummyClusterOptions.Name = "second_cluster"
|
|
||||||
|
|
||||||
modified, err := config.RunSetCluster(dummyClusterOptions, conf, false)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.False(t, modified)
|
|
||||||
assert.Contains(t, conf.Clusters, "second_cluster")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("testModifyCluster", func(t *testing.T) {
|
|
||||||
conf := testutil.DummyConfig()
|
|
||||||
dummyClusterOptions := testutil.DummyClusterOptions()
|
|
||||||
dummyClusterOptions.Server = "http://123.45.67.890"
|
|
||||||
|
|
||||||
modified, err := config.RunSetCluster(dummyClusterOptions, conf, false)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.True(t, modified)
|
|
||||||
assert.Equal(
|
|
||||||
t, "http://123.45.67.890",
|
|
||||||
conf.Clusters["dummy_cluster"].ClusterTypes["ephemeral"].KubeCluster().Server)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRunSetContext(t *testing.T) {
|
func TestRunSetContext(t *testing.T) {
|
||||||
t.Run("testAddContext", func(t *testing.T) {
|
t.Run("testAddContext", func(t *testing.T) {
|
||||||
conf := testutil.DummyConfig()
|
conf := testutil.DummyConfig()
|
||||||
@ -95,12 +40,10 @@ func TestRunSetContext(t *testing.T) {
|
|||||||
t.Run("testModifyContext", func(t *testing.T) {
|
t.Run("testModifyContext", func(t *testing.T) {
|
||||||
conf := testutil.DummyConfig()
|
conf := testutil.DummyConfig()
|
||||||
dummyContextOptions := testutil.DummyContextOptions()
|
dummyContextOptions := testutil.DummyContextOptions()
|
||||||
dummyContextOptions.Namespace = "new_namespace"
|
|
||||||
|
|
||||||
modified, err := config.RunSetContext(dummyContextOptions, conf, false)
|
modified, err := config.RunSetContext(dummyContextOptions, conf, false)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, modified)
|
assert.True(t, modified)
|
||||||
assert.Equal(t, "new_namespace", conf.Contexts["dummy_context"].KubeContext().Namespace)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,9 +18,7 @@ package config_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -35,10 +33,6 @@ const (
|
|||||||
stringDelta = "_changed"
|
stringDelta = "_changed"
|
||||||
currentContextName = "def_ephemeral"
|
currentContextName = "def_ephemeral"
|
||||||
defaultString = "default"
|
defaultString = "default"
|
||||||
newToken = "dummy_token_changed"
|
|
||||||
newPassword = "dummy_password_changed"
|
|
||||||
newCertificate = "dummy_certificate_changed"
|
|
||||||
newKey = "dummy_key_changed"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestString(t *testing.T) {
|
func TestString(t *testing.T) {
|
||||||
@ -56,14 +50,6 @@ func TestString(t *testing.T) {
|
|||||||
name: "context",
|
name: "context",
|
||||||
stringer: testutil.DummyContext(),
|
stringer: testutil.DummyContext(),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "cluster",
|
|
||||||
stringer: testutil.DummyCluster(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "authinfo",
|
|
||||||
stringer: testutil.DummyAuthInfo(),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "manifest",
|
name: "manifest",
|
||||||
stringer: testutil.DummyManifest(),
|
stringer: testutil.DummyManifest(),
|
||||||
@ -106,11 +92,7 @@ func TestLoadConfig(t *testing.T) {
|
|||||||
conf, cleanup := testutil.InitConfig(t)
|
conf, cleanup := testutil.InitConfig(t)
|
||||||
defer cleanup(t)
|
defer cleanup(t)
|
||||||
|
|
||||||
assert.Len(t, conf.Clusters, 6)
|
assert.Len(t, conf.Contexts, 4)
|
||||||
require.Contains(t, conf.Clusters, "def")
|
|
||||||
assert.Len(t, conf.Clusters["def"].ClusterTypes, 2)
|
|
||||||
assert.Len(t, conf.Contexts, 3)
|
|
||||||
assert.Len(t, conf.AuthInfos, 3)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPersistConfig(t *testing.T) {
|
func TestPersistConfig(t *testing.T) {
|
||||||
@ -124,13 +106,7 @@ func TestPersistConfig(t *testing.T) {
|
|||||||
assert.FileExists(t, conf.LoadedConfigPath())
|
assert.FileExists(t, conf.LoadedConfigPath())
|
||||||
assert.FileExists(t, conf.KubeConfigPath())
|
assert.FileExists(t, conf.KubeConfigPath())
|
||||||
// Check that the invalid name was changed to a valid one
|
// Check that the invalid name was changed to a valid one
|
||||||
assert.Contains(t, conf.KubeConfig().Clusters, "invalidName_target")
|
assert.Contains(t, conf.KubeConfig().Clusters, "def_ephemeral")
|
||||||
|
|
||||||
// Check that the missing cluster was added to the airshipconfig
|
|
||||||
assert.Contains(t, conf.Clusters, "onlyinkubeconf")
|
|
||||||
|
|
||||||
// Check that the "stragglers" were removed from the airshipconfig
|
|
||||||
assert.NotContains(t, conf.Clusters, "straggler")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnsureComplete(t *testing.T) {
|
func TestEnsureComplete(t *testing.T) {
|
||||||
@ -143,33 +119,9 @@ func TestEnsureComplete(t *testing.T) {
|
|||||||
config config.Config
|
config config.Config
|
||||||
expectedErr error
|
expectedErr error
|
||||||
}{
|
}{
|
||||||
{
|
|
||||||
name: "no clusters defined",
|
|
||||||
config: config.Config{
|
|
||||||
Clusters: map[string]*config.ClusterPurpose{},
|
|
||||||
AuthInfos: map[string]*config.AuthInfo{"testAuthInfo": {}},
|
|
||||||
Contexts: map[string]*config.Context{"testContext": {Manifest: "testManifest"}},
|
|
||||||
Manifests: map[string]*config.Manifest{"testManifest": {}},
|
|
||||||
CurrentContext: "testContext",
|
|
||||||
},
|
|
||||||
expectedErr: config.ErrMissingConfig{What: "At least one cluster needs to be defined"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "no users defined",
|
|
||||||
config: config.Config{
|
|
||||||
Clusters: map[string]*config.ClusterPurpose{"testCluster": {}},
|
|
||||||
AuthInfos: map[string]*config.AuthInfo{},
|
|
||||||
Contexts: map[string]*config.Context{"testContext": {Manifest: "testManifest"}},
|
|
||||||
Manifests: map[string]*config.Manifest{"testManifest": {}},
|
|
||||||
CurrentContext: "testContext",
|
|
||||||
},
|
|
||||||
expectedErr: config.ErrMissingConfig{What: "At least one Authentication Information (User) needs to be defined"},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "no contexts defined",
|
name: "no contexts defined",
|
||||||
config: config.Config{
|
config: config.Config{
|
||||||
Clusters: map[string]*config.ClusterPurpose{"testCluster": {}},
|
|
||||||
AuthInfos: map[string]*config.AuthInfo{"testAuthInfo": {}},
|
|
||||||
Contexts: map[string]*config.Context{},
|
Contexts: map[string]*config.Context{},
|
||||||
Manifests: map[string]*config.Manifest{"testManifest": {}},
|
Manifests: map[string]*config.Manifest{"testManifest": {}},
|
||||||
CurrentContext: "testContext",
|
CurrentContext: "testContext",
|
||||||
@ -179,8 +131,6 @@ func TestEnsureComplete(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "no manifests defined",
|
name: "no manifests defined",
|
||||||
config: config.Config{
|
config: config.Config{
|
||||||
Clusters: map[string]*config.ClusterPurpose{"testCluster": {}},
|
|
||||||
AuthInfos: map[string]*config.AuthInfo{"testAuthInfo": {}},
|
|
||||||
Contexts: map[string]*config.Context{"testContext": {Manifest: "testManifest"}},
|
Contexts: map[string]*config.Context{"testContext": {Manifest: "testManifest"}},
|
||||||
Manifests: map[string]*config.Manifest{},
|
Manifests: map[string]*config.Manifest{},
|
||||||
CurrentContext: "testContext",
|
CurrentContext: "testContext",
|
||||||
@ -190,8 +140,6 @@ func TestEnsureComplete(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "current context not defined",
|
name: "current context not defined",
|
||||||
config: config.Config{
|
config: config.Config{
|
||||||
Clusters: map[string]*config.ClusterPurpose{"testCluster": {}},
|
|
||||||
AuthInfos: map[string]*config.AuthInfo{"testAuthInfo": {}},
|
|
||||||
Contexts: map[string]*config.Context{"testContext": {Manifest: "testManifest"}},
|
Contexts: map[string]*config.Context{"testContext": {Manifest: "testManifest"}},
|
||||||
Manifests: map[string]*config.Manifest{"testManifest": {}},
|
Manifests: map[string]*config.Manifest{"testManifest": {}},
|
||||||
CurrentContext: "",
|
CurrentContext: "",
|
||||||
@ -201,8 +149,6 @@ func TestEnsureComplete(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "no context for current context",
|
name: "no context for current context",
|
||||||
config: config.Config{
|
config: config.Config{
|
||||||
Clusters: map[string]*config.ClusterPurpose{"testCluster": {}},
|
|
||||||
AuthInfos: map[string]*config.AuthInfo{"testAuthInfo": {}},
|
|
||||||
Contexts: map[string]*config.Context{"DIFFERENT_CONTEXT": {Manifest: "testManifest"}},
|
Contexts: map[string]*config.Context{"DIFFERENT_CONTEXT": {Manifest: "testManifest"}},
|
||||||
Manifests: map[string]*config.Manifest{"testManifest": {}},
|
Manifests: map[string]*config.Manifest{"testManifest": {}},
|
||||||
CurrentContext: "testContext",
|
CurrentContext: "testContext",
|
||||||
@ -212,8 +158,6 @@ func TestEnsureComplete(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "no manifest for current context",
|
name: "no manifest for current context",
|
||||||
config: config.Config{
|
config: config.Config{
|
||||||
Clusters: map[string]*config.ClusterPurpose{"testCluster": {}},
|
|
||||||
AuthInfos: map[string]*config.AuthInfo{"testAuthInfo": {}},
|
|
||||||
Contexts: map[string]*config.Context{"testContext": {Manifest: "testManifest"}},
|
Contexts: map[string]*config.Context{"testContext": {Manifest: "testManifest"}},
|
||||||
Manifests: map[string]*config.Manifest{"DIFFERENT_MANIFEST": {}},
|
Manifests: map[string]*config.Manifest{"DIFFERENT_MANIFEST": {}},
|
||||||
CurrentContext: "testContext",
|
CurrentContext: "testContext",
|
||||||
@ -223,11 +167,9 @@ func TestEnsureComplete(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "complete config",
|
name: "complete config",
|
||||||
config: config.Config{
|
config: config.Config{
|
||||||
Clusters: map[string]*config.ClusterPurpose{"testCluster": {}},
|
EncryptionConfigs: map[string]*config.EncryptionConfig{"testEncryptionConfig": {}},
|
||||||
AuthInfos: map[string]*config.AuthInfo{"testAuthInfo": {}},
|
|
||||||
Contexts: map[string]*config.Context{"testContext": {Manifest: "testManifest"}},
|
Contexts: map[string]*config.Context{"testContext": {Manifest: "testManifest"}},
|
||||||
Manifests: map[string]*config.Manifest{"testManifest": {}},
|
Manifests: map[string]*config.Manifest{"testManifest": {}},
|
||||||
EncryptionConfigs: map[string]*config.EncryptionConfig{"testEncryptionConfig": {}},
|
|
||||||
CurrentContext: "testContext",
|
CurrentContext: "testContext",
|
||||||
},
|
},
|
||||||
expectedErr: nil,
|
expectedErr: nil,
|
||||||
@ -247,17 +189,13 @@ func TestCurrentContextManagementConfig(t *testing.T) {
|
|||||||
conf, cleanup := testutil.InitConfig(t)
|
conf, cleanup := testutil.InitConfig(t)
|
||||||
defer cleanup(t)
|
defer cleanup(t)
|
||||||
|
|
||||||
clusterName := "def"
|
|
||||||
clusterType := "ephemeral"
|
|
||||||
|
|
||||||
managementConfig, err := conf.CurrentContextManagementConfig()
|
managementConfig, err := conf.CurrentContextManagementConfig()
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Nil(t, managementConfig)
|
assert.Nil(t, managementConfig)
|
||||||
|
|
||||||
conf.CurrentContext = currentContextName
|
conf.CurrentContext = currentContextName
|
||||||
conf.Clusters[clusterName].ClusterTypes[clusterType].ManagementConfiguration = defaultString
|
conf.Contexts[currentContextName].ManagementConfiguration = defaultString
|
||||||
conf.Contexts[currentContextName].Manifest = defaultString
|
conf.Contexts[currentContextName].Manifest = defaultString
|
||||||
conf.Contexts[currentContextName].KubeContext().Cluster = clusterName
|
|
||||||
|
|
||||||
managementConfig, err = conf.CurrentContextManagementConfig()
|
managementConfig, err = conf.CurrentContextManagementConfig()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -308,42 +246,12 @@ func TestSetKubeConfigPath(t *testing.T) {
|
|||||||
assert.Equal(t, testPath, conf.KubeConfigPath())
|
assert.Equal(t, testPath, conf.KubeConfigPath())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestModifyCluster(t *testing.T) {
|
|
||||||
conf, cleanup := testutil.InitConfig(t)
|
|
||||||
defer cleanup(t)
|
|
||||||
|
|
||||||
co := testutil.DummyClusterOptions()
|
|
||||||
cluster, err := conf.AddCluster(co)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
co.Server += stringDelta
|
|
||||||
co.InsecureSkipTLSVerify = true
|
|
||||||
co.EmbedCAData = true
|
|
||||||
mcluster, err := conf.ModifyCluster(cluster, co)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.EqualValues(t, conf.Clusters[co.Name].ClusterTypes[co.ClusterType].KubeCluster().Server, co.Server)
|
|
||||||
assert.EqualValues(t, conf.Clusters[co.Name].ClusterTypes[co.ClusterType], mcluster)
|
|
||||||
|
|
||||||
// Error case
|
|
||||||
co.CertificateAuthority = "unknown"
|
|
||||||
_, err = conf.ModifyCluster(cluster, co)
|
|
||||||
assert.Error(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetClusters(t *testing.T) {
|
|
||||||
conf, cleanup := testutil.InitConfig(t)
|
|
||||||
defer cleanup(t)
|
|
||||||
|
|
||||||
clusters := conf.GetClusters()
|
|
||||||
assert.Len(t, clusters, 6)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetContexts(t *testing.T) {
|
func TestGetContexts(t *testing.T) {
|
||||||
conf, cleanup := testutil.InitConfig(t)
|
conf, cleanup := testutil.InitConfig(t)
|
||||||
defer cleanup(t)
|
defer cleanup(t)
|
||||||
|
|
||||||
contexts := conf.GetContexts()
|
contexts := conf.GetContexts()
|
||||||
assert.Len(t, contexts, 3)
|
assert.Len(t, contexts, 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetContext(t *testing.T) {
|
func TestGetContext(t *testing.T) {
|
||||||
@ -355,7 +263,6 @@ func TestGetContext(t *testing.T) {
|
|||||||
|
|
||||||
// Test Positives
|
// Test Positives
|
||||||
assert.EqualValues(t, context.NameInKubeconf, "def_ephemeral")
|
assert.EqualValues(t, context.NameInKubeconf, "def_ephemeral")
|
||||||
assert.EqualValues(t, context.KubeContext().Cluster, "def_ephemeral")
|
|
||||||
|
|
||||||
// Test Wrong Cluster
|
// Test Wrong Cluster
|
||||||
_, err = conf.GetContext("unknown")
|
_, err = conf.GetContext("unknown")
|
||||||
@ -378,14 +285,8 @@ func TestModifyContext(t *testing.T) {
|
|||||||
co := testutil.DummyContextOptions()
|
co := testutil.DummyContextOptions()
|
||||||
context := conf.AddContext(co)
|
context := conf.AddContext(co)
|
||||||
|
|
||||||
co.Namespace += stringDelta
|
|
||||||
co.Cluster += stringDelta
|
|
||||||
co.AuthInfo += stringDelta
|
|
||||||
co.Manifest += stringDelta
|
co.Manifest += stringDelta
|
||||||
conf.ModifyContext(context, co)
|
conf.ModifyContext(context, co)
|
||||||
assert.EqualValues(t, conf.Contexts[co.Name].KubeContext().Namespace, co.Namespace)
|
|
||||||
assert.EqualValues(t, conf.Contexts[co.Name].KubeContext().Cluster, co.Cluster)
|
|
||||||
assert.EqualValues(t, conf.Contexts[co.Name].KubeContext().AuthInfo, co.AuthInfo)
|
|
||||||
assert.EqualValues(t, conf.Contexts[co.Name].Manifest, co.Manifest)
|
assert.EqualValues(t, conf.Contexts[co.Name].Manifest, co.Manifest)
|
||||||
assert.EqualValues(t, conf.Contexts[co.Name], context)
|
assert.EqualValues(t, conf.Contexts[co.Name], context)
|
||||||
}
|
}
|
||||||
@ -408,55 +309,16 @@ func TestGetCurrentContext(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCurrentContextCluster(t *testing.T) {
|
|
||||||
conf, cleanup := testutil.InitConfig(t)
|
|
||||||
defer cleanup(t)
|
|
||||||
|
|
||||||
clusterName := "def"
|
|
||||||
clusterType := "ephemeral"
|
|
||||||
|
|
||||||
cluster, err := conf.CurrentContextCluster()
|
|
||||||
require.Error(t, err)
|
|
||||||
assert.Nil(t, cluster)
|
|
||||||
|
|
||||||
conf.CurrentContext = currentContextName
|
|
||||||
conf.Contexts[currentContextName].Manifest = defaultString
|
|
||||||
conf.Contexts[currentContextName].KubeContext().Cluster = clusterName
|
|
||||||
|
|
||||||
cluster, err = conf.CurrentContextCluster()
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, conf.Clusters[clusterName].ClusterTypes[clusterType], cluster)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCurrentContextAuthInfo(t *testing.T) {
|
|
||||||
conf, cleanup := testutil.InitConfig(t)
|
|
||||||
defer cleanup(t)
|
|
||||||
|
|
||||||
authInfo, err := conf.CurrentContextAuthInfo()
|
|
||||||
require.Error(t, err)
|
|
||||||
assert.Nil(t, authInfo)
|
|
||||||
|
|
||||||
conf.CurrentContext = currentContextName
|
|
||||||
conf.Contexts[currentContextName].Manifest = defaultString
|
|
||||||
|
|
||||||
authInfo, err = conf.CurrentContextAuthInfo()
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, conf.AuthInfos["k-admin"], authInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCurrentContextManifest(t *testing.T) {
|
func TestCurrentContextManifest(t *testing.T) {
|
||||||
conf, cleanup := testutil.InitConfig(t)
|
conf, cleanup := testutil.InitConfig(t)
|
||||||
defer cleanup(t)
|
defer cleanup(t)
|
||||||
|
|
||||||
clusterName := "def"
|
|
||||||
|
|
||||||
manifest, err := conf.CurrentContextManifest()
|
manifest, err := conf.CurrentContextManifest()
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Nil(t, manifest)
|
assert.Nil(t, manifest)
|
||||||
|
|
||||||
conf.CurrentContext = currentContextName
|
conf.CurrentContext = currentContextName
|
||||||
conf.Contexts[currentContextName].Manifest = defaultString
|
conf.Contexts[currentContextName].Manifest = defaultString
|
||||||
conf.Contexts[currentContextName].KubeContext().Cluster = clusterName
|
|
||||||
|
|
||||||
manifest, err = conf.CurrentContextManifest()
|
manifest, err = conf.CurrentContextManifest()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -467,15 +329,12 @@ func TestCurrentTargetPath(t *testing.T) {
|
|||||||
conf, cleanup := testutil.InitConfig(t)
|
conf, cleanup := testutil.InitConfig(t)
|
||||||
defer cleanup(t)
|
defer cleanup(t)
|
||||||
|
|
||||||
clusterName := "def"
|
|
||||||
|
|
||||||
manifest, err := conf.CurrentContextManifest()
|
manifest, err := conf.CurrentContextManifest()
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Nil(t, manifest)
|
assert.Nil(t, manifest)
|
||||||
|
|
||||||
conf.CurrentContext = currentContextName
|
conf.CurrentContext = currentContextName
|
||||||
conf.Contexts[currentContextName].Manifest = defaultString
|
conf.Contexts[currentContextName].Manifest = defaultString
|
||||||
conf.Contexts[currentContextName].KubeContext().Cluster = clusterName
|
|
||||||
|
|
||||||
targetPath, err := conf.CurrentContextTargetPath()
|
targetPath, err := conf.CurrentContextTargetPath()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -486,15 +345,12 @@ func TestCurrentContextEntryPoint(t *testing.T) {
|
|||||||
conf, cleanup := testutil.InitConfig(t)
|
conf, cleanup := testutil.InitConfig(t)
|
||||||
defer cleanup(t)
|
defer cleanup(t)
|
||||||
|
|
||||||
clusterName := "def"
|
|
||||||
|
|
||||||
entryPoint, err := conf.CurrentContextEntryPoint(defaultString)
|
entryPoint, err := conf.CurrentContextEntryPoint(defaultString)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Equal(t, "", entryPoint)
|
assert.Equal(t, "", entryPoint)
|
||||||
|
|
||||||
conf.CurrentContext = currentContextName
|
conf.CurrentContext = currentContextName
|
||||||
conf.Contexts[currentContextName].Manifest = defaultString
|
conf.Contexts[currentContextName].Manifest = defaultString
|
||||||
conf.Contexts[currentContextName].KubeContext().Cluster = clusterName
|
|
||||||
|
|
||||||
entryPoint, err = conf.CurrentContextEntryPoint(defaultString)
|
entryPoint, err = conf.CurrentContextEntryPoint(defaultString)
|
||||||
assert.Equal(t, config.ErrMissingPhaseDocument{PhaseName: defaultString}, err)
|
assert.Equal(t, config.ErrMissingPhaseDocument{PhaseName: defaultString}, err)
|
||||||
@ -661,144 +517,6 @@ func TestNewClusterComplexNameFromKubeClusterName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestImport(t *testing.T) {
|
|
||||||
conf, cleanupConfig := testutil.InitConfig(t)
|
|
||||||
defer cleanupConfig(t)
|
|
||||||
|
|
||||||
kubeDir, cleanupKubeConfig := testutil.TempDir(t, "airship-import-tests")
|
|
||||||
defer cleanupKubeConfig(t)
|
|
||||||
|
|
||||||
kubeConfigPath := filepath.Join(kubeDir, "config")
|
|
||||||
//nolint: lll
|
|
||||||
kubeConfigContent := `
|
|
||||||
apiVersion: v1
|
|
||||||
clusters:
|
|
||||||
- cluster:
|
|
||||||
server: https://1.2.3.4:9000
|
|
||||||
name: cluster_target
|
|
||||||
- cluster:
|
|
||||||
server: https://1.2.3.4:9001
|
|
||||||
name: dummycluster_ephemeral
|
|
||||||
- cluster:
|
|
||||||
server: https://1.2.3.4:9002
|
|
||||||
name: def_target
|
|
||||||
- cluster:
|
|
||||||
server: https://1.2.3.4:9003
|
|
||||||
name: noncomplex
|
|
||||||
contexts:
|
|
||||||
- context:
|
|
||||||
cluster: cluster_target
|
|
||||||
user: cluster-admin
|
|
||||||
name: cluster-admin@cluster
|
|
||||||
- context:
|
|
||||||
cluster: dummycluster_ephemeral
|
|
||||||
user: kubernetes-admin
|
|
||||||
name: dummy_cluster
|
|
||||||
- context:
|
|
||||||
cluster: dummycluster_ephemeral
|
|
||||||
user: kubernetes-admin
|
|
||||||
name: def_target
|
|
||||||
- context:
|
|
||||||
cluster: noncomplex
|
|
||||||
user: kubernetes-admin
|
|
||||||
name: noncomplex
|
|
||||||
current-context: dummy_cluster
|
|
||||||
kind: Config
|
|
||||||
preferences: {}
|
|
||||||
users:
|
|
||||||
- name: cluster-admin
|
|
||||||
user:
|
|
||||||
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4akNDQWRxZ0F3SUJBZ0lJQXhEdzk2RUY4SXN3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB4T1RBNU1qa3hOekF6TURsYUZ3MHlNREE1TWpneE56QXpNVEphTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXV6R0pZdlBaNkRvaTQyMUQKSzhXSmFaQ25OQWQycXo1cC8wNDJvRnpRUGJyQWd6RTJxWVZrek9MOHhBVmVSN1NONXdXb1RXRXlGOEVWN3JyLwo0K0hoSEdpcTVQbXF1SUZ5enpuNi9JWmM4alU5eEVmenZpa2NpckxmVTR2UlhKUXdWd2dBU05sMkFXQUloMmRECmRUcmpCQ2ZpS1dNSHlqMFJiSGFsc0J6T3BnVC9IVHYzR1F6blVRekZLdjJkajVWMU5rUy9ESGp5UlJKK0VMNlEKQlltR3NlZzVQNE5iQzllYnVpcG1NVEFxL0p1bU9vb2QrRmpMMm5acUw2Zkk2ZkJ0RjVPR2xwQ0IxWUo4ZnpDdApHUVFaN0hUSWJkYjJ0cDQzRlZPaHlRYlZjSHFUQTA0UEoxNSswV0F5bVVKVXo4WEE1NDRyL2J2NzRKY0pVUkZoCmFyWmlRd0lEQVFBQm95Y3dKVEFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFMMmhIUmVibEl2VHJTMFNmUVg1RG9ueVVhNy84aTg1endVWApSd3dqdzFuS0U0NDJKbWZWRGZ5b0hRYUM4Ti9MQkxyUXM0U0lqU1JYdmFHU1dSQnRnT1RRV21Db1laMXdSbjdwCndDTXZQTERJdHNWWm90SEZpUFl2b1lHWFFUSXA3YlROMmg1OEJaaEZ3d25nWUovT04zeG1rd29IN1IxYmVxWEYKWHF1TTluekhESk41VlZub1lQR09yRHMwWlg1RnNxNGtWVU0wVExNQm9qN1ZIRDhmU0E5RjRYNU4yMldsZnNPMAo4aksrRFJDWTAyaHBrYTZQQ0pQS0lNOEJaMUFSMG9ZakZxT0plcXpPTjBqcnpYWHh4S2pHVFVUb1BldVA5dCtCCjJOMVA1TnI4a2oxM0lrend5Q1NZclFVN09ZM3ltZmJobHkrcXZxaFVFa014MlQ1SkpmQT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
|
|
||||||
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBdXpHSll2UFo2RG9pNDIxREs4V0phWkNuTkFkMnF6NXAvMDQyb0Z6UVBickFnekUyCnFZVmt6T0w4eEFWZVI3U041d1dvVFdFeUY4RVY3cnIvNCtIaEhHaXE1UG1xdUlGeXp6bjYvSVpjOGpVOXhFZnoKdmlrY2lyTGZVNHZSWEpRd1Z3Z0FTTmwyQVdBSWgyZERkVHJqQkNmaUtXTUh5ajBSYkhhbHNCek9wZ1QvSFR2MwpHUXpuVVF6Rkt2MmRqNVYxTmtTL0RIanlSUkorRUw2UUJZbUdzZWc1UDROYkM5ZWJ1aXBtTVRBcS9KdW1Pb29kCitGakwyblpxTDZmSTZmQnRGNU9HbHBDQjFZSjhmekN0R1FRWjdIVEliZGIydHA0M0ZWT2h5UWJWY0hxVEEwNFAKSjE1KzBXQXltVUpVejhYQTU0NHIvYnY3NEpjSlVSRmhhclppUXdJREFRQUJBb0lCQVFDU0pycjlaeVpiQ2dqegpSL3VKMFZEWCt2aVF4c01BTUZyUjJsOE1GV3NBeHk1SFA4Vk4xYmc5djN0YUVGYnI1U3hsa3lVMFJRNjNQU25DCm1uM3ZqZ3dVQWlScllnTEl5MGk0UXF5VFBOU1V4cnpTNHRxTFBjM3EvSDBnM2FrNGZ2cSsrS0JBUUlqQnloamUKbnVFc1JpMjRzT3NESlM2UDE5NGlzUC9yNEpIM1M5bFZGbkVuOGxUR2c0M1kvMFZoMXl0cnkvdDljWjR5ZUNpNwpjMHFEaTZZcXJZaFZhSW9RRW1VQjdsbHRFZkZzb3l4VDR6RTE5U3pVbkRoMmxjYTF1TzhqcmI4d2xHTzBoQ2JyClB1R1l2WFFQa3Q0VlNmalhvdGJ3d2lBNFRCVERCRzU1bHp6MmNKeS9zSS8zSHlYbEMxcTdXUmRuQVhhZ1F0VzkKOE9DZGRkb0JBb0dCQU5NcUNtSW94REtyckhZZFRxT1M1ZFN4cVMxL0NUN3ZYZ0pScXBqd2Y4WHA2WHo0KzIvTAozVXFaVDBEL3dGTkZkc1Z4eFYxMnNYMUdwMHFWZVlKRld5OVlCaHVSWGpTZ0ZEWldSY1Z1Y01sNVpPTmJsbmZGCjVKQ0xnNXFMZ1g5VTNSRnJrR3A0R241UDQxamg4TnhKVlhzZG5xWE9xNTFUK1RRT1UzdkpGQjc1QW9HQkFPTHcKalp1cnZtVkZyTHdaVGgvRDNpWll5SVV0ZUljZ2NKLzlzbTh6L0pPRmRIbFd4dGRHUFVzYVd1MnBTNEhvckFtbgpqTm4vSTluUXd3enZ3MWUzVVFPbUhMRjVBczk4VU5hbk5TQ0xNMW1yaXZHRXJ1VHFnTDM1bU41eFZPdTUxQU5JCm4yNkFtODBJT2JDeEtLa0R0ZXJSaFhHd3g5c1pONVJCbG9VRThZNGJBb0dBQ3ZsdVhMZWRxcng5VkE0bDNoNXUKVDJXRVUxYjgxZ1orcmtRc1I1S0lNWEw4cllBTElUNUpHKzFuendyN3BkaEFXZmFWdVV2SDRhamdYT0h6MUs5aQpFODNSVTNGMG9ldUg0V01PY1RwU0prWm0xZUlXcWRiaEVCb1FGdUlWTXRib1BsV0d4ZUhFRHJoOEtreGp4aThSCmdEcUQyajRwY1IzQ0g5QjJ5a0lqQjVFQ2dZRUExc0xXLys2enE1c1lNSm14K1JXZThhTXJmL3pjQnVTSU1LQWgKY0dNK0wwMG9RSHdDaUU4TVNqcVN1ajV3R214YUFuanhMb3ZwSFlRV1VmUEVaUW95UE1YQ2VhRVBLOU4xbk8xMwp0V2lHRytIZkIxaU5PazFCc0lhNFNDbndOM1FRVTFzeXBaeEgxT3hueS9LYmkvYmEvWEZ5VzNqMGFUK2YvVWxrCmJGV1ZVdWtDZ1lFQTBaMmRTTFlmTjV5eFNtYk5xMWVqZXdWd1BjRzQxR2hQclNUZEJxdHFac1doWGE3aDdLTWEKeHdvamh5SXpnTXNyK2tXODdlajhDQ2h0d21sQ1p5QU92QmdOZytncnJ1cEZLM3FOSkpKeU9YREdHckdpbzZmTQp5aXB3Q2tZVGVxRThpZ1J6UkI5QkdFUGY4eVpjMUtwdmZhUDVhM0lRZmxiV0czbGpUemNNZVZjPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
|
|
||||||
- name: kubernetes-admin
|
|
||||||
user:
|
|
||||||
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4akNDQWRxZ0F3SUJBZ0lJQXhEdzk2RUY4SXN3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB4T1RBNU1qa3hOekF6TURsYUZ3MHlNREE1TWpneE56QXpNVEphTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXV6R0pZdlBaNkRvaTQyMUQKSzhXSmFaQ25OQWQycXo1cC8wNDJvRnpRUGJyQWd6RTJxWVZrek9MOHhBVmVSN1NONXdXb1RXRXlGOEVWN3JyLwo0K0hoSEdpcTVQbXF1SUZ5enpuNi9JWmM4alU5eEVmenZpa2NpckxmVTR2UlhKUXdWd2dBU05sMkFXQUloMmRECmRUcmpCQ2ZpS1dNSHlqMFJiSGFsc0J6T3BnVC9IVHYzR1F6blVRekZLdjJkajVWMU5rUy9ESGp5UlJKK0VMNlEKQlltR3NlZzVQNE5iQzllYnVpcG1NVEFxL0p1bU9vb2QrRmpMMm5acUw2Zkk2ZkJ0RjVPR2xwQ0IxWUo4ZnpDdApHUVFaN0hUSWJkYjJ0cDQzRlZPaHlRYlZjSHFUQTA0UEoxNSswV0F5bVVKVXo4WEE1NDRyL2J2NzRKY0pVUkZoCmFyWmlRd0lEQVFBQm95Y3dKVEFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFMMmhIUmVibEl2VHJTMFNmUVg1RG9ueVVhNy84aTg1endVWApSd3dqdzFuS0U0NDJKbWZWRGZ5b0hRYUM4Ti9MQkxyUXM0U0lqU1JYdmFHU1dSQnRnT1RRV21Db1laMXdSbjdwCndDTXZQTERJdHNWWm90SEZpUFl2b1lHWFFUSXA3YlROMmg1OEJaaEZ3d25nWUovT04zeG1rd29IN1IxYmVxWEYKWHF1TTluekhESk41VlZub1lQR09yRHMwWlg1RnNxNGtWVU0wVExNQm9qN1ZIRDhmU0E5RjRYNU4yMldsZnNPMAo4aksrRFJDWTAyaHBrYTZQQ0pQS0lNOEJaMUFSMG9ZakZxT0plcXpPTjBqcnpYWHh4S2pHVFVUb1BldVA5dCtCCjJOMVA1TnI4a2oxM0lrend5Q1NZclFVN09ZM3ltZmJobHkrcXZxaFVFa014MlQ1SkpmQT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
|
|
||||||
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBdXpHSll2UFo2RG9pNDIxREs4V0phWkNuTkFkMnF6NXAvMDQyb0Z6UVBickFnekUyCnFZVmt6T0w4eEFWZVI3U041d1dvVFdFeUY4RVY3cnIvNCtIaEhHaXE1UG1xdUlGeXp6bjYvSVpjOGpVOXhFZnoKdmlrY2lyTGZVNHZSWEpRd1Z3Z0FTTmwyQVdBSWgyZERkVHJqQkNmaUtXTUh5ajBSYkhhbHNCek9wZ1QvSFR2MwpHUXpuVVF6Rkt2MmRqNVYxTmtTL0RIanlSUkorRUw2UUJZbUdzZWc1UDROYkM5ZWJ1aXBtTVRBcS9KdW1Pb29kCitGakwyblpxTDZmSTZmQnRGNU9HbHBDQjFZSjhmekN0R1FRWjdIVEliZGIydHA0M0ZWT2h5UWJWY0hxVEEwNFAKSjE1KzBXQXltVUpVejhYQTU0NHIvYnY3NEpjSlVSRmhhclppUXdJREFRQUJBb0lCQVFDU0pycjlaeVpiQ2dqegpSL3VKMFZEWCt2aVF4c01BTUZyUjJsOE1GV3NBeHk1SFA4Vk4xYmc5djN0YUVGYnI1U3hsa3lVMFJRNjNQU25DCm1uM3ZqZ3dVQWlScllnTEl5MGk0UXF5VFBOU1V4cnpTNHRxTFBjM3EvSDBnM2FrNGZ2cSsrS0JBUUlqQnloamUKbnVFc1JpMjRzT3NESlM2UDE5NGlzUC9yNEpIM1M5bFZGbkVuOGxUR2c0M1kvMFZoMXl0cnkvdDljWjR5ZUNpNwpjMHFEaTZZcXJZaFZhSW9RRW1VQjdsbHRFZkZzb3l4VDR6RTE5U3pVbkRoMmxjYTF1TzhqcmI4d2xHTzBoQ2JyClB1R1l2WFFQa3Q0VlNmalhvdGJ3d2lBNFRCVERCRzU1bHp6MmNKeS9zSS8zSHlYbEMxcTdXUmRuQVhhZ1F0VzkKOE9DZGRkb0JBb0dCQU5NcUNtSW94REtyckhZZFRxT1M1ZFN4cVMxL0NUN3ZYZ0pScXBqd2Y4WHA2WHo0KzIvTAozVXFaVDBEL3dGTkZkc1Z4eFYxMnNYMUdwMHFWZVlKRld5OVlCaHVSWGpTZ0ZEWldSY1Z1Y01sNVpPTmJsbmZGCjVKQ0xnNXFMZ1g5VTNSRnJrR3A0R241UDQxamg4TnhKVlhzZG5xWE9xNTFUK1RRT1UzdkpGQjc1QW9HQkFPTHcKalp1cnZtVkZyTHdaVGgvRDNpWll5SVV0ZUljZ2NKLzlzbTh6L0pPRmRIbFd4dGRHUFVzYVd1MnBTNEhvckFtbgpqTm4vSTluUXd3enZ3MWUzVVFPbUhMRjVBczk4VU5hbk5TQ0xNMW1yaXZHRXJ1VHFnTDM1bU41eFZPdTUxQU5JCm4yNkFtODBJT2JDeEtLa0R0ZXJSaFhHd3g5c1pONVJCbG9VRThZNGJBb0dBQ3ZsdVhMZWRxcng5VkE0bDNoNXUKVDJXRVUxYjgxZ1orcmtRc1I1S0lNWEw4cllBTElUNUpHKzFuendyN3BkaEFXZmFWdVV2SDRhamdYT0h6MUs5aQpFODNSVTNGMG9ldUg0V01PY1RwU0prWm0xZUlXcWRiaEVCb1FGdUlWTXRib1BsV0d4ZUhFRHJoOEtreGp4aThSCmdEcUQyajRwY1IzQ0g5QjJ5a0lqQjVFQ2dZRUExc0xXLys2enE1c1lNSm14K1JXZThhTXJmL3pjQnVTSU1LQWgKY0dNK0wwMG9RSHdDaUU4TVNqcVN1ajV3R214YUFuanhMb3ZwSFlRV1VmUEVaUW95UE1YQ2VhRVBLOU4xbk8xMwp0V2lHRytIZkIxaU5PazFCc0lhNFNDbndOM1FRVTFzeXBaeEgxT3hueS9LYmkvYmEvWEZ5VzNqMGFUK2YvVWxrCmJGV1ZVdWtDZ1lFQTBaMmRTTFlmTjV5eFNtYk5xMWVqZXdWd1BjRzQxR2hQclNUZEJxdHFac1doWGE3aDdLTWEKeHdvamh5SXpnTXNyK2tXODdlajhDQ2h0d21sQ1p5QU92QmdOZytncnJ1cEZLM3FOSkpKeU9YREdHckdpbzZmTQp5aXB3Q2tZVGVxRThpZ1J6UkI5QkdFUGY4eVpjMUtwdmZhUDVhM0lRZmxiV0czbGpUemNNZVZjPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
|
|
||||||
- name: def-user
|
|
||||||
user:
|
|
||||||
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4akNDQWRxZ0F3SUJBZ0lJQXhEdzk2RUY4SXN3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB4T1RBNU1qa3hOekF6TURsYUZ3MHlNREE1TWpneE56QXpNVEphTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXV6R0pZdlBaNkRvaTQyMUQKSzhXSmFaQ25OQWQycXo1cC8wNDJvRnpRUGJyQWd6RTJxWVZrek9MOHhBVmVSN1NONXdXb1RXRXlGOEVWN3JyLwo0K0hoSEdpcTVQbXF1SUZ5enpuNi9JWmM4alU5eEVmenZpa2NpckxmVTR2UlhKUXdWd2dBU05sMkFXQUloMmRECmRUcmpCQ2ZpS1dNSHlqMFJiSGFsc0J6T3BnVC9IVHYzR1F6blVRekZLdjJkajVWMU5rUy9ESGp5UlJKK0VMNlEKQlltR3NlZzVQNE5iQzllYnVpcG1NVEFxL0p1bU9vb2QrRmpMMm5acUw2Zkk2ZkJ0RjVPR2xwQ0IxWUo4ZnpDdApHUVFaN0hUSWJkYjJ0cDQzRlZPaHlRYlZjSHFUQTA0UEoxNSswV0F5bVVKVXo4WEE1NDRyL2J2NzRKY0pVUkZoCmFyWmlRd0lEQVFBQm95Y3dKVEFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFMMmhIUmVibEl2VHJTMFNmUVg1RG9ueVVhNy84aTg1endVWApSd3dqdzFuS0U0NDJKbWZWRGZ5b0hRYUM4Ti9MQkxyUXM0U0lqU1JYdmFHU1dSQnRnT1RRV21Db1laMXdSbjdwCndDTXZQTERJdHNWWm90SEZpUFl2b1lHWFFUSXA3YlROMmg1OEJaaEZ3d25nWUovT04zeG1rd29IN1IxYmVxWEYKWHF1TTluekhESk41VlZub1lQR09yRHMwWlg1RnNxNGtWVU0wVExNQm9qN1ZIRDhmU0E5RjRYNU4yMldsZnNPMAo4aksrRFJDWTAyaHBrYTZQQ0pQS0lNOEJaMUFSMG9ZakZxT0plcXpPTjBqcnpYWHh4S2pHVFVUb1BldVA5dCtCCjJOMVA1TnI4a2oxM0lrend5Q1NZclFVN09ZM3ltZmJobHkrcXZxaFVFa014MlQ1SkpmQT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
|
|
||||||
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBdXpHSll2UFo2RG9pNDIxREs4V0phWkNuTkFkMnF6NXAvMDQyb0Z6UVBickFnekUyCnFZVmt6T0w4eEFWZVI3U041d1dvVFdFeUY4RVY3cnIvNCtIaEhHaXE1UG1xdUlGeXp6bjYvSVpjOGpVOXhFZnoKdmlrY2lyTGZVNHZSWEpRd1Z3Z0FTTmwyQVdBSWgyZERkVHJqQkNmaUtXTUh5ajBSYkhhbHNCek9wZ1QvSFR2MwpHUXpuVVF6Rkt2MmRqNVYxTmtTL0RIanlSUkorRUw2UUJZbUdzZWc1UDROYkM5ZWJ1aXBtTVRBcS9KdW1Pb29kCitGakwyblpxTDZmSTZmQnRGNU9HbHBDQjFZSjhmekN0R1FRWjdIVEliZGIydHA0M0ZWT2h5UWJWY0hxVEEwNFAKSjE1KzBXQXltVUpVejhYQTU0NHIvYnY3NEpjSlVSRmhhclppUXdJREFRQUJBb0lCQVFDU0pycjlaeVpiQ2dqegpSL3VKMFZEWCt2aVF4c01BTUZyUjJsOE1GV3NBeHk1SFA4Vk4xYmc5djN0YUVGYnI1U3hsa3lVMFJRNjNQU25DCm1uM3ZqZ3dVQWlScllnTEl5MGk0UXF5VFBOU1V4cnpTNHRxTFBjM3EvSDBnM2FrNGZ2cSsrS0JBUUlqQnloamUKbnVFc1JpMjRzT3NESlM2UDE5NGlzUC9yNEpIM1M5bFZGbkVuOGxUR2c0M1kvMFZoMXl0cnkvdDljWjR5ZUNpNwpjMHFEaTZZcXJZaFZhSW9RRW1VQjdsbHRFZkZzb3l4VDR6RTE5U3pVbkRoMmxjYTF1TzhqcmI4d2xHTzBoQ2JyClB1R1l2WFFQa3Q0VlNmalhvdGJ3d2lBNFRCVERCRzU1bHp6MmNKeS9zSS8zSHlYbEMxcTdXUmRuQVhhZ1F0VzkKOE9DZGRkb0JBb0dCQU5NcUNtSW94REtyckhZZFRxT1M1ZFN4cVMxL0NUN3ZYZ0pScXBqd2Y4WHA2WHo0KzIvTAozVXFaVDBEL3dGTkZkc1Z4eFYxMnNYMUdwMHFWZVlKRld5OVlCaHVSWGpTZ0ZEWldSY1Z1Y01sNVpPTmJsbmZGCjVKQ0xnNXFMZ1g5VTNSRnJrR3A0R241UDQxamg4TnhKVlhzZG5xWE9xNTFUK1RRT1UzdkpGQjc1QW9HQkFPTHcKalp1cnZtVkZyTHdaVGgvRDNpWll5SVV0ZUljZ2NKLzlzbTh6L0pPRmRIbFd4dGRHUFVzYVd1MnBTNEhvckFtbgpqTm4vSTluUXd3enZ3MWUzVVFPbUhMRjVBczk4VU5hbk5TQ0xNMW1yaXZHRXJ1VHFnTDM1bU41eFZPdTUxQU5JCm4yNkFtODBJT2JDeEtLa0R0ZXJSaFhHd3g5c1pONVJCbG9VRThZNGJBb0dBQ3ZsdVhMZWRxcng5VkE0bDNoNXUKVDJXRVUxYjgxZ1orcmtRc1I1S0lNWEw4cllBTElUNUpHKzFuendyN3BkaEFXZmFWdVV2SDRhamdYT0h6MUs5aQpFODNSVTNGMG9ldUg0V01PY1RwU0prWm0xZUlXcWRiaEVCb1FGdUlWTXRib1BsV0d4ZUhFRHJoOEtreGp4aThSCmdEcUQyajRwY1IzQ0g5QjJ5a0lqQjVFQ2dZRUExc0xXLys2enE1c1lNSm14K1JXZThhTXJmL3pjQnVTSU1LQWgKY0dNK0wwMG9RSHdDaUU4TVNqcVN1ajV3R214YUFuanhMb3ZwSFlRV1VmUEVaUW95UE1YQ2VhRVBLOU4xbk8xMwp0V2lHRytIZkIxaU5PazFCc0lhNFNDbndOM1FRVTFzeXBaeEgxT3hueS9LYmkvYmEvWEZ5VzNqMGFUK2YvVWxrCmJGV1ZVdWtDZ1lFQTBaMmRTTFlmTjV5eFNtYk5xMWVqZXdWd1BjRzQxR2hQclNUZEJxdHFac1doWGE3aDdLTWEKeHdvamh5SXpnTXNyK2tXODdlajhDQ2h0d21sQ1p5QU92QmdOZytncnJ1cEZLM3FOSkpKeU9YREdHckdpbzZmTQp5aXB3Q2tZVGVxRThpZ1J6UkI5QkdFUGY4eVpjMUtwdmZhUDVhM0lRZmxiV0czbGpUemNNZVZjPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
|
|
||||||
`
|
|
||||||
err := ioutil.WriteFile(kubeConfigPath, []byte(kubeConfigContent), 0600)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = conf.ImportFromKubeConfig(kubeConfigPath)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
t.Run("importClusters", func(t *testing.T) {
|
|
||||||
// Verify that only 3 clusters have been added (original 5 plus 3 new clusters)
|
|
||||||
// This is important since the above kubeconfig actually has 4
|
|
||||||
// clusters, but one was already defined in the airship config
|
|
||||||
assert.Len(t, conf.Clusters, 6+3)
|
|
||||||
|
|
||||||
// verify that the new clusters have been added to the config
|
|
||||||
_, err := conf.GetCluster("cluster", config.Target)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
_, err = conf.GetCluster("dummycluster", config.Ephemeral)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
// verify that the "noncomplex" cluster was added as a target cluster
|
|
||||||
_, err = conf.GetCluster("noncomplex", config.Target)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("importContexts", func(t *testing.T) {
|
|
||||||
// Verify that only 3 contexts have been added (original 3 plus 3 new contexts)
|
|
||||||
// This is important since the above kubeconfig actually has 4
|
|
||||||
// contexts, but one was already defined in the airship config
|
|
||||||
assert.Len(t, conf.Contexts, 3+3)
|
|
||||||
|
|
||||||
// verify that the new contexts have been added to the config
|
|
||||||
_, err := conf.GetContext("cluster-admin@cluster")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
_, err = conf.GetContext("dummy_cluster")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
// verify that the "noncomplex" context refers to the proper target "noncomplex" cluster
|
|
||||||
noncomplex, err := conf.GetContext("noncomplex")
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, "noncomplex_target", noncomplex.NameInKubeconf)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("importAuthInfos", func(t *testing.T) {
|
|
||||||
// Verify that only 2 users have been added (original 3 plus 2 new users)
|
|
||||||
// This is important since the above kubeconfig actually has 3
|
|
||||||
// users, but one was already defined in the airship config
|
|
||||||
assert.Len(t, conf.AuthInfos, 3+2)
|
|
||||||
|
|
||||||
// verify that the new users have been added to the config
|
|
||||||
_, err := conf.GetAuthInfo("cluster-admin")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
_, err = conf.GetAuthInfo("kubernetes-admin")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestImportErrors(t *testing.T) {
|
|
||||||
conf, cleanupConfig := testutil.InitConfig(t)
|
|
||||||
defer cleanupConfig(t)
|
|
||||||
|
|
||||||
t.Run("nonexistent kubeConfig", func(t *testing.T) {
|
|
||||||
err := conf.ImportFromKubeConfig("./non/existent/file/path")
|
|
||||||
assert.Contains(t, err.Error(), "no such file or directory")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("malformed kubeConfig", func(t *testing.T) {
|
|
||||||
kubeDir, cleanupKubeConfig := testutil.TempDir(t, "airship-import-tests")
|
|
||||||
defer cleanupKubeConfig(t)
|
|
||||||
|
|
||||||
kubeConfigPath := filepath.Join(kubeDir, "config")
|
|
||||||
//nolint: lll
|
|
||||||
kubeConfigContent := "malformed content"
|
|
||||||
|
|
||||||
err := ioutil.WriteFile(kubeConfigPath, []byte(kubeConfigContent), 0600)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
err = conf.ImportFromKubeConfig(kubeConfigPath)
|
|
||||||
assert.Contains(t, err.Error(), "json parse error")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestManagementConfigurationByName(t *testing.T) {
|
func TestManagementConfigurationByName(t *testing.T) {
|
||||||
conf, cleanupConfig := testutil.InitConfig(t)
|
conf, cleanupConfig := testutil.InitConfig(t)
|
||||||
defer cleanupConfig(t)
|
defer cleanupConfig(t)
|
||||||
|
@ -18,8 +18,8 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"k8s.io/client-go/tools/clientcmd/api"
|
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -37,8 +37,8 @@ type Context struct {
|
|||||||
// +optional
|
// +optional
|
||||||
EncryptionConfig string `json:"encryptionConfig,omitempty"`
|
EncryptionConfig string `json:"encryptionConfig,omitempty"`
|
||||||
|
|
||||||
// KubeConfig Context Object
|
// Management configuration which will be used for all hosts in the cluster
|
||||||
context *api.Context
|
ManagementConfiguration string `json:"managementConfiguration"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) String() string {
|
func (c *Context) String() string {
|
||||||
@ -46,12 +46,10 @@ func (c *Context) String() string {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
kcluster := c.KubeContext()
|
|
||||||
kyaml, err := yaml.Marshal(&kcluster)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return string(cyaml)
|
return string(cyaml)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s\n%s", string(cyaml), string(kyaml))
|
return string(cyaml)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrettyString returns cluster name in a formatted string
|
// PrettyString returns cluster name in a formatted string
|
||||||
@ -60,16 +58,6 @@ func (c *Context) PrettyString() string {
|
|||||||
return fmt.Sprintf("Context: %s\n%s\n", clusterName.Name, c)
|
return fmt.Sprintf("Context: %s\n%s\n", clusterName.Name, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// KubeContext returns kube context object
|
|
||||||
func (c *Context) KubeContext() *api.Context {
|
|
||||||
return c.context
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetKubeContext updates kube contect with given context details
|
|
||||||
func (c *Context) SetKubeContext(kc *api.Context) {
|
|
||||||
c.context = kc
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClusterType returns cluster type by extracting the type portion from
|
// ClusterType returns cluster type by extracting the type portion from
|
||||||
// the complex cluster name
|
// the complex cluster name
|
||||||
func (c *Context) ClusterType() string {
|
func (c *Context) ClusterType() string {
|
||||||
@ -81,3 +69,48 @@ func (c *Context) ClusterType() string {
|
|||||||
func (c *Context) ClusterName() string {
|
func (c *Context) ClusterName() string {
|
||||||
return NewClusterComplexNameFromKubeClusterName(c.NameInKubeconf).Name
|
return NewClusterComplexNameFromKubeClusterName(c.NameInKubeconf).Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClusterComplexName holds the complex cluster name information
|
||||||
|
// Encapsulates the different operations around using it.
|
||||||
|
type ClusterComplexName struct {
|
||||||
|
Name string
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClusterComplexName returns a ClusterComplexName with the given name and type.
|
||||||
|
func NewClusterComplexName(clusterName, clusterType string) ClusterComplexName {
|
||||||
|
return ClusterComplexName{
|
||||||
|
Name: clusterName,
|
||||||
|
Type: clusterType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClusterComplexNameFromKubeClusterName takes the name of a cluster in a
|
||||||
|
// format which might be found in a kubeconfig file. This may be a simple
|
||||||
|
// string (e.g. myCluster), or it may be prepended with the type of the cluster
|
||||||
|
// (e.g. myCluster_target)
|
||||||
|
//
|
||||||
|
// If a valid cluster type was appended, the returned ClusterComplexName will
|
||||||
|
// have that type. If no cluster type is provided, the
|
||||||
|
// AirshipDefaultClusterType will be used.
|
||||||
|
func NewClusterComplexNameFromKubeClusterName(kubeClusterName string) ClusterComplexName {
|
||||||
|
parts := strings.Split(kubeClusterName, AirshipClusterNameSeparator)
|
||||||
|
|
||||||
|
if len(parts) == 1 {
|
||||||
|
return NewClusterComplexName(kubeClusterName, AirshipDefaultClusterType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// kubeClusterName matches the format myCluster_something.
|
||||||
|
// Let's check if "something" is a clusterType.
|
||||||
|
potentialType := parts[len(parts)-1]
|
||||||
|
for _, ct := range AllClusterTypes {
|
||||||
|
if potentialType == ct {
|
||||||
|
// Rejoin the parts in the case of "my_cluster_etc_etc_<clusterType>"
|
||||||
|
name := strings.Join(parts[:len(parts)-1], AirshipClusterNameSeparator)
|
||||||
|
return NewClusterComplexName(name, potentialType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "something" is not a valid clusterType, so just use the default
|
||||||
|
return NewClusterComplexName(kubeClusterName, AirshipDefaultClusterType)
|
||||||
|
}
|
||||||
|
@ -163,12 +163,12 @@ func (e ErrMissingCurrentContext) Error() string {
|
|||||||
|
|
||||||
// ErrMissingManagementConfiguration means the management configuration was not defined for the active cluster.
|
// ErrMissingManagementConfiguration means the management configuration was not defined for the active cluster.
|
||||||
type ErrMissingManagementConfiguration struct {
|
type ErrMissingManagementConfiguration struct {
|
||||||
cluster *Cluster
|
context *Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e ErrMissingManagementConfiguration) Error() string {
|
func (e ErrMissingManagementConfiguration) Error() string {
|
||||||
return fmt.Sprintf("Management configuration %s for cluster %s undefined.", e.cluster.ManagementConfiguration,
|
return fmt.Sprintf("Management configuration %s for cluster %s undefined.", e.context.ManagementConfiguration,
|
||||||
e.cluster.NameInKubeconf)
|
e.context.NameInKubeconf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrMissingPrimaryRepo returned when Primary Repository is not set in context manifest
|
// ErrMissingPrimaryRepo returned when Primary Repository is not set in context manifest
|
||||||
@ -206,14 +206,6 @@ func (e ErrConflictingClusterOptions) Error() string {
|
|||||||
return "Specifying certificate-authority and insecure-skip-tls-verify mode is not allowed at the same time."
|
return "Specifying certificate-authority and insecure-skip-tls-verify mode is not allowed at the same time."
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrEmptyClusterName returned when empty cluster name is set
|
|
||||||
type ErrEmptyClusterName struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e ErrEmptyClusterName) Error() string {
|
|
||||||
return "Cluster name must not be empty."
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrConflictingContextOptions returned when both context and --current is set at same time
|
// ErrConflictingContextOptions returned when both context and --current is set at same time
|
||||||
type ErrConflictingContextOptions struct {
|
type ErrConflictingContextOptions struct {
|
||||||
}
|
}
|
||||||
|
@ -22,39 +22,15 @@ import (
|
|||||||
"opendev.org/airship/airshipctl/pkg/errors"
|
"opendev.org/airship/airshipctl/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AuthInfoOptions holds all configurable options for
|
|
||||||
// authentication information or credential
|
|
||||||
type AuthInfoOptions struct {
|
|
||||||
Name string
|
|
||||||
ClientCertificate string
|
|
||||||
ClientKey string
|
|
||||||
Token string
|
|
||||||
Username string
|
|
||||||
Password string
|
|
||||||
EmbedCertData bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContextOptions holds all configurable options for context
|
// ContextOptions holds all configurable options for context
|
||||||
type ContextOptions struct {
|
type ContextOptions struct {
|
||||||
Name string
|
Name string
|
||||||
ClusterType string
|
ClusterType string
|
||||||
CurrentContext bool
|
CurrentContext bool
|
||||||
Cluster string
|
|
||||||
AuthInfo string
|
|
||||||
Manifest string
|
Manifest string
|
||||||
EncryptionConfig string
|
|
||||||
Namespace string
|
|
||||||
Current bool
|
Current bool
|
||||||
}
|
ManagementConfiguration string
|
||||||
|
EncryptionConfig string
|
||||||
// ClusterOptions holds all configurable options for cluster configuration
|
|
||||||
type ClusterOptions struct {
|
|
||||||
Name string
|
|
||||||
ClusterType string
|
|
||||||
Server string
|
|
||||||
InsecureSkipTLSVerify bool
|
|
||||||
CertificateAuthority string
|
|
||||||
EmbedCAData bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ManifestOptions holds all configurable options for manifest configuration
|
// ManifestOptions holds all configurable options for manifest configuration
|
||||||
@ -86,33 +62,6 @@ type EncryptionConfigOptions struct {
|
|||||||
// is possible to create (and validate) these objects without using the command
|
// is possible to create (and validate) these objects without using the command
|
||||||
// line.
|
// line.
|
||||||
|
|
||||||
// Validate checks for the possible authentication values and returns
|
|
||||||
// Error when invalid value or incompatible choice of values given
|
|
||||||
func (o *AuthInfoOptions) Validate() error {
|
|
||||||
// TODO(howell): This prevents a user of airshipctl from creating a
|
|
||||||
// credential with both a bearer-token and a user/password, but it does
|
|
||||||
// not prevent a user from adding a bearer-token to a credential which
|
|
||||||
// already had a user/pass and visa-versa. This could create bugs if a
|
|
||||||
// user at first chooses one method, but later switches to another.
|
|
||||||
if o.Token != "" && (o.Username != "" || o.Password != "") {
|
|
||||||
return ErrConflictingAuthOptions{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !o.EmbedCertData {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := checkExists("client-certificate", o.ClientCertificate); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := checkExists("client-key", o.ClientKey); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate checks for the possible context option values and returns
|
// Validate checks for the possible context option values and returns
|
||||||
// Error when invalid value or incompatible choice of values given
|
// Error when invalid value or incompatible choice of values given
|
||||||
func (o *ContextOptions) Validate() error {
|
func (o *ContextOptions) Validate() error {
|
||||||
@ -129,58 +78,10 @@ func (o *ContextOptions) Validate() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the cluster-type was specified, verify that it's valid
|
|
||||||
if o.ClusterType != "" {
|
|
||||||
if err := ValidClusterType(o.ClusterType); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Manifest, Cluster could be validated against the existing config maps
|
// TODO Manifest, Cluster could be validated against the existing config maps
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks for the possible cluster option values and returns
|
|
||||||
// Error when invalid value or incompatible choice of values given
|
|
||||||
func (o *ClusterOptions) Validate() error {
|
|
||||||
if o.Name == "" {
|
|
||||||
return ErrEmptyClusterName{}
|
|
||||||
}
|
|
||||||
|
|
||||||
err := ValidClusterType(o.ClusterType)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.InsecureSkipTLSVerify && o.CertificateAuthority != "" {
|
|
||||||
return ErrConflictingClusterOptions{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !o.EmbedCAData {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := checkExists("certificate-authority", o.CertificateAuthority); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkExists(flagName, path string) error {
|
|
||||||
if path == "" {
|
|
||||||
return ErrMissingFlag{FlagName: flagName}
|
|
||||||
}
|
|
||||||
if _, err := os.Stat(path); err != nil {
|
|
||||||
return ErrCheckFile{
|
|
||||||
FlagName: flagName,
|
|
||||||
Path: path,
|
|
||||||
InternalErr: err,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate checks for the possible manifest option values and returns
|
// Validate checks for the possible manifest option values and returns
|
||||||
// Error when invalid value or incompatible choice of values given
|
// Error when invalid value or incompatible choice of values given
|
||||||
func (o *ManifestOptions) Validate() error {
|
func (o *ManifestOptions) Validate() error {
|
||||||
@ -247,3 +148,17 @@ func (o EncryptionConfigOptions) backedByFileSystem() bool {
|
|||||||
func (o EncryptionConfigOptions) backedByAPIServer() bool {
|
func (o EncryptionConfigOptions) backedByAPIServer() bool {
|
||||||
return o.KeySecretName != "" || o.KeySecretNamespace != ""
|
return o.KeySecretName != "" || o.KeySecretNamespace != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkExists(flagName, path string) error {
|
||||||
|
if path == "" {
|
||||||
|
return ErrMissingFlag{FlagName: flagName}
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(path); err != nil {
|
||||||
|
return ErrCheckFile{
|
||||||
|
FlagName: flagName,
|
||||||
|
Path: path,
|
||||||
|
InternalErr: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -17,83 +17,13 @@ limitations under the License.
|
|||||||
package config_test
|
package config_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"opendev.org/airship/airshipctl/pkg/config"
|
"opendev.org/airship/airshipctl/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAuthInfoOptionsValidate(t *testing.T) {
|
|
||||||
aRealFile, err := ioutil.TempFile("", "a-real-file")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
aRealFilename := aRealFile.Name()
|
|
||||||
defer os.Remove(aRealFilename)
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
testOptions config.AuthInfoOptions
|
|
||||||
expectError bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "TokenAndUserPass",
|
|
||||||
testOptions: config.AuthInfoOptions{
|
|
||||||
Token: "testToken",
|
|
||||||
Username: "testUser",
|
|
||||||
Password: "testPassword",
|
|
||||||
},
|
|
||||||
expectError: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "DontEmbed",
|
|
||||||
testOptions: config.AuthInfoOptions{
|
|
||||||
EmbedCertData: false,
|
|
||||||
},
|
|
||||||
expectError: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "EmbedWithoutCert",
|
|
||||||
testOptions: config.AuthInfoOptions{
|
|
||||||
EmbedCertData: true,
|
|
||||||
},
|
|
||||||
expectError: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "EmbedWithoutClientKey",
|
|
||||||
testOptions: config.AuthInfoOptions{
|
|
||||||
EmbedCertData: true,
|
|
||||||
ClientCertificate: aRealFilename,
|
|
||||||
},
|
|
||||||
expectError: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "EmbedWithCertAndClientKey",
|
|
||||||
testOptions: config.AuthInfoOptions{
|
|
||||||
EmbedCertData: true,
|
|
||||||
ClientCertificate: aRealFilename,
|
|
||||||
ClientKey: aRealFilename,
|
|
||||||
},
|
|
||||||
expectError: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
tt := tt
|
|
||||||
t.Run(tt.name, func(subTest *testing.T) {
|
|
||||||
err := tt.testOptions.Validate()
|
|
||||||
if tt.expectError {
|
|
||||||
assert.Error(t, err)
|
|
||||||
} else {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContextOptionsValidate(t *testing.T) {
|
func TestContextOptionsValidate(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@ -107,14 +37,6 @@ func TestContextOptionsValidate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expectError: true,
|
expectError: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "InvalidClusterType",
|
|
||||||
testOptions: config.ContextOptions{
|
|
||||||
Name: "testContext",
|
|
||||||
ClusterType: "badType",
|
|
||||||
},
|
|
||||||
expectError: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "SettingCurrentContext",
|
name: "SettingCurrentContext",
|
||||||
testOptions: config.ContextOptions{
|
testOptions: config.ContextOptions{
|
||||||
@ -152,93 +74,3 @@ func TestContextOptionsValidate(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClusterOptionsValidate(t *testing.T) {
|
|
||||||
aRealfile, err := ioutil.TempFile("", "a-real-file")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
aRealFilename := aRealfile.Name()
|
|
||||||
defer os.Remove(aRealFilename)
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
testOptions config.ClusterOptions
|
|
||||||
expectError bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "MissingName",
|
|
||||||
testOptions: config.ClusterOptions{
|
|
||||||
Name: "",
|
|
||||||
},
|
|
||||||
expectError: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "InvalidClusterType",
|
|
||||||
testOptions: config.ClusterOptions{
|
|
||||||
Name: "testCluster",
|
|
||||||
ClusterType: "badType",
|
|
||||||
},
|
|
||||||
expectError: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "InsecureSkipTLSVerifyAndCertificateAuthority",
|
|
||||||
testOptions: config.ClusterOptions{
|
|
||||||
Name: "testCluster",
|
|
||||||
ClusterType: "target",
|
|
||||||
InsecureSkipTLSVerify: true,
|
|
||||||
CertificateAuthority: "cert_file",
|
|
||||||
},
|
|
||||||
expectError: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "DontEmbed",
|
|
||||||
testOptions: config.ClusterOptions{
|
|
||||||
Name: "testCluster",
|
|
||||||
ClusterType: "target",
|
|
||||||
EmbedCAData: false,
|
|
||||||
},
|
|
||||||
expectError: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "EmbedWithoutCA",
|
|
||||||
testOptions: config.ClusterOptions{
|
|
||||||
Name: "testCluster",
|
|
||||||
ClusterType: "target",
|
|
||||||
EmbedCAData: true,
|
|
||||||
},
|
|
||||||
expectError: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "EmbedWithFaultyCA",
|
|
||||||
testOptions: config.ClusterOptions{
|
|
||||||
Name: "testCluster",
|
|
||||||
ClusterType: "target",
|
|
||||||
EmbedCAData: true,
|
|
||||||
CertificateAuthority: "not-a-real-file",
|
|
||||||
},
|
|
||||||
expectError: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "EmbedWithGoodCA",
|
|
||||||
testOptions: config.ClusterOptions{
|
|
||||||
Name: "testCluster",
|
|
||||||
ClusterType: "target",
|
|
||||||
EmbedCAData: true,
|
|
||||||
CertificateAuthority: aRealFilename,
|
|
||||||
},
|
|
||||||
expectError: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
tt := tt
|
|
||||||
t.Run(tt.name, func(subTest *testing.T) {
|
|
||||||
err := tt.testOptions.Validate()
|
|
||||||
if tt.expectError {
|
|
||||||
assert.Error(t, err)
|
|
||||||
} else {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
6
pkg/config/testdata/authinfo-string.yaml
vendored
6
pkg/config/testdata/authinfo-string.yaml
vendored
@ -1,6 +0,0 @@
|
|||||||
LocationOfOrigin: ""
|
|
||||||
client-certificate: ZHVtbXlfY2VydGlmaWNhdGU=
|
|
||||||
client-key: ZHVtbXlfa2V5
|
|
||||||
password: ZHVtbXlfcGFzc3dvcmQ=
|
|
||||||
token: ZHVtbXlfdG9rZW4=
|
|
||||||
username: dummy_username
|
|
6
pkg/config/testdata/cluster-string.yaml
vendored
6
pkg/config/testdata/cluster-string.yaml
vendored
@ -1,6 +0,0 @@
|
|||||||
clusterKubeconf: dummy_cluster_target
|
|
||||||
managementConfiguration: dummy_management_config
|
|
||||||
|
|
||||||
LocationOfOrigin: ""
|
|
||||||
certificate-authority: dummy_ca
|
|
||||||
server: http://dummy.server
|
|
12
pkg/config/testdata/config-string.yaml
vendored
12
pkg/config/testdata/config-string.yaml
vendored
@ -1,17 +1,9 @@
|
|||||||
apiVersion: airshipit.org/v1alpha1
|
apiVersion: airshipit.org/v1alpha1
|
||||||
clusters:
|
|
||||||
dummy_cluster:
|
|
||||||
clusterType:
|
|
||||||
ephemeral:
|
|
||||||
clusterKubeconf: dummy_cluster_ephemeral
|
|
||||||
managementConfiguration: dummy_management_config
|
|
||||||
target:
|
|
||||||
clusterKubeconf: dummy_cluster_target
|
|
||||||
managementConfiguration: dummy_management_config
|
|
||||||
contexts:
|
contexts:
|
||||||
dummy_context:
|
dummy_context:
|
||||||
contextKubeconf: dummy_cluster_ephemeral
|
contextKubeconf: dummy_cluster_ephemeral
|
||||||
encryptionConfig: dummy_encryption_config
|
encryptionConfig: dummy_encryption_config
|
||||||
|
managementConfiguration: dummy_management_config
|
||||||
manifest: dummy_manifest
|
manifest: dummy_manifest
|
||||||
currentContext: dummy_context
|
currentContext: dummy_context
|
||||||
encryptionConfigs:
|
encryptionConfigs:
|
||||||
@ -43,5 +35,3 @@ manifests:
|
|||||||
permissions:
|
permissions:
|
||||||
DirectoryPermission: 488
|
DirectoryPermission: 488
|
||||||
FilePermission: 416
|
FilePermission: 416
|
||||||
users:
|
|
||||||
dummy_user: {}
|
|
||||||
|
6
pkg/config/testdata/context-string.yaml
vendored
6
pkg/config/testdata/context-string.yaml
vendored
@ -1,8 +1,4 @@
|
|||||||
contextKubeconf: dummy_cluster_ephemeral
|
contextKubeconf: dummy_cluster_ephemeral
|
||||||
encryptionConfig: dummy_encryption_config
|
encryptionConfig: dummy_encryption_config
|
||||||
|
managementConfiguration: dummy_management_config
|
||||||
manifest: dummy_manifest
|
manifest: dummy_manifest
|
||||||
|
|
||||||
LocationOfOrigin: ""
|
|
||||||
cluster: dummy_cluster_ephemeral
|
|
||||||
namespace: dummy_namespace
|
|
||||||
user: dummy_user
|
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
Cluster: dummy_cluster
|
|
||||||
target:
|
|
||||||
clusterKubeconf: dummy_cluster_target
|
|
||||||
managementConfiguration: dummy_management_config
|
|
||||||
|
|
||||||
LocationOfOrigin: ""
|
|
||||||
certificate-authority: dummy_ca
|
|
||||||
server: http://dummy.server
|
|
@ -27,15 +27,14 @@ func NewConfig() *Config {
|
|||||||
return &Config{
|
return &Config{
|
||||||
Kind: AirshipConfigKind,
|
Kind: AirshipConfigKind,
|
||||||
APIVersion: AirshipConfigAPIVersion,
|
APIVersion: AirshipConfigAPIVersion,
|
||||||
Clusters: make(map[string]*ClusterPurpose),
|
|
||||||
Permissions: Permissions{
|
Permissions: Permissions{
|
||||||
DirectoryPermission: AirshipDefaultDirectoryPermission,
|
DirectoryPermission: AirshipDefaultDirectoryPermission,
|
||||||
FilePermission: AirshipDefaultFilePermission,
|
FilePermission: AirshipDefaultFilePermission,
|
||||||
},
|
},
|
||||||
AuthInfos: make(map[string]*AuthInfo),
|
|
||||||
Contexts: map[string]*Context{
|
Contexts: map[string]*Context{
|
||||||
AirshipDefaultContext: {
|
AirshipDefaultContext: {
|
||||||
Manifest: AirshipDefaultManifest,
|
Manifest: AirshipDefaultManifest,
|
||||||
|
ManagementConfiguration: AirshipDefaultManagementConfiguration,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
CurrentContext: AirshipDefaultContext,
|
CurrentContext: AirshipDefaultContext,
|
||||||
@ -87,14 +86,6 @@ func NewContext() *Context {
|
|||||||
return &Context{}
|
return &Context{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCluster is a convenience function that returns a new Cluster
|
|
||||||
func NewCluster() *Cluster {
|
|
||||||
return &Cluster{
|
|
||||||
NameInKubeconf: "",
|
|
||||||
ManagementConfiguration: AirshipDefaultManagementConfiguration,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewManifest is a convenience function that returns a new Manifest
|
// NewManifest is a convenience function that returns a new Manifest
|
||||||
// object with non-nil maps
|
// object with non-nil maps
|
||||||
func NewManifest() *Manifest {
|
func NewManifest() *Manifest {
|
||||||
@ -114,11 +105,6 @@ func NewRepository() *Repository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAuthInfo is a convenience function that returns a new AuthInfo
|
|
||||||
func NewAuthInfo() *AuthInfo {
|
|
||||||
return &AuthInfo{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeString returns the base64 encoding of given string
|
// EncodeString returns the base64 encoding of given string
|
||||||
func EncodeString(given string) string {
|
func EncodeString(given string) string {
|
||||||
return base64.StdEncoding.EncodeToString([]byte(given))
|
return base64.StdEncoding.EncodeToString([]byte(given))
|
||||||
|
@ -60,7 +60,6 @@ func TestDeploy(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
expectedErrorString string
|
expectedErrorString string
|
||||||
clusterPurposes map[string]*config.ClusterPurpose
|
|
||||||
phaseName string
|
phaseName string
|
||||||
events []applyevent.Event
|
events []applyevent.Event
|
||||||
}{
|
}{
|
||||||
@ -95,9 +94,6 @@ func TestDeploy(t *testing.T) {
|
|||||||
ao.Applier = cliApplier
|
ao.Applier = cliApplier
|
||||||
ao.EventChannel = ch
|
ao.EventChannel = ch
|
||||||
}
|
}
|
||||||
if tt.clusterPurposes != nil {
|
|
||||||
rs.Clusters = tt.clusterPurposes
|
|
||||||
}
|
|
||||||
if tt.phaseName != "" {
|
if tt.phaseName != "" {
|
||||||
ao.PhaseName = tt.phaseName
|
ao.PhaseName = tt.phaseName
|
||||||
}
|
}
|
||||||
|
22
pkg/phase/apply/testdata/config.yaml
vendored
22
pkg/phase/apply/testdata/config.yaml
vendored
@ -1,25 +1,7 @@
|
|||||||
apiVersion: airshipit.org/v1alpha1
|
apiVersion: airshipit.org/v1alpha1
|
||||||
bootstrapInfo:
|
|
||||||
dummy_bootstrap_config:
|
|
||||||
container:
|
|
||||||
volume: /tmp/airship:/config
|
|
||||||
image: quay.io/airshipit/isogen:latest-ubuntu_focal
|
|
||||||
containerRuntime: docker
|
|
||||||
builder:
|
|
||||||
userDataFileName: user-data
|
|
||||||
networkConfigFileName: network-config
|
|
||||||
outputMetadataFileName: output-metadata.yaml
|
|
||||||
remoteDirect:
|
|
||||||
isoUrl: http://localhost:8099/ubuntu-focal.iso
|
|
||||||
clusters:
|
|
||||||
dummycluster:
|
|
||||||
clusterType:
|
|
||||||
ephemeral:
|
|
||||||
bootstrapInfo: dummy_bootstrap_config
|
|
||||||
clusterKubeconf: dummycluster_ephemeral
|
|
||||||
contexts:
|
contexts:
|
||||||
dummy_cluster:
|
dummy_cluster:
|
||||||
contextKubeconf: dummy_cluster
|
contextKubeconf: dummycluster_ephemeral
|
||||||
manifest: dummy_manifest
|
manifest: dummy_manifest
|
||||||
currentContext: dummy_cluster
|
currentContext: dummy_cluster
|
||||||
kind: Config
|
kind: Config
|
||||||
@ -39,5 +21,3 @@ manifests:
|
|||||||
url: http://dummy.url.com/primary.git
|
url: http://dummy.url.com/primary.git
|
||||||
subPath: primary/site/test-site
|
subPath: primary/site/test-site
|
||||||
targetPath: testdata
|
targetPath: testdata
|
||||||
users:
|
|
||||||
dummy_user: {}
|
|
23
pkg/phase/testdata/airshipconfig.yaml
vendored
23
pkg/phase/testdata/airshipconfig.yaml
vendored
@ -1,26 +1,7 @@
|
|||||||
apiVersion: airshipit.org/v1alpha1
|
apiVersion: airshipit.org/v1alpha1
|
||||||
bootstrapInfo:
|
|
||||||
dummy_bootstrap_config:
|
|
||||||
container:
|
|
||||||
volume: /tmp/airship:/config
|
|
||||||
image: quay.io/airshipit/isogen:latest-ubuntu_focal
|
|
||||||
containerRuntime: docker
|
|
||||||
builder:
|
|
||||||
userDataFileName: user-data
|
|
||||||
networkConfigFileName: network-config
|
|
||||||
outputMetadataFileName: output-metadata.yaml
|
|
||||||
remoteDirect:
|
|
||||||
isoUrl: http://localhost:8099/ubuntu-focal.iso
|
|
||||||
remoteType: redfish
|
|
||||||
clusters:
|
|
||||||
dummycluster:
|
|
||||||
clusterType:
|
|
||||||
ephemeral:
|
|
||||||
bootstrapInfo: dummy_bootstrap_config
|
|
||||||
clusterKubeconf: dummycluster_ephemeral
|
|
||||||
contexts:
|
contexts:
|
||||||
dummy_cluster:
|
dummy_cluster:
|
||||||
contextKubeconf: dummy_cluster
|
contextKubeconf: dummycluster_ephemeral
|
||||||
manifest: dummy_manifest
|
manifest: dummy_manifest
|
||||||
currentContext: dummy_cluster
|
currentContext: dummy_cluster
|
||||||
kind: Config
|
kind: Config
|
||||||
@ -41,5 +22,3 @@ manifests:
|
|||||||
tag: v1.0.1
|
tag: v1.0.1
|
||||||
url: http://dummy.url.com/primary.git
|
url: http://dummy.url.com/primary.git
|
||||||
subPath: valid_site
|
subPath: valid_site
|
||||||
users:
|
|
||||||
dummy_user: {}
|
|
22
testdata/k8s/config.yaml
vendored
22
testdata/k8s/config.yaml
vendored
@ -1,24 +1,4 @@
|
|||||||
apiVersion: airshipit.org/v1alpha1
|
apiVersion: airshipit.org/v1alpha1
|
||||||
bootstrapInfo:
|
|
||||||
default:
|
|
||||||
builder:
|
|
||||||
networkConfigFileName: network-config
|
|
||||||
outputMetadataFileName: output-metadata.yaml
|
|
||||||
userDataFileName: user-data
|
|
||||||
container:
|
|
||||||
containerRuntime: docker
|
|
||||||
image: quay.io/airshipit/isogen:latest-ubuntu_focal
|
|
||||||
volume: /srv/iso:/config
|
|
||||||
remoteDirect:
|
|
||||||
isoUrl: http://localhost:8099/ubuntu-focal.iso
|
|
||||||
clusters:
|
|
||||||
default:
|
|
||||||
clusterType:
|
|
||||||
target:
|
|
||||||
bootstrapInfo: ""
|
|
||||||
clusterKubeconf: default_target
|
|
||||||
kubernetes:
|
|
||||||
clusterType: {}
|
|
||||||
contexts:
|
contexts:
|
||||||
default:
|
default:
|
||||||
contextKubeconf: default_target
|
contextKubeconf: default_target
|
||||||
@ -36,5 +16,3 @@ manifests:
|
|||||||
tag: ""
|
tag: ""
|
||||||
url: https://opendev.org/airship/treasuremap
|
url: https://opendev.org/airship/treasuremap
|
||||||
targetPath: /tmp/default
|
targetPath: /tmp/default
|
||||||
users:
|
|
||||||
admin: {}
|
|
||||||
|
@ -36,12 +36,6 @@ func DummyConfig() *config.Config {
|
|||||||
conf := &config.Config{
|
conf := &config.Config{
|
||||||
Kind: config.AirshipConfigKind,
|
Kind: config.AirshipConfigKind,
|
||||||
APIVersion: config.AirshipConfigAPIVersion,
|
APIVersion: config.AirshipConfigAPIVersion,
|
||||||
Clusters: map[string]*config.ClusterPurpose{
|
|
||||||
"dummy_cluster": DummyClusterPurpose(),
|
|
||||||
},
|
|
||||||
AuthInfos: map[string]*config.AuthInfo{
|
|
||||||
"dummy_user": DummyAuthInfo(),
|
|
||||||
},
|
|
||||||
Permissions: config.Permissions{
|
Permissions: config.Permissions{
|
||||||
DirectoryPermission: config.AirshipDefaultDirectoryPermission,
|
DirectoryPermission: config.AirshipDefaultDirectoryPermission,
|
||||||
FilePermission: config.AirshipDefaultFilePermission,
|
FilePermission: config.AirshipDefaultFilePermission,
|
||||||
@ -61,10 +55,6 @@ func DummyConfig() *config.Config {
|
|||||||
CurrentContext: "dummy_context",
|
CurrentContext: "dummy_context",
|
||||||
}
|
}
|
||||||
conf.SetKubeConfig(kubeconfig.NewConfig())
|
conf.SetKubeConfig(kubeconfig.NewConfig())
|
||||||
|
|
||||||
dummyCluster := conf.Clusters["dummy_cluster"]
|
|
||||||
conf.KubeConfig().Clusters["dummy_cluster_target"] = dummyCluster.ClusterTypes[config.Target].KubeCluster()
|
|
||||||
conf.KubeConfig().Clusters["dummy_cluster_ephemeral"] = dummyCluster.ClusterTypes[config.Ephemeral].KubeCluster()
|
|
||||||
return conf
|
return conf
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,26 +63,7 @@ func DummyContext() *config.Context {
|
|||||||
c := config.NewContext()
|
c := config.NewContext()
|
||||||
c.NameInKubeconf = "dummy_cluster_ephemeral"
|
c.NameInKubeconf = "dummy_cluster_ephemeral"
|
||||||
c.Manifest = "dummy_manifest"
|
c.Manifest = "dummy_manifest"
|
||||||
context := kubeconfig.NewContext()
|
|
||||||
context.Namespace = "dummy_namespace"
|
|
||||||
context.AuthInfo = "dummy_user"
|
|
||||||
context.Cluster = "dummy_cluster_ephemeral"
|
|
||||||
c.EncryptionConfig = "dummy_encryption_config"
|
c.EncryptionConfig = "dummy_encryption_config"
|
||||||
c.SetKubeContext(context)
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// DummyCluster creates a Cluster config object for unit testing
|
|
||||||
func DummyCluster() *config.Cluster {
|
|
||||||
c := config.NewCluster()
|
|
||||||
|
|
||||||
cluster := kubeconfig.NewCluster()
|
|
||||||
cluster.Server = "http://dummy.server"
|
|
||||||
cluster.InsecureSkipTLSVerify = false
|
|
||||||
cluster.CertificateAuthority = "dummy_ca"
|
|
||||||
c.SetKubeCluster(cluster)
|
|
||||||
c.NameInKubeconf = "dummy_cluster_target"
|
|
||||||
c.ManagementConfiguration = "dummy_management_config"
|
c.ManagementConfiguration = "dummy_management_config"
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
@ -140,29 +111,6 @@ func DummyRepoCheckout() *config.RepoCheckout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DummyAuthInfo creates a AuthInfo config object for unit testing
|
|
||||||
func DummyAuthInfo() *config.AuthInfo {
|
|
||||||
a := config.NewAuthInfo()
|
|
||||||
authinfo := kubeconfig.NewAuthInfo()
|
|
||||||
authinfo.Username = "dummy_username"
|
|
||||||
authinfo.Password = "dummy_password"
|
|
||||||
authinfo.ClientCertificate = "dummy_certificate"
|
|
||||||
authinfo.ClientKey = "dummy_key"
|
|
||||||
authinfo.Token = "dummy_token"
|
|
||||||
encodedAuthInfo := config.EncodeAuthInfo(authinfo)
|
|
||||||
a.SetKubeAuthInfo(encodedAuthInfo)
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
// DummyClusterPurpose creates ClusterPurpose config object for unit testing
|
|
||||||
func DummyClusterPurpose() *config.ClusterPurpose {
|
|
||||||
cp := config.NewClusterPurpose()
|
|
||||||
cp.ClusterTypes["ephemeral"] = DummyCluster()
|
|
||||||
cp.ClusterTypes["ephemeral"].NameInKubeconf = "dummy_cluster_ephemeral"
|
|
||||||
cp.ClusterTypes["target"] = DummyCluster()
|
|
||||||
return cp
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitConfig creates a Config object meant for testing.
|
// InitConfig creates a Config object meant for testing.
|
||||||
//
|
//
|
||||||
// The returned config object will be associated with real files stored in a
|
// The returned config object will be associated with real files stored in a
|
||||||
@ -188,46 +136,17 @@ func InitConfig(t *testing.T) (conf *config.Config, cleanup func(*testing.T)) {
|
|||||||
return conf, cleanup
|
return conf, cleanup
|
||||||
}
|
}
|
||||||
|
|
||||||
// DummyClusterOptions creates ClusterOptions config object
|
|
||||||
// for unit testing
|
|
||||||
func DummyClusterOptions() *config.ClusterOptions {
|
|
||||||
co := &config.ClusterOptions{}
|
|
||||||
co.Name = "dummy_cluster"
|
|
||||||
co.ClusterType = config.Ephemeral
|
|
||||||
co.Server = "http://1.1.1.1"
|
|
||||||
co.InsecureSkipTLSVerify = false
|
|
||||||
co.CertificateAuthority = ""
|
|
||||||
co.EmbedCAData = false
|
|
||||||
|
|
||||||
return co
|
|
||||||
}
|
|
||||||
|
|
||||||
// DummyContextOptions creates ContextOptions config object
|
// DummyContextOptions creates ContextOptions config object
|
||||||
// for unit testing
|
// for unit testing
|
||||||
func DummyContextOptions() *config.ContextOptions {
|
func DummyContextOptions() *config.ContextOptions {
|
||||||
co := &config.ContextOptions{}
|
co := &config.ContextOptions{}
|
||||||
co.Name = "dummy_context"
|
co.Name = "dummy_context"
|
||||||
co.Manifest = "dummy_manifest"
|
co.Manifest = "dummy_manifest"
|
||||||
co.AuthInfo = "dummy_user"
|
|
||||||
co.CurrentContext = false
|
co.CurrentContext = false
|
||||||
co.Namespace = "dummy_namespace"
|
|
||||||
co.EncryptionConfig = "dummy_encryption_config"
|
co.EncryptionConfig = "dummy_encryption_config"
|
||||||
|
|
||||||
return co
|
return co
|
||||||
}
|
}
|
||||||
|
|
||||||
// DummyAuthInfoOptions creates AuthInfoOptions config object
|
|
||||||
// for unit testing
|
|
||||||
func DummyAuthInfoOptions() *config.AuthInfoOptions {
|
|
||||||
authinfo := &config.AuthInfoOptions{}
|
|
||||||
authinfo.Username = "dummy_username"
|
|
||||||
authinfo.Password = "dummy_password"
|
|
||||||
authinfo.ClientCertificate = "dummy_certificate"
|
|
||||||
authinfo.ClientKey = "dummy_key"
|
|
||||||
authinfo.Token = "dummy_token"
|
|
||||||
return authinfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// DummyEncryptionConfig creates EncryptionConfigOptions object
|
// DummyEncryptionConfig creates EncryptionConfigOptions object
|
||||||
// for unit testing
|
// for unit testing
|
||||||
func DummyEncryptionConfig() *config.EncryptionConfig {
|
func DummyEncryptionConfig() *config.EncryptionConfig {
|
||||||
@ -275,31 +194,6 @@ func DummyManifestOptions() *config.ManifestOptions {
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
testConfigYAML = `apiVersion: airshipit.org/v1alpha1
|
testConfigYAML = `apiVersion: airshipit.org/v1alpha1
|
||||||
bootstrapInfo:
|
|
||||||
default: {}
|
|
||||||
clusters:
|
|
||||||
straggler:
|
|
||||||
clusterType:
|
|
||||||
ephemeral:
|
|
||||||
clusterKubeconf: notThere
|
|
||||||
def:
|
|
||||||
clusterType:
|
|
||||||
ephemeral:
|
|
||||||
clusterKubeconf: def_ephemeral
|
|
||||||
target:
|
|
||||||
clusterKubeconf: def_target
|
|
||||||
onlyinkubeconf:
|
|
||||||
clusterType:
|
|
||||||
target:
|
|
||||||
clusterKubeconf: onlyinkubeconf_target
|
|
||||||
wrongonlyinconfig:
|
|
||||||
clusterType: {}
|
|
||||||
wrongonlyinkubeconf:
|
|
||||||
clusterType:
|
|
||||||
target:
|
|
||||||
clusterKubeconf: wrongonlyinkubeconf_target
|
|
||||||
clustertypenil:
|
|
||||||
clusterType: null
|
|
||||||
contexts:
|
contexts:
|
||||||
def_ephemeral:
|
def_ephemeral:
|
||||||
contextKubeconf: def_ephemeral
|
contextKubeconf: def_ephemeral
|
||||||
@ -310,11 +204,7 @@ contexts:
|
|||||||
encryptionConfigs: {}
|
encryptionConfigs: {}
|
||||||
currentContext: ""
|
currentContext: ""
|
||||||
kind: Config
|
kind: Config
|
||||||
manifests: {}
|
manifests: {}`
|
||||||
users:
|
|
||||||
k-admin: {}
|
|
||||||
k-other: {}
|
|
||||||
def-user: {}`
|
|
||||||
|
|
||||||
//nolint:lll
|
//nolint:lll
|
||||||
testKubeConfigYAML = `apiVersion: v1
|
testKubeConfigYAML = `apiVersion: v1
|
||||||
|
@ -53,4 +53,3 @@ mkdir -p $HOME/.airship
|
|||||||
echo "Generate ~/.airship/config and ~/.airship/kubeconfig"
|
echo "Generate ~/.airship/config and ~/.airship/kubeconfig"
|
||||||
envsubst <"${AIRSHIPCTL_WS}/tools/deployment/templates/airshipconfig_template" > ~/.airship/config
|
envsubst <"${AIRSHIPCTL_WS}/tools/deployment/templates/airshipconfig_template" > ~/.airship/config
|
||||||
envsubst <"${AIRSHIPCTL_WS}/tools/deployment/templates/kubeconfig_template" > ~/.airship/kubeconfig
|
envsubst <"${AIRSHIPCTL_WS}/tools/deployment/templates/kubeconfig_template" > ~/.airship/kubeconfig
|
||||||
|
|
||||||
|
@ -1,19 +1,4 @@
|
|||||||
apiVersion: airshipit.org/v1alpha1
|
apiVersion: airshipit.org/v1alpha1
|
||||||
bootstrapInfo:
|
|
||||||
dummy_bootstrap_config:
|
|
||||||
container:
|
|
||||||
volume: ${AIRSHIP_CONFIG_ISO_GEN_TARGET_PATH}:/config
|
|
||||||
image: ${AIRSHIP_CONFIG_ISO_BUILDER_DOCKER_IMAGE}
|
|
||||||
containerRuntime: docker
|
|
||||||
remoteDirect:
|
|
||||||
remoteType: ${REMOTE_TYPE}
|
|
||||||
insecure: ${REMOTE_INSECURE}
|
|
||||||
useproxy: ${REMOTE_PROXY}
|
|
||||||
isoUrl: http://${AIRSHIP_CONFIG_ISO_SERVE_HOST}:${AIRSHIP_CONFIG_ISO_PORT}/${AIRSHIP_CONFIG_ISO_NAME}
|
|
||||||
builder:
|
|
||||||
userDataFileName: user-data
|
|
||||||
networkConfigFileName: network-config
|
|
||||||
outputMetadataFileName: output-metadata.yaml
|
|
||||||
managementConfiguration:
|
managementConfiguration:
|
||||||
dummy_management_config:
|
dummy_management_config:
|
||||||
type: ${REMOTE_TYPE}
|
type: ${REMOTE_TYPE}
|
||||||
@ -21,26 +6,15 @@ managementConfiguration:
|
|||||||
useproxy: ${REMOTE_PROXY}
|
useproxy: ${REMOTE_PROXY}
|
||||||
systemActionRetries: ${SYSTEM_ACTION_RETRIES}
|
systemActionRetries: ${SYSTEM_ACTION_RETRIES}
|
||||||
systemRebootDelay: ${SYSTEM_REBOOT_DELAY}
|
systemRebootDelay: ${SYSTEM_REBOOT_DELAY}
|
||||||
|
|
||||||
clusters:
|
|
||||||
ephemeral-cluster:
|
|
||||||
clusterType:
|
|
||||||
ephemeral:
|
|
||||||
bootstrapInfo: dummy_bootstrap_config
|
|
||||||
clusterKubeconf: ephemeral-cluster_ephemeral
|
|
||||||
managementConfiguration: dummy_management_config
|
|
||||||
target-cluster:
|
|
||||||
clusterType:
|
|
||||||
target:
|
|
||||||
clusterKubeconf: target-cluster_target
|
|
||||||
managementConfiguration: dummy_management_config
|
|
||||||
contexts:
|
contexts:
|
||||||
ephemeral-cluster:
|
ephemeral-cluster:
|
||||||
contextKubeconf: ephemeral-context
|
contextKubeconf: ephemeral-cluster_ephemeral
|
||||||
manifest: dummy_manifest
|
manifest: dummy_manifest
|
||||||
|
managementConfiguration: dummy_management_config
|
||||||
target-cluster:
|
target-cluster:
|
||||||
contextKubeconf: target-context
|
contextKubeconf: target-cluster_target
|
||||||
manifest: dummy_manifest
|
manifest: dummy_manifest
|
||||||
|
managementConfiguration: dummy_management_config
|
||||||
currentContext: ephemeral-cluster
|
currentContext: ephemeral-cluster
|
||||||
kind: Config
|
kind: Config
|
||||||
manifests:
|
manifests:
|
||||||
@ -57,6 +31,3 @@ manifests:
|
|||||||
metadataPath: manifests/metadata.yaml
|
metadataPath: manifests/metadata.yaml
|
||||||
subPath: ${AIRSHIP_SITE_NAME}
|
subPath: ${AIRSHIP_SITE_NAME}
|
||||||
targetPath: ${AIRSHIP_CONFIG_MANIFEST_DIRECTORY}
|
targetPath: ${AIRSHIP_CONFIG_MANIFEST_DIRECTORY}
|
||||||
users:
|
|
||||||
ephemeral-cluster-admin: {}
|
|
||||||
target-cluster-admin: {}
|
|
||||||
|
@ -54,17 +54,11 @@ function generate_airshipconf {
|
|||||||
|
|
||||||
cat <<EOL > ${AIRSHIPCONFIG}
|
cat <<EOL > ${AIRSHIPCONFIG}
|
||||||
apiVersion: airshipit.org/v1alpha1
|
apiVersion: airshipit.org/v1alpha1
|
||||||
clusters:
|
|
||||||
${CONTEXT}_${cluster}:
|
|
||||||
clusterType:
|
|
||||||
${cluster}:
|
|
||||||
bootstrapInfo: default
|
|
||||||
clusterKubeconf: ${CONTEXT}_${cluster}
|
|
||||||
managementConfiguration: default
|
|
||||||
contexts:
|
contexts:
|
||||||
${CONTEXT}_${cluster}:
|
${CONTEXT}_${cluster}:
|
||||||
contextKubeconf: ${CONTEXT}_${cluster}
|
contextKubeconf: ${CONTEXT}_${cluster}
|
||||||
manifest: ${CONTEXT}_${cluster}
|
manifest: ${CONTEXT}_${cluster}
|
||||||
|
managementConfiguration: default
|
||||||
currentContext: ${CONTEXT}_${cluster}
|
currentContext: ${CONTEXT}_${cluster}
|
||||||
kind: Config
|
kind: Config
|
||||||
managementConfiguration:
|
managementConfiguration:
|
||||||
@ -86,8 +80,6 @@ manifests:
|
|||||||
url: https://opendev.org/airship/treasuremap
|
url: https://opendev.org/airship/treasuremap
|
||||||
subPath: ${SITE_ROOT}/${SITE}
|
subPath: ${SITE_ROOT}/${SITE}
|
||||||
targetPath: ${MANIFEST_ROOT}
|
targetPath: ${MANIFEST_ROOT}
|
||||||
users:
|
|
||||||
${CONTEXT}_${cluster}: {}
|
|
||||||
EOL
|
EOL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user