github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/pkg/clusterfile/decoder_test.go (about)

     1  // Copyright © 2022 Alibaba Group Holding Ltd.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package clusterfile
    16  
    17  import (
    18  	"net"
    19  	"os"
    20  	"testing"
    21  
    22  	"github.com/sealerio/sealer/types/api/constants"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  	"k8s.io/kube-proxy/config/v1alpha1"
    26  
    27  	v1 "github.com/sealerio/sealer/types/api/v1"
    28  	v2 "github.com/sealerio/sealer/types/api/v2"
    29  )
    30  
    31  const data = `apiVersion: sealer.com/v1alpha1
    32  kind: Config
    33  metadata:
    34    name: mysql-config
    35  spec:
    36    path: etc/mysql.yaml
    37    data: |
    38         mysql-user: root
    39         mysql-passwd: xxx
    40  ---
    41  apiVersion: sealer.io/v2
    42  kind: Application
    43  metadata:
    44    name: my-apps
    45  spec:
    46    launchApps:
    47      - app1
    48      - app2
    49    configs:
    50      - name: app2
    51        launch:
    52          cmds:
    53            - kubectl get pods -A
    54  ---
    55  apiVersion: sealer.io/v1
    56  kind: Plugin
    57  metadata:
    58    name: MyHostname # Specify this plugin name,will dump in $rootfs/plugins dir.
    59  spec:
    60    type: HOSTNAME # fixed string,should not change this name.
    61    action: PreInit # Specify which phase to run.
    62    data: |
    63      192.168.0.2 master-0
    64  ---
    65  apiVersion: sealer.io/v1
    66  kind: Plugin
    67  metadata:
    68    name: MyShell # Specify this plugin name,will dump in $rootfs/plugins dir.
    69  spec:
    70    type: SHELL
    71    action: PostInstall # PreInit PostInstall
    72    scope: master
    73    data: |
    74      kubectl get nodes
    75  ---
    76  apiVersion: sealer.io/v2
    77  kind: Cluster
    78  metadata:
    79    name: my-cluster
    80  spec:
    81    image: kubernetes:v1.19.8
    82    env:
    83      - key1=value1
    84      - key2=value2;value3 #key2=[value2, value3]
    85    ssh:
    86      passwd: test123
    87      pk: xxx
    88      pkPasswd: xxx
    89      user: root
    90      port: "22"
    91    hosts:
    92      - ips: [ 192.168.0.2 ]
    93        roles: [ master ] # add role field to specify the node role
    94        env: # rewrite some nodes has different env config
    95          - etcd-dir=/data/etcd
    96        ssh: # rewrite ssh config if some node has different passwd...
    97          user: root
    98          passwd: test456
    99          port: "22"
   100      - ips: [ 192.168.0.3 ]
   101        roles: [ node,db ]
   102  ---
   103  apiVersion: kubeadm.k8s.io/v1beta3
   104  kind: InitConfiguration
   105  localAPIEndpoint:
   106    bindPort: 6443
   107  nodeRegistration:
   108    criSocket: /var/run/dockershim.sock
   109  ---
   110  apiVersion: kubeproxy.config.k8s.io/v1alpha1
   111  kind: KubeProxyConfiguration
   112  mode: "ipvs"
   113  ipvs:
   114    excludeCIDRs:
   115      - "10.103.97.2/32"`
   116  
   117  func TestDecodeClusterFile(t *testing.T) {
   118  	cluster := v2.Cluster{
   119  		Spec: v2.ClusterSpec{
   120  			Image:    "kubernetes:v1.19.8",
   121  			DataRoot: "/var/lib/sealer/data",
   122  			Env:      []string{"key1=value1", "key2=value2;value3", "LocalRegistryDomain=sea.hub", "LocalRegistryPort=5000", "LocalRegistryURL=sea.hub:5000", "RegistryDomain=sea.hub", "RegistryPort=5000", "RegistryURL=sea.hub:5000"},
   123  			SSH: v1.SSH{
   124  				User:     "root",
   125  				Passwd:   "test123",
   126  				Port:     "22",
   127  				Pk:       "xxx",
   128  				PkPasswd: "xxx",
   129  			},
   130  			Registry: v2.Registry{
   131  				LocalRegistry: &v2.LocalRegistry{
   132  					RegistryConfig: v2.RegistryConfig{
   133  						Domain: "sea.hub",
   134  						Port:   5000,
   135  					},
   136  					HA:       &defaultHA,
   137  					Insecure: &defaultInsecure,
   138  				},
   139  			},
   140  			Hosts: []v2.Host{
   141  				{
   142  					IPS:   []net.IP{net.IPv4(192, 168, 0, 2)},
   143  					Roles: []string{"master"},
   144  					Env:   []string{"etcd-dir=/data/etcd"},
   145  					SSH: v1.SSH{
   146  						User:   "root",
   147  						Passwd: "test456",
   148  						Port:   "22",
   149  					},
   150  				},
   151  				{
   152  					IPS:   []net.IP{net.IPv4(192, 168, 0, 3)},
   153  					Roles: []string{"node", "db"},
   154  				},
   155  			},
   156  		},
   157  	}
   158  	cluster.APIVersion = "sealer.io/v2"
   159  	cluster.Kind = "Cluster"
   160  	cluster.Name = "my-cluster"
   161  
   162  	plugin1 := v1.Plugin{
   163  		Spec: v1.PluginSpec{
   164  			Type:   "HOSTNAME",
   165  			Data:   "192.168.0.2 master-0\n",
   166  			Action: "PreInit",
   167  		},
   168  	}
   169  	plugin1.Name = "MyHostname"
   170  	plugin1.Kind = constants.PluginKind
   171  	plugin1.APIVersion = v1.GroupVersion.String()
   172  
   173  	plugin2 := v1.Plugin{
   174  		Spec: v1.PluginSpec{
   175  			Type:   "SHELL",
   176  			Data:   "kubectl get nodes\n",
   177  			Scope:  "master",
   178  			Action: "PostInstall",
   179  		},
   180  	}
   181  	plugin2.Name = "MyShell"
   182  	plugin2.Kind = "Plugin"
   183  	plugin2.APIVersion = "sealer.io/v1"
   184  
   185  	config := v1.Config{
   186  		Spec: v1.ConfigSpec{
   187  			Path: "etc/mysql.yaml",
   188  			Data: "mysql-user: root\nmysql-passwd: xxx\n",
   189  		},
   190  	}
   191  	config.Name = "mysql-config"
   192  	config.Kind = "Config"
   193  	config.APIVersion = "sealer.com/v1alpha1"
   194  
   195  	app := &v2.Application{
   196  		Spec: v2.ApplicationSpec{
   197  			LaunchApps: []string{"app1", "app2"},
   198  			Configs: []v2.ApplicationConfig{
   199  				{
   200  					Name: "app2",
   201  					Launch: &v2.Launch{
   202  						Cmds: []string{
   203  							"kubectl get pods -A",
   204  						},
   205  					},
   206  				},
   207  			},
   208  		},
   209  	}
   210  	app.Name = "my-apps"
   211  	app.Kind = constants.ApplicationKind
   212  	app.APIVersion = v2.GroupVersion.String()
   213  
   214  	type wanted struct {
   215  		cluster     v2.Cluster
   216  		config      []v1.Config
   217  		plugins     []v1.Plugin
   218  		application *v2.Application
   219  	}
   220  
   221  	type args struct {
   222  		data   []byte
   223  		wanted wanted
   224  	}
   225  
   226  	var tests = []struct {
   227  		name string
   228  		args args
   229  	}{
   230  		{
   231  			"test decode cluster file",
   232  			args{
   233  				data: []byte(data),
   234  				wanted: wanted{
   235  					cluster:     cluster,
   236  					config:      []v1.Config{config},
   237  					plugins:     []v1.Plugin{plugin1, plugin2},
   238  					application: app,
   239  				},
   240  			},
   241  		},
   242  	}
   243  
   244  	f, err := os.CreateTemp("", "tmpfile-")
   245  	if err != nil {
   246  		assert.Error(t, err)
   247  	}
   248  
   249  	defer os.Remove(f.Name())
   250  
   251  	if _, err = f.Write([]byte(data)); err != nil {
   252  		assert.Error(t, err)
   253  	}
   254  	if err = f.Close(); err != nil {
   255  		assert.Error(t, err)
   256  	}
   257  
   258  	for _, tt := range tests {
   259  		t.Run(tt.name, func(t *testing.T) {
   260  			i, err := NewClusterFile([]byte(data))
   261  			if err != nil {
   262  				assert.Errorf(t, err, "failed to NewClusterFile by name")
   263  			}
   264  
   265  			assert.NotNil(t, i)
   266  
   267  			assert.Equal(t, tt.args.wanted.cluster, i.GetCluster())
   268  
   269  			assert.Equal(t, tt.args.wanted.config, i.GetConfigs())
   270  
   271  			assert.Equal(t, tt.args.wanted.plugins, i.GetPlugins())
   272  
   273  			assert.Equal(t, tt.args.wanted.application, i.GetApplication())
   274  
   275  			kubeadm := i.GetKubeadmConfig()
   276  			assert.NotNil(t, kubeadm)
   277  
   278  			assert.Equal(t, kubeadm.LocalAPIEndpoint.BindPort, int32(6443))
   279  			assert.Equal(t, kubeadm.InitConfiguration.NodeRegistration.CRISocket, "/var/run/dockershim.sock")
   280  
   281  			assert.Equal(t, kubeadm.Mode, v1alpha1.ProxyMode("ipvs"))
   282  			assert.Equal(t, kubeadm.IPVS.ExcludeCIDRs, []string{"10.103.97.2/32"})
   283  		})
   284  	}
   285  }