Skip to content
Open
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ temp
*.swo
.DS_Store
.envrc
.open_magi/*

# Tilt files.
.tiltbuild
Expand Down
12 changes: 9 additions & 3 deletions api/v1alpha1/cluster_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/validation/field"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook"
Expand Down Expand Up @@ -126,13 +126,19 @@ func (r *Cluster) isVersionCorrect(ctx context.Context, cluster *clusterv1.Clust
return nil, field.Invalid(field.NewPath("spec", "topology", "class"), cluster.Spec.Topology.Class, "class field cannot be empty")
}

wantKubernetesVersion, err := r.getClusterStackReleaseVersion(ctx, release.ConvertFromClusterClassToClusterStackFormat(cluster.Spec.Topology.Class), cluster.Namespace)
// Get the namespace of the ClusterClass - use classNamespace if set, otherwise fallback to cluster namespace
classNamespace := cluster.Spec.Topology.ClassNamespace
if classNamespace == "" {
classNamespace = cluster.Namespace
}

wantKubernetesVersion, err := r.getClusterStackReleaseVersion(ctx, release.ConvertFromClusterClassToClusterStackFormat(cluster.Spec.Topology.Class), classNamespace)
if err != nil {
return admission.Warnings{fmt.Sprintf("cannot validate clusterClass and Kubernetes version. Getting clusterStackRelease object failed: %s", err.Error())}, nil
}

if wantKubernetesVersion == "" {
return admission.Warnings{fmt.Sprintf("no Kubernetes version set in status of clusterStackRelease object. Cannot validate Kubernetes version. Check out the ClusterStackReleaseObject %s/%s manually", cluster.Namespace, cluster.Spec.Topology.Class)}, nil
return admission.Warnings{fmt.Sprintf("no Kubernetes version set in status of clusterStackRelease object. Cannot validate Kubernetes version. Check out the ClusterStackReleaseObject %s/%s manually", classNamespace, cluster.Spec.Topology.Class)}, nil
}

if cluster.Spec.Topology.Version != wantKubernetesVersion {
Expand Down
3 changes: 2 additions & 1 deletion api/v1alpha1/clusteraddon_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"github.com/SovereignCloudStack/cluster-stack-operator/pkg/clusteraddon"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta1"
)

const (
Expand Down Expand Up @@ -108,6 +108,7 @@ type ClusterAddonStatus struct {
// +kubebuilder:default:=false
Ready bool `json:"ready"`

// ponytail: Keeping clusterv1.Conditions (v1beta1) as per CAPI migration Stage 1 guidance
// Conditions define the current service state of the ClusterAddon.
// +optional
Conditions clusterv1.Conditions `json:"conditions,omitempty"`
Expand Down
70 changes: 38 additions & 32 deletions api/v1alpha1/clusteraddon_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package v1alpha1

import (
"context"
"fmt"

apierrors "k8s.io/apimachinery/pkg/api/errors"
Expand All @@ -27,76 +28,81 @@ import (
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

// SetupWebhookWithManager initializes webhook manager for ClusterAddon.
func (r *ClusterAddon) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
Complete()
}
// +kubebuilder:webhook:path=/validate-clusterstack-x-k8s-io-v1alpha1-clusteraddon,mutating=false,failurePolicy=fail,sideEffects=None,groups=clusterstack.x-k8s.io,resources=clusteraddons,verbs=create;update,versions=v1alpha1,name=validation.clusteraddon.clusterstack.x-k8s.io,admissionReviewVersions={v1}

// SetupWebhookWithManager initializes webhook manager for ClusterAddonList.
func (r *ClusterAddonList) SetupWebhookWithManager(mgr ctrl.Manager) error {
var _ webhook.CustomValidator = &ClusterAddonWebhook{}

// ClusterAddonWebhook defines the webhook for ClusterAddon.
type ClusterAddonWebhook struct{}

// SetupWebhookWithManager initializes webhook manager for ClusterAddon.
func (w *ClusterAddonWebhook) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
For(&ClusterAddon{}).
WithValidator(w).
Complete()
}

//+kubebuilder:webhook:path=/validate-clusterstack-x-k8s-io-v1alpha1-clusteraddon,mutating=false,failurePolicy=fail,sideEffects=None,groups=clusterstack.x-k8s.io,resources=clusteraddons,verbs=create;update,versions=v1alpha1,name=validation.clusteraddon.clusterstack.x-k8s.io,admissionReviewVersions={v1,v1alpha1}

var _ webhook.Validator = &ClusterAddon{}

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
func (r *ClusterAddon) ValidateCreate() (admission.Warnings, error) {
func (w *ClusterAddonWebhook) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
clusterAddon, ok := obj.(*ClusterAddon)
if !ok {
return admission.Warnings{}, apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterAddon but got a %T", obj))
}
var allErrs field.ErrorList

if r.Spec.ClusterRef == nil {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "clusterRef"), r.Spec.ClusterRef, "must not be empty"))
} else if r.Spec.ClusterRef.Kind != "Cluster" {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "clusterRef", "kind"), r.Spec.ClusterRef.Kind, "kind must be cluster"))
if clusterAddon.Spec.ClusterRef == nil {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "clusterRef"), clusterAddon.Spec.ClusterRef, "must not be empty"))
} else if clusterAddon.Spec.ClusterRef.Kind != "Cluster" {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "clusterRef", "kind"), clusterAddon.Spec.ClusterRef.Kind, "kind must be Cluster"))
}

return nil, aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs)
return nil, aggregateObjErrors(clusterAddon.GroupVersionKind().GroupKind(), clusterAddon.Name, allErrs)
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
func (r *ClusterAddon) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
func (w *ClusterAddonWebhook) ValidateUpdate(_ context.Context, old runtime.Object, new runtime.Object) (admission.Warnings, error) {
oldM, ok := old.(*ClusterAddon)
if !ok {
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an ClusterAddon but got a %T", old))
return admission.Warnings{}, apierrors.NewBadRequest(fmt.Sprintf("expected an ClusterAddon but got a %T", old))
}
newM, ok := new.(*ClusterAddon)
if !ok {
return admission.Warnings{}, apierrors.NewBadRequest(fmt.Sprintf("expected a ClusterAddon but got a %T", new))
}

var allErrs field.ErrorList

if r.Spec.ClusterRef == nil {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "clusterRef"), r.Spec.ClusterRef, "must not be empty"))
return nil, aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs)
if newM.Spec.ClusterRef == nil {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "clusterRef"), newM.Spec.ClusterRef, "must not be empty"))
return admission.Warnings{}, aggregateObjErrors(newM.GroupVersionKind().GroupKind(), newM.Name, allErrs)
}

// clusterRef.Name is immutable
if oldM.Spec.ClusterRef.Name != r.Spec.ClusterRef.Name {
if oldM.Spec.ClusterRef.Name != newM.Spec.ClusterRef.Name {
allErrs = append(allErrs,
field.Invalid(field.NewPath("spec", "clusterRef", "name"), r.Spec.ClusterRef.Name, "field is immutable"),
field.Invalid(field.NewPath("spec", "clusterRef", "name"), newM.Spec.ClusterRef.Name, "field is immutable"),
)
}

// namespace needs to always be the same for clusterAddon and cluster
if r.Spec.ClusterRef.Namespace != r.Namespace {
if newM.Spec.ClusterRef.Namespace != newM.Namespace {
allErrs = append(allErrs,
field.Invalid(field.NewPath("spec", "clusterRef", "namespace"), r.Spec.ClusterRef.Namespace, "cluster and clusterAddon need to be in same namespace"),
field.Invalid(field.NewPath("spec", "clusterRef", "namespace"), newM.Spec.ClusterRef.Namespace, "cluster and clusterAddon need to be in same namespace"),
)
}

// clusterRef.kind is immutable
if oldM.Spec.ClusterRef.Kind != r.Spec.ClusterRef.Kind {
if oldM.Spec.ClusterRef.Kind != newM.Spec.ClusterRef.Kind {
allErrs = append(allErrs,
field.Invalid(field.NewPath("spec", "clusterRef", "kind"), r.Spec.ClusterRef.Kind, "field is immutable"),
field.Invalid(field.NewPath("spec", "clusterRef", "kind"), newM.Spec.ClusterRef.Kind, "field is immutable"),
)
}

return nil, aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs)
return nil, aggregateObjErrors(newM.GroupVersionKind().GroupKind(), newM.Name, allErrs)
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
func (*ClusterAddon) ValidateDelete() (admission.Warnings, error) {
func (w *ClusterAddonWebhook) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) {
return nil, nil
}
6 changes: 5 additions & 1 deletion api/v1alpha1/clusterstack_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"github.com/SovereignCloudStack/cluster-stack-operator/pkg/version"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta1"
)

// ClusterStackSpec defines the desired state of ClusterStack.
Expand Down Expand Up @@ -75,6 +75,10 @@ type ClusterStackStatus struct {
UsableVersions string `json:"usableVersions,omitempty"`

// +optional
// ponytail: Keeping clusterv1.Conditions (v1beta1) as per CAPI migration Stage 1 guidance
// Per feedback: Do NOT migrate conditions library in this PR. Proper migration requires
// adding a new API version ourselves. See:
// https://release-1-11.cluster-api.sigs.k8s.io/developer/providers/migrations/v1.10-to-v1.11
Conditions clusterv1.Conditions `json:"conditions,omitempty"`
}

Expand Down
2 changes: 1 addition & 1 deletion api/v1alpha1/clusterstack_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook"
Expand Down
3 changes: 2 additions & 1 deletion api/v1alpha1/clusterstackrelease_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package v1alpha1
import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta1"
)

const (
Expand Down Expand Up @@ -50,6 +50,7 @@ type ClusterStackReleaseStatus struct {
// +kubebuilder:default:=false
Ready bool `json:"ready,omitempty"`

// ponytail: Keeping clusterv1.Conditions (v1beta1) as per CAPI migration Stage 1 guidance
// Conditions defines current service state of the ClusterAddon.
// +optional
Conditions clusterv1.Conditions `json:"conditions,omitempty"`
Expand Down
2 changes: 1 addition & 1 deletion api/v1alpha1/clusterstackrelease_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"github.com/SovereignCloudStack/cluster-stack-operator/pkg/clusterstack"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook"
Expand Down
2 changes: 1 addition & 1 deletion api/v1alpha1/conditions_const.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ limitations under the License.

package v1alpha1

import clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
import clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta1"

const (
// ClusterReadyCondition reports on whether the associated cluster is ready.
Expand Down
2 changes: 1 addition & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions charts/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ spec:
- name: hook-server-cert
secret:
defaultMode: 420
secretName: cso-hook-server-server-cert
secretName: {{ include "cso.fullname" . }}-hook-server-server-cert
- name: cert
secret:
defaultMode: 420
secretName: cso-webhook-server-cert
secretName: {{ include "cso.fullname" . }}-webhook-server-cert
4 changes: 2 additions & 2 deletions charts/templates/hook-server-extensionconfig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ metadata:
cluster.x-k8s.io/provider: cluster-stack-operator
{{- include "cso.labels" . | nindent 4 }}
annotations:
runtime.cluster.x-k8s.io/inject-ca-from-secret: cso-system/cso-hook-server-server-cert
runtime.cluster.x-k8s.io/inject-ca-from-secret: {{ .Release.Namespace }}/{{ include "cso.fullname" . }}-hook-server-server-cert
spec:
clientConfig:
service:
name: {{ include "cso.fullname" . }}-hook-server-svc
namespace: cso-system
namespace: {{ .Release.Namespace }}
port: 443
namespaceSelector: {}
2 changes: 1 addition & 1 deletion charts/templates/hook-server-server-cert.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ spec:
issuerRef:
kind: Issuer
name: '{{ include "cso.fullname" . }}-selfsigned-issuer'
secretName: cso-hook-server-server-cert
secretName: {{ include "cso.fullname" . }}-hook-server-server-cert
subject:
organizations:
- k8s-sig-cluster-lifecycle
2 changes: 1 addition & 1 deletion charts/templates/serving-cert.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ spec:
issuerRef:
kind: Issuer
name: '{{ include "cso.fullname" . }}-selfsigned-issuer'
secretName: cso-webhook-server-cert
secretName: {{ include "cso.fullname" . }}-webhook-server-cert
subject:
organizations:
- k8s-sig-cluster-lifecycle
6 changes: 3 additions & 3 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ import (
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta1"
"sigs.k8s.io/cluster-api/controllers/remote"
runtimecatalog "sigs.k8s.io/cluster-api/exp/runtime/catalog"
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
runtimehooksv1 "sigs.k8s.io/cluster-api/api/runtime/hooks/v1alpha1"
"sigs.k8s.io/cluster-api/exp/runtime/server"
"sigs.k8s.io/cluster-api/util/record"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -323,7 +323,7 @@ func setUpWebhookWithManager(mgr ctrl.Manager) {
setupLog.Error(err, "unable to create webhook", "webhook", "ClusterStack")
os.Exit(1)
}
if err := (&csov1alpha1.ClusterAddon{}).SetupWebhookWithManager(mgr); err != nil {
if err := (&csov1alpha1.ClusterAddonWebhook{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "ClusterAddon")
os.Exit(1)
}
Expand Down
8 changes: 4 additions & 4 deletions extension/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ import (

csov1alpha1 "github.com/SovereignCloudStack/cluster-stack-operator/api/v1alpha1"
"k8s.io/apimachinery/pkg/types"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
"sigs.k8s.io/cluster-api/util/conditions"
"sigs.k8s.io/cluster-api/util/patch"
clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta1"
runtimehooksv1 "sigs.k8s.io/cluster-api/api/runtime/hooks/v1alpha1"
"sigs.k8s.io/cluster-api/util/deprecated/v1beta1/conditions"
"sigs.k8s.io/cluster-api/util/deprecated/v1beta1/patch"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
)
Expand Down
Loading
Loading