diff --git a/.github/workflows/compat-matrix.yaml b/.github/workflows/compat-matrix.yaml new file mode 100644 index 000000000..e28ceb8d4 --- /dev/null +++ b/.github/workflows/compat-matrix.yaml @@ -0,0 +1,32 @@ +name: Matrix compat + +on: + release: + types: [created] + pull_request: + branches: + - main + paths: + - "**.go" + - "!test/**" # exclude changes in e2e tests + - ".github/workflows/unit-tests.yaml" + - "hack/test.sh" + - "charts/**" + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + name: generates automated matrix + runs-on: ubuntu-22.04 + steps: + - name: Set up Go 1.21 + uses: actions/setup-go@v5 + with: + go-version: "1.21" + cache: false + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + - name: Execute unit tests + run: just validate-compat-matrix diff --git a/.github/workflows/compatibility.yaml b/.github/workflows/compatibility.yaml new file mode 100644 index 000000000..eef4934a6 --- /dev/null +++ b/.github/workflows/compatibility.yaml @@ -0,0 +1,31 @@ +name: Matrix compatibility + +on: + push: + branches: + - version-auto-update + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + go-unit-test: + name: Generate the compatibility matrix + runs-on: ubuntu-22.04 + steps: + - name: Set up Go 1.21 + uses: actions/setup-go@v5 + with: + go-version: "1.21" + cache: false + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + - name: run compat + run: go run hack/compat-matrix/main.go docs/pages/deploying-vclusters/compat-matrix.mdx + - name: setup git + run: | + git config user.email "bot@loft.sh" + git config user.name "loft bot" + git diff --quiet && git diff --staged --quiet || git commit -am 'updated compatibility matrix' + git push diff --git a/Justfile b/Justfile index d100edbb1..b17cac5c6 100644 --- a/Justfile +++ b/Justfile @@ -126,3 +126,9 @@ cli version="0.0.0" *ARGS="": # Version the docs for the given version docs-version id="pro" version="1.0.0": yarn docusaurus docs:version {{version}} + +generate-compatibility: + go run hack/compat-matrix/main.go generate docs/pages/deploying-vclusters/compat-matrix.mdx + +validate-compat-matrix: + go run hack/compat-matrix/main.go validate docs/pages/deploying-vclusters/compat-matrix.mdx diff --git a/docs/pages/deploying-vclusters/compat-matrix.mdx b/docs/pages/deploying-vclusters/compat-matrix.mdx new file mode 100644 index 000000000..ef407d121 --- /dev/null +++ b/docs/pages/deploying-vclusters/compat-matrix.mdx @@ -0,0 +1,76 @@ +## Compatibility Matrix for k3s distro + +The following table provides a compatibility matrix of which k8s version are supported aginst which vcluster distro versions: + +| DISTRO VERSION | V1.29.0-K3S1 | V1.28.5-K3S1 | V1.27.9-K3S1 | V1.26.12-K3S1 | +| HOST VERSION | | | | | +|----------------|--------------|--------------|--------------|---------------| +| 1.29 | recommended | + | + | + | +| 1.28 | + | recommended | + | + | +| 1.27 | + | + | recommended | + | +| 1.26 | + | + | + | recommended | + + +Legend: + +! : known issue + ++ : likely compatible + +## Compatibility Matrix for k8s distro + +The following table provides a compatibility matrix of which k8s version are supported aginst which vcluster distro versions: + +| DISTRO VERSION | V1.29.0 | V1.28.4 | V1.27.8 | V1.26.11 | +| HOST VERSION | | | | | +|----------------|-------------|-------------|-------------|-------------| +| 1.29 | recommended | + | + | + | +| 1.28 | + | recommended | + | + | +| 1.27 | + | + | recommended | + | +| 1.26 | + | + | + | recommended | + + +Legend: + +! : known issue + ++ : likely compatible + +## Compatibility Matrix for k0s distro + +The following table provides a compatibility matrix of which k8s version are supported aginst which vcluster distro versions: + +| DISTRO VERSION | V1.29.1-K0S 0 | V1.28.2-K0S 0 | V1.27.6-K0S 0 | V1.26.9-K0S 0 | +| HOST VERSION | | | | | +|----------------|---------------|---------------|---------------|---------------| +| 1.29 | recommended | + | + | + | +| 1.28 | + | recommended | + | + | +| 1.27 | + | + | recommended | + | +| 1.26 | + | + | + | recommended | + + +Legend: + +! : known issue + ++ : likely compatible + +## Compatibility Matrix for eks distro + +The following table provides a compatibility matrix of which k8s version are supported aginst which vcluster distro versions: + +| DISTRO VERSION | V1.28.2-EKS-1-28-6 | V1.27.6-EKS-1-27-13 | V1.26.9-EKS-1-26-19 | V1.25.14-EKS-1-25-23 | +| HOST VERSION | | | | | +|----------------|--------------------|---------------------|---------------------|----------------------| +| 1.28 | recommended | + | + | + | +| 1.27 | + | recommended | + | + | +| 1.26 | + | + | recommended | + | +| 1.25 | + | + | + | recommended | + + +Legend: + +! : known issue + ++ : likely compatible + diff --git a/docs/pages/deploying-vclusters/supported-distros.mdx b/docs/pages/deploying-vclusters/supported-distros.mdx index 25069863b..09779ab8e 100644 --- a/docs/pages/deploying-vclusters/supported-distros.mdx +++ b/docs/pages/deploying-vclusters/supported-distros.mdx @@ -114,27 +114,3 @@ For multi binary distributions, vCluster can even create those with a pre-instal In general, if you need vCluster to support another Kubernetes distribution, we are always happy to help you or accept a pull request in our GitHub repository. - - -## Compatibility Matrix - -The following table provides a compatibility matrix of which k8s version are supported aginst which vcluster distro versions: - -| Vcluster Distro | k8s Host version | Distro Version | -| --------------- | ---------------- | -------------------- | -| eks | 1.28 | v1.28.2-eks-1-28-6 | -| | 1.27 | v1.27.6-eks-1-27-13 | -| | 1.26 | v1.26.9-eks-1-26-19 | -| | 1.25 | v1.25.14-eks-1-25-23 | -| k0s | 1.28 | v1.28.2-k0s.0 | -| | 1.26 | v1.26.9-k0s.0 | -| | 1.27 | v1.27.6-k0s.0 | -| | 1.25 | v1.25.14-k0s.0 | -| k3s | 1.28 | v1.28.2-k3s1 | -| | 1.27 | v1.27.6-k3s1 | -| | 1.26 | v1.26.9-k3s1 | -| | 1.25 | v1.25.14-k3s1 | -| k8s | 1.28 | v1.28.2 | -| | 1.27 | v1.27.6 | -| | 1.26 | v1.26.9 | -| | 1.25 | v1.25.14 | diff --git a/docs/sidebars.js b/docs/sidebars.js index 303b5ad19..f49965da5 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -150,6 +150,12 @@ module.exports = { collapsed: true, items: ["deploying-vclusters/supported-distros"], }, + { + type: "category", + label: "Compatibility Matrix", + collapsed: true, + items: ["deploying-vclusters/compat-matrix"], + }, { type: "category", label: "Persistent vClusters", diff --git a/go.mod b/go.mod index 21d4aba18..2ce1c04bc 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/moby/locker v1.0.1 github.com/moby/term v0.5.0 + github.com/olekukonko/tablewriter v0.0.5 github.com/onsi/ginkgo/v2 v2.14.0 github.com/onsi/gomega v1.30.0 github.com/pkg/errors v0.9.1 @@ -92,7 +93,6 @@ require ( github.com/mitchellh/go-testing-interface v1.0.0 // indirect github.com/oklog/run v1.0.0 // indirect github.com/oklog/ulid v1.3.1 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/otiai10/copy v1.11.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect diff --git a/hack/compat-matrix/main.go b/hack/compat-matrix/main.go new file mode 100644 index 000000000..713da4a48 --- /dev/null +++ b/hack/compat-matrix/main.go @@ -0,0 +1,175 @@ +package main + +import ( + "bytes" + _ "embed" + "fmt" + "os" + "slices" + "strings" + + "github.com/olekukonko/tablewriter" + "gopkg.in/yaml.v2" + + "github.com/loft-sh/vcluster-values/values" + "golang.org/x/exp/maps" +) + +//go:embed matrix-template.tmpl +var templateString string + +type issueList map[string]string + +type KnownIssues struct { + K3s map[string]issueList + K0s map[string]issueList + K8s map[string]issueList + Eks map[string]issueList +} + +func main() { + if len(os.Args) != 3 { + fmt.Println("usage: compat-matrix generate/validate outputfile") + os.Exit(1) + } + knowIssuesBytes, err := os.ReadFile("known_issues.yaml") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + issues := KnownIssues{} + err = yaml.UnmarshalStrict(knowIssuesBytes, &issues) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + renderedBytes := &bytes.Buffer{} + buff := updateTableWithDistro("k3s", values.K3SVersionMap, issues) + renderedBytes.WriteString(fmt.Sprintf(templateString, "k3s", buff.String())) + renderedBytes.WriteString(createKnownIssue(issues.K3s)) + buff.Reset() + buff = updateTableWithDistro("k8s", values.K8SAPIVersionMap, issues) + renderedBytes.WriteString(fmt.Sprintf(templateString, "k8s", buff.String())) + renderedBytes.WriteString(createKnownIssue(issues.K8s)) + buff.Reset() + buff = updateTableWithDistro("k0s", values.K0SVersionMap, issues) + renderedBytes.WriteString(fmt.Sprintf(templateString, "k0s", buff.String())) + renderedBytes.WriteString(createKnownIssue(issues.K0s)) + buff.Reset() + buff = updateTableWithDistro("eks", values.EKSAPIVersionMap, issues) + renderedBytes.WriteString(fmt.Sprintf(templateString, "eks", buff.String())) + renderedBytes.WriteString(createKnownIssue(issues.Eks)) + buff.Reset() + + switch os.Args[1] { + case "generate": + os.WriteFile(os.Args[2], renderedBytes.Bytes(), 0644) + case "validate": + currentFile, err := os.ReadFile(os.Args[2]) + if err != nil { + os.Stderr.WriteString(err.Error()) + os.Exit(1) + } + if !slices.Equal(currentFile, renderedBytes.Bytes()) { + fmt.Println("compatibility matrix is not up to date, please update it by running `just validate-compat-matrix`") + os.Exit(1) + } + } +} + +func updateTableWithDistro(distroName string, versionMap map[string]string, knownIssues KnownIssues) *bytes.Buffer { + hostVersions := maps.Keys(versionMap) + vclusterApis := maps.Values(versionMap) + slices.Sort(hostVersions) + slices.Reverse(hostVersions) + slices.Sort(vclusterApis) + slices.Reverse(vclusterApis) + + buff := &bytes.Buffer{} + table := tablewriter.NewWriter(buff) + for i, v := range vclusterApis { + vclusterApis[i] = removeRegistry(v) + } + table.SetHeader(append([]string{"distro version\nhost version"}, vclusterApis...)) + + var issues map[string]issueList + switch distroName { + case "k3s": + issues = knownIssues.K3s + case "k0s": + issues = knownIssues.K0s + case "k8s": + issues = knownIssues.K8s + case "eks": + issues = knownIssues.Eks + } + + for hostVersion, issueList := range issues { + for vclusterApi, issueDesc := range issueList { + issues[hostVersion][removeRegistry(vclusterApi)] = issueDesc + if removeRegistry(vclusterApi) != vclusterApi { + // avoids removing valid entries + delete(issues[hostVersion], vclusterApi) + } + } + } + + for i, v := range hostVersions { + table.Append(createLine(v, issues[v], vclusterApis, i)) + } + + table.SetAlignment(tablewriter.ALIGN_LEFT) + table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) + table.SetCenterSeparator("|") + table.Render() + + return buff +} + +func createKnownIssue(issues map[string]issueList) string { + if len(issues) == 0 { + return "" + } + keys := maps.Keys(issues) + slices.Sort(keys) + buff := &bytes.Buffer{} + table := tablewriter.NewWriter(buff) + table.SetHeader([]string{"vCluster Distro Version", "Host K8s Version", "Known Issues"}) + + for _, hostVersion := range keys { + for vclusterVersion, issue := range issues[hostVersion] { + table.Append([]string{vclusterVersion, hostVersion, issue}) + } + } + table.Render() + if buff.Len() > 0 { + buff.WriteString("\n") + } + return buff.String() +} + +func createLine(version string, list issueList, vclusterApiVersion []string, lineNumber int) []string { + line := make([]string, 1, len(vclusterApiVersion)+1) + line[0] = version + for i, v := range vclusterApiVersion { + char := "" + if list[v] != "" { + char = "!" + } else if i == lineNumber { + char = "recommended" + } else { + char = "+" + } + line = append(line, char) + } + return line +} + +func removeRegistry(vclusterApiVersion string) string { + lastColon := strings.LastIndex(vclusterApiVersion, ":") + if lastColon == -1 { + return vclusterApiVersion + } + return vclusterApiVersion[lastColon+1:] +} diff --git a/hack/compat-matrix/matrix-template.tmpl b/hack/compat-matrix/matrix-template.tmpl new file mode 100644 index 000000000..97a3be47e --- /dev/null +++ b/hack/compat-matrix/matrix-template.tmpl @@ -0,0 +1,12 @@ +## Compatibility Matrix for %s distro + +The following table provides a compatibility matrix of which k8s version are supported aginst which vcluster distro versions: + +%s + +Legend: + +! : known issue + ++ : likely compatible + diff --git a/known_issues.yaml b/known_issues.yaml new file mode 100644 index 000000000..68c19acd0 --- /dev/null +++ b/known_issues.yaml @@ -0,0 +1,5 @@ +#k3s: +# 1.29: +# rancher/k3s:v1.27.9-k3s1: there is some issue there +# 1.28: +# rancher/k3s:v1.27.9-k3s1: there is some issue there diff --git a/vendor/modules.txt b/vendor/modules.txt index 2c0ed8db2..2a0aa92e2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -185,6 +185,8 @@ github.com/go-openapi/strfmt # github.com/go-openapi/swag v0.22.7 ## explicit; go 1.19 github.com/go-openapi/swag +# github.com/go-spectest/markdown v0.0.7 +## explicit; go 1.18 # github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 ## explicit; go 1.13 github.com/go-task/slim-sprig @@ -323,6 +325,8 @@ github.com/json-iterator/go # github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 ## explicit github.com/k0kubun/go-ansi +# github.com/karrick/godirwalk v1.17.0 +## explicit; go 1.13 # github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 ## explicit github.com/kballard/go-shellquote