Organize CLI helper functions

* moving cli helper functions to the respective packages with _helper.
* removed cmds.go within pkg/ dir and added config_helper.go

* In the first commit(https://review.opendev.org/#/c/707216/) commit CLI helper
  functions were moved from the cmd/config package to the pkg/config package
* Now we are trying to move the CLI helper functions within their respective packages instead of a command cmds.go.
* Creating and implementing this convention will help us better distinguish library code and CLI helper code
* Added MaxNArgs as 1 for get-credentials and updated test cases

Relates-To: #43
Change-Id: Ibb8139102bd98c6c7596bd97377cf83381cbeb00
This commit is contained in:
Yasin, Siraj (SY495P) 2020-03-18 18:16:56 -05:00
parent e9f8ac3ac3
commit 01d66c834d
15 changed files with 199 additions and 392 deletions

View File

@ -17,6 +17,8 @@ limitations under the License.
package config
import (
"fmt"
"github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/config"
@ -42,11 +44,26 @@ func NewCmdConfigGetAuthInfo(rootSettings *environment.AirshipCTLSettings) *cobr
Short: "Gets a user entry from the airshipctl config",
Long: getAuthInfoLong,
Example: getAuthInfoExample,
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
airconfig := rootSettings.Config
if len(args) == 1 {
o.Name = args[0]
authinfo, err := airconfig.GetAuthInfo(o.Name)
if err != nil {
return err
}
fmt.Fprintln(cmd.OutOrStdout(), authinfo)
} else {
authinfos := airconfig.GetAuthInfos()
if len(authinfos) == 0 {
fmt.Fprintln(cmd.OutOrStdout(), "No User credentials found in the configuration.")
}
for _, authinfo := range authinfos {
fmt.Fprintln(cmd.OutOrStdout(), authinfo)
}
}
return config.RunGetAuthInfo(o, cmd.OutOrStdout(), rootSettings.Config)
return nil
},
}

View File

@ -54,13 +54,12 @@ func TestGetAuthInfoCmd(t *testing.T) {
},
{
Name: "get-all-credentials",
CmdLine: fmt.Sprintf("%s %s", fooAuthInfo, barAuthInfo),
CmdLine: fmt.Sprintf(""),
Cmd: cmd.NewCmdConfigGetAuthInfo(settings),
},
// This is not implemented yet
{
Name: "get-multiple-credentials",
CmdLine: fmt.Sprintf("%s %s", fooAuthInfo, barAuthInfo),
Name: "get-specific-credentials",
CmdLine: fmt.Sprintf("%s", fooAuthInfo),
Cmd: cmd.NewCmdConfigGetAuthInfo(settings),
},

View File

@ -44,16 +44,31 @@ func NewCmdConfigGetCluster(rootSettings *environment.AirshipCTLSettings) *cobra
Short: getClusterLong,
Example: getClusterExample,
RunE: func(cmd *cobra.Command, args []string) error {
airconfig := rootSettings.Config
if len(args) == 1 {
o.Name = args[0]
err := validate(o)
if err != nil {
return err
}
cluster, err := airconfig.GetCluster(o.Name, o.ClusterType)
if err != nil {
return err
}
fmt.Fprintln(cmd.OutOrStdout(), cluster.PrettyString())
return nil
}
err := validate(o)
if err != nil {
return err
clusters := airconfig.GetClusters()
if len(clusters) == 0 {
fmt.Fprintln(cmd.OutOrStdout(), "No clusters found in the configuration.")
}
return config.RunGetCluster(o, cmd.OutOrStdout(), rootSettings.Config)
for _, cluster := range clusters {
fmt.Fprintln(cmd.OutOrStdout(), cluster.PrettyString())
}
return nil
},
}

View File

@ -51,10 +51,31 @@ func NewCmdConfigGetContext(rootSettings *environment.AirshipCTLSettings) *cobra
Short: getContextLong,
Example: getContextExample,
RunE: func(cmd *cobra.Command, args []string) error {
airconfig := rootSettings.Config
if len(args) == 1 {
o.Name = args[0]
}
return config.RunGetContext(o, cmd.OutOrStdout(), rootSettings.Config)
if o.Name == "" && !o.CurrentContext {
contexts := airconfig.GetContexts()
if len(contexts) == 0 {
fmt.Fprintln(cmd.OutOrStdout(), "No Contexts found in the configuration.")
}
for _, context := range contexts {
fmt.Fprintln(cmd.OutOrStdout(), context.PrettyString())
}
return nil
}
if o.CurrentContext {
o.Name = airconfig.CurrentContext
}
context, err := airconfig.GetContext(o.Name)
if err != nil {
return err
}
fmt.Fprintln(cmd.OutOrStdout(), context.PrettyString())
return nil
},
}

View File

@ -1,21 +0,0 @@
LocationOfOrigin: ""
client-certificate: dummy_certificate
client-key: dummy_key
password: dummy_password
token: dummy_token
username: dummy_user
LocationOfOrigin: ""
client-certificate: dummy_certificate
client-key: dummy_key
password: dummy_password
token: dummy_token
username: dummy_user
LocationOfOrigin: ""
client-certificate: dummy_certificate
client-key: dummy_key
password: dummy_password
token: dummy_token
username: dummy_user

View File

@ -0,0 +1,7 @@
LocationOfOrigin: ""
client-certificate: dummy_certificate
client-key: dummy_key
password: dummy_password
token: dummy_token
username: dummy_user

View File

@ -6,3 +6,4 @@ cluster-kubeconf: clusterFoo_ephemeral
LocationOfOrigin: ""
insecure-skip-tls-verify: true
server: ""

View File

@ -6,3 +6,4 @@ cluster-kubeconf: clusterFoo_target
LocationOfOrigin: ""
insecure-skip-tls-verify: true
server: ""

View File

@ -7,6 +7,7 @@ cluster: dummycluster_ephemeral
namespace: dummy_namespace
user: dummy_user
Context: ContextBaz
context-kubeconf: ContextBaz_ephemeral
manifest: Manifest_ContextBaz
@ -16,6 +17,7 @@ cluster: dummycluster_ephemeral
namespace: dummy_namespace
user: dummy_user
Context: ContextFoo
context-kubeconf: ContextFoo_ephemeral
manifest: Manifest_ContextFoo
@ -25,3 +27,4 @@ cluster: dummycluster_ephemeral
namespace: dummy_namespace
user: dummy_user

View File

@ -7,3 +7,4 @@ cluster: dummycluster_ephemeral
namespace: dummy_namespace
user: dummy_user

View File

@ -7,3 +7,4 @@ cluster: dummycluster_ephemeral
namespace: dummy_namespace
user: dummy_user

View File

@ -7,6 +7,7 @@ cluster: dummycluster_ephemeral
namespace: dummy_namespace
user: dummy_user
Context: ContextBaz
context-kubeconf: ContextBaz_ephemeral
manifest: Manifest_ContextBaz
@ -16,6 +17,7 @@ cluster: dummycluster_ephemeral
namespace: dummy_namespace
user: dummy_user
Context: ContextFoo
context-kubeconf: ContextFoo_ephemeral
manifest: Manifest_ContextFoo
@ -25,3 +27,4 @@ cluster: dummycluster_ephemeral
namespace: dummy_namespace
user: dummy_user

View File

