Skip to content

Commit

Permalink
refatcor: make run command args dealing more explicit
Browse files Browse the repository at this point in the history
Signed-off-by: Allen Sun <[email protected]>
  • Loading branch information
allencloud committed Jun 10, 2022
1 parent ec33c1e commit 99726a2
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 90 deletions.
3 changes: 3 additions & 0 deletions apply/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ func NewApplierFromFile(path string) (applydriver.Interface, error) {
}, nil
}

// NewApplier news an applier.
// In NewApplier, we guarantee that no raw data could be passed in.
// And all data has to be validated and processed in the pre-process layer.
func NewApplier(cluster *v2.Cluster) (applydriver.Interface, error) {
return NewDefaultApplier(cluster)
}
Expand Down
119 changes: 64 additions & 55 deletions apply/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,107 +15,116 @@
package apply

import (
"fmt"
"strconv"
"strings"

v1 "github.com/sealerio/sealer/types/api/v1"

"github.com/sealerio/sealer/apply/applydriver"

"github.com/sealerio/sealer/common"
v1 "github.com/sealerio/sealer/types/api/v1"
v2 "github.com/sealerio/sealer/types/api/v2"
"github.com/sealerio/sealer/utils/net"
)

type ClusterArgs struct {
cluster *v2.Cluster
imageName string
runArgs *Args
hosts []v2.Host
}

