Skip to content

Commit

Permalink
Introduce latest changes for SKE 1.1 (#211)
Browse files Browse the repository at this point in the history
Co-authored-by: Robert Hoppe <[email protected]>
  • Loading branch information
roberth1988 and Robert Hoppe authored Mar 3, 2024
1 parent 2fc2749 commit 8b44c26
Show file tree
Hide file tree
Showing 19 changed files with 7,908 additions and 0 deletions.
85 changes: 85 additions & 0 deletions internal/config/kubernetes/v1.1/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package: kubernetes
output: ../../../../pkg/services/kubernetes/v1.1/kubernetes.go
generate:
models: true
client: true
output-options:
custom-doer:
enabled: true
import: contracts "github.com/SchwarzIT/community-stackit-go-client/pkg/contracts"
name: "contracts.BaseClientInterface"
split-by-tags:
verbose: false
enabled: true
extend-response:
- field: Error
type: error
description: "Aggregated error"
apply-to: ["*"]
imports: ["github.com/SchwarzIT/community-stackit-go-client/pkg/validate"]
set: "validate.DefaultResponseErrorHandler(rsp)"
copy:
- from: include/cluster/wait.go
to: cluster/wait.go
tidy:
- replace: "cluster."
all: true
- from: include/cluster/validate.go
to: cluster/validate.go
tidy:
- replace: "cluster."
all: true
- from: include/service.go
to: service.go
tidy:
- replace: "kubernetes."
all: true
- from: include/project/wait.go
to: project/wait.go
tidy:
- replace: "project."
all: true
tidy:
verbose: false
functions:
- replace: SkeService
with:
prefix: true
- replace: Clusters
with:
suffix: true
- replace: Cluster
with:
suffix: true
- replace: TriggerCluster
with: Trigger
prefix: true
- replace: GetClusterCredentials
with: List
prefix: true
- replace: TriggerCredentialRotation
with: TriggerRotation
prefix: true
- replace: Project
with:
suffix: true
- replace: GetProviderOptions
with: List
prefix: true
params:
- replace: Id
with: ID
suffix: true
schemas:
- replace: v1
with:
prefix: true
- replace: Id
with: ID
suffix: true
- replace: Cri
with: CRI
match: true
- replace: Cpu
with: CPU
match: true
3 changes: 3 additions & 0 deletions internal/config/kubernetes/v1.1/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package gen

//go:generate go run github.com/do87/stackit-client-generator/cmd/[email protected] -config config.yaml kubernetes.json
14 changes: 14 additions & 0 deletions internal/config/kubernetes/v1.1/include/cluster/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// this file is only used to prevent wait.go
// from showing errors

package cluster

import "github.com/SchwarzIT/community-stackit-go-client/pkg/services/kubernetes/v1.1/cluster"

type CreateOrUpdateResponse struct {
cluster.ClientWithResponsesInterface
}

type DeleteResponse struct {
cluster.ClientWithResponsesInterface
}
187 changes: 187 additions & 0 deletions internal/config/kubernetes/v1.1/include/cluster/validate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
// this file is used for validating cluster data and properties

package cluster

import (
"errors"
"fmt"
"regexp"

"github.com/SchwarzIT/community-stackit-go-client/pkg/services/kubernetes/v1.1/cluster"
"github.com/SchwarzIT/community-stackit-go-client/pkg/validate"
)

// Validate validates the given cluster data (dry validation)
func Validate(
clusterName string,
clusterConfig cluster.Kubernetes,
nodePools []cluster.Nodepool,
maintenance *cluster.Maintenance,
hibernation *cluster.Hibernation,
extensions *cluster.Extension,
) error {
if err := validate.SemVer(clusterConfig.Version); err != nil {
return err
}
if err := ValidateClusterName(clusterName); err != nil {
return err
}
if len(nodePools) == 0 {
return errors.New("at least one node pool must be specified")
}
for _, np := range nodePools {
if err := ValidateNodePool(np); err != nil {
return err
}
}
if err := ValidateMaintenance(maintenance); err != nil {
return err
}
if err := ValidateHibernation(hibernation); err != nil {
return err
}
if err := ValidateExtensions(extensions); err != nil {
return err
}
return nil
}

// ValidateClusterName validates a given cluster name
func ValidateClusterName(name string) error {
exp := `^[a-z0-9]{1}[a-z0-9-]{0,10}$`
r := regexp.MustCompile(exp)
if !r.MatchString(name) {
return fmt.Errorf("invalid cluster name. valid name is of: %s", exp)
}
return nil
}

// ValidateNodePoolName validates a given pool name
func ValidateNodePoolName(name string) error {
exp := `^[a-z0-9]{1}[a-z0-9-]{0,14}$`
r := regexp.MustCompile(exp)
if !r.MatchString(name) {
return fmt.Errorf("invalid node pool name. valid name is of: %s", exp)
}
return nil
}

// ValidateNodePool validates a given node pool
func ValidateNodePool(np cluster.Nodepool) error {
if err := ValidateNodePoolName(np.Name); err != nil {
return err
}
if np.Machine.Type == "" {
return errors.New("machine type must be specified")
}
if np.Machine.Image.Version == "" {
return errors.New("machine image version must be specified")
}
if np.Minimum > np.Maximum {
return errors.New("minimum value can't be larger than maximum")
}
if np.Minimum < 1 || np.Minimum > 100 {
return errors.New("minimum value must be in the range of 1..100")
}
if np.Maximum < 1 || np.Maximum > 100 {
return errors.New("maximum value must be in the range of 1..100")
}
if np.MaxSurge != nil {
if *np.MaxSurge < 1 || *np.MaxSurge > 10 {
return errors.New("max surge value must be in the range of 1..10")
}
}
if np.Volume.Size < 20 || np.Volume.Size > 10240 {
return errors.New("volume size value must be in the range of 20..10240")
}
if np.Taints != nil {
for _, t := range *np.Taints {
if err := ValidateTaint(t); err != nil {
return err
}
}
}
if err := ValidateCRI(np.CRI); err != nil {
return err
}
return nil
}

// ValidateTaint validates a given node pool taint
func ValidateTaint(t cluster.Taint) error {
switch t.Effect {
case cluster.NO_EXECUTE:
fallthrough
case cluster.NO_SCHEDULE:
fallthrough
case cluster.PREFER_NO_SCHEDULE:
default:
return fmt.Errorf("invalid taint effect '%s'", t.Effect)
}

if t.Key == "" {
return errors.New("taint key is required")
}
return nil
}

// ValidateCRI validates the given cri struct
func ValidateCRI(c *cluster.CRI) error {
if c == nil {
return nil
}
if c.Name == nil {
return nil
}
switch *c.Name {
case cluster.CONTAINERD:
fallthrough
case cluster.DOCKER:
default:
return fmt.Errorf("invalid CRI name '%s'", string(*c.Name))
}
return nil
}

// ValidateMaintenance validates a given cluster maintenance
func ValidateMaintenance(m *cluster.Maintenance) error {
if m == nil {
return nil
}
if m.TimeWindow.End == "" {
return errors.New("maintenance end time window is required")
}
if m.TimeWindow.Start == "" {
return errors.New("maintenance start time window is required")
}
return nil
}

// ValidateHibernation validates a given cluster hibernation
func ValidateHibernation(h *cluster.Hibernation) error {
if h == nil {
return nil
}
for _, s := range h.Schedules {
if s.End == "" {
return errors.New("hibernation end time is required")
}
if s.Start == "" {
return errors.New("hibernation start time is required")
}
}
return nil
}

// ValidateExtensions validates a given cluster extensions
func ValidateExtensions(e *cluster.Extension) error {
if e == nil {
return nil
}
if e.Argus != nil {
if e.Argus.Enabled && e.Argus.ArgusInstanceID == "" {
return errors.New("argus instance ID is mandatory when Argus is enabled")
}
}
return nil
}
59 changes: 59 additions & 0 deletions internal/config/kubernetes/v1.1/include/cluster/wait.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cluster

import (
"context"
"net/http"
"strings"

"github.com/SchwarzIT/community-stackit-go-client/pkg/services/kubernetes/v1.1/cluster"
"github.com/SchwarzIT/community-stackit-go-client/pkg/wait"
)

func (*CreateOrUpdateResponse) WaitHandler(ctx context.Context, c *cluster.ClientWithResponses, projectID, clusterName string) *wait.Handler {
return wait.New(func() (res interface{}, done bool, err error) {
resp, err := c.Get(ctx, projectID, clusterName)
if err != nil {
if strings.Contains(err.Error(), http.StatusText(http.StatusForbidden)) {
return nil, false, nil
}
return nil, false, err
}
if resp.StatusCode() == http.StatusForbidden {
return nil, false, nil
}
if resp.StatusCode() == http.StatusInternalServerError {
return nil, false, nil
}
if resp.Error != nil {
return nil, false, resp.Error
}

status := *resp.JSON200.Status.Aggregated
if status == cluster.STATE_HEALTHY || status == cluster.STATE_HIBERNATED {
return resp, true, nil
}
return resp, false, nil
})
}

func (*DeleteResponse) WaitHandler(ctx context.Context, c *cluster.ClientWithResponses, projectID, clusterName string) *wait.Handler {
return wait.New(func() (res interface{}, done bool, err error) {
resp, err := c.Get(ctx, projectID, clusterName)
if err != nil {
if strings.Contains(err.Error(), http.StatusText(http.StatusNotFound)) {
return nil, true, nil
}
return nil, false, err
}
if resp.StatusCode() == http.StatusInternalServerError {
return nil, false, nil
}
if resp.Error != nil {
if resp.StatusCode() == http.StatusNotFound {
return nil, true, nil
}
return nil, false, err
}
return nil, false, nil
})
}
14 changes: 14 additions & 0 deletions internal/config/kubernetes/v1.1/include/project/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// this file is only used to prevent wait.go
// from showing errors

package project

import "github.com/SchwarzIT/community-stackit-go-client/pkg/services/kubernetes/v1.1/project"

type CreateResponse struct {
project.ClientWithResponsesInterface
}

type DeleteResponse struct {
project.ClientWithResponsesInterface
}
Loading

0 comments on commit 8b44c26

Please sign in to comment.