mirror of https://github.com/kubernetes/kops.git
Merge pull request #20 from justinsb/upup_export_kubecfg
upup: add command to generate kubecfg
This commit is contained in:
commit
7dc7e848a7
|
@ -0,0 +1,21 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// kubecfgCmd represents the kubecfg command
|
||||
var kubecfgCmd = &cobra.Command{
|
||||
Use: "kubecfg",
|
||||
Short: "Manage kubecfg files",
|
||||
Long: `Manage kubecfg files`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("Usage: generate")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(kubecfgCmd)
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"k8s.io/kube-deploy/upup/pkg/fi"
|
||||
"k8s.io/kube-deploy/upup/pkg/kubecfg"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
type KubecfgGenerateCommand struct {
|
||||
StateDir string
|
||||
ClusterName string
|
||||
CloudProvider string
|
||||
Project string
|
||||
Master string
|
||||
|
||||
tmpdir string
|
||||
caStore fi.CAStore
|
||||
}
|
||||
|
||||
var kubecfgGenerateCommand KubecfgGenerateCommand
|
||||
|
||||
func init() {
|
||||
cmd := &cobra.Command{
|
||||
Use: "generate",
|
||||
Short: "Generate a kubecfg file for a cluster",
|
||||
Long: `Creates a kubecfg file for a cluster, based on the state`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := kubecfgGenerateCommand.Run()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
kubecfgCmd.AddCommand(cmd)
|
||||
|
||||
// TODO: We need to store this in the persistent state dir
|
||||
cmd.Flags().StringVarP(&kubecfgGenerateCommand.ClusterName, "name", "", kubecfgGenerateCommand.ClusterName, "Name for cluster")
|
||||
cmd.Flags().StringVarP(&kubecfgGenerateCommand.CloudProvider, "cloud", "", kubecfgGenerateCommand.CloudProvider, "Cloud provider to use - gce, aws")
|
||||
cmd.Flags().StringVarP(&kubecfgGenerateCommand.Project, "project", "", kubecfgGenerateCommand.Project, "Project to use (must be set on GCE)")
|
||||
|
||||
cmd.Flags().StringVarP(&kubecfgGenerateCommand.Master, "master", "", kubecfgGenerateCommand.Master, "IP adddress or host of API server")
|
||||
|
||||
cmd.Flags().StringVarP(&kubecfgGenerateCommand.StateDir, "state", "", "", "State directory")
|
||||
}
|
||||
|
||||
func (c *KubecfgGenerateCommand) Run() error {
|
||||
if c.StateDir == "" {
|
||||
return fmt.Errorf("state must be specified")
|
||||
}
|
||||
|
||||
if c.Master == "" {
|
||||
return fmt.Errorf("master must be specified")
|
||||
}
|
||||
|
||||
if c.ClusterName == "" {
|
||||
return fmt.Errorf("name must be specified")
|
||||
}
|
||||
if c.CloudProvider == "" {
|
||||
return fmt.Errorf("cloud must be specified")
|
||||
}
|
||||
|
||||
var err error
|
||||
c.tmpdir, err = ioutil.TempDir("", "k8s")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating temporary directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(c.tmpdir)
|
||||
|
||||
b := &kubecfg.KubeconfigBuilder{}
|
||||
b.Init()
|
||||
|
||||
switch c.CloudProvider {
|
||||
case "aws":
|
||||
b.Context = "aws_" + c.ClusterName
|
||||
|
||||
case "gce":
|
||||
if c.Project == "" {
|
||||
return fmt.Errorf("--project must be specified (for GCE)")
|
||||
}
|
||||
b.Context = c.Project + "_" + c.ClusterName
|
||||
|
||||
default:
|
||||
return fmt.Errorf("Unknown cloud provider %q", c.CloudProvider)
|
||||
}
|
||||
|
||||
c.caStore, err = fi.NewFilesystemCAStore(path.Join(c.StateDir, "pki"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error building CA store: %v", err)
|
||||
}
|
||||
|
||||
if b.CACert, err = c.copyCertificate(fi.CertificateId_CA); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if b.KubecfgCert, err = c.copyCertificate("kubecfg"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if b.KubecfgKey, err = c.copyPrivateKey("kubecfg"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b.KubeMasterIP = c.Master
|
||||
|
||||
err = b.CreateKubeconfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *KubecfgGenerateCommand) copyCertificate(id string) (string, error) {
|
||||
p := path.Join(c.tmpdir, id+".crt")
|
||||
cert, err := c.caStore.Cert(id)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error fetching certificate %q: %v", id, err)
|
||||
}
|
||||
|
||||
_, err = writeFile(p, cert)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error writing certificate %q: %v", id, err)
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (c *KubecfgGenerateCommand) copyPrivateKey(id string) (string, error) {
|
||||
p := path.Join(c.tmpdir, id+".key")
|
||||
cert, err := c.caStore.PrivateKey(id)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error fetching private key %q: %v", id, err)
|
||||
}
|
||||
|
||||
_, err = writeFile(p, cert)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error writing private key %q: %v", id, err)
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func writeFile(dst string, src io.WriterTo) (int64, error) {
|
||||
f, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error creating file %q: %v", dst, err)
|
||||
}
|
||||
defer fi.SafeClose(f)
|
||||
return src.WriteTo(f)
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package main
|
||||
|
||||
func main() {
|
||||
Execute()
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var cfgFile string
|
||||
|
||||
// This represents the base command when called without any subcommands
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "upup",
|
||||
Short: "upup manages kubernetes clusters",
|
||||
Long: `upup manages kubernetes clusters.
|
||||
It allows you to create, destroy, upgrade and maintain them.`,
|
||||
}
|
||||
|
||||
func Execute() {
|
||||
if err := RootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
|
||||
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.upup.yaml)")
|
||||
}
|
||||
|
||||
// initConfig reads in config file and ENV variables if set.
|
||||
func initConfig() {
|
||||
if cfgFile != "" { // enable ability to specify config file via flag
|
||||
viper.SetConfigFile(cfgFile)
|
||||
}
|
||||
|
||||
viper.SetConfigName(".upup") // name of config file (without extension)
|
||||
viper.AddConfigPath("$HOME") // adding home directory as first search path
|
||||
viper.AutomaticEnv() // read in environment variables that match
|
||||
|
||||
// If a config file is found, read it in.
|
||||
if err := viper.ReadInConfig(); err == nil {
|
||||
fmt.Println("Using config file:", viper.ConfigFileUsed())
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
hash: 9864d4fe0b94042cab08d2e80910638776d3d1e655b5a3cb9006731ae0306761
|
||||
updated: 2016-05-13T09:50:25.860201305-04:00
|
||||
hash: a9f93fedfb45e32b891cdf1f53c475acff2dd80fc02577b7c1d4da4e099bc450
|
||||
updated: 2016-05-17T12:58:07.23069873-04:00
|
||||
imports:
|
||||
- name: github.com/aws/aws-sdk-go
|
||||
version: d85fa529a99a833067e11c0a838b9db7a5d5ea71
|
||||
version: bf2f8fe7f45e68017086d069498638893feddf64
|
||||
subpackages:
|
||||
- aws
|
||||
- aws/awserr
|
||||
|
@ -29,27 +29,60 @@ imports:
|
|||
- private/protocol/rest
|
||||
- aws/credentials/ec2rolecreds
|
||||
- aws/ec2metadata
|
||||
- name: github.com/BurntSushi/toml
|
||||
version: f0aeabca5a127c4078abb8c8d64298b147264b55
|
||||
- name: github.com/cloudfoundry-incubator/candiedyaml
|
||||
version: 99c3df83b51532e3615f851d8c2dbb638f5313bf
|
||||
- name: github.com/fsnotify/fsnotify
|
||||
version: 30411dbcefb7a1da7e84f75530ad3abe4011b4f8
|
||||
- name: github.com/ghodss/yaml
|
||||
version: e8e0db9016175449df0e9c4b6e6995a9433a395c
|
||||
- name: github.com/go-ini/ini
|
||||
version: 12f418cc7edc5a618a51407b7ac1f1f512139df3
|
||||
version: 2e44421e256d82ebbf3d4d4fcabe8930b905eff3
|
||||
- name: github.com/golang/glog
|
||||
version: 23def4e6c14b4da8ac2ed8007337bc5eb5007998
|
||||
- name: github.com/golang/protobuf
|
||||
version: 7cc19b78d562895b13596ddce7aafb59dd789318
|
||||
version: b982704f8bb716bb608144408cff30e15fbde841
|
||||
subpackages:
|
||||
- proto
|
||||
- name: github.com/hashicorp/hcl
|
||||
version: 9a905a34e6280ce905da1a32344b25e81011197a
|
||||
subpackages:
|
||||
- hcl/ast
|
||||
- hcl/parser
|
||||
- hcl/token
|
||||
- json/parser
|
||||
- hcl/scanner
|
||||
- hcl/strconv
|
||||
- json/scanner
|
||||
- json/token
|
||||
- name: github.com/inconshreveable/mousetrap
|
||||
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
||||
- name: github.com/jmespath/go-jmespath
|
||||
version: 0b12d6b521d83fc7f755e7cfc1b1fbdd35a01a74
|
||||
version: 3433f3ea46d9f8019119e7dd41274e112a2359a9
|
||||
- name: github.com/magiconair/properties
|
||||
version: c265cfa48dda6474e208715ca93e987829f572f8
|
||||
- name: github.com/mitchellh/mapstructure
|
||||
version: d2dd0262208475919e1a362f675cfc0e7c10e905
|
||||
- name: github.com/spf13/cast
|
||||
version: 27b586b42e29bec072fe7379259cc719e1289da6
|
||||
- name: github.com/spf13/cobra
|
||||
version: 0f866a6211e33cde2091d9290c08f6afd6c9ebbc
|
||||
- name: github.com/spf13/jwalterweatherman
|
||||
version: 33c24e77fb80341fe7130ee7c594256ff08ccc46
|
||||
- name: github.com/spf13/pflag
|
||||
version: cb88ea77998c3f024757528e3305022ab50b43be
|
||||
- name: github.com/spf13/viper
|
||||
version: d8a428b8a30606e1d0b355d91edf282609ade1a6
|
||||
- name: golang.org/x/crypto
|
||||
version: 47ff8dfbc528fea3003fc0ce2d88ffbbfbc46a43
|
||||
version: c84e1f8e3a7e322d497cd16c0e8a13c7e127baf3
|
||||
subpackages:
|
||||
- ssh
|
||||
- curve25519
|
||||
- ed25519
|
||||
- ed25519/internal/edwards25519
|
||||
- name: golang.org/x/net
|
||||
version: 7e42c0e1329bb108f7376a7618a2871ab90f1c4d
|
||||
version: ef00b378c73f107bf44d5c9b69875255ce89b79a
|
||||
subpackages:
|
||||
- context
|
||||
- context/ctxhttp
|
||||
|
@ -60,8 +93,12 @@ imports:
|
|||
- internal
|
||||
- jws
|
||||
- jwt
|
||||
- name: golang.org/x/sys
|
||||
version: 833a04a10549a95dc34458c195cbad61bbb6cb4d
|
||||
subpackages:
|
||||
- unix
|
||||
- name: google.golang.org/api
|
||||
version: f9a4669e07732c84854dce1f5c451c22427228fb
|
||||
version: b34a26664e9b96e9d4aab8a6e8175ea07af5b8b6
|
||||
subpackages:
|
||||
- compute/v1
|
||||
- googleapi
|
||||
|
@ -81,14 +118,16 @@ imports:
|
|||
- internal/log
|
||||
- internal/remote_api
|
||||
- name: google.golang.org/cloud
|
||||
version: 200292f09e3aaa34878d801ab71fe823b1f7d36a
|
||||
version: eb47ba841d53d93506cfbfbc03927daf9cc48f88
|
||||
subpackages:
|
||||
- compute/metadata
|
||||
- internal
|
||||
- name: google.golang.org/grpc
|
||||
version: 9604a2bb7dd81d87c2873a9580258465f3c311c8
|
||||
version: e802f420af1fde2c7e456cec047c51fbeff2d8fc
|
||||
- name: gopkg.in/yaml.v2
|
||||
version: a83829b6f1293c91addabc89d0571c246397bbf4
|
||||
- name: k8s.io/kubernetes
|
||||
version: bb3f5b1768f3bf6c81914c5bb1d7e846561fdc31
|
||||
version: a24f03c3c99bd305ace7745b7a5749790be060e3
|
||||
subpackages:
|
||||
- pkg/util/exec
|
||||
- pkg/util/mount
|
||||
|
|
|
@ -22,3 +22,4 @@ import:
|
|||
subpackages:
|
||||
- ssh
|
||||
- package: github.com/cloudfoundry-incubator/candiedyaml
|
||||
- package: github.com/spf13/cobra
|
||||
|
|
|
@ -17,6 +17,8 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
const CertificateId_CA = "ca"
|
||||
|
||||
type Certificate struct {
|
||||
Subject pkix.Name
|
||||
IsCA bool
|
||||
|
@ -45,7 +47,7 @@ func (c *Certificate) UnmarshalJSON(b []byte) error {
|
|||
|
||||
func (c *Certificate) MarshalJSON() ([]byte, error) {
|
||||
var data bytes.Buffer
|
||||
err := c.WriteCertificate(&data)
|
||||
_, err := c.WriteTo(&data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error writing SSL certificate: %v", err)
|
||||
}
|
||||
|
@ -70,7 +72,7 @@ func (c *Certificate) AsString() (string, error) {
|
|||
}
|
||||
|
||||
var data bytes.Buffer
|
||||
err := c.WriteCertificate(&data)
|
||||
_, err := c.WriteTo(&data)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error writing SSL certificate: %v", err)
|
||||
}
|
||||
|
@ -88,7 +90,7 @@ func (c *PrivateKey) AsString() (string, error) {
|
|||
}
|
||||
|
||||
var data bytes.Buffer
|
||||
err := WritePrivateKey(c.Key, &data)
|
||||
_, err := c.WriteTo(&data)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error writing SSL private key: %v", err)
|
||||
}
|
||||
|
@ -114,13 +116,33 @@ func (k *PrivateKey) UnmarshalJSON(b []byte) (err error) {
|
|||
|
||||
func (k *PrivateKey) MarshalJSON() ([]byte, error) {
|
||||
var data bytes.Buffer
|
||||
err := WritePrivateKey(k.Key, &data)
|
||||
_, err := k.WriteTo(&data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error writing SSL private key: %v", err)
|
||||
}
|
||||
return json.Marshal(data.String())
|
||||
}
|
||||
|
||||
var _ io.WriterTo = &PrivateKey{}
|
||||
|
||||
func (k *PrivateKey) WriteTo(w io.Writer) (int64, error) {
|
||||
var data bytes.Buffer
|
||||
var err error
|
||||
|
||||
switch pk := k.Key.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
err = pem.Encode(w, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(pk)})
|
||||
default:
|
||||
return 0, fmt.Errorf("unknown private key type: %T", k.Key)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error writing SSL private key: %v", err)
|
||||
}
|
||||
|
||||
return data.WriteTo(w)
|
||||
}
|
||||
|
||||
func LoadPEMCertificate(pemData []byte) (*Certificate, error) {
|
||||
cert, err := parsePEMCertificate(pemData)
|
||||
if err != nil {
|
||||
|
@ -199,8 +221,15 @@ func SignNewCertificate(privateKey *PrivateKey, template *x509.Certificate, sign
|
|||
return c, nil
|
||||
}
|
||||
|
||||
func (c *Certificate) WriteCertificate(w io.Writer) error {
|
||||
return pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: c.Certificate.Raw})
|
||||
var _ io.WriterTo = &Certificate{}
|
||||
|
||||
func (c *Certificate) WriteTo(w io.Writer) (int64, error) {
|
||||
var b bytes.Buffer
|
||||
err := pem.Encode(&b, &pem.Block{Type: "CERTIFICATE", Bytes: c.Certificate.Raw})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return b.WriteTo(w)
|
||||
}
|
||||
|
||||
func parsePEMCertificate(pemData []byte) (*x509.Certificate, error) {
|
||||
|
@ -221,15 +250,6 @@ func parsePEMCertificate(pemData []byte) (*x509.Certificate, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func WritePrivateKey(privateKey crypto.PrivateKey, w io.Writer) error {
|
||||
rsaPrivateKey, ok := privateKey.(*rsa.PrivateKey)
|
||||
if ok {
|
||||
return pem.Encode(w, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(rsaPrivateKey)})
|
||||
}
|
||||
|
||||
return fmt.Errorf("unknown private key type: %T", privateKey)
|
||||
}
|
||||
|
||||
func parsePEMPrivateKey(pemData []byte) (crypto.PrivateKey, error) {
|
||||
for {
|
||||
block, rest := pem.Decode(pemData)
|
||||
|
|
|
@ -2,7 +2,6 @@ package fi
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
crypto_rand "crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
|
@ -72,12 +71,14 @@ func (c *FilesystemCAStore) generateCACertificate() error {
|
|||
IsCA: true,
|
||||
}
|
||||
|
||||
caPrivateKey, err := rsa.GenerateKey(crypto_rand.Reader, 2048)
|
||||
caRsaKey, err := rsa.GenerateKey(crypto_rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating RSA private key: %v", err)
|
||||
}
|
||||
|
||||
caCertificate, err := SignNewCertificate(&PrivateKey{Key: caPrivateKey}, template, nil, nil)
|
||||
caPrivateKey := &PrivateKey{Key: caRsaKey}
|
||||
|
||||
caCertificate, err := SignNewCertificate(caPrivateKey, template, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -100,7 +101,7 @@ func (c *FilesystemCAStore) generateCACertificate() error {
|
|||
return err
|
||||
}
|
||||
|
||||
c.caPrivateKey = &PrivateKey{Key: caPrivateKey}
|
||||
c.caPrivateKey = caPrivateKey
|
||||
c.caCertificate = caCertificate
|
||||
return nil
|
||||
}
|
||||
|
@ -176,7 +177,7 @@ func (c *FilesystemCAStore) Cert(id string) (*Certificate, error) {
|
|||
|
||||
func (c *FilesystemCAStore) FindCert(id string) (*Certificate, error) {
|
||||
var cert *Certificate
|
||||
if id == "ca" {
|
||||
if id == CertificateId_CA {
|
||||
cert = c.caCertificate
|
||||
} else {
|
||||
var err error
|
||||
|
@ -228,7 +229,7 @@ func (c *FilesystemCAStore) loadPrivateKey(p string) (*PrivateKey, error) {
|
|||
|
||||
func (c *FilesystemCAStore) FindPrivateKey(id string) (*PrivateKey, error) {
|
||||
var key *PrivateKey
|
||||
if id == "ca" {
|
||||
if id == CertificateId_CA {
|
||||
key = c.caPrivateKey
|
||||
} else {
|
||||
var err error
|
||||
|
@ -253,22 +254,23 @@ func (c *FilesystemCAStore) PrivateKey(id string) (*PrivateKey, error) {
|
|||
func (c *FilesystemCAStore) CreatePrivateKey(id string) (*PrivateKey, error) {
|
||||
p := c.buildPrivateKeyPath(id)
|
||||
|
||||
privateKey, err := rsa.GenerateKey(crypto_rand.Reader, 2048)
|
||||
rsaKey, err := rsa.GenerateKey(crypto_rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error generating RSA private key: %v", err)
|
||||
}
|
||||
|
||||
privateKey := &PrivateKey{Key: rsaKey}
|
||||
err = c.storePrivateKey(privateKey, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &PrivateKey{Key: privateKey}, nil
|
||||
return privateKey, nil
|
||||
}
|
||||
|
||||
func (c *FilesystemCAStore) storePrivateKey(privateKey crypto.PrivateKey, p string) error {
|
||||
func (c *FilesystemCAStore) storePrivateKey(privateKey *PrivateKey, p string) error {
|
||||
var data bytes.Buffer
|
||||
err := WritePrivateKey(privateKey, &data)
|
||||
_, err := privateKey.WriteTo(&data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -277,8 +279,9 @@ func (c *FilesystemCAStore) storePrivateKey(privateKey crypto.PrivateKey, p stri
|
|||
}
|
||||
|
||||
func (c *FilesystemCAStore) storeCertificate(cert *Certificate, p string) error {
|
||||
// TODO: replace storePrivateKey & storeCertificate with writeFile(io.WriterTo)?
|
||||
var data bytes.Buffer
|
||||
err := cert.WriteCertificate(&data)
|
||||
_, err := cert.WriteTo(&data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
package kubecfg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/golang/glog"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// KubeconfigBuilder builds a kubecfg file
|
||||
// This logic previously lives in the bash scripts (create-kubeconfig in cluster/common.sh)
|
||||
type KubeconfigBuilder struct {
|
||||
KubectlPath string
|
||||
KubeconfigPath string
|
||||
|
||||
KubeMasterIP string
|
||||
|
||||
Context string
|
||||
|
||||
KubeBearerToken string
|
||||
KubeUser string
|
||||
KubePassword string
|
||||
|
||||
CACert string
|
||||
KubecfgCert string
|
||||
KubecfgKey string
|
||||
}
|
||||
|
||||
func (c *KubeconfigBuilder) Init() {
|
||||
c.KubectlPath = "kubectl" // default to in-path
|
||||
|
||||
kubeconfig := os.Getenv("KUBECONFIG")
|
||||
if kubeconfig == "" {
|
||||
homedir := os.Getenv("HOME")
|
||||
kubeconfig = path.Join(homedir, ".kube", "config")
|
||||
}
|
||||
c.KubeconfigPath = kubeconfig
|
||||
}
|
||||
|
||||
func (c *KubeconfigBuilder) CreateKubeconfig() error {
|
||||
if _, err := os.Stat(c.KubeconfigPath); os.IsNotExist(err) {
|
||||
err := os.MkdirAll(path.Dir(c.KubeconfigPath), 0700)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating directories for %q: %v", c.KubeconfigPath, err)
|
||||
}
|
||||
f, err := os.OpenFile(c.KubeconfigPath, os.O_RDWR|os.O_CREATE, 0600)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating config file %q: %v", c.KubeconfigPath, err)
|
||||
}
|
||||
f.Close()
|
||||
}
|
||||
|
||||
var clusterArgs []string
|
||||
|
||||
clusterArgs = append(clusterArgs, "--server=https://"+c.KubeMasterIP)
|
||||
|
||||
if c.CACert == "" {
|
||||
clusterArgs = append(clusterArgs, "--insecure-skip-tls-verify=true")
|
||||
} else {
|
||||
clusterArgs = append(clusterArgs, "--certificate-authority="+c.CACert)
|
||||
clusterArgs = append(clusterArgs, "--embed-certs=true")
|
||||
}
|
||||
|
||||
var userArgs []string
|
||||
|
||||
if c.KubeBearerToken != "" {
|
||||
userArgs = append(userArgs, "--token="+c.KubeBearerToken)
|
||||
} else if c.KubeUser != "" && c.KubePassword != "" {
|
||||
userArgs = append(userArgs, "--username="+c.KubeUser)
|
||||
userArgs = append(userArgs, "--password="+c.KubePassword)
|
||||
}
|
||||
|
||||
if c.KubecfgCert != "" && c.KubecfgKey != "" {
|
||||
userArgs = append(userArgs, "--client-certificate="+c.KubecfgCert)
|
||||
userArgs = append(userArgs, "--client-key="+c.KubecfgKey)
|
||||
userArgs = append(userArgs, "--embed-certs=true")
|
||||
}
|
||||
|
||||
setClusterArgs := []string{"config", "set-cluster", c.Context}
|
||||
setClusterArgs = append(setClusterArgs, clusterArgs...)
|
||||
err := c.execKubectl(setClusterArgs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(userArgs) != 0 {
|
||||
setCredentialsArgs := []string{"config", "set-credentials", c.Context}
|
||||
setCredentialsArgs = append(setCredentialsArgs, userArgs...)
|
||||
err := c.execKubectl(setCredentialsArgs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = c.execKubectl("config", "set-context", c.Context, "--cluster="+c.Context, "--user="+c.Context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = c.execKubectl("config", "use-context", c.Context, "--cluster="+c.Context, "--user="+c.Context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If we have a bearer token, also create a credential entry with basic auth
|
||||
// so that it is easy to discover the basic auth password for your cluster
|
||||
// to use in a web browser.
|
||||
if c.KubeBearerToken != "" && c.KubeUser != "" && c.KubePassword != "" {
|
||||
err := c.execKubectl("config", "set-credentials", c.Context+"-basic-auth", "--username="+c.KubeUser, "--password="+c.KubePassword)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Wrote config for %s to %q\n", c.Context, c.KubeconfigPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *KubeconfigBuilder) execKubectl(args ...string) error {
|
||||
cmd := exec.Command(c.KubectlPath, args...)
|
||||
env := os.Environ()
|
||||
env = append(env, fmt.Sprintf("KUBECONFIG=%s", c.KubeconfigPath))
|
||||
cmd.Env = env
|
||||
|
||||
glog.V(2).Infof("Running command: %s %s", cmd.Path, strings.Join(cmd.Args, " "))
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
glog.Info("error running kubectl:")
|
||||
glog.Info(string(output))
|
||||
return fmt.Errorf("error running kubectl")
|
||||
}
|
||||
|
||||
glog.V(2).Info(string(output))
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue