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
}