Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1 from StrongMonkey/stub
Browse files Browse the repository at this point in the history
Stub
  • Loading branch information
StrongMonkey authored Nov 8, 2017
2 parents c8a3a30 + 92e1bbc commit 0c3a858
Show file tree
Hide file tree
Showing 46 changed files with 5,028 additions and 262 deletions.
277 changes: 59 additions & 218 deletions cluster/cluster.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,8 @@
package cluster

import (
"encoding/base64"
"encoding/json"
"fmt"
"os"
"path/filepath"

rpcDriver "github.com/rancher/kontainer-engine/driver"
"github.com/rancher/kontainer-engine/utils"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"gopkg.in/yaml.v2"
"io/ioutil"
)

const (
caPem = "ca.pem"
clientKey = "key.pem"
clientCert = "cert.pem"
defaultConfigName = "config.json"
)

// Cluster represents a kubernetes cluster
Expand Down Expand Up @@ -54,7 +37,18 @@ type Cluster struct {
// Metadata store specific driver options per cloud provider
Metadata map[string]string

Ctx *cli.Context `json:"-"`
PersistStore PersistStore `json:"-,omitempty" yaml:"-,omitempty"`

ConfigGetter ConfigGetter `json:"-,omitempty" yaml:"-,omitempty"`
}

type PersistStore interface {
Check(name string) (bool, error)
Store(cluster Cluster) error
}

type ConfigGetter interface {
GetConfig() (rpcDriver.DriverOptions, error)
}

