Skip to content

Commit

Permalink
add harborcluster validator
Browse files Browse the repository at this point in the history
Signed-off-by: cndoit18 <cndoit18@outlook.com>
  • Loading branch information
cndoit18 authored and bitsf committed Jun 30, 2021
1 parent 678182a commit 112e363
Show file tree
Hide file tree
Showing 11 changed files with 282 additions and 37 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ install: go-generate
uninstall: go-generate
kubectl delete -f config/crd/bases

go-generate: controller-gen stringer
go-generate: controller-gen stringer manifests
export PATH="$(BIN):$${PATH}" ; \
go generate ./...

Expand Down
4 changes: 1 addition & 3 deletions apis/goharbor.io/v1alpha3/groupversion_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,4 @@ var (
AddToScheme = SchemeBuilder.AddToScheme
)

//go:generate controller-gen crd:crdVersions="v1" output:artifacts:config="../../../config/crd/bases" paths="../..."
//go:generate controller-gen webhook output:artifacts:config="../../../config/webhook" paths="../..."
//go:generate controller-gen object paths="../..."
//go:generate controller-gen object paths="./..."
2 changes: 2 additions & 0 deletions apis/goharbor.io/v1beta1/groupversion_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ var (
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)

//go:generate controller-gen object paths="./..."
4 changes: 0 additions & 4 deletions apis/goharbor.io/v1beta1/harbor_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,6 @@ func (spec *HarborSpec) ValidateNotary() *field.Error {
return nil
}

func required(mainPath *field.Path) *field.Error {
return field.Required(mainPath, fmt.Sprintf("%s should be configured", mainPath.String()))
}

func (spec *HarborSpec) ValidateRegistryController() *field.Error {
if spec.RegistryController == nil {
return nil
Expand Down
3 changes: 1 addition & 2 deletions apis/goharbor.io/v1beta1/harborcluster_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,4 @@ import (

var _ conversion.Hub = &HarborCluster{}

func (h *HarborCluster) Hub() {
}
func (harborcluster *HarborCluster) Hub() {}
167 changes: 165 additions & 2 deletions apis/goharbor.io/v1beta1/harborcluster_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,177 @@ package v1beta1

import (
"context"
"fmt"

"github.com/goharbor/harbor-operator/pkg/version"
"github.com/pkg/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
runtime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation/field"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)

func (h *HarborCluster) SetupWebhookWithManager(_ context.Context, mgr ctrl.Manager) error {
func (harborcluster *HarborCluster) SetupWebhookWithManager(_ context.Context, mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(h).
For(harborcluster).
Complete()
}

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!

const (
// The minimal number of volumes created by minio.
minimalVolumeCount = 4
)

// Log used this webhook.
var clog = logf.Log.WithName("harborcluster-resource")

// +kubebuilder:webhook:verbs=create;update,path=/validate-goharbor-io-v1beta1-harborcluster,mutating=false,failurePolicy=fail,groups=goharbor.io,resources=harborclusters,versions=v1beta1,name=vharborcluster.kb.io.v1beta1,admissionReviewVersions={"v1beta1"},sideEffects=None

var _ webhook.Validator = &HarborCluster{}

func (harborcluster *HarborCluster) ValidateCreate() error {
clog.Info("validate creation", "name", harborcluster.Name, "namespace", harborcluster.Namespace)

return harborcluster.validate(harborcluster)
}

func (harborcluster *HarborCluster) ValidateUpdate(old runtime.Object) error {
clog.Info("validate updating", "name", harborcluster.Name, "namespace", harborcluster.Namespace)

obj, ok := old.(*HarborCluster)
if !ok {
return errors.Errorf("failed type assertion on kind: %s", old.GetObjectKind().GroupVersionKind().String())
}

return harborcluster.validate(obj)
}

func (harborcluster *HarborCluster) ValidateDelete() error {
clog.Info("validate deletion", "name", harborcluster.Name, "namespace", harborcluster.Namespace)

return nil
}

func (harborcluster *HarborCluster) validate(old *HarborCluster) error {
var allErrs field.ErrorList

// For database(psql), cache(Redis) and storage, either external services or in-cluster services MUST be configured
if err := harborcluster.validateStorage(); err != nil {
allErrs = append(allErrs, err)
}

if err := harborcluster.validateDatabase(); err != nil {
allErrs = append(allErrs, err)
}

if err := harborcluster.validateCache(); err != nil {
allErrs = append(allErrs, err)
}

if old == nil { // create harbor resource
if err := version.Validate(harborcluster.Spec.Version); err != nil {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("version"), harborcluster.Spec.Version, err.Error()))
}
} else {
if err := version.UpgradeAllowed(old.Spec.Version, harborcluster.Spec.Version); err != nil {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("version"), harborcluster.Spec.Version, err.Error()))
}
}

if len(allErrs) == 0 {
return nil
}

return apierrors.NewInvalid(schema.GroupKind{Group: GroupVersion.Group, Kind: "HarborCluster"}, harborcluster.Name, allErrs)
}

func (harborcluster *HarborCluster) validateStorage() *field.Error {
// in cluster storage has high priority
fp := field.NewPath("spec").Child("storage").Child("spec")

// Storage
if harborcluster.Spec.Storage.Kind == KindStorageS3 && harborcluster.Spec.Storage.Spec.S3 == nil {
// Invalid and not acceptable
return required(fp.Child("s3"))
}

if harborcluster.Spec.Storage.Kind == KindStorageMinIO && harborcluster.Spec.Storage.Spec.MinIO == nil {
// Invalid and not acceptable
return required(fp.Child("minIO"))
}

if harborcluster.Spec.Storage.Kind == KindStorageSwift && harborcluster.Spec.Storage.Spec.Swift == nil {
// Invalid and not acceptable
return required(fp.Child("swift"))
}

if harborcluster.Spec.Storage.Kind == KindStorageFileSystem && harborcluster.Spec.Storage.Spec.FileSystem == nil {
// Invalid and not acceptable
return required(fp.Child("fileSystem"))
}

// Validate more if incluster storage is configured.
if harborcluster.Spec.Storage.Kind == KindStorageMinIO {
desiredReplicas := harborcluster.Spec.Storage.Spec.MinIO.Replicas
volumePerServer := harborcluster.Spec.Storage.Spec.MinIO.VolumesPerServer

if desiredReplicas*volumePerServer < minimalVolumeCount {
return invalid(fp, harborcluster.Spec.Storage.Spec.MinIO, fmt.Sprintf("minIO.replicas * minIO.volumesPerServer should be >=%d", minimalVolumeCount))
}
}

return nil
}

func (harborcluster *HarborCluster) validateDatabase() *field.Error {
// in cluster database has high priority
fp := field.NewPath("spec").Child("database").Child("spec")

// Database
// External is not configured
// And also in-cluster psql is not specified
if harborcluster.Spec.Database.Kind == KindDatabasePostgreSQL && harborcluster.Spec.Database.Spec.PostgreSQL == nil {
// Invalid and not acceptable
return required(fp.Child("postgreSQL"))
}

// Both are configured then conflict
if harborcluster.Spec.Database.Kind == KindDatabaseZlandoPostgreSQL && harborcluster.Spec.Database.Spec.ZlandoPostgreSQL == nil {
// Invalid and not acceptable
return required(fp.Child("zlandoPostgreSQL"))
}

return nil
}

func (harborcluster *HarborCluster) validateCache() *field.Error {
fp := field.NewPath("spec").Child("cache").Child("spec")

// Cache
// External is not configured
if harborcluster.Spec.Cache.Kind == KindCacheRedis && harborcluster.Spec.Cache.Spec.Redis == nil {
// Invalid and not acceptable
return required(fp.Child("redis"))
}

// Both are configured and then conflict
if harborcluster.Spec.Cache.Kind == KindCacheRedisFailover && harborcluster.Spec.Cache.Spec.RedisFailover == nil {
// Invalid and not acceptable
return required(fp.Child("redisFailover"))
}

return nil
}

func required(mainPath *field.Path) *field.Error {
return field.Required(mainPath, fmt.Sprintf("%s should be configured", mainPath.String()))
}

func invalid(mainPath *field.Path, value interface{}, details string) *field.Error {
return field.Invalid(mainPath, value, details)
}
2 changes: 1 addition & 1 deletion apis/goharbor.io/v1beta1/zz_generated.deepcopy.go

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

Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,23 @@ webhooks:
resources:
- harborclusters
sideEffects: None
- admissionReviewVersions:
- v1beta1
clientConfig:
service:
name: '{{ include "chart.fullname" . }}-webhook-service'
namespace: {{ .Release.Namespace | quote }}
path: /validate-goharbor-io-v1beta1-harborcluster
failurePolicy: Fail
name: vharborcluster.kb.io.v1beta1
rules:
- apiGroups:
- goharbor.io
apiVersions:
- v1beta1
operations:
- CREATE
- UPDATE
resources:
- harborclusters
sideEffects: None
51 changes: 42 additions & 9 deletions manifests/cluster/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,24 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
cert-manager.io/inject-ca-from: harbor-operator-ns/serving-cert
controller-gen.kubebuilder.io/version: v0.5.0
goharbor.io/deploy-engine: Kustomization
goharbor.io/deploy-mode: cluster
goharbor.io/operator-version: v1.0.0
creationTimestamp: null
name: chartmuseums.goharbor.io
spec:
conversion:
strategy: Webhook
webhook:
clientConfig:
caBundle: Cg==
service:
name: webhook-service
namespace: harbor-operator-ns
path: /convert
conversionReviewVersions:
- v1
group: goharbor.io
names:
categories:
Expand Down Expand Up @@ -3704,13 +3715,24 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
cert-manager.io/inject-ca-from: harbor-operator-ns/serving-cert
controller-gen.kubebuilder.io/version: v0.5.0
goharbor.io/deploy-engine: Kustomization
goharbor.io/deploy-mode: cluster
goharbor.io/operator-version: v1.0.0
creationTimestamp: null
name: exporters.goharbor.io
spec:
conversion:
strategy: Webhook
webhook:
clientConfig:
caBundle: Cg==
service:
name: webhook-service
namespace: harbor-operator-ns
path: /convert
conversionReviewVersions:
- v1
group: goharbor.io
names:
categories:
Expand Down Expand Up @@ -27859,13 +27881,24 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
cert-manager.io/inject-ca-from: harbor-operator-ns/serving-cert
controller-gen.kubebuilder.io/version: v0.5.0
goharbor.io/deploy-engine: Kustomization
goharbor.io/deploy-mode: cluster
goharbor.io/operator-version: v1.0.0
creationTimestamp: null
name: trivies.goharbor.io
spec:
conversion:
strategy: Webhook
webhook:
clientConfig:
caBundle: Cg==
service:
name: webhook-service
namespace: harbor-operator-ns
path: /convert
conversionReviewVersions:
- v1
group: goharbor.io
names:
categories:
Expand Down Expand Up @@ -34071,9 +34104,9 @@ webhooks:
service:
name: webhook-service
namespace: harbor-operator-ns
path: /validate-goharbor-io-v1alpha3-harbor
path: /validate-goharbor-io-v1alpha3-harborcluster
failurePolicy: Fail
name: vharbor.kb.io
name: vharborcluster.kb.io
rules:
- apiGroups:
- goharbor.io
Expand All @@ -34083,17 +34116,17 @@ webhooks:
- CREATE
- UPDATE
resources:
- harbors
- harborclusters
sideEffects: None
- admissionReviewVersions:
- v1beta1
clientConfig:
service:
name: webhook-service
namespace: harbor-operator-ns
path: /validate-goharbor-io-v1alpha3-harborcluster
path: /validate-goharbor-io-v1alpha3-harbor
failurePolicy: Fail
name: vharborcluster.kb.io
name: vharbor.kb.io
rules:
- apiGroups:
- goharbor.io
Expand All @@ -34103,7 +34136,7 @@ webhooks:
- CREATE
- UPDATE
resources:
- harborclusters
- harbors
sideEffects: None
- admissionReviewVersions:
- v1beta1
Expand Down
Loading

0 comments on commit 112e363

Please sign in to comment.