Skip to content

Commit

Permalink
[installer]: validate the node labels by kind in config
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon Emms authored and roboquat committed Nov 15, 2022
1 parent 983b483 commit 151f8d5
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 45 deletions.
14 changes: 13 additions & 1 deletion install/installer/pkg/cluster/affinity.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,22 @@ const (
AffinityLabelWorkspacesHeadless = "gitpod.io/workload_workspace_headless"
)

var AffinityList = []string{
var AffinityListMeta = []string{
AffinityLabelMeta,
AffinityLabelIDE,
}

var AffinityListWorkspace = []string{
AffinityLabelWorkspaceServices,
AffinityLabelWorkspacesRegular,
AffinityLabelWorkspacesHeadless,
}

var AffinityList = func() []string {
list := []string{}

list = append(list, AffinityListMeta...)
list = append(list, AffinityListWorkspace...)

return list
}()
40 changes: 3 additions & 37 deletions install/installer/pkg/cluster/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,40 +24,6 @@ const (
kubernetesVersionConstraint = ">= 1.21.0-0"
)

// checkAffinityLabels validates that the nodes have all the required affinity labels applied
// It assumes all the values are `true`
func checkAffinityLabels(ctx context.Context, config *rest.Config, namespace string) ([]ValidationError, error) {
nodes, err := listNodesFromContext(ctx, config)
if err != nil {
return nil, err
}

affinityList := map[string]bool{}
for _, affinity := range AffinityList {
affinityList[affinity] = false
}

var res []ValidationError
for _, node := range nodes {
for k, v := range node.GetLabels() {
if _, found := affinityList[k]; found {
affinityList[k] = v == "true"
}
}
}

// Check all the values in the map are `true`
for k, v := range affinityList {
if !v {
res = append(res, ValidationError{
Message: "Affinity label not found in cluster: " + k,
Type: ValidationStatusError,
})
}
}
return res, nil
}

// checkCertManagerInstalled checks that cert-manager is installed as a cluster dependency
func checkCertManagerInstalled(ctx context.Context, config *rest.Config, namespace string) ([]ValidationError, error) {
client, err := certmanager.NewForConfig(config)
Expand Down Expand Up @@ -91,7 +57,7 @@ func checkCertManagerInstalled(ctx context.Context, config *rest.Config, namespa

// checkContainerDRuntime checks that the nodes are running with the containerd runtime
func checkContainerDRuntime(ctx context.Context, config *rest.Config, namespace string) ([]ValidationError, error) {
nodes, err := listNodesFromContext(ctx, config)
nodes, err := ListNodesFromContext(ctx, config)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -139,7 +105,7 @@ func checkKubernetesVersion(ctx context.Context, config *rest.Config, namespace
})
}

nodes, err := listNodesFromContext(ctx, config)
nodes, err := ListNodesFromContext(ctx, config)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -263,7 +229,7 @@ func checkKernelVersion(ctx context.Context, config *rest.Config, namespace stri
return nil, err
}

nodes, err := listNodesFromContext(ctx, config)
nodes, err := ListNodesFromContext(ctx, config)
if err != nil {
return nil, err
}
Expand Down
10 changes: 3 additions & 7 deletions install/installer/pkg/cluster/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"encoding/json"
"fmt"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/version"
Expand Down Expand Up @@ -65,11 +66,6 @@ var ClusterChecks = ValidationChecks{
Description: "all cluster nodes run kubernetes version " + kubernetesVersionConstraint,
Check: checkKubernetesVersion,
},
{
Name: "affinity labels",
Check: checkAffinityLabels,
Description: "all required affinity node labels " + fmt.Sprint(AffinityList) + " are present in the cluster",
},
{
Name: "cert-manager installed",
Check: checkCertManagerInstalled,
Expand Down Expand Up @@ -100,7 +96,7 @@ func (checks ValidationChecks) Validate(ctx context.Context, config *rest.Config
}
ctx = context.WithValue(ctx, keyClientset, client)

list, err := listNodesFromContext(ctx, config)
list, err := ListNodesFromContext(ctx, config)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -147,7 +143,7 @@ const (
keyClientset = "clientset"
)

func listNodesFromContext(ctx context.Context, config *rest.Config) ([]corev1.Node, error) {
func ListNodesFromContext(ctx context.Context, config *rest.Config) ([]corev1.Node, error) {
client, err := clientsetFromContext(ctx, config)
if err != nil {
return nil, err
Expand Down
57 changes: 57 additions & 0 deletions install/installer/pkg/config/v1/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package config

import (
"context"
"fmt"
"regexp"

Expand All @@ -15,6 +16,7 @@ import (

"github.com/go-playground/validator/v10"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/rest"
)

var InstallationKindList = map[InstallationKind]struct{}{
Expand Down Expand Up @@ -121,6 +123,12 @@ func (v version) ClusterValidation(rcfg interface{}) cluster.ValidationChecks {
var res cluster.ValidationChecks
res = append(res, cluster.CheckSecret(cfg.Certificate.Name, cluster.CheckSecretRequiredData("tls.crt", "tls.key")))

res = append(res, cluster.ValidationCheck{
Name: "affinity labels",
Check: checkAffinityLabels(getAffinityListByKind(cfg.Kind)),
Description: "all required affinity node labels " + fmt.Sprint(getAffinityListByKind(cfg.Kind)) + " are present in the cluster",
})

if cfg.ObjectStorage.CloudStorage != nil {
secretName := cfg.ObjectStorage.CloudStorage.ServiceAccount.Name
res = append(res, cluster.CheckSecret(secretName, cluster.CheckSecretRequiredData("service-account.json")))
Expand Down Expand Up @@ -252,3 +260,52 @@ func (v version) ClusterValidation(rcfg interface{}) cluster.ValidationChecks {

return res
}

// checkAffinityLabels validates that the nodes have all the required affinity labels applied
// It assumes all the values are `true`
func checkAffinityLabels(targetAffinityList []string) func(context.Context, *rest.Config, string) ([]cluster.ValidationError, error) {
return func(ctx context.Context, config *rest.Config, namespace string) ([]cluster.ValidationError, error) {
nodes, err := cluster.ListNodesFromContext(ctx, config)
if err != nil {
return nil, err
}

affinityList := map[string]bool{}
for _, affinity := range targetAffinityList {
affinityList[affinity] = false
}

var res []cluster.ValidationError
for _, node := range nodes {
for k, v := range node.GetLabels() {
if _, found := affinityList[k]; found {
affinityList[k] = v == "true"
}
}
}

// Check all the values in the map are `true`
for k, v := range affinityList {
if !v {
res = append(res, cluster.ValidationError{
Message: "Affinity label not found in cluster: " + k,
Type: cluster.ValidationStatusError,
})
}
}
return res, nil
}
}

func getAffinityListByKind(kind InstallationKind) []string {
var affinityList []string
switch kind {
case InstallationMeta:
affinityList = cluster.AffinityListMeta
case InstallationWorkspace:
affinityList = cluster.AffinityListWorkspace
default:
affinityList = cluster.AffinityList
}
return affinityList
}

0 comments on commit 151f8d5

Please sign in to comment.