// Driver defines how a cluster should be created and managed.
Expand Down Expand Up @@ -87,33 +81,47 @@ type Driver interface {

// Create creates a cluster
func (c *Cluster) Create() error {
if c.IsCreated() {
logrus.Warnf("Cluster %s already exists. If it doesn't exist on the provider, make sure to clean them up by running `kontainer-engine rm %s`", c.Name, c.Name)
// check if it is already created
if ok, err := c.IsCreated(); err == nil && ok {
logrus.Warnf("Cluster %s already exists.", c.Name)
return nil
} else if err != nil {
return err
}
driverOpts := getDriverOpts(c.Ctx)
driverOpts.StringOptions["name"] = c.Name
err := c.Driver.SetDriverOptions(driverOpts)

// get cluster config from cli flags or json config
driverOpts, err := c.ConfigGetter.GetConfig()
if err != nil {
return err
}
if err := c.Driver.Create(); err != nil {

// pass cluster config to rpc driver
if err := c.Driver.SetDriverOptions(driverOpts); err != nil {
return err
}
info, err := c.Driver.Get(c.Name)
if err != nil {

// create cluster
if err := c.Driver.Create(); err != nil {
return err
}
transformClusterInfo(c, info)
if err := c.StoreConfig(); err != nil {

// receive cluster info back
if info, err := c.Driver.Get(c.Name); err != nil {
return err
} else {
transformClusterInfo(c, info)
}

// persist cluster info
return c.Store()
}

// Update updates a cluster
func (c *Cluster) Update() error {
driverOpts := getDriverOpts(c.Ctx)
driverOpts, err := c.ConfigGetter.GetConfig()
if err != nil {
return err
}
driverOpts.StringOptions["name"] = c.Name
for k, v := range c.Metadata {
driverOpts.StringOptions[k] = v
Expand All @@ -132,24 +140,6 @@ func (c *Cluster) Update() error {
return c.Store()
}

// Remove removes a cluster
func (c *Cluster) Remove() error {
driverOptions := rpcDriver.DriverOptions{
BoolOptions: make(map[string]bool),
StringOptions: make(map[string]string),
IntOptions: make(map[string]int64),
StringSliceOptions: make(map[string]*rpcDriver.StringSlice),
}
for k, v := range c.Metadata {
driverOptions.StringOptions[k] = v
}
driverOptions.StringOptions["name"] = c.Name
if err := c.Driver.SetDriverOptions(driverOptions); err != nil {
return err
}
return c.Driver.Remove()
}

func transformClusterInfo(c *Cluster, clusterInfo rpcDriver.ClusterInfo) {
c.ClientCertificate = clusterInfo.ClientCertificate
c.ClientKey = clusterInfo.ClientKey
Expand All @@ -163,191 +153,42 @@ func transformClusterInfo(c *Cluster, clusterInfo rpcDriver.ClusterInfo) {
c.ServiceAccountToken = clusterInfo.ServiceAccountToken
}

func (c *Cluster) IsCreated() bool {
if _, err := os.Stat(filepath.Join(c.GetFileDir(), defaultConfigName)); os.IsNotExist(err) {
return false
}
return true
}

func (c *Cluster) GetFileDir() string {
return filepath.Join(utils.HomeDir(), "clusters", c.Name)
}

// Store persists cluster information
func (c *Cluster) Store() error {
// todo: implement store logic to store the cluster info files. this might need to be a interface where we can store on disk or remote
for k, v := range map[string]string{
c.RootCACert: caPem,
c.ClientKey: clientKey,
c.ClientCertificate: clientCert,
} {
data, err := base64.StdEncoding.DecodeString(k)
if err != nil {
return err
}
if err := utils.WriteToFile(data, filepath.Join(c.GetFileDir(), v)); err != nil {
return err
}
}
data, err := json.Marshal(c)
// Remove removes a cluster
func (c *Cluster) Remove() error {
driverOptions, err := c.ConfigGetter.GetConfig()
if err != nil {
return err
}
return utils.WriteToFile(data, filepath.Join(c.GetFileDir(), defaultConfigName))
}

func (c *Cluster) StoreConfig() error {
isBasicOn := false
if c.Username != "" && c.Password != "" {
isBasicOn = true
}
username, password, token := "", "", ""
if isBasicOn {
username = c.Username
password = c.Password
} else {
token = c.ServiceAccountToken
}

configFile := utils.KubeConfigFilePath()
config := KubeConfig{}
if _, err := os.Stat(configFile); err == nil {
data, err := ioutil.ReadFile(configFile)
if err != nil {
return err
}
if err := yaml.Unmarshal(data, &config); err != nil {
return err
}
}
config.APIVersion = "v1"
config.Kind = "Config"

// setup clusters
cluster := ConfigCluster{
Cluster: DataCluster{
CertificateAuthorityData: string(c.RootCACert),
Server: fmt.Sprintf("https://%s", c.Endpoint),
},
Name: c.Name,
}
if config.Clusters == nil || len(config.Clusters) == 0 {
config.Clusters = []ConfigCluster{cluster}
} else {
exist := false
for _, cluster := range config.Clusters {
if cluster.Name == c.Name {
exist = true
break
}
}
if !exist {
config.Clusters = append(config.Clusters, cluster)
}
}

// setup users
user := ConfigUser{
User: UserData{
Username: username,
Password: password,
Token: token,
},
Name: c.Name,
}
if config.Users == nil || len(config.Users) == 0 {
config.Users = []ConfigUser{user}
} else {
exist := false
for _, user := range config.Users {
if user.Name == c.Name {
exist = true
break
}
}
if !exist {
config.Users = append(config.Users, user)
}
}

// setup context
context := ConfigContext{
Context: ContextData{
Cluster: c.Name,
User: c.Name,
},
Name: c.Name,
}
if config.Contexts == nil || len(config.Contexts) == 0 {
config.Contexts = []ConfigContext{context}
} else {
exist := false
for _, context := range config.Contexts {
if context.Name == c.Name {
exist = true
break
}
}
if !exist {
config.Contexts = append(config.Contexts, context)
}
}

data, err := yaml.Marshal(config)
if err != nil {
return err
for k, v := range c.Metadata {
driverOptions.StringOptions[k] = v
}
fileToWrite := utils.KubeConfigFilePath()
if err := utils.WriteToFile(data, fileToWrite); err != nil {
driverOptions.StringOptions["name"] = c.Name
if err := c.Driver.SetDriverOptions(driverOptions); err != nil {
return err
}
logrus.Debugf("KubeConfig files is saved to %s", fileToWrite)
logrus.Debug("Kubeconfig file\n" + string(data))
return c.Driver.Remove()
}

func (c *Cluster) IsCreated() (bool, error) {
return c.PersistStore.Check(c.Name)
}

return nil
// Store persists cluster information
func (c *Cluster) Store() error {
return c.PersistStore.Store(*c)
}

// NewCluster create a cluster interface to do operations
func NewCluster(driverName string, ctx *cli.Context) (*Cluster, error) {
addr := ctx.String("plugin-listen-addr")
func NewCluster(driverName, addr, name string, configGetter ConfigGetter, persistStore PersistStore) (*Cluster, error) {
rpcClient, err := rpcDriver.NewClient(driverName, addr)
if err != nil {
return nil, err
}
name := ""
if ctx.NArg() > 0 {
name = ctx.Args().Get(0)
}
return &Cluster{
Driver: rpcClient,
DriverName: driverName,
Name: name,
Ctx: ctx,
Driver: rpcClient,
DriverName: driverName,
Name: name,
ConfigGetter: configGetter,
PersistStore: persistStore,
}, nil
}

// getDriverOpts get the flags and value and generate DriverOptions
func getDriverOpts(ctx *cli.Context) rpcDriver.DriverOptions {
driverOptions := rpcDriver.DriverOptions{
BoolOptions: make(map[string]bool),
StringOptions: make(map[string]string),
IntOptions: make(map[string]int64),
StringSliceOptions: make(map[string]*rpcDriver.StringSlice),
}
for _, flag := range ctx.Command.Flags {
switch flag.(type) {
case cli.StringFlag:
driverOptions.StringOptions[flag.GetName()] = ctx.String(flag.GetName())
case cli.BoolFlag:
driverOptions.BoolOptions[flag.GetName()] = ctx.Bool(flag.GetName())
case cli.Int64Flag:
driverOptions.IntOptions[flag.GetName()] = ctx.Int64(flag.GetName())
case cli.StringSliceFlag:
driverOptions.StringSliceOptions[flag.GetName()] = &rpcDriver.StringSlice{
Value: ctx.StringSlice(flag.GetName()),
}
}
}
return driverOptions
}
Loading

0 comments on commit 0c3a858

Please sign in to comment.