Skip to content
Snippets Groups Projects
Commit e3e35d30 authored by Jessica Yuen's avatar Jessica Yuen
Browse files

Init env metadata from provided context

`ks env add myenv --context=dev` will initialize the environment URI
and namespace based on the context `dev`, as specfied in the
kubeconfig file. The same applies for `ks init foo --context=dev`.

If both the context and uri argument is not provided, the current
context is used.

This change will also remove uri as a mandatory arg in `ks env add`.
The uri will be moved to a flag. It cannot be used at the same time as
`context`.
parent 6a281b9a
No related branches found
No related tags found
No related merge requests found
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
"os" "os"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/ksonnet/ksonnet/metadata" "github.com/ksonnet/ksonnet/metadata"
"github.com/ksonnet/ksonnet/pkg/kubecfg" "github.com/ksonnet/ksonnet/pkg/kubecfg"
...@@ -29,6 +30,7 @@ const ( ...@@ -29,6 +30,7 @@ const (
flagEnvName = "name" flagEnvName = "name"
flagEnvURI = "uri" flagEnvURI = "uri"
flagEnvNamespace = "namespace" flagEnvNamespace = "namespace"
flagEnvContext = "context"
) )
func init() { func init() {
...@@ -45,6 +47,10 @@ func init() { ...@@ -45,6 +47,10 @@ func init() {
"Manually specify API version from OpenAPI schema, cluster, or Kubernetes version") "Manually specify API version from OpenAPI schema, cluster, or Kubernetes version")
envAddCmd.PersistentFlags().String(flagEnvNamespace, "", envAddCmd.PersistentFlags().String(flagEnvNamespace, "",
"Specify namespace that the environment cluster should use") "Specify namespace that the environment cluster should use")
envAddCmd.PersistentFlags().String(flagEnvURI, "",
"Specify the server URI that the environment should use")
envAddCmd.PersistentFlags().String(flagEnvContext, "",
"Specify the context in your kubecfg file that this environment should use")
envSetCmd.PersistentFlags().String(flagEnvName, "", envSetCmd.PersistentFlags().String(flagEnvName, "",
"Specify name to rename environment to. Name must not already exist") "Specify name to rename environment to. Name must not already exist")
...@@ -52,6 +58,8 @@ func init() { ...@@ -52,6 +58,8 @@ func init() {
"Specify URI to point environment cluster to a new location") "Specify URI to point environment cluster to a new location")
envSetCmd.PersistentFlags().String(flagEnvNamespace, "", envSetCmd.PersistentFlags().String(flagEnvNamespace, "",
"Specify namespace that the environment cluster should use") "Specify namespace that the environment cluster should use")
envSetCmd.PersistentFlags().String(flagEnvContext, "",
"Specify the context in your kubecfg file that this environment should use. This will update the server URI for your environment")
} }
var envCmd = &cobra.Command{ var envCmd = &cobra.Command{
...@@ -95,22 +103,41 @@ environments/ ...@@ -95,22 +103,41 @@ environments/
} }
var envAddCmd = &cobra.Command{ var envAddCmd = &cobra.Command{
Use: "add <env-name> <env-uri>", Use: "add <env-name>",
Short: "Add a new environment to a ksonnet project", Short: "Add a new environment to a ksonnet project",
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
flags := cmd.Flags() flags := cmd.Flags()
if len(args) != 2 { if len(args) != 1 {
return fmt.Errorf("'env add' takes two arguments, the name and the uri of the environment, respectively") return fmt.Errorf("'env add' takes exactly one argument, which is the name of the environment")
} }
envName := args[0] name := args[0]
envURI := args[1]
envNamespace, err := flags.GetString(flagEnvNamespace) uri, namespace, context, err := commonEnvFlags(flags)
if err != nil { if err != nil {
return err return err
} }
if len(uri) == 0 {
// If uri is not provided, use the provided context.
// If context is also not provided, use the current context.
var ctx *string
if len(context) != 0 {
ctx = &context
}
var ns string
uri, ns, err = resolveContext(ctx)
if err != nil {
return err
}
// If namespace is not provided, use the default namespace provided in the context.
if len(namespace) == 0 {
namespace = ns
}
}
appDir, err := os.Getwd() appDir, err := os.Getwd()
if err != nil { if err != nil {
return err return err
...@@ -127,7 +154,7 @@ var envAddCmd = &cobra.Command{ ...@@ -127,7 +154,7 @@ var envAddCmd = &cobra.Command{
return err return err
} }
c, err := kubecfg.NewEnvAddCmd(envName, envURI, envNamespace, specFlag, manager) c, err := kubecfg.NewEnvAddCmd(name, uri, namespace, specFlag, manager)
if err != nil { if err != nil {
return err return err
} }
...@@ -164,17 +191,20 @@ environments/ ...@@ -164,17 +191,20 @@ environments/
swagger.json swagger.json
spec.json [This will contain the uri of the environment and other environment metadata], spec.json [This will contain the uri of the environment and other environment metadata],
staging.jsonnet`, staging.jsonnet`,
Example: ` # Initialize a new staging environment at 'us-west'. Using the Example: ` # Initialize a new staging environment at 'us-west'.
# namespace 'my-namespace'. The directory structure rooted at 'us-west' in the # The environment will be setup using the current context in your kubecfg file. The directory
# documentation above will be generated. # structure rooted at 'us-west' in the documentation above will be generated.
ks env add us-west/staging https://ksonnet-1.us-west.elb.amazonaws.com --namespace=my-namespace ks env add us-west/staging
# Initialize a new staging environment at 'us-west', using the OpenAPI specification # Initialize a new staging environment at 'us-west' with the namespace 'staging', using
# generated in the Kubernetes v1.7.1 build to generate 'ksonnet-lib'. # the OpenAPI specification generated in the Kubernetes v1.7.1 build to generate 'ksonnet-lib'.
ks env add us-west/staging https://ksonnet-1.us-west.elb.amazonaws.com --api-spec=version:v1.7.1 ks env add us-west/staging --api-spec=version:v1.7.1 --namespace=staging
# Initialize a new development environment locally. # Initialize a new environment using the 'dev' context in your kubeconfig file.
ks env add local localhost:8000`, ks env add my-env --context=dev
# Initialize a new environment using a server URI.
ks env add my-env --uri=https://ksonnet-1.us-west.elb.amazonaws.com`,
} }
var envRmCmd = &cobra.Command{ var envRmCmd = &cobra.Command{
...@@ -255,7 +285,7 @@ var envSetCmd = &cobra.Command{ ...@@ -255,7 +285,7 @@ var envSetCmd = &cobra.Command{
return fmt.Errorf("'env set' takes a single argument, that is the name of the environment") return fmt.Errorf("'env set' takes a single argument, that is the name of the environment")
} }
envName := args[0] originalName := args[0]
appDir, err := os.Getwd() appDir, err := os.Getwd()
if err != nil { if err != nil {
...@@ -268,22 +298,24 @@ var envSetCmd = &cobra.Command{ ...@@ -268,22 +298,24 @@ var envSetCmd = &cobra.Command{
return err return err
} }
desiredEnvName, err := flags.GetString(flagEnvName) name, err := flags.GetString(flagEnvName)
if err != nil { if err != nil {
return err return err
} }
desiredEnvURI, err := flags.GetString(flagEnvURI) uri, namespace, context, err := commonEnvFlags(flags)
if err != nil { if err != nil {
return err return err
} }
desiredEnvNamespace, err := flags.GetString(flagEnvNamespace) if len(context) != 0 {
if err != nil { uri, _, err = resolveContext(&context)
return err if err != nil {
return err
}
} }
c, err := kubecfg.NewEnvSetCmd(envName, desiredEnvName, desiredEnvURI, desiredEnvNamespace, manager) c, err := kubecfg.NewEnvSetCmd(originalName, name, uri, namespace, manager)
if err != nil { if err != nil {
return err return err
} }
...@@ -300,6 +332,34 @@ the name of an environment will also update the directory structure in ...@@ -300,6 +332,34 @@ the name of an environment will also update the directory structure in
ks env set us-west/staging --namespace=staging ks env set us-west/staging --namespace=staging
# Updates both the name and the URI of the environment 'us-west/staging'. # Updates both the name and the URI of the environment 'us-west/staging'.
# Updating the name will update the directory structure in 'environments' # Updating the name will update the directory structure in 'environments'.
ks env set us-west/staging --uri=http://example.com --name=us-east/staging`, ks env set us-west/staging --uri=http://example.com --name=us-east/staging
# Updates URI of the environment 'us-west/staging' based on the server URI
# in the context 'staging-west' in your kubeconfig file.
ks env set us-west/staging --context=staging-west`,
}
func commonEnvFlags(flags *pflag.FlagSet) (uri, namespace, context string, err error) {
uri, err = flags.GetString(flagEnvURI)
if err != nil {
return "", "", "", err
}
namespace, err = flags.GetString(flagEnvNamespace)
if err != nil {
return "", "", "", err
}
context, err = flags.GetString(flagEnvContext)
if err != nil {
return "", "", "", err
}
if len(context) != 0 && len(uri) != 0 {
return "", "", "", fmt.Errorf("flags '%s' and '%s' are mutually exclusive, because '%s' has a URI. Try setting '%s', '%s' to the desired values",
flagEnvContext, flagEnvURI, flagEnvContext, flagEnvURI, flagEnvNamespace)
}
return uri, namespace, context, nil
} }
...@@ -20,8 +20,6 @@ import ( ...@@ -20,8 +20,6 @@ import (
"os" "os"
"path" "path"
"k8s.io/client-go/tools/clientcmd/api"
"github.com/ksonnet/ksonnet/metadata" "github.com/ksonnet/ksonnet/metadata"
"github.com/ksonnet/ksonnet/pkg/kubecfg" "github.com/ksonnet/ksonnet/pkg/kubecfg"
"github.com/spf13/cobra" "github.com/spf13/cobra"
...@@ -57,32 +55,22 @@ var initCmd = &cobra.Command{ ...@@ -57,32 +55,22 @@ var initCmd = &cobra.Command{
return err return err
} }
// context, err := flags.GetString(flagEnvContext)
// Find the URI of the current cluster, if it exists.
//
rawConfig, err := clientConfig.RawConfig()
if err != nil { if err != nil {
return err return err
} }
var currCtx *api.Context // Find the URI and namespace of the current cluster, if it exists.
for name, ctx := range rawConfig.Contexts { var ctx *string
if name == rawConfig.CurrentContext { if len(context) != 0 {
currCtx = ctx ctx = &context
}
} }
uri, namespace, err := resolveContext(ctx)
var currClusterURI *string if err != nil {
if rawConfig.CurrentContext != "" && currCtx != nil { return err
for name, cluster := range rawConfig.Clusters {
if currCtx.Cluster == name {
currClusterURI = &cluster.Server
}
}
} }
c, err := kubecfg.NewInitCmd(appRoot, specFlag, currClusterURI, &currCtx.Namespace) c, err := kubecfg.NewInitCmd(appRoot, specFlag, &uri, &namespace)
if err != nil { if err != nil {
return err return err
} }
...@@ -123,5 +111,9 @@ consists of two steps: ...@@ -123,5 +111,9 @@ consists of two steps:
# Initialize ksonnet application, using an OpenAPI specification file # Initialize ksonnet application, using an OpenAPI specification file
# generated by a build of Kubernetes to generate 'ksonnet-lib'. # generated by a build of Kubernetes to generate 'ksonnet-lib'.
ks init app-name --api-spec=file:swagger.json`, ks init app-name --api-spec=file:swagger.json
# Initialize ksonnet application, using the context 'dev' from the kubeconfig
# file.
ks init app-name --context=dev`,
} }
...@@ -128,6 +128,28 @@ func namespace() (string, error) { ...@@ -128,6 +128,28 @@ func namespace() (string, error) {
return ns, err return ns, err
} }
// resolveContext returns the server URI and namespace of the cluster at the provided
// context. If context is nil, the current context is used.
func resolveContext(context *string) (uri, namespace string, err error) {
rawConfig, err := clientConfig.RawConfig()
if err != nil {
return "", "", err
}
ctxName := rawConfig.CurrentContext
if context != nil {
ctxName = *context
}
ctx := rawConfig.Contexts[ctxName]
if ctx == nil {
return "", "", fmt.Errorf("context '%s' does not exist in the kubeconfig file", *context)
}
log.Infof("Using context '%s'", ctxName)
cluster := rawConfig.Clusters[ctx.Cluster]
return cluster.Server, ctx.Namespace, nil
}
func logLevel(verbosity int) log.Level { func logLevel(verbosity int) log.Level {
switch verbosity { switch verbosity {
case 0: case 0:
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment