Skip to content

Commit

Permalink
Feat: ssset better deletion, subst configmap refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
ionoscloudsdk authored Aug 26, 2024
2 parents 97dd390 + d5bf7c2 commit 622983d
Show file tree
Hide file tree
Showing 18 changed files with 439 additions and 208 deletions.
1 change: 0 additions & 1 deletion apis/compute/v1alpha1/server_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ type ServerParameters struct {
// available CPU architectures can be retrieved from the datacenter resource.
//
// +immutable
// +kubebuilder:validation:Enum=AMD_OPTERON;INTEL_SKYLAKE;INTEL_XEON
CPUFamily string `json:"cpuFamily,omitempty"`
// +kubebuilder:validation:Optional
BootCdromID string `json:"bootCdromId,omitempty"`
Expand Down
1 change: 0 additions & 1 deletion apis/compute/v1alpha1/serverset_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ type ServerSetTemplateSpec struct {
// available CPU architectures can be retrieved from the datacenter resource.
//
// +immutable
// +kubebuilder:validation:Enum=AMD_OPTERON;INTEL_SKYLAKE;INTEL_XEON
CPUFamily string `json:"cpuFamily,omitempty"`
// The total number of cores for the server.
//
Expand Down
11 changes: 8 additions & 3 deletions examples/ionoscloud/compute/serverset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ spec:
providerConfigRef:
name: example
forProvider:
replicas: 1
replicas: 2
datacenterConfig:
datacenterIdRef:
name: example
Expand Down Expand Up @@ -100,13 +100,18 @@ spec:
# createBeforeDestroyBootVolume createAllBeforeDestroy
type: "createBeforeDestroyBootVolume"
image: "28d0fa34-927f-11ee-8008-6202af74e858"
size: 10
size: 20
type: HDD
userData: "" #cloud-config
imagePassword: "thisshouldbesecret"
substitutions:
- options:
cidr: "10.0.0.0/24"
cidr: "fd1d:15db:cf64:1337::/64"
key: __ipv6Address
type: ipv6Address
unique: true
- options:
cidr: "192.168.42.0/24"
key: ipv4Address
type: ipv4Address
unique: true
Expand Down
23 changes: 15 additions & 8 deletions examples/ionoscloud/compute/statefulserverset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ spec:
metadata:
name: server-name
spec:
cpuFamily: AMD_OPTERON
cpuFamily: INTEL_XEON
cores: 1
ram: 1024 # (32*storageTB)
nics:
Expand All @@ -49,12 +49,24 @@ spec:
name: boot-volume
spec:
updateStrategy:
type: "createAllBeforeDestroy" # createBeforeDestroyBootVolume createAllBeforeDestroy
type: "createBeforeDestroyBootVolume" # createBeforeDestroyBootVolume createAllBeforeDestroy
image: "28d0fa34-927f-11ee-8008-6202af74e858"
size: 10
type: HDD
type: SSD
userData: "" #cloud-config
imagePassword: "thisshouldwork11"
substitutions:
- options:
cidr: "fd1d:15db:cf64:1337::/64"
key: __ipv6Address
type: ipv6Address
unique: true
- options:
cidr: "192.168.42.0/24"
key: ipv4Address
type: ipv4Address
unique: true

lans:
# Three LANs are defined - an internal one (data) with IPv6 enabled and DHCP disabled for DRBD + VRRP traffic,
# a management network for connectivity to K8S and management as well as
Expand All @@ -80,11 +92,6 @@ spec:
spec:
size: 10
type: SSD
- metadata:
name: storage-disk-extend-1
spec:
size: 10
type: SSD
providerConfigRef:
name: example
---
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ require (
github.com/stretchr/testify v1.8.4
go.uber.org/zap v1.26.0
golang.org/x/crypto v0.22.0
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3
gopkg.in/alecthomas/kingpin.v2 v2.2.6
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.29.1
Expand Down Expand Up @@ -79,7 +80,6 @@ require (
github.com/stretchr/objx v0.5.0 // indirect
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/oauth2 v0.15.0 // indirect
Expand Down
15 changes: 11 additions & 4 deletions internal/controller/compute/statefulserverset/fakes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import (
)

const (
create = "Create"
ensure = "Ensure"
update = "Update"
create = "Create"
ensure = "Ensure"
update = "Update"
ddelete = "Delete"
)

type fakeKubeLANController struct {
Expand Down Expand Up @@ -95,7 +96,10 @@ func (f *fakeKubeServerSetController) Create(ctx context.Context, cr *v1alpha1.S
f.methodCallCount[create]++
return nil, nil
}

func (f *fakeKubeServerSetController) Delete(ctx context.Context, name, namespace string) error {
f.methodCallCount[ddelete]++
return nil
}
func (f *fakeKubeServerSetController) Ensure(ctx context.Context, cr *v1alpha1.StatefulServerSet) error {
f.methodCallCount[ensure]++
return nil
Expand All @@ -115,6 +119,9 @@ func (f fakeKubeVolumeSelectorController) Get(ctx context.Context, name, ns stri
return &f.Volume, f.Err
}

func (f fakeKubeVolumeSelectorController) Delete(ctx context.Context, name, ns string) error {
return nil
}
func fakeKubeClientWithObjs(objs ...client.Object) client.WithWatch {
scheme := runtime.NewScheme()
v1.AddToScheme(scheme) // Add the core k8s types to the Scheme
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type kubeSSetControlManager interface {
Ensure(ctx context.Context, cr *v1alpha1.StatefulServerSet) error
Update(ctx context.Context, cr *v1alpha1.StatefulServerSet) (v1alpha1.ServerSet, error)
Get(ctx context.Context, ssetName, ns string) (*v1alpha1.ServerSet, error)
Delete(ctx context.Context, name, namespace string) error
}

// kubeServerSetController - kubernetes client wrapper for server set resources
Expand Down Expand Up @@ -114,7 +115,7 @@ func (k *kubeServerSetController) Ensure(ctx context.Context, cr *v1alpha1.State
return err
}
if err = kube.WaitForResource(ctx, kube.ServerSetReadyTimeout, k.isAvailable, SSetName, cr.Namespace); err != nil {
_ = k.delete(ctx, SSetName, cr.Namespace)
_ = k.Delete(ctx, SSetName, cr.Namespace)
return err
}
case err != nil:
Expand Down Expand Up @@ -165,8 +166,8 @@ func getSSetName(cr *v1alpha1.StatefulServerSet) string {
return cr.Spec.ForProvider.Template.Metadata.Name
}

// delete - deletes the serverset k8s object and waits until it is deleted
func (k *kubeServerSetController) delete(ctx context.Context, name, namespace string) error {
// Delete - deletes the serverset k8s object and waits until it is deleted
func (k *kubeServerSetController) Delete(ctx context.Context, name, namespace string) error {
serverset, err := k.Get(ctx, name, namespace)
if err != nil {
return err
Expand Down
39 changes: 21 additions & 18 deletions internal/controller/compute/statefulserverset/statefulserverset.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,31 +293,34 @@ func (e *external) Delete(ctx context.Context, mg resource.Managed) error {
}
cr.SetConditions(xpv1.Deleting())

e.log.Info("Deleting the DataVolumes with label", "label", cr.Name)
if err := e.kube.DeleteAllOf(ctx, &v1alpha1.Volume{}, client.InNamespace(cr.Namespace), client.MatchingLabels{
statefulServerSetLabel: cr.Name,
}); err != nil {
return err
for replicaIndex := 0; replicaIndex < cr.Spec.ForProvider.Replicas; replicaIndex++ {
for volumeIndex := range cr.Spec.ForProvider.Volumes {
name := generateNameFrom(cr.Spec.ForProvider.Volumes[volumeIndex].Metadata.Name, replicaIndex, volumeIndex)
e.log.Info("Deleting the DataVolume with name", "name", name)
err := e.dataVolumeController.Delete(ctx, name, cr.Namespace)
if err != nil {
return err
}
}
}

e.log.Info("Deleting the ServerSet with label", "label", cr.Name)
if err := e.kube.DeleteAllOf(ctx, &v1alpha1.ServerSet{}, client.InNamespace(cr.Namespace), client.MatchingLabels{
statefulServerSetLabel: cr.Name,
}); err != nil {
e.log.Info("Deleting the ServerSet with name", "name", cr.Spec.ForProvider.Template.Metadata.Name)
if err := e.SSetController.Delete(ctx, cr.Spec.ForProvider.Template.Metadata.Name, cr.Namespace); err != nil {
return err
}

e.log.Info("Deleting the LANs with label", "label", cr.Name)
if err := e.kube.DeleteAllOf(ctx, &v1alpha1.Lan{}, client.InNamespace(cr.Namespace), client.MatchingLabels{
statefulServerSetLabel: cr.Name,
}); err != nil {
return err
for lanIndex := range cr.Spec.ForProvider.Lans {
name := cr.Spec.ForProvider.Lans[lanIndex].Metadata.Name
e.log.Info("Deleting the LANs with name", "name", name)
err := e.LANController.Delete(ctx, name, cr.Namespace)
if err != nil {
return err
}
}
e.log.Info("Deleting the volumeselector with name", "name", cr.Name)

e.log.Info("Deleting the VolumeSelectors with label", "label", cr.Name)
if err := e.kube.DeleteAllOf(ctx, &v1alpha1.Volumeselector{}, client.InNamespace(cr.Namespace), client.MatchingLabels{
statefulServerSetLabel: cr.Name,
}); err != nil {
err := e.volumeSelectorController.Delete(ctx, fmt.Sprintf(volumeSelectorName, cr.Name), cr.Namespace)
if err != nil {
return err
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const volumeSelectorName = "%s-volume-selector"

type kubeVolumeSelectorManager interface {
Get(ctx context.Context, name, ns string) (*v1alpha1.Volumeselector, error)
Delete(ctx context.Context, name, ns string) error
CreateOrUpdate(ctx context.Context, cr *v1alpha1.StatefulServerSet) error
}

Expand All @@ -32,6 +33,35 @@ type kubeVolumeSelectorController struct {
log logging.Logger
}

func (k *kubeVolumeSelectorController) Delete(ctx context.Context, name, ns string) error {
obj, err := k.Get(ctx, name, ns)
if err != nil {
if apiErrors.IsNotFound(err) {
return nil
}
return err
}
if err := k.kube.Delete(ctx, obj); err != nil {
return err
}
err = kube.WaitForResource(ctx, kube.ResourceReadyTimeout, k.isDeleted, name, ns)
if err != nil {
return fmt.Errorf("an error occurred while deleting %w", err)
}
return nil
}

func (k *kubeVolumeSelectorController) isDeleted(ctx context.Context, name, namespace string) (bool, error) {
_, err := k.Get(ctx, name, namespace)
if err != nil {
if apiErrors.IsNotFound(err) {
return true, nil
}
return false, err
}
return false, nil
}

// Get - returns a volume selector kubernetes object
func (k *kubeVolumeSelectorController) Get(ctx context.Context, name, ns string) (*v1alpha1.Volumeselector, error) {
obj := &v1alpha1.Volumeselector{}
Expand Down
28 changes: 23 additions & 5 deletions internal/controller/serverset/bootvolume_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ type kubeBootVolumeControlManager interface {

// kubeBootVolumeController - kubernetes client wrapper for server resources
type kubeBootVolumeController struct {
kube client.Client
log logging.Logger
kube client.Client
log logging.Logger
mapController kubeConfigmapControlManager
}

// Create creates a volume CR and waits until in reaches AVAILABLE state
Expand All @@ -40,7 +41,7 @@ func (k *kubeBootVolumeController) Create(ctx context.Context, cr *v1alpha1.Serv
k.log.Info("Creating BootVolume", "name", name)
var userDataPatcher *ccpatch.CloudInitPatcher
var err error
userDataPatcher, err = setPatcher(ctx, cr, replicaIndex, name, k.kube)
userDataPatcher, err = k.setPatcher(ctx, cr, replicaIndex, version, name, k.kube)
if err != nil {
return v1alpha1.Volume{}, err
}
Expand All @@ -67,7 +68,7 @@ func (k *kubeBootVolumeController) Create(ctx context.Context, cr *v1alpha1.Serv
// one global state where to hold used ip addressed for substitutions for each statefulserverset
var globalStateMap = make(map[string]substitution.GlobalState)

func setPatcher(ctx context.Context, cr *v1alpha1.ServerSet, replicaIndex int, name string, kube client.Client) (*ccpatch.CloudInitPatcher, error) {
func (k *kubeBootVolumeController) setPatcher(ctx context.Context, cr *v1alpha1.ServerSet, replicaIndex, version int, name string, kube client.Client) (*ccpatch.CloudInitPatcher, error) { // nolint:gocyclo
var userDataPatcher *ccpatch.CloudInitPatcher
var err error
userData := cr.Spec.ForProvider.BootVolumeTemplate.Spec.UserData
Expand All @@ -81,7 +82,24 @@ func setPatcher(ctx context.Context, cr *v1alpha1.ServerSet, replicaIndex int, n
if err != nil {
return userDataPatcher, fmt.Errorf("while creating cloud init patcher with substitutions for BootVolume %s %w", name, err)
}

namespace := "default"
if cr.Spec.ForProvider.IdentityConfigMap.Namespace != "" {
namespace = cr.Spec.ForProvider.IdentityConfigMap.Namespace
}
k.mapController.SetSubstitutionConfigMap(cr.Name, namespace)
for substIndex, subst := range substitutions {
if stateMapVal, exists := globalStateMap[cr.Name]; exists {
stateSlice := stateMapVal.GetByIdentifier(identifier)
if len(stateSlice) > 0 && substIndex <= len(stateSlice)-1 {
val := stateSlice[substIndex].Value
k.mapController.SetIdentity(cr.Name, strconv.Itoa(replicaIndex)+"."+strconv.Itoa(version)+"."+subst.Key, val)
}
}
}
err := k.mapController.CreateOrUpdate(ctx, cr.Name)
if err != nil {
k.log.Info("while writing to substConfig map", "error", err)
}
} else {
userDataPatcher, err = ccpatch.NewCloudInitPatcher(userData)
if err != nil {
Expand Down
Loading

0 comments on commit 622983d

Please sign in to comment.