Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce latest changes for SKE 1.1 #211

Merged
merged 1 commit into from
Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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/oapi-codegen@v0.0.2 -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
Loading