Skip to content

Commit

Permalink
feat(addon): support create cluster with addons
Browse files Browse the repository at this point in the history
  • Loading branch information
JacieChao committed Aug 21, 2023
1 parent b31cd96 commit 4dd449e
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 3 deletions.
92 changes: 89 additions & 3 deletions pkg/cluster/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"strconv"
"strings"
"sync"
"text/template"

"github.com/cnrancher/autok3s/pkg/common"
"github.com/cnrancher/autok3s/pkg/hosts/dialer"
Expand All @@ -38,6 +39,8 @@ const (
defaultCidr = "10.42.0.0/16"
uploadManifestCmd = "echo \"%s\" | base64 -d | tee \"%s/%s\""
dockerInstallScript = "https://get.docker.com"

deployPluginCmd = "echo \"%s\" | base64 -d | tee \"%s/%s.yaml\""
)

// ProviderBase provider base struct.
Expand Down Expand Up @@ -115,6 +118,12 @@ func (p *ProviderBase) GetCreateOptions() []types.Flag {
V: p.PackagePath,
Usage: "The airgap package path. The \"package-name\" flag will be ignored if this flag is also provided",
},
{
Name: "set",
P: &p.Values,
V: p.Values,
Usage: "set values for addon when enabled by --enable. e.g. --enable rancher --set rancher.Version=v2.7.5 --set rancher.Hostname=aa.bb.cc",
},
}
}

Expand Down Expand Up @@ -430,13 +439,55 @@ func (p *ProviderBase) InitCluster(options interface{}, deployPlugins func() []s
}
}

// deploy custom manifests.
cmds := []string{}
if p.Manifests != "" {
deployCmd, err := p.GetCustomManifests()
if err != nil {
return err
p.Logger.Errorf("[%s] failed to get custom manifests by manifest %s: %v", p.Provider, p.Manifests, err)
}
cmds = append(cmds, deployCmd...)
}

if p.Enable != nil {
for _, plugin := range p.Enable {
if plugin != "explorer" {
// check addon plugin
addon, err := common.DefaultDB.GetAddon(plugin)
if err != nil {
p.Logger.Errorf("[%s] failed to get addon by name %s, got error: %v", p.Provider, plugin, err)
continue
}
manifest := addon.Manifest
defaultValues := addon.Values
// check --set values
setValues := map[string]string{}
for key, value := range p.Values {
if strings.HasPrefix(key, fmt.Sprintf("%s.", plugin)) {
setValues[strings.TrimPrefix(key, fmt.Sprintf("%s.", plugin))] = value
} else {
setValues[key] = value
}
}
values, err := common.GenerateValues(setValues, defaultValues)
if err != nil {
p.Logger.Errorf("[%s] failed to generate values for addon %s with values %v: %v", p.Provider, plugin, p.Values, err)
continue
}
p.Logger.Debugf("assemble manifest with value %++v", values)
assembleManifest, err := common.AssembleManifest(values, string(manifest), p.parseDefaultTemplates())
if err != nil {
p.Logger.Errorf("[%s] failed to assemble manifest for addon %s with values %v: %v", p.Provider, plugin, setValues, err)
continue
}
cmds = append(cmds, fmt.Sprintf(deployPluginCmd,
base64.StdEncoding.EncodeToString(assembleManifest), common.K3sManifestsDir, plugin))
}
}
if err = p.DeployExtraManifest(c, deployCmd); err != nil {
}

// deploy custom manifests.
if len(cmds) > 0 {
if err = p.DeployExtraManifest(c, cmds); err != nil {
return err
}
p.Logger.Infof("[%s] successfully deployed custom manifests", p.Provider)
Expand Down Expand Up @@ -1331,3 +1382,38 @@ func (p *ProviderBase) ValidateRequireSSHPrivateKey() error {
}
return nil
}

func (p *ProviderBase) parseDefaultTemplates() template.FuncMap {
templateValues := p.MasterNodes
return template.FuncMap{
"providerTemplate": func(metaName string) string {
node := templateValues[0]
nodeType := reflect.TypeOf(node)
fieldValue := ""
found := true
for i := 0; i < nodeType.NumField(); i++ {
field := nodeType.Field(i)
if v, ok := field.Tag.Lookup("json"); ok {
fieldName := strings.Split(v, ",")[0]
if strings.EqualFold(fieldName, metaName) {
found = true
if field.Type.Kind() == reflect.Slice {
value, ok := reflect.ValueOf(node).Field(i).Interface().([]string)
if ok {
fieldValue = value[0]
}
} else {
fieldValue = reflect.ValueOf(node).Field(i).String()
}
break
}

}
}
if !found {
p.Logger.Warnf("[%s] there's no metaName %s defined", p.Provider, metaName)
}
return fieldValue
},
}
}
1 change: 1 addition & 0 deletions pkg/providers/alibaba/alibaba.go
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ func (p *Alibaba) assembleInstanceStatus(ssh *types.SSH, uploadKeyPair bool, pub
v.InternalIPAddress = status.VpcAttributes.PrivateIpAddress.IpAddress
v.PublicIPAddress = publicIPAddress
v.EipAllocationIds = eip
v.LocalHostname = status.HostName
v.SSH = *ssh
// check upload keypair
if uploadKeyPair {
Expand Down
1 change: 1 addition & 0 deletions pkg/providers/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ func (p *Amazon) getInstanceStatus(aimStatus string) error {
v.InstanceStatus = aimStatus
v.InternalIPAddress = []string{aws.StringValue(status.PrivateIpAddress)}
v.PublicIPAddress = []string{aws.StringValue(status.PublicIpAddress)}
v.LocalHostname = aws.StringValue(status.PrivateDnsName)
p.M.Store(aws.StringValue(status.InstanceId), v)
}
continue
Expand Down
1 change: 1 addition & 0 deletions pkg/providers/google/google.go
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ func (p *Google) startInstance(num int, master bool) error {
InstanceStatus: ins.Status,
InternalIPAddress: []string{networkInterface.NetworkIP},
PublicIPAddress: []string{networkInterface.AccessConfigs[0].NatIP},
LocalHostname: ins.Hostname,
SSH: p.SSH,
})
}
Expand Down
1 change: 1 addition & 0 deletions pkg/providers/k3d/k3d.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ func (p *K3d) k3dStatus() ([]types.Node, error) {
InstanceStatus: n.State.Status,
InternalIPAddress: []string{},
PublicIPAddress: []string{},
LocalHostname: "",
}
// save to the store because of the rollback logic needed.
p.M.Store(n.Name, nodeWrapper)
Expand Down
1 change: 1 addition & 0 deletions pkg/providers/native/native.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ func (p *Native) syncNodesMap(ipList []string, master bool, ssh *types.SSH) {
InstanceStatus: "-",
InternalIPAddress: []string{ip},
PublicIPAddress: []string{ip},
LocalHostname: "",
Current: true,
SSH: *ssh,
})
Expand Down
2 changes: 2 additions & 0 deletions pkg/providers/tencent/tencent.go
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,9 @@ func (p *Tencent) assembleInstanceStatus(ssh *types.SSH, uploadKeyPair bool, pub
v.Current = true
v.InternalIPAddress = tencentCommon.StringValues(status.PrivateIpAddresses)
v.PublicIPAddress = tencentCommon.StringValues(status.PublicIpAddresses)
v.LocalHostname = ""
v.EipAllocationIds = eip

v.SSH = *ssh
// check upload keypair.
if uploadKeyPair {
Expand Down
3 changes: 3 additions & 0 deletions pkg/types/autok3s.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type Metadata struct {
DataStoreCertFileContent string `json:"datastore-certfile-content,omitempty" yaml:"datastore-certfile-content,omitempty"`
DataStoreKeyFileContent string `json:"datastore-keyfile-content,omitempty" yaml:"datastore-keyfile-content,omitempty"`
Rollback bool `json:"rollback,omitempty" yaml:"rollback,omitempty" gorm:"type:bool"`
Values StringMap `json:"values,omitempty" yaml:"values,omitempty" gorm:"type:stringMap"`
}

// Status struct for status.
Expand All @@ -82,6 +83,8 @@ type Node struct {
RollBack bool `json:"-" yaml:"-"`
Current bool `json:"-" yaml:"-"`
Standalone bool `json:"standalone"`

LocalHostname string `json:"local-hostname,omitempty" yaml:"local-hostname,omitempty"`
}

// SSH struct for ssh.
Expand Down
73 changes: 73 additions & 0 deletions pkg/utils/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package utils
import (
"bytes"
"encoding/csv"
"fmt"
"strings"

"github.com/cnrancher/autok3s/pkg/types"
Expand Down Expand Up @@ -31,6 +32,8 @@ func ConvertFlags(cmd *cobra.Command, fs []types.Flag) *pflag.FlagSet {
pf.StringArrayVar(f.P.(*[]string), f.Name, t, f.Usage)
case types.StringArray:
pf.Var(newStringArrayValue(t, f.P.(*types.StringArray)), f.Name, f.Usage)
case types.StringMap:
pf.Var(newStringMapValue(t, f.P.(*types.StringMap)), f.Name, f.Usage)
case int:
pf.IntVar(f.P.(*int), f.Name, t, f.Usage)
default:
Expand All @@ -54,6 +57,8 @@ func ConvertFlags(cmd *cobra.Command, fs []types.Flag) *pflag.FlagSet {
pf.StringArrayVarP(f.P.(*[]string), f.Name, f.ShortHand, t, f.Usage)
case types.StringArray:
pf.VarP(newStringArrayValue(t, f.P.(*types.StringArray)), f.Name, f.ShortHand, f.Usage)
case types.StringMap:
pf.Var(newStringMapValue(t, f.P.(*types.StringMap)), f.Name, f.Usage)
default:
continue
}
Expand Down Expand Up @@ -149,3 +154,71 @@ func writeAsCSV(ss []string) (string, error) {
w.Flush()
return strings.TrimSuffix(b.String(), "\n"), nil
}

type stringMapValue struct {
value *types.StringMap
changed bool
}

func newStringMapValue(val map[string]string, p *types.StringMap) *stringMapValue {
ssv := new(stringMapValue)
ssv.value = p
*ssv.value = val
return ssv
}

func (s *stringMapValue) Set(val string) error {
var ss []string
//Format for: a=1,b=2
n := strings.Count(val, "=")
switch n {
case 0:
return fmt.Errorf("%s must be formatted as key=value", val)
case 1:
ss = append(ss, strings.Trim(val, `"`))
default:
r := csv.NewReader(strings.NewReader(val))
var err error
ss, err = r.Read()
if err != nil {
return err
}
}

out := make(map[string]string, len(ss))
for _, pair := range ss {
kv := strings.SplitN(pair, "=", 2)
if len(kv) != 2 {
return fmt.Errorf("%s must be formatted as key=value", pair)
}
out[kv[0]] = kv[1]
}
if !s.changed {
*s.value = out
} else {
for k, v := range out {
(*s.value)[k] = v
}
}
s.changed = true
return nil
}

func (s *stringMapValue) Type() string {
return "stringMap"
}

func (s *stringMapValue) String() string {
records := make([]string, 0, len(*s.value)>>1)
for k, v := range *s.value {
records = append(records, k+"="+v)
}

var buf bytes.Buffer
w := csv.NewWriter(&buf)
if err := w.Write(records); err != nil {
panic(err)
}
w.Flush()
return "[" + strings.TrimSpace(buf.String()) + "]"
}

0 comments on commit 4dd449e

Please sign in to comment.