@ -1,270 +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 (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/testutil"
)
func TestRunGetAuthInfo(t *testing.T) {
t.Run("testNonExistentAuthInfo", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyAuthInfoOptions := testutil.DummyAuthInfoOptions()
dummyAuthInfoOptions.Name = "nonexistent_user"
output := new(bytes.Buffer)
err := config.RunGetAuthInfo(dummyAuthInfoOptions, output, conf)
assert.Error(t, err)
})
t.Run("testSingleAuthInfo", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyAuthInfoOptions := testutil.DummyAuthInfoOptions()
output := new(bytes.Buffer)
err := config.RunGetAuthInfo(dummyAuthInfoOptions, output, conf)
expectedOutput := conf.AuthInfos["dummy_user"].String() + "\n"
assert.NoError(t, err)
assert.Equal(t, expectedOutput, output.String())
})
t.Run("testAllAuthInfo", func(t *testing.T) {
conf := testutil.DummyConfig()
secondAuthInfo := testutil.DummyAuthInfo()
secondUserName := "second_user"
newKubeAuthInfo := testutil.DummyKubeAuthInfo()
newKubeAuthInfo.Username = secondUserName
secondAuthInfo.SetKubeAuthInfo(newKubeAuthInfo)
conf.AuthInfos[secondUserName] = secondAuthInfo
dummyAuthInfoOptions := testutil.DummyAuthInfoOptions()
dummyAuthInfoOptions.Name = ""
output := new(bytes.Buffer)
err := config.RunGetAuthInfo(dummyAuthInfoOptions, output, conf)
expectedOutput := conf.AuthInfos["dummy_user"].String() + "\n" + conf.AuthInfos[secondUserName].String() + "\n"
assert.NoError(t, err)
assert.Equal(t, expectedOutput, output.String())
})
t.Run("testNoAuthInfos", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyAuthInfoOptions := testutil.DummyAuthInfoOptions()
dummyAuthInfoOptions.Name = ""
delete(conf.AuthInfos, "dummy_user")
output := new(bytes.Buffer)
err := config.RunGetAuthInfo(dummyAuthInfoOptions, output, conf)
expectedMessage := "No User credentials found in the configuration.\n"
assert.NoError(t, err)
assert.Equal(t, expectedMessage, output.String())
})
}
func TestRunGetCluster(t *testing.T) {
const dummyClusterEphemeralName = "dummy_cluster_ephemeral"
t.Run("testNonExistentCluster", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyClusterOptions := testutil.DummyClusterOptions()
dummyClusterOptions.Name = "nonexistent_cluster"
output := new(bytes.Buffer)
err := config.RunGetCluster(dummyClusterOptions, output, conf)
assert.Error(t, err)
})
t.Run("testSingleCluster", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyClusterOptions := testutil.DummyClusterOptions()
output := new(bytes.Buffer)
err := config.RunGetCluster(dummyClusterOptions, output, conf)
expectedCluster := testutil.DummyCluster()
expectedCluster.NameInKubeconf = dummyClusterEphemeralName
assert.NoError(t, err)
assert.Equal(t, expectedCluster.PrettyString(), output.String())
})
t.Run("testAllClusters", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyClusterOptions := testutil.DummyClusterOptions()
dummyClusterOptions.Name = ""
output := new(bytes.Buffer)
err := config.RunGetCluster(dummyClusterOptions, output, conf)
expectedClusterTarget := testutil.DummyCluster()
expectedClusterEphemeral := testutil.DummyCluster()
expectedClusterEphemeral.NameInKubeconf = dummyClusterEphemeralName
expectedOutput := expectedClusterEphemeral.PrettyString() + "\n" + expectedClusterTarget.PrettyString() + "\n"
assert.NoError(t, err)
assert.Equal(t, expectedOutput, output.String())
})
t.Run("testNoClusters", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyClusterOptions := testutil.DummyClusterOptions()
dummyClusterOptions.Name = ""
delete(conf.Clusters, "dummy_cluster")
output := new(bytes.Buffer)
err := config.RunGetCluster(dummyClusterOptions, output, conf)
expectedMessage := "No clusters found in the configuration.\n"
assert.NoError(t, err)
assert.Equal(t, expectedMessage, output.String())
})
}
func TestRunGetContext(t *testing.T) {
t.Run("testNonExistentContext", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyContextOptions := testutil.DummyContextOptions()
dummyContextOptions.Name = "nonexistent_context"
output := new(bytes.Buffer)
err := config.RunGetContext(dummyContextOptions, output, conf)
assert.Error(t, err)
})
t.Run("testSingleContext", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyContextOptions := testutil.DummyContextOptions()
output := new(bytes.Buffer)
err := config.RunGetContext(dummyContextOptions, output, conf)
assert.NoError(t, err)
assert.Equal(t, conf.Contexts["dummy_context"].PrettyString(), output.String())
})
t.Run("testAllContext", func(t *testing.T) {
conf := testutil.DummyConfig()
newCtx := testutil.DummyContext()
newCtx.NameInKubeconf = "second_context"
conf.Contexts["second_context"] = newCtx
dummyContextOptions := testutil.DummyContextOptions()
dummyContextOptions.Name = ""
output := new(bytes.Buffer)
err := config.RunGetContext(dummyContextOptions, output, conf)
expectedOutput := conf.Contexts["dummy_context"].PrettyString() + conf.Contexts["second_context"].PrettyString()
assert.NoError(t, err)
assert.Equal(t, expectedOutput, output.String())
})
t.Run("testNoContexts", func(t *testing.T) {
conf := testutil.DummyConfig()
delete(conf.Contexts, "dummy_context")
dummyContextOptions := testutil.DummyContextOptions()
dummyContextOptions.Name = ""
output := new(bytes.Buffer)
err := config.RunGetContext(dummyContextOptions, output, conf)
expectedOutput := "No Contexts found in the configuration.\n"
assert.NoError(t, err)
assert.Equal(t, expectedOutput, output.String())
})
}
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) {
t.Run("testAddContext", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyContextOptions := testutil.DummyContextOptions()
dummyContextOptions.Name = "second_context"
modified, err := config.RunSetContext(dummyContextOptions, conf, false)
assert.NoError(t, err)
assert.False(t, modified)
assert.Contains(t, conf.Contexts, "second_context")
})
t.Run("testModifyContext", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyContextOptions := testutil.DummyContextOptions()
dummyContextOptions.Namespace = "new_namespace"
modified, err := config.RunSetContext(dummyContextOptions, conf, false)
assert.NoError(t, err)
assert.True(t, modified)
assert.Equal(t, "new_namespace", conf.Contexts["dummy_context"].KubeContext().Namespace)
})
}
func TestRunUseContext(t *testing.T) {
t.Run("testUseContext", func(t *testing.T) {
conf := testutil.DummyConfig()
err := config.RunUseContext("dummy_context", conf)
assert.Nil(t, err)
})
t.Run("testUseContextDoesNotExist", func(t *testing.T) {
conf := config.NewConfig()
err := config.RunUseContext("foo", conf)
assert.Error(t, err)
})
}

View File

@ -18,98 +18,8 @@ package config
import (
"errors"
"fmt"
"io"
)
// RunGetAuthInfo performs the execution of 'config get-credentials' sub command
func RunGetAuthInfo(o *AuthInfoOptions, out io.Writer, airconfig *Config) error {
if o.Name == "" {
getAuthInfos(out, airconfig)
return nil
}
return getAuthInfo(o, out, airconfig)
}
func getAuthInfo(o *AuthInfoOptions, out io.Writer, airconfig *Config) error {
authinfo, err := airconfig.GetAuthInfo(o.Name)
if err != nil {
return err
}
fmt.Fprintln(out, authinfo)
return nil
}
func getAuthInfos(out io.Writer, airconfig *Config) {
authinfos := airconfig.GetAuthInfos()
if len(authinfos) == 0 {
fmt.Fprintln(out, "No User credentials found in the configuration.")
}
for _, authinfo := range authinfos {
fmt.Fprintln(out, authinfo)
}
}
// RunGetCluster performs the execution of 'config get-cluster' sub command
func RunGetCluster(o *ClusterOptions, out io.Writer, airconfig *Config) error {
if o.Name == "" {
getClusters(out, airconfig)
return nil
}
return getCluster(o.Name, o.ClusterType, out, airconfig)
}
func getCluster(cName, cType string, out io.Writer, airconfig *Config) error {
cluster, err := airconfig.GetCluster(cName, cType)
if err != nil {
return err
}
fmt.Fprintf(out, "%s", cluster.PrettyString())
return nil
}
func getClusters(out io.Writer, airconfig *Config) {
clusters := airconfig.GetClusters()
if len(clusters) == 0 {
fmt.Fprintln(out, "No clusters found in the configuration.")
}
for _, cluster := range clusters {
fmt.Fprintf(out, "%s\n", cluster.PrettyString())
}
}
// RunGetContext performs the execution of 'config get-Context' sub command
func RunGetContext(o *ContextOptions, out io.Writer, airconfig *Config) error {
if o.Name == "" && !o.CurrentContext {
getContexts(out, airconfig)
return nil
}
return getContext(o, out, airconfig)
}
func getContext(o *ContextOptions, out io.Writer, airconfig *Config) error {
if o.CurrentContext {
o.Name = airconfig.CurrentContext
}
context, err := airconfig.GetContext(o.Name)
if err != nil {
return err
}
fmt.Fprintf(out, "%s", context.PrettyString())
return nil
}
func getContexts(out io.Writer, airconfig *Config) {
contexts := airconfig.GetContexts()
if len(contexts) == 0 {
fmt.Fprintln(out, "No Contexts found in the configuration.")
}
for _, context := range contexts {
fmt.Fprintf(out, "%s", context.PrettyString())
}
}
func RunSetAuthInfo(o *AuthInfoOptions, airconfig *Config, writeToStorage bool) (bool, error) {
modified := false
err := o.Validate()

View File

@ -0,0 +1,119 @@
/*
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"
"opendev.org/airship/airshipctl/pkg/config"
"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) {
t.Run("testAddContext", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyContextOptions := testutil.DummyContextOptions()
dummyContextOptions.Name = "second_context"
modified, err := config.RunSetContext(dummyContextOptions, conf, false)
assert.NoError(t, err)
assert.False(t, modified)
assert.Contains(t, conf.Contexts, "second_context")
})
t.Run("testModifyContext", func(t *testing.T) {
conf := testutil.DummyConfig()
dummyContextOptions := testutil.DummyContextOptions()
dummyContextOptions.Namespace = "new_namespace"
modified, err := config.RunSetContext(dummyContextOptions, conf, false)
assert.NoError(t, err)
assert.True(t, modified)
assert.Equal(t, "new_namespace", conf.Contexts["dummy_context"].KubeContext().Namespace)
})
}
func TestRunUseContext(t *testing.T) {
t.Run("testUseContext", func(t *testing.T) {
conf := testutil.DummyConfig()
err := config.RunUseContext("dummy_context", conf)
assert.Nil(t, err)
})
t.Run("testUseContextDoesNotExist", func(t *testing.T) {
conf := config.NewConfig()
err := config.RunUseContext("foo", conf)
assert.Error(t, err)
})
}