diff --git a/.github/workflows/provider-packaging.yaml b/.github/workflows/provider-packaging.yaml index 366e309..d678748 100644 --- a/.github/workflows/provider-packaging.yaml +++ b/.github/workflows/provider-packaging.yaml @@ -13,10 +13,16 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: docker-practice/actions-setup-docker@master + - name: Set up QEMU + uses: docker/setup-qemu-action@master + with: + platforms: all + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@master - uses: earthly/actions-setup@v1 with: - version: "v0.6.30" + version: "latest" - run: earthly --ci +lint build-provider-package: runs-on: ubuntu-latest @@ -24,29 +30,15 @@ jobs: packages: write steps: - uses: actions/checkout@v4 - - uses: docker-practice/actions-setup-docker@master - - uses: earthly/actions-setup@v1 - with: - version: "v0.6.30" - - uses: docker/login-action@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@master with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - run: earthly --ci --push +provider-package-all-platforms --IMAGE_REPOSITORY=ghcr.io/kairos-io - build-provider-fips-package: - runs-on: ubuntu-latest - permissions: - packages: write - steps: - - uses: actions/checkout@v4 - - uses: docker-practice/actions-setup-docker@master + platforms: all + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@master - uses: earthly/actions-setup@v1 with: - version: "v0.6.30" - - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - run: earthly --ci --push +provider-fips-package-all-platforms --IMAGE_REPOSITORY=ghcr.io/kairos-io --FIPS_ENABLED=true + version: "latest" + - run: echo "${{ secrets.GCR_DEV_PUBLIC_B64_TOKEN }}" | base64 -d | docker login -u _json_key --password-stdin https://gcr.io + - run: earthly --ci --push +provider-package-all-platforms --IMAGE_REPOSITORY=gcr.io/spectro-dev-public/kairos-io diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..073b89e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,26 @@ +# install pre-commit on your system and then +# run pre-commit install in this repository. +# You can by pass commit hooks with: +# git commit -n +repos: + - repo: https://github.com/compilerla/conventional-pre-commit + rev: v2.4.0 + hooks: + - id: conventional-pre-commit + stages: [commit-msg] + - repo: https://github.com/tekwizely/pre-commit-golang + rev: v1.0.0-rc.1 + hooks: + - id: go-mod-tidy + - repo: https://github.com/golangci/golangci-lint + rev: v1.61.0 + hooks: + - id: golangci-lint + name: golangci-lint + description: Fast linters runner for Go. Note that only modified files are linted, so linters like 'unused' that need to scan all files won't work as expected. + entry: golangci-lint run --new-from-rev HEAD --whole-files -v + types: [go] + language: golang + require_serial: true + pass_filenames: false + verbose: true diff --git a/Earthfile b/Earthfile index dc2f722..ce943d8 100644 --- a/Earthfile +++ b/Earthfile @@ -5,8 +5,8 @@ ARG BASE_IMAGE=quay.io/kairos/core-opensuse-leap:v2.4.3 ARG IMAGE_REPOSITORY=quay.io/kairos ARG LUET_VERSION=0.35.1 -ARG GOLINT_VERSION=v1.56.2 -ARG GOLANG_VERSION=1.22 +ARG GOLINT_VERSION=v1.61.0 +ARG GOLANG_VERSION=1.23 ARG RKE2_VERSION=latest ARG BASE_IMAGE_NAME=$(echo $BASE_IMAGE | grep -o [^/]*: | rev | cut -c2- | rev) @@ -55,7 +55,7 @@ VERSION: COPY . ./ - RUN echo $(git describe --exact-match --tags || echo "v0.0.0-$(git log --oneline -n 1 | cut -d" " -f1)") > VERSION + RUN echo $(git describe --exact-match --tags || echo "v0.0.0-$(git rev-parse --short=8 HEAD)") > VERSION SAVE ARTIFACT VERSION VERSION diff --git a/go.mod b/go.mod index 7a01690..e4c6fb7 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,12 @@ module github.com/c3os-io/c3os/provider-rke2 -go 1.22.5 +go 1.23.1 require ( - github.com/kairos-io/kairos-sdk v0.4.2 - github.com/mudler/yip v1.9.4 + github.com/kairos-io/kairos-sdk v0.5.0 + github.com/mudler/go-pluggable v0.0.0-20230126220627-7710299a0ae5 + github.com/mudler/yip v1.10.0 github.com/sirupsen/logrus v1.9.3 - gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 sigs.k8s.io/yaml v1.4.0 ) @@ -20,7 +20,6 @@ require ( github.com/itchyny/gojq v0.12.16 // indirect github.com/itchyny/timefmt-go v0.1.6 // indirect github.com/kr/pretty v0.3.1 // indirect - github.com/mudler/go-pluggable v0.0.0-20230126220627-7710299a0ae5 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect @@ -28,5 +27,5 @@ require ( github.com/twpayne/go-vfs/v4 v4.3.0 // indirect golang.org/x/sys v0.24.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect - gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 1729e05..24eb7d2 100644 --- a/go.sum +++ b/go.sum @@ -40,8 +40,8 @@ github.com/itchyny/gojq v0.12.16 h1:yLfgLxhIr/6sJNVmYfQjTIv0jGctu6/DgDoivmxTr7g= github.com/itchyny/gojq v0.12.16/go.mod h1:6abHbdC2uB9ogMS38XsErnfqJ94UlngIJGlRAIj4jTM= github.com/itchyny/timefmt-go v0.1.6 h1:ia3s54iciXDdzWzwaVKXZPbiXzxxnv1SPGFfM/myJ5Q= github.com/itchyny/timefmt-go v0.1.6/go.mod h1:RRDZYC5s9ErkjQvTvvU7keJjxUYzIISJGxm9/mAERQg= -github.com/kairos-io/kairos-sdk v0.4.2 h1:tq0a6R9qSotatFt20q/+oIHJSN+XTQWji4XgHk5Vvlw= -github.com/kairos-io/kairos-sdk v0.4.2/go.mod h1:1x8VaVt1ppXxQUlNyDRksoDglR423hxfEtjx6qWDO7w= +github.com/kairos-io/kairos-sdk v0.5.0 h1:CtYz2WXe5huKkjPSro2J1kiLVjDr6T9909uckK17Bqw= +github.com/kairos-io/kairos-sdk v0.5.0/go.mod h1:RO5ad3gCd2O2zJE5mEnPHLUy/+fRKKQL4fe7xV6FtyA= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -51,8 +51,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mudler/go-pluggable v0.0.0-20230126220627-7710299a0ae5 h1:FaZD86+A9mVt7lh9glAryzQblMsbJYU2VnrdZ8yHlTs= github.com/mudler/go-pluggable v0.0.0-20230126220627-7710299a0ae5/go.mod h1:WmKcT8ONmhDQIqQ+HxU+tkGWjzBEyY/KFO8LTGCu4AI= -github.com/mudler/yip v1.9.4 h1:yaiPKWG5kt/DTNCf7ZGfyWdb1j5c06zYqWF3F+SVKsE= -github.com/mudler/yip v1.9.4/go.mod h1:nqf8JFCq7a7rIkm7cSs+SOc8QbiyvVJ/xLbUw4GgzFs= +github.com/mudler/yip v1.10.0 h1:MwEIySEfSRRwTUz2BmQQpRn6+M7jqVGf/OldsepBvz0= +github.com/mudler/yip v1.10.0/go.mod h1:gwH7iGcr1Jimox2xKtN2AprEO00GzY7smvuycqCL7+Y= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -127,8 +127,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0 h1:POO/ycCATvegFmVuPpQzZFJ+pGZeX22Ufu6fibxDVjU= -gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -136,7 +134,5 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/main.go b/main.go index 911d52d..e09a990 100644 --- a/main.go +++ b/main.go @@ -1,226 +1,21 @@ package main import ( - "bytes" - "encoding/json" - "fmt" - "net" - "path/filepath" - "strings" - + "github.com/c3os-io/c3os/provider-rke2/pkg/provider" "github.com/kairos-io/kairos-sdk/clusterplugin" - yip "github.com/mudler/yip/pkg/schema" + "github.com/mudler/go-pluggable" "github.com/sirupsen/logrus" - "gopkg.in/yaml.v2" - kyaml "sigs.k8s.io/yaml" -) - -const ( - configurationPath = "/etc/rancher/rke2/config.d" - containerdEnvConfigPath = "/etc/default" - - serverSystemName = "rke2-server" - agentSystemName = "rke2-agent" - K8SNoProxy = ".svc,.svc.cluster,.svc.cluster.local" - localImagesPath = "/opt/content/images" ) -type RKE2Config struct { - Token string `yaml:"token"` - Server string `yaml:"server"` - TLSSan []string `yaml:"tls-san"` -} - -func clusterProvider(cluster clusterplugin.Cluster) yip.YipConfig { - - var importStage yip.Stage - rke2Config := RKE2Config{ - Token: cluster.ClusterToken, - // RKE2 server listens on 9345 for node registration https://docs.rke2.io/install/quickstart/#3-configure-the-rke2-agent-service - Server: fmt.Sprintf("https://%s:9345", cluster.ControlPlaneHost), - TLSSan: []string{ - cluster.ControlPlaneHost, - }, - } - - if cluster.Role == clusterplugin.RoleInit { - rke2Config.Server = "" - - } - - systemName := serverSystemName - if cluster.Role == clusterplugin.RoleWorker { - systemName = agentSystemName - } - - // ensure we always have a valid user config - if cluster.Options == "" { - cluster.Options = "{}" - } - - var providerConfig bytes.Buffer - _ = yaml.NewEncoder(&providerConfig).Encode(&rke2Config) - - userOptions, _ := kyaml.YAMLToJSON([]byte(cluster.Options)) - options, _ := kyaml.YAMLToJSON(providerConfig.Bytes()) - - proxyValues := proxyEnv(userOptions, cluster.Env) - - files := []yip.File{ - { - Path: filepath.Join(configurationPath, "90_userdata.yaml"), - Permissions: 0400, - Content: string(userOptions), - }, - { - Path: filepath.Join(configurationPath, "99_userdata.yaml"), - Permissions: 0400, - Content: string(options), - }, - } - - if len(proxyValues) > 0 { - files = append(files, yip.File{ - Path: filepath.Join(containerdEnvConfigPath, systemName), - Permissions: 0400, - Content: proxyValues, - }) - } - - stages := []yip.Stage{ - { - Name: "Install RKE2 Configuration Files", - Files: files, - - Commands: []string{ - fmt.Sprintf("jq -s 'def flatten: reduce .[] as $i([]; if $i | type == \"array\" then . + ($i | flatten) else . + [$i] end); [.[] | to_entries] | flatten | reduce .[] as $dot ({}; .[$dot.key] += $dot.value)' %s/*.yaml > /etc/rancher/rke2/config.yaml", configurationPath), - }, - }, - } - - if cluster.ImportLocalImages { - if cluster.LocalImagesPath == "" { - cluster.LocalImagesPath = localImagesPath - } - - importStage = yip.Stage{ - Commands: []string{ - fmt.Sprintf("/bin/sh /opt/rke2/scripts/import.sh %s > /var/log/import.log", cluster.LocalImagesPath), - }, - If: fmt.Sprintf("[ -d %s ]", cluster.LocalImagesPath), - } - stages = append(stages, importStage) - } - - stages = append(stages, - yip.Stage{ - Name: "Waiting to finish extracting content", - Commands: []string{ - "sleep 120", - }, - }, - yip.Stage{ - Name: "Enable Systemd Services", - Commands: []string{ - fmt.Sprintf("systemctl enable %s", systemName), - fmt.Sprintf("systemctl restart %s", systemName), - }, - }) - - cfg := yip.YipConfig{ - Name: "RKE2 Kairos Cluster Provider", - Stages: map[string][]yip.Stage{ - "boot.before": stages, - }, - } - - return cfg -} - -func proxyEnv(userOptions []byte, proxyMap map[string]string) string { - var proxy []string - var noProxy string - var isProxyConfigured bool - - httpProxy := proxyMap["HTTP_PROXY"] - httpsProxy := proxyMap["HTTPS_PROXY"] - userNoProxy := proxyMap["NO_PROXY"] - defaultNoProxy := getDefaultNoProxy(userOptions) - - if len(httpProxy) > 0 { - proxy = append(proxy, fmt.Sprintf("HTTP_PROXY=%s", httpProxy)) - proxy = append(proxy, fmt.Sprintf("CONTAINERD_HTTP_PROXY=%s", httpProxy)) - isProxyConfigured = true - } - - if len(httpsProxy) > 0 { - proxy = append(proxy, fmt.Sprintf("HTTPS_PROXY=%s", httpsProxy)) - proxy = append(proxy, fmt.Sprintf("CONTAINERD_HTTPS_PROXY=%s", httpsProxy)) - isProxyConfigured = true - } - - if isProxyConfigured { - noProxy = defaultNoProxy - } - - if len(userNoProxy) > 0 { - noProxy = noProxy + "," + userNoProxy - } - - if len(noProxy) > 0 { - proxy = append(proxy, fmt.Sprintf("NO_PROXY=%s", noProxy)) - proxy = append(proxy, fmt.Sprintf("CONTAINERD_NO_PROXY=%s", noProxy)) - } - - return strings.Join(proxy, "\n") -} - -func getDefaultNoProxy(userOptions []byte) string { - - var noProxy string - - data := make(map[string]interface{}) - err := json.Unmarshal(userOptions, &data) - if err != nil { - fmt.Println("error while unmarshalling user options", err) - } - - if data != nil { - clusterCIDR := data["cluster-cidr"].(string) - serviceCIDR := data["service-cidr"].(string) - - if len(clusterCIDR) > 0 { - noProxy = noProxy + "," + clusterCIDR - } - if len(serviceCIDR) > 0 { - noProxy = noProxy + "," + serviceCIDR - } - noProxy = noProxy + "," + getNodeCIDR() + "," + K8SNoProxy - } - - return noProxy -} - -func getNodeCIDR() string { - addrs, _ := net.InterfaceAddrs() - var result string - for _, addr := range addrs { - if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { - if ipnet.IP.To4() != nil { - result = addr.String() - break - } - } - } - return result -} - func main() { plugin := clusterplugin.ClusterPlugin{ - Provider: clusterProvider, + Provider: provider.ClusterProvider, } - if err := plugin.Run(); err != nil { + if err := plugin.Run(pluggable.FactoryPlugin{ + EventType: clusterplugin.EventClusterReset, + PluginHandler: provider.HandleClusterReset, + }); err != nil { logrus.Fatal(err) } } diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go new file mode 100644 index 0000000..5737a1d --- /dev/null +++ b/pkg/constants/constants.go @@ -0,0 +1,16 @@ +package constants + +const ( + ConfigurationPath = "/etc/rancher/rke2/config.d" + ContainerdEnvConfigPath = "/etc/default" + + ServerSystemName = "rke2-server" + AgentSystemName = "rke2-agent" + K8SNoProxy = ".svc,.svc.cluster,.svc.cluster.local" + LocalImagesPath = "/opt/content/images" +) + +const ( + ClusterRootPath = "cluster_root_path" + RunSystemdSystemDir = "/run/systemd/system" +) diff --git a/pkg/provider/provider.go b/pkg/provider/provider.go new file mode 100644 index 0000000..4bb0fe9 --- /dev/null +++ b/pkg/provider/provider.go @@ -0,0 +1,206 @@ +package provider + +import ( + "bytes" + "encoding/json" + "fmt" + "net" + "path/filepath" + "strings" + + _ "embed" + + "github.com/c3os-io/c3os/provider-rke2/pkg/constants" + "github.com/c3os-io/c3os/provider-rke2/pkg/types" + "github.com/kairos-io/kairos-sdk/clusterplugin" + yip "github.com/mudler/yip/pkg/schema" + "gopkg.in/yaml.v3" + kyaml "sigs.k8s.io/yaml" +) + +func ClusterProvider(cluster clusterplugin.Cluster) yip.YipConfig { + var stages []yip.Stage + clusterRootPath := getClusterRootPath(cluster) + + rke2Config := types.RKE2Config{ + Token: cluster.ClusterToken, + // RKE2 server listens on 9345 for node registration https://docs.rke2.io/install/quickstart/#3-configure-the-rke2-agent-service + Server: fmt.Sprintf("https://%s:9345", cluster.ControlPlaneHost), + TLSSan: []string{ + cluster.ControlPlaneHost, + }, + } + + if cluster.Role == clusterplugin.RoleInit { + rke2Config.Server = "" + } + + systemName := constants.ServerSystemName + if cluster.Role == clusterplugin.RoleWorker { + systemName = constants.AgentSystemName + } + + // ensure we always have a valid user config + if cluster.Options == "" { + cluster.Options = "{}" + } + + var providerConfig bytes.Buffer + _ = yaml.NewEncoder(&providerConfig).Encode(&rke2Config) + + userOptions, _ := kyaml.YAMLToJSON([]byte(cluster.Options)) + options, _ := kyaml.YAMLToJSON(providerConfig.Bytes()) + + proxyValues := proxyEnv(userOptions, cluster.Env) + + files := []yip.File{ + { + Path: filepath.Join(constants.ConfigurationPath, "90_userdata.yaml"), + Permissions: 0400, + Content: string(userOptions), + }, + { + Path: filepath.Join(constants.ConfigurationPath, "99_userdata.yaml"), + Permissions: 0400, + Content: string(options), + }, + } + + if len(proxyValues) > 0 { + files = append(files, yip.File{ + Path: filepath.Join(constants.ContainerdEnvConfigPath, systemName), + Permissions: 0400, + Content: proxyValues, + }) + } + + stages = append(stages, yip.Stage{ + Name: "Install RKE2 Configuration Files", + Files: files, + + Commands: []string{ + fmt.Sprintf("jq -s 'def flatten: reduce .[] as $i([]; if $i | type == \"array\" then . + ($i | flatten) else . + [$i] end); [.[] | to_entries] | flatten | reduce .[] as $dot ({}; .[$dot.key] += $dot.value)' %s/*.yaml > /etc/rancher/rke2/config.yaml", constants.ConfigurationPath), + }, + }, + ) + + if cluster.ImportLocalImages { + if cluster.LocalImagesPath == "" { + cluster.LocalImagesPath = constants.LocalImagesPath + } + + importStage := yip.Stage{ + Commands: []string{ + fmt.Sprintf("/bin/sh %s/opt/rke2/scripts/import.sh %s > /var/log/import.log", clusterRootPath, cluster.LocalImagesPath), + }, + If: fmt.Sprintf("[ -d %s ]", cluster.LocalImagesPath), + } + stages = append(stages, importStage) + } + + stages = append(stages, + yip.Stage{ + Name: "Waiting to finish extracting content", + Commands: []string{ + "sleep 120", + }, + }, + yip.Stage{ + Name: "Enable Systemd Services", + Commands: []string{ + fmt.Sprintf("systemctl enable %s", systemName), + fmt.Sprintf("systemctl restart %s", systemName), + }, + }) + + cfg := yip.YipConfig{ + Name: "RKE2 Kairos Cluster Provider", + Stages: map[string][]yip.Stage{ + "boot.before": stages, + }, + } + + return cfg +} + +func proxyEnv(userOptions []byte, proxyMap map[string]string) string { + var proxy []string + var noProxy string + var isProxyConfigured bool + + httpProxy := proxyMap["HTTP_PROXY"] + httpsProxy := proxyMap["HTTPS_PROXY"] + userNoProxy := proxyMap["NO_PROXY"] + defaultNoProxy := getDefaultNoProxy(userOptions) + + if len(httpProxy) > 0 { + proxy = append(proxy, fmt.Sprintf("HTTP_PROXY=%s", httpProxy)) + proxy = append(proxy, fmt.Sprintf("CONTAINERD_HTTP_PROXY=%s", httpProxy)) + isProxyConfigured = true + } + + if len(httpsProxy) > 0 { + proxy = append(proxy, fmt.Sprintf("HTTPS_PROXY=%s", httpsProxy)) + proxy = append(proxy, fmt.Sprintf("CONTAINERD_HTTPS_PROXY=%s", httpsProxy)) + isProxyConfigured = true + } + + if isProxyConfigured { + noProxy = defaultNoProxy + } + + if len(userNoProxy) > 0 { + noProxy = noProxy + "," + userNoProxy + } + + if len(noProxy) > 0 { + proxy = append(proxy, fmt.Sprintf("NO_PROXY=%s", noProxy)) + proxy = append(proxy, fmt.Sprintf("CONTAINERD_NO_PROXY=%s", noProxy)) + } + + return strings.Join(proxy, "\n") +} + +func getDefaultNoProxy(userOptions []byte) string { + + var noProxy string + + data := make(map[string]interface{}) + err := json.Unmarshal(userOptions, &data) + if err != nil { + fmt.Println("error while unmarshalling user options", err) + } + + if data != nil { + clusterCIDR := data["cluster-cidr"].(string) + serviceCIDR := data["service-cidr"].(string) + + if len(clusterCIDR) > 0 { + noProxy = noProxy + "," + clusterCIDR + } + if len(serviceCIDR) > 0 { + noProxy = noProxy + "," + serviceCIDR + } + noProxy = noProxy + "," + getNodeCIDR() + "," + constants.K8SNoProxy + } + + return noProxy +} + +func getNodeCIDR() string { + addrs, _ := net.InterfaceAddrs() + var result string + for _, addr := range addrs { + if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + if ipnet.IP.To4() != nil { + result = addr.String() + break + } + } + } + return result +} + +func getClusterRootPath(cluster clusterplugin.Cluster) string { + return cluster.ProviderOptions[constants.ClusterRootPath] +} diff --git a/pkg/provider/reset.go b/pkg/provider/reset.go new file mode 100644 index 0000000..f1a7b25 --- /dev/null +++ b/pkg/provider/reset.go @@ -0,0 +1,44 @@ +package provider + +import ( + "encoding/json" + "fmt" + "os/exec" + "path/filepath" + + "github.com/kairos-io/kairos-sdk/bus" + "github.com/kairos-io/kairos-sdk/clusterplugin" + "github.com/mudler/go-pluggable" + "gopkg.in/yaml.v3" +) + +func HandleClusterReset(event *pluggable.Event) pluggable.EventResponse { + var payload bus.EventPayload + var config clusterplugin.Config + var response pluggable.EventResponse + + // parse the boot payload + if err := json.Unmarshal([]byte(event.Data), &payload); err != nil { + response.Error = fmt.Sprintf("failed to parse boot event: %s", err.Error()) + return response + } + + // parse config from boot payload + if err := yaml.Unmarshal([]byte(payload.Config), &config); err != nil { + response.Error = fmt.Sprintf("failed to parse config from boot event: %s", err.Error()) + return response + } + + if config.Cluster == nil { + return response + } + + clusterRootPath := getClusterRootPath(*config.Cluster) + cmd := exec.Command("/bin/sh", "-c", filepath.Join(clusterRootPath, "/opt/rke2/scripts", "rke2-uninstall.sh")) + output, err := cmd.CombinedOutput() + if err != nil { + response.Error = fmt.Sprintf("failed to reset cluster: %s", string(output)) + } + + return response +} diff --git a/pkg/types/mount.go b/pkg/types/mount.go new file mode 100644 index 0000000..477602c --- /dev/null +++ b/pkg/types/mount.go @@ -0,0 +1,7 @@ +package types + +type MountPoint struct { + Name string + Source string + Target string +} diff --git a/pkg/types/rke2.go b/pkg/types/rke2.go new file mode 100644 index 0000000..cf30660 --- /dev/null +++ b/pkg/types/rke2.go @@ -0,0 +1,7 @@ +package types + +type RKE2Config struct { + Token string `yaml:"token"` + Server string `yaml:"server"` + TLSSan []string `yaml:"tls-san"` +}