package admin import ( "errors" "fmt" "io/ioutil" "path" "github.com/golang/glog" "github.com/spf13/cobra" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" ) type CreateClientOptions struct { GetSignerCertOptions *GetSignerCertOptions ClientDir string User string Groups util.StringList APIServerCAFile string APIServerURL string PublicAPIServerURL string } func NewCommandCreateClient() *cobra.Command { options := &CreateClientOptions{GetSignerCertOptions: &GetSignerCertOptions{}} cmd := &cobra.Command{ Use: "create-api-client-config", Short: "Create a portable client folder containing a client certificate, a client key, a server certificate authority, and a .kubeconfig file.", Run: func(c *cobra.Command, args []string) { if err := options.Validate(args); err != nil { fmt.Println(err.Error()) c.Help() return } if err := options.CreateClientFolder(); err != nil { glog.Fatal(err) } }, } flags := cmd.Flags() BindGetSignerCertOptions(options.GetSignerCertOptions, flags, "") flags.StringVar(&options.ClientDir, "client-dir", "", "The client data directory.") flags.StringVar(&options.User, "user", "", "The scope qualified username.") flags.Var(&options.Groups, "groups", "The list of groups this user belongs to. Comma delimited list") flags.StringVar(&options.APIServerURL, "master", "https://localhost:8443", "The API server's URL.") flags.StringVar(&options.PublicAPIServerURL, "public-master", "", "The API public facing server's URL (if applicable).") flags.StringVar(&options.APIServerCAFile, "certificate-authority", "openshift.local.certificates/ca/cert.crt", "Path to the API server's CA file.") return cmd } func (o CreateClientOptions) Validate(args []string) error { if len(args) != 0 { return errors.New("no arguments are supported") } if len(o.ClientDir) == 0 { return errors.New("client-dir must be provided") } if len(o.User) == 0 { return errors.New("user must be provided") } if len(o.APIServerURL) == 0 { return errors.New("master must be provided") } if len(o.APIServerCAFile) == 0 { return errors.New("certificate-authority must be provided") } if o.GetSignerCertOptions == nil { return errors.New("signer options are required") } if err := o.GetSignerCertOptions.Validate(); err != nil { return err } return nil } func (o CreateClientOptions) CreateClientFolder() error { glog.V(2).Infof("creating a .kubeconfig with: %#v", o) clientCertFile := path.Join(o.ClientDir, "cert.crt") clientKeyFile := path.Join(o.ClientDir, "key.key") clientCopyOfCAFile := path.Join(o.ClientDir, "ca.crt") kubeConfigFile := path.Join(o.ClientDir, ".kubeconfig") createClientCertOptions := CreateClientCertOptions{ GetSignerCertOptions: o.GetSignerCertOptions, CertFile: clientCertFile, KeyFile: clientKeyFile, User: o.User, Groups: o.Groups, Overwrite: true, } if _, err := createClientCertOptions.CreateClientCert(); err != nil { return err } // copy the CA file over if caBytes, err := ioutil.ReadFile(o.APIServerCAFile); err != nil { return err } else if err := ioutil.WriteFile(clientCopyOfCAFile, caBytes, 0644); err != nil { return nil } createKubeConfigOptions := CreateKubeConfigOptions{ APIServerURL: o.APIServerURL, PublicAPIServerURL: o.PublicAPIServerURL, APIServerCAFile: clientCopyOfCAFile, ServerNick: "master", CertFile: clientCertFile, KeyFile: clientKeyFile, UserNick: o.User, KubeConfigFile: kubeConfigFile, } if _, err := createKubeConfigOptions.CreateKubeConfig(); err != nil { return err } return nil }