func PreProcessIPList(joinArgs *Args) error {
if err := net.AssemblyIPList(&joinArgs.Masters); err != nil {
return err
func ConstructClusterFromArg(imageName string, runArgs *Args) (*v2.Cluster, error) {
var passwd string
if runArgs.Password != "" {
passwd = runArgs.Password
}
if err := net.AssemblyIPList(&joinArgs.Nodes); err != nil {
return err
}
return nil
}

func (c *ClusterArgs) SetClusterArgs() error {
c.cluster.APIVersion = common.APIVersion
c.cluster.Kind = common.Cluster
c.cluster.Name = c.runArgs.ClusterName
c.cluster.Spec.Image = c.imageName
c.cluster.Spec.SSH.User = c.runArgs.User
c.cluster.Spec.SSH.Pk = c.runArgs.Pk
c.cluster.Spec.SSH.PkPasswd = c.runArgs.PkPassword
c.cluster.Spec.SSH.Port = strconv.Itoa(int(c.runArgs.Port))
c.cluster.Spec.Env = append(c.cluster.Spec.Env, c.runArgs.CustomEnv...)
c.cluster.Spec.CMDArgs = append(c.cluster.Spec.CMDArgs, c.runArgs.CMDArgs...)
if c.runArgs.Password != "" {
c.cluster.Spec.SSH.Passwd = c.runArgs.Password
masters, err := net.AssemblyIPList(runArgs.Masters)
if err != nil {
return nil, fmt.Errorf("failed to parse master(%s):%v", runArgs.Masters, err)
}
err := PreProcessIPList(c.runArgs)
nodes, err := net.AssemblyIPList(runArgs.Nodes)
if err != nil {
return err
return nil, fmt.Errorf("failed to parse nodes(%s):%v", runArgs.Nodes, err)
}
if net.IsIPList(c.runArgs.Masters) && (net.IsIPList(c.runArgs.Nodes) || c.runArgs.Nodes == "") {
masters := strings.Split(c.runArgs.Masters, ",")
nodes := strings.Split(c.runArgs.Nodes, ",")
c.hosts = []v2.Host{}
c.setHostWithIpsPort(masters, common.MASTER)

resultHosts := []v2.Host{}
if net.IsIPList(runArgs.Masters) && (net.IsIPList(runArgs.Nodes) || runArgs.Nodes == "") {
masters := strings.Split(masters, ",")
nodes := strings.Split(nodes, ",")
masterHosts := getHostsWithIpsPort(masters, runArgs.Port, common.MASTER)
resultHosts = append(resultHosts, masterHosts...)
if len(nodes) != 0 {
c.setHostWithIpsPort(nodes, common.NODE)
nodeHosts := getHostsWithIpsPort(nodes, runArgs.Port, common.NODE)
resultHosts = append(resultHosts, nodeHosts...)
}
c.cluster.Spec.Hosts = c.hosts
} else {
ip, err := net.GetLocalDefaultIP()
if err != nil {
return err
return nil, fmt.Errorf("failed to get local default IP: %v", err)
}
c.cluster.Spec.Hosts = []v2.Host{
resultHosts = []v2.Host{
{
IPS: []string{ip},
Roles: []string{common.MASTER},
},
}
}
return err

cluster := v2.Cluster{
Spec: v2.ClusterSpec{
SSH: v1.SSH{
User: runArgs.User,
Passwd: passwd,
PkPasswd: runArgs.PkPassword,
Pk: runArgs.Pk,
Port: strconv.Itoa(int(runArgs.Port)),
},
Image: imageName,
Hosts: resultHosts,
Env: runArgs.CustomEnv,
CMDArgs: runArgs.CMDArgs,
},
}
cluster.APIVersion = common.APIVersion
cluster.Kind = common.Kind
cluster.Name = runArgs.ClusterName

return &cluster, nil
}

func (c *ClusterArgs) setHostWithIpsPort(ips []string, role string) {
func getHostsWithIpsPort(ips []string, port uint16, role string) []v2.Host {
var hosts []v2.Host
//map[ssh port]*host
hostMap := map[string]*v2.Host{}
for i := range ips {
ip, port := net.GetHostIPAndPortOrDefault(ips[i], strconv.Itoa(int(c.runArgs.Port)))
ip, port := net.GetHostIPAndPortOrDefault(ips[i], strconv.Itoa(int(port)))
if _, ok := hostMap[port]; !ok {
hostMap[port] = &v2.Host{IPS: []string{ip}, Roles: []string{role}, SSH: v1.SSH{Port: port}}
continue
}
hostMap[port].IPS = append(hostMap[port].IPS, ip)
}
_, master0Port := net.GetHostIPAndPortOrDefault(ips[0], strconv.Itoa(int(c.runArgs.Port)))
_, master0Port := net.GetHostIPAndPortOrDefault(ips[0], strconv.Itoa(int(port)))
for port, host := range hostMap {
host.IPS = removeIPListDuplicatesAndEmpty(host.IPS)
if port == master0Port && role == common.MASTER {
c.hosts = append([]v2.Host{*host}, c.hosts...)
hosts = append([]v2.Host{*host}, hosts...)
continue
}
c.hosts = append(c.hosts, *host)
hosts = append(hosts, *host)
}

return hosts
}

func NewApplierFromArgs(imageName string, runArgs *Args) (applydriver.Interface, error) {
c := &ClusterArgs{
cluster: &v2.Cluster{},
imageName: imageName,
runArgs: runArgs,
if err := validateArgs(runArgs); err != nil {
return nil, fmt.Errorf("failed to validate input args: %v", err)
}
if err := c.SetClusterArgs(); err != nil {
return nil, err
cluster, err := ConstructClusterFromArg(imageName, runArgs)
if err != nil {
return nil, fmt.Errorf("failed to initialize cluster instance with command args: %v", err)
}
return NewApplier(c.cluster)

return NewApplier(cluster)
}

// validateArgs validates all the input args from sealer run command.
func validateArgs(runArgs *Args) error {
// TODO: add detailed validation steps.
return nil
}
9 changes: 7 additions & 2 deletions apply/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,13 @@ func TestAssemblyIPList(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := net.AssemblyIPList(&tt.args.Masters); (err != nil) != tt.wantErr {
logrus.Errorf("masters : %v , nodes : %v", &tt.args.Masters, &tt.args.Nodes)
masters, err := net.AssemblyIPList(tt.args.Masters)
if (err != nil) != tt.wantErr {
logrus.Errorf("masters: %v ", masters)
}
nodes, err := net.AssemblyIPList(tt.args.Nodes)
if (err != nil) != tt.wantErr {
logrus.Errorf("nodes: %v", nodes)
}
logrus.Infof("masters : %v , nodes : %v", &tt.args.Masters, &tt.args.Nodes)
})
Expand Down
43 changes: 26 additions & 17 deletions apply/scale.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,12 @@ import (
"fmt"
"strings"

"github.com/sealerio/sealer/utils/yaml"

"github.com/sealerio/sealer/utils/net"

"github.com/sealerio/sealer/apply/applydriver"
"github.com/sealerio/sealer/common"
v2 "github.com/sealerio/sealer/types/api/v2"
"github.com/sealerio/sealer/utils/net"
strUtils "github.com/sealerio/sealer/utils/strings"
"github.com/sealerio/sealer/utils/yaml"
)

// NewScaleApplierFromArgs will filter ip list from command parameters.
Expand Down Expand Up @@ -74,14 +72,20 @@ func Join(cluster *v2.Cluster, scalingArgs *Args) error {
}

func joinBaremetalNodes(cluster *v2.Cluster, scaleArgs *Args) error {
if err := PreProcessIPList(scaleArgs); err != nil {
masters, err := net.AssemblyIPList(scaleArgs.Masters)
if err != nil {
return err
}
nodes, err := net.AssemblyIPList(scaleArgs.Nodes)
if err != nil {
return err
}
if (!net.IsIPList(scaleArgs.Nodes) && scaleArgs.Nodes != "") || (!net.IsIPList(scaleArgs.Masters) && scaleArgs.Masters != "") {
return fmt.Errorf(" Parameter error: The current mode should submit iplist!")

if (!net.IsIPList(nodes) && nodes != "") || (!net.IsIPList(masters) && masters != "") {
return fmt.Errorf("parameter error: The current mode should submit iplist!")
}

if scaleArgs.Masters != "" && net.IsIPList(scaleArgs.Masters) {
if masters != "" && net.IsIPList(masters) {
for i := 0; i < len(cluster.Spec.Hosts); i++ {
role := cluster.Spec.Hosts[i].Roles
if !strUtils.NotIn(common.MASTER, role) {
Expand All @@ -94,15 +98,15 @@ func joinBaremetalNodes(cluster *v2.Cluster, scaleArgs *Args) error {
}
}
//add join node
if scaleArgs.Nodes != "" && net.IsIPList(scaleArgs.Nodes) {
if nodes != "" && net.IsIPList(nodes) {
for i := 0; i < len(cluster.Spec.Hosts); i++ {
role := cluster.Spec.Hosts[i].Roles
if !strUtils.NotIn(common.NODE, role) {
cluster.Spec.Hosts[i].IPS = removeIPListDuplicatesAndEmpty(append(cluster.Spec.Hosts[i].IPS, strings.Split(scaleArgs.Nodes, ",")...))
cluster.Spec.Hosts[i].IPS = removeIPListDuplicatesAndEmpty(append(cluster.Spec.Hosts[i].IPS, strings.Split(nodes, ",")...))
break
}
if i == len(cluster.Spec.Hosts)-1 {
hosts := v2.Host{IPS: removeIPListDuplicatesAndEmpty(strings.Split(scaleArgs.Nodes, ",")), Roles: []string{common.NODE}}
hosts := v2.Host{IPS: removeIPListDuplicatesAndEmpty(strings.Split(nodes, ",")), Roles: []string{common.NODE}}
cluster.Spec.Hosts = append(cluster.Spec.Hosts, hosts)
}
}
Expand All @@ -119,20 +123,25 @@ func Delete(cluster *v2.Cluster, scaleArgs *Args) error {
}

func deleteBaremetalNodes(cluster *v2.Cluster, scaleArgs *Args) error {
if err := PreProcessIPList(scaleArgs); err != nil {
masters, err := net.AssemblyIPList(scaleArgs.Masters)
if err != nil {
return err
}
nodes, err := net.AssemblyIPList(scaleArgs.Nodes)
if err != nil {
return err
}
if (!net.IsIPList(scaleArgs.Nodes) && scaleArgs.Nodes != "") || (!net.IsIPList(scaleArgs.Masters) && scaleArgs.Masters != "") {
return fmt.Errorf(" Parameter error: The current mode should submit iplist")
if (!net.IsIPList(nodes) && nodes != "") || (!net.IsIPList(masters) && masters != "") {
return fmt.Errorf("parameter error: The current mode should submit iplist!")
}
//master0 machine cannot be deleted
if !strUtils.NotIn(cluster.GetMaster0IP(), strings.Split(scaleArgs.Masters, ",")) {
if !strUtils.NotIn(cluster.GetMaster0IP(), strings.Split(masters, ",")) {
return fmt.Errorf("master0 machine cannot be deleted")
}
if scaleArgs.Masters != "" && net.IsIPList(scaleArgs.Masters) {
if masters != "" && net.IsIPList(masters) {
for i := range cluster.Spec.Hosts {
if !strUtils.NotIn(common.MASTER, cluster.Spec.Hosts[i].Roles) {
cluster.Spec.Hosts[i].IPS = returnFilteredIPList(cluster.Spec.Hosts[i].IPS, strings.Split(scaleArgs.Masters, ","))
cluster.Spec.Hosts[i].IPS = returnFilteredIPList(cluster.Spec.Hosts[i].IPS, strings.Split(masters, ","))
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/plugin/taint_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,14 @@ func (l *Taint) formatData(data string) error {
return fmt.Errorf("faild to split taint argument: %s", v)
}
ips := temps[0]
err := net.AssemblyIPList(&ips)
ipStr, err := net.AssemblyIPList(ips)
if err != nil {
return err
}
l.IPList = append(l.IPList, ips)
l.IPList = append(l.IPList, ipStr)
//kubectl taint nodes xxx key- : remove all key related taints
if l.TaintList[ips] == nil {
l.TaintList[ips] = &taintList{}
if l.TaintList[ipStr] == nil {
l.TaintList[ipStr] = &taintList{}
}
if strings.HasSuffix(temps[1], DelSymbol) && !strings.Contains(temps[1], ColonSymbol) && !strings.Contains(temps[1], EqualSymbol) {
l.TaintList[ips].DelTaintList = append(l.TaintList[ips].DelTaintList, newTaintStruct(strings.TrimSuffix(temps[1], DelSymbol), "", ""))
Expand Down
24 changes: 12 additions & 12 deletions utils/net/iputils.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,17 +135,17 @@ func GetLocalIP(master0IP string) (string, error) {
return strings.Split(localAddr, ":")[0], err
}

func AssemblyIPList(args *string) error {
func AssemblyIPList(args string) (string, error) {
var result []string
var ips = strings.Split(*args, "-")
if *args == "" || !strings.Contains(*args, "-") {
return nil
var ips = strings.Split(args, "-")
if args == "" || !strings.Contains(args, "-") {
return "", nil
}
if len(ips) != 2 {
return fmt.Errorf("ip is invalid, ip range format is xxx.xxx.xxx.1-xxx.xxx.xxx.2")
return "", fmt.Errorf("ip is invalid, ip range format is xxx.xxx.xxx.1-xxx.xxx.xxx.2")
}
if !CheckIP(ips[0]) || !CheckIP(ips[1]) {
return fmt.Errorf("ip is invalid, check you command agrs")
return "", fmt.Errorf("ip is invalid, check you command agrs")
}
//ips[0],ips[1] = 192.168.56.3, 192.168.56.7; result = [192.168.56.3, 192.168.56.4, 192.168.56.5, 192.168.56.6, 192.168.56.7]
for res, _ := CompareIP(ips[0], ips[1]); res <= 0; {
Expand All @@ -154,10 +154,9 @@ func AssemblyIPList(args *string) error {
res, _ = CompareIP(ips[0], ips[1])
}
if len(result) == 0 {
return fmt.Errorf("ip is invalid, check you command agrs")
return "", fmt.Errorf("ip is invalid, check you command agrs")
}
*args = strings.Join(result, ",")
return nil
return strings.Join(result, ","), nil
}

func CheckIP(i string) bool {
Expand All @@ -175,11 +174,12 @@ func DisassembleIPList(arg string) (res []string) {
for _, i := range ipList {
if strings.Contains(i, "-") {
// #nosec
if err := AssemblyIPList(&i); err != nil {
fmt.Printf("failed to get Addrs, %s", err.Error())
ipStr, err := AssemblyIPList(i)
if err != nil {
fmt.Printf("failed to get Addr: %v", err)
continue
}
res = append(res, strings.Split(i, ",")...)
res = append(res, strings.Split(ipStr, ",")...)
}
res = append(res, i)
}
Expand Down

0 comments on commit 99726a2

Please sign in to comment.