package uuid import ( "errors" "unicode" artifactregistryAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/artifactregistry/v1beta1" bigqueryAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/bigquery/v1beta1" containerAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/container/v1beta1" iamAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/iam/v1beta1" pubsubAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/pubsub/v1beta1" resourceAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/resourcemanager/v1beta1" secretmanagerAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/secretmanager/v1beta1" storageAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/storage/v1beta1" goext "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" kustomizeApi "github.com/fluxcd/kustomize-controller/api/v1" sourceApi "github.com/fluxcd/source-controller/api/v1" "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/client" bannerApi "edge-infra.dev/pkg/edge/apis/banner/v1alpha1" clusterApi "edge-infra.dev/pkg/edge/apis/cluster/v1alpha1" ) // ResourceRequirements represents naming requirements for KCC, Flux and Edge kubernetes resources. type ResourceRequirements struct { GV schema.GroupVersion CanStartWithDigit bool MinLength int MaxLength int Labels bool SpecialCharacters bool } var ( // ErrGVKNotSupported error returned when the gvk of the resource provided is not supported. // to add support for the gvk of this resource, add the resource to resources which is a map // of ResourceRequirements. ErrGVKNotSupported = errors.New("provided resource group version kind not supported") // ErrVersionNotSupported error returned when the version of the resource provided is not supported. // to add support for the version of this resource, add the version to resources which is a map // of ResourceRequirements. ErrVersionNotSupported = errors.New("provided resource version not supported") // resources is list of kcc, flux and edge resources and their name requirements resources = map[string]ResourceRequirements{ resourceAPI.ProjectGVK.Kind: { GV: schema.GroupVersion{ Group: resourceAPI.ProjectGVK.Group, Version: resourceAPI.ProjectGVK.Version, }, CanStartWithDigit: false, MinLength: 6, MaxLength: 30, SpecialCharacters: true, }, resourceAPI.FolderGVK.Kind: { GV: schema.GroupVersion{ Group: resourceAPI.FolderGVK.Group, Version: resourceAPI.FolderGVK.Version, }, CanStartWithDigit: false, MinLength: 6, MaxLength: 30, SpecialCharacters: true, }, pubsubAPI.PubSubTopicGVK.Kind: { GV: schema.GroupVersion{ Group: pubsubAPI.PubSubTopicGVK.Group, Version: pubsubAPI.PubSubTopicGVK.Version, }, CanStartWithDigit: false, MinLength: 3, MaxLength: 255, SpecialCharacters: true, }, pubsubAPI.PubSubSubscriptionGVK.Kind: { GV: schema.GroupVersion{ Group: pubsubAPI.PubSubSubscriptionGVK.Group, Version: pubsubAPI.PubSubSubscriptionGVK.Version, }, CanStartWithDigit: false, MinLength: 3, MaxLength: 255, SpecialCharacters: true, }, storageAPI.StorageBucketGVK.Kind: { GV: schema.GroupVersion{ Group: storageAPI.StorageBucketGVK.Group, Version: storageAPI.StorageBucketGVK.Version, }, CanStartWithDigit: true, MinLength: 3, MaxLength: 63, SpecialCharacters: true, }, containerAPI.ContainerClusterGVK.Kind: { GV: schema.GroupVersion{ Group: containerAPI.ContainerClusterGVK.Group, Version: containerAPI.ContainerClusterGVK.Version, }, CanStartWithDigit: false, MinLength: 3, MaxLength: 39, SpecialCharacters: true, }, containerAPI.ContainerNodePoolGVK.Kind: { GV: schema.GroupVersion{ Group: containerAPI.ContainerNodePoolGVK.Group, Version: containerAPI.ContainerNodePoolGVK.Version, }, CanStartWithDigit: false, MinLength: 3, MaxLength: 39, SpecialCharacters: true, }, secretmanagerAPI.SecretManagerSecretGVK.Kind: { GV: schema.GroupVersion{ Group: secretmanagerAPI.SecretManagerSecretGVK.Group, Version: secretmanagerAPI.SecretManagerSecretGVK.Version, }, CanStartWithDigit: true, MinLength: 3, MaxLength: 255, SpecialCharacters: true, }, iamAPI.IAMServiceAccountGVK.Kind: { GV: schema.GroupVersion{ Group: iamAPI.IAMServiceAccountGVK.Group, Version: iamAPI.IAMServiceAccountGVK.Version, }, CanStartWithDigit: true, //verify, it works on the UI though MinLength: 6, MaxLength: 30, SpecialCharacters: true, }, bigqueryAPI.BigQueryTableGVK.Kind: { GV: schema.GroupVersion{ Group: bigqueryAPI.BigQueryTableGVK.Group, Version: bigqueryAPI.BigQueryTableGVK.Version, }, CanStartWithDigit: true, MinLength: 3, MaxLength: 1024, SpecialCharacters: true, }, bigqueryAPI.BigQueryDatasetGVK.Kind: { GV: schema.GroupVersion{ Group: bigqueryAPI.BigQueryDatasetGVK.Group, Version: bigqueryAPI.BigQueryDatasetGVK.Version, }, CanStartWithDigit: true, MinLength: 3, MaxLength: 1024, SpecialCharacters: false, }, artifactregistryAPI.ArtifactRegistryRepositoryGVK.Kind: { GV: schema.GroupVersion{ Group: artifactregistryAPI.ArtifactRegistryRepositoryGVK.Group, Version: artifactregistryAPI.ArtifactRegistryRepositoryGVK.Version, }, CanStartWithDigit: false, MinLength: 1, MaxLength: 63, SpecialCharacters: false, //only hyphen }, iamAPI.IAMCustomRoleGVK.Kind: { GV: schema.GroupVersion{ Group: iamAPI.IAMCustomRoleGVK.Group, Version: iamAPI.IAMCustomRoleGVK.Version, }, CanStartWithDigit: true, MinLength: 1, MaxLength: 100, SpecialCharacters: false, //only hyphen }, goext.ExtSecretGroupVersionKind.Kind: { GV: schema.GroupVersion{ Group: goext.ExtSecretGroupVersionKind.Group, Version: goext.ExtSecretGroupVersionKind.Version, }, CanStartWithDigit: true, MinLength: 1, MaxLength: 100, SpecialCharacters: false, //only hyphen }, goext.ClusterExtSecretGroupVersionKind.Kind: { GV: schema.GroupVersion{ Group: goext.ClusterExtSecretGroupVersionKind.Group, Version: goext.ClusterExtSecretGroupVersionKind.Version, }, CanStartWithDigit: true, MinLength: 1, MaxLength: 100, SpecialCharacters: false, //only hyphen }, kustomizeApi.KustomizationKind: { GV: schema.GroupVersion{ Group: kustomizeApi.GroupVersion.Group, Version: kustomizeApi.GroupVersion.Version, }, CanStartWithDigit: true, MinLength: 1, MaxLength: 100, SpecialCharacters: false, //only hyphen }, sourceApi.BucketKind: { GV: schema.GroupVersion{ Group: sourceApi.GroupVersion.Group, Version: sourceApi.GroupVersion.Version, }, CanStartWithDigit: true, MinLength: 1, MaxLength: 100, SpecialCharacters: false, //only hyphen }, sourceApi.GitRepositoryKind: { GV: schema.GroupVersion{ Group: sourceApi.GroupVersion.Group, Version: sourceApi.GroupVersion.Version, }, CanStartWithDigit: true, MinLength: 1, MaxLength: 100, SpecialCharacters: false, //only hyphen }, sourceApi.HelmRepositoryKind: { GV: schema.GroupVersion{ Group: sourceApi.GroupVersion.Group, Version: sourceApi.GroupVersion.Version, }, CanStartWithDigit: true, MinLength: 1, MaxLength: 100, SpecialCharacters: false, //only hyphen }, sourceApi.HelmChartKind: { GV: schema.GroupVersion{ Group: sourceApi.GroupVersion.Group, Version: sourceApi.GroupVersion.Version, }, CanStartWithDigit: true, MinLength: 1, MaxLength: 100, SpecialCharacters: false, //only hyphen }, bannerApi.BannerKind: { GV: schema.GroupVersion{ Group: bannerApi.GroupVersion.Group, Version: bannerApi.GroupVersion.Version, }, CanStartWithDigit: true, MinLength: 1, MaxLength: 100, SpecialCharacters: false, }, clusterApi.ClusterKind: { GV: schema.GroupVersion{ Group: bannerApi.GroupVersion.Group, Version: bannerApi.GroupVersion.Version, }, CanStartWithDigit: true, MinLength: 1, MaxLength: 100, SpecialCharacters: false, }, } ) // CanUseUUID checks if the provided resource can use uuid according to the naming requirements of that resource. func CanUseUUID(gvk schema.GroupVersionKind) (bool, error) { v, k := gvk.ToAPIVersionAndKind() if val, exists := resources[k]; exists { switch val.GV.String() { case v: if val.MaxLength >= 36 && val.CanStartWithDigit { return true, nil } return false, nil default: return false, ErrVersionNotSupported } } return false, ErrGVKNotSupported } // CanUseHash checks if the provided resource can use a hash according to the naming requirements of that resource. func CanUseHash(gvk schema.GroupVersionKind) (bool, error) { v, k := gvk.ToAPIVersionAndKind() if val, exists := resources[k]; exists { switch val.GV.String() { case v: if val.MaxLength >= 12 && val.CanStartWithDigit && val.SpecialCharacters { return true, nil } return false, nil default: return false, ErrVersionNotSupported } } return false, ErrGVKNotSupported } func SatisfiesRequirement(obj client.Object) (bool, error) { return satisfiesRequirement(obj) } func satisfiesRequirement(obj client.Object) (bool, error) { name := obj.GetName() firstCharOfName := []rune(name[0:1]) gvk := obj.GetObjectKind().GroupVersionKind() v, k := gvk.ToAPIVersionAndKind() if val, exists := resources[k]; exists { switch val.GV.String() { case v: return len(name) <= val.MaxLength && len(name) >= val.MinLength && (unicode.IsDigit(firstCharOfName[0]) && val.CanStartWithDigit), nil default: return false, ErrVersionNotSupported } } return false, ErrGVKNotSupported }