...

Source file src/edge-infra.dev/pkg/x/uuid/verify.go

Documentation: edge-infra.dev/pkg/x/uuid

     1  package uuid
     2  
     3  import (
     4  	"errors"
     5  	"unicode"
     6  
     7  	artifactregistryAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/artifactregistry/v1beta1"
     8  	bigqueryAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/bigquery/v1beta1"
     9  	containerAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/container/v1beta1"
    10  	iamAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/iam/v1beta1"
    11  	pubsubAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/pubsub/v1beta1"
    12  	resourceAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/resourcemanager/v1beta1"
    13  	secretmanagerAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/secretmanager/v1beta1"
    14  	storageAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/storage/v1beta1"
    15  	goext "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
    16  	kustomizeApi "github.com/fluxcd/kustomize-controller/api/v1"
    17  	sourceApi "github.com/fluxcd/source-controller/api/v1"
    18  	"k8s.io/apimachinery/pkg/runtime/schema"
    19  	"sigs.k8s.io/controller-runtime/pkg/client"
    20  
    21  	bannerApi "edge-infra.dev/pkg/edge/apis/banner/v1alpha1"
    22  	clusterApi "edge-infra.dev/pkg/edge/apis/cluster/v1alpha1"
    23  )
    24  
    25  // ResourceRequirements represents naming requirements for KCC, Flux and Edge kubernetes resources.
    26  type ResourceRequirements struct {
    27  	GV                schema.GroupVersion
    28  	CanStartWithDigit bool
    29  	MinLength         int
    30  	MaxLength         int
    31  	Labels            bool
    32  	SpecialCharacters bool
    33  }
    34  
    35  var (
    36  	// ErrGVKNotSupported error returned when the gvk of the resource provided is not supported.
    37  	// to add support for the gvk of this resource, add the resource to resources which is a map
    38  	// of ResourceRequirements.
    39  	ErrGVKNotSupported = errors.New("provided resource group version kind not supported")
    40  	// ErrVersionNotSupported error returned when the version of the resource provided is not supported.
    41  	// to add support for the version of this resource, add the version to resources which is a map
    42  	// of ResourceRequirements.
    43  	ErrVersionNotSupported = errors.New("provided resource version not supported")
    44  	// resources is list of kcc, flux and edge resources and their name requirements
    45  	resources = map[string]ResourceRequirements{
    46  		resourceAPI.ProjectGVK.Kind: {
    47  			GV: schema.GroupVersion{
    48  				Group:   resourceAPI.ProjectGVK.Group,
    49  				Version: resourceAPI.ProjectGVK.Version,
    50  			},
    51  			CanStartWithDigit: false,
    52  			MinLength:         6,
    53  			MaxLength:         30,
    54  			SpecialCharacters: true,
    55  		},
    56  		resourceAPI.FolderGVK.Kind: {
    57  			GV: schema.GroupVersion{
    58  				Group:   resourceAPI.FolderGVK.Group,
    59  				Version: resourceAPI.FolderGVK.Version,
    60  			},
    61  			CanStartWithDigit: false,
    62  			MinLength:         6,
    63  			MaxLength:         30,
    64  			SpecialCharacters: true,
    65  		},
    66  		pubsubAPI.PubSubTopicGVK.Kind: {
    67  			GV: schema.GroupVersion{
    68  				Group:   pubsubAPI.PubSubTopicGVK.Group,
    69  				Version: pubsubAPI.PubSubTopicGVK.Version,
    70  			},
    71  			CanStartWithDigit: false,
    72  			MinLength:         3,
    73  			MaxLength:         255,
    74  			SpecialCharacters: true,
    75  		},
    76  		pubsubAPI.PubSubSubscriptionGVK.Kind: {
    77  			GV: schema.GroupVersion{
    78  				Group:   pubsubAPI.PubSubSubscriptionGVK.Group,
    79  				Version: pubsubAPI.PubSubSubscriptionGVK.Version,
    80  			},
    81  			CanStartWithDigit: false,
    82  			MinLength:         3,
    83  			MaxLength:         255,
    84  			SpecialCharacters: true,
    85  		},
    86  		storageAPI.StorageBucketGVK.Kind: {
    87  			GV: schema.GroupVersion{
    88  				Group:   storageAPI.StorageBucketGVK.Group,
    89  				Version: storageAPI.StorageBucketGVK.Version,
    90  			},
    91  			CanStartWithDigit: true,
    92  			MinLength:         3,
    93  			MaxLength:         63,
    94  			SpecialCharacters: true,
    95  		},
    96  		containerAPI.ContainerClusterGVK.Kind: {
    97  			GV: schema.GroupVersion{
    98  				Group:   containerAPI.ContainerClusterGVK.Group,
    99  				Version: containerAPI.ContainerClusterGVK.Version,
   100  			},
   101  			CanStartWithDigit: false,
   102  			MinLength:         3,
   103  			MaxLength:         39,
   104  			SpecialCharacters: true,
   105  		},
   106  		containerAPI.ContainerNodePoolGVK.Kind: {
   107  			GV: schema.GroupVersion{
   108  				Group:   containerAPI.ContainerNodePoolGVK.Group,
   109  				Version: containerAPI.ContainerNodePoolGVK.Version,
   110  			},
   111  			CanStartWithDigit: false,
   112  			MinLength:         3,
   113  			MaxLength:         39,
   114  			SpecialCharacters: true,
   115  		},
   116  		secretmanagerAPI.SecretManagerSecretGVK.Kind: {
   117  			GV: schema.GroupVersion{
   118  				Group:   secretmanagerAPI.SecretManagerSecretGVK.Group,
   119  				Version: secretmanagerAPI.SecretManagerSecretGVK.Version,
   120  			},
   121  			CanStartWithDigit: true,
   122  			MinLength:         3,
   123  			MaxLength:         255,
   124  			SpecialCharacters: true,
   125  		},
   126  		iamAPI.IAMServiceAccountGVK.Kind: {
   127  			GV: schema.GroupVersion{
   128  				Group:   iamAPI.IAMServiceAccountGVK.Group,
   129  				Version: iamAPI.IAMServiceAccountGVK.Version,
   130  			},
   131  			CanStartWithDigit: true, //verify, it works on the UI though
   132  			MinLength:         6,
   133  			MaxLength:         30,
   134  			SpecialCharacters: true,
   135  		},
   136  		bigqueryAPI.BigQueryTableGVK.Kind: {
   137  			GV: schema.GroupVersion{
   138  				Group:   bigqueryAPI.BigQueryTableGVK.Group,
   139  				Version: bigqueryAPI.BigQueryTableGVK.Version,
   140  			},
   141  			CanStartWithDigit: true,
   142  			MinLength:         3,
   143  			MaxLength:         1024,
   144  			SpecialCharacters: true,
   145  		},
   146  		bigqueryAPI.BigQueryDatasetGVK.Kind: {
   147  			GV: schema.GroupVersion{
   148  				Group:   bigqueryAPI.BigQueryDatasetGVK.Group,
   149  				Version: bigqueryAPI.BigQueryDatasetGVK.Version,
   150  			},
   151  			CanStartWithDigit: true,
   152  			MinLength:         3,
   153  			MaxLength:         1024,
   154  			SpecialCharacters: false,
   155  		},
   156  		artifactregistryAPI.ArtifactRegistryRepositoryGVK.Kind: {
   157  			GV: schema.GroupVersion{
   158  				Group:   artifactregistryAPI.ArtifactRegistryRepositoryGVK.Group,
   159  				Version: artifactregistryAPI.ArtifactRegistryRepositoryGVK.Version,
   160  			},
   161  			CanStartWithDigit: false,
   162  			MinLength:         1,
   163  			MaxLength:         63,
   164  			SpecialCharacters: false, //only hyphen
   165  		},
   166  		iamAPI.IAMCustomRoleGVK.Kind: {
   167  			GV: schema.GroupVersion{
   168  				Group:   iamAPI.IAMCustomRoleGVK.Group,
   169  				Version: iamAPI.IAMCustomRoleGVK.Version,
   170  			},
   171  			CanStartWithDigit: true,
   172  			MinLength:         1,
   173  			MaxLength:         100,
   174  			SpecialCharacters: false, //only hyphen
   175  		},
   176  		goext.ExtSecretGroupVersionKind.Kind: {
   177  			GV: schema.GroupVersion{
   178  				Group:   goext.ExtSecretGroupVersionKind.Group,
   179  				Version: goext.ExtSecretGroupVersionKind.Version,
   180  			},
   181  			CanStartWithDigit: true,
   182  			MinLength:         1,
   183  			MaxLength:         100,
   184  			SpecialCharacters: false, //only hyphen
   185  		},
   186  		goext.ClusterExtSecretGroupVersionKind.Kind: {
   187  			GV: schema.GroupVersion{
   188  				Group:   goext.ClusterExtSecretGroupVersionKind.Group,
   189  				Version: goext.ClusterExtSecretGroupVersionKind.Version,
   190  			},
   191  			CanStartWithDigit: true,
   192  			MinLength:         1,
   193  			MaxLength:         100,
   194  			SpecialCharacters: false, //only hyphen
   195  		},
   196  		kustomizeApi.KustomizationKind: {
   197  			GV: schema.GroupVersion{
   198  				Group:   kustomizeApi.GroupVersion.Group,
   199  				Version: kustomizeApi.GroupVersion.Version,
   200  			},
   201  			CanStartWithDigit: true,
   202  			MinLength:         1,
   203  			MaxLength:         100,
   204  			SpecialCharacters: false, //only hyphen
   205  		},
   206  		sourceApi.BucketKind: {
   207  			GV: schema.GroupVersion{
   208  				Group:   sourceApi.GroupVersion.Group,
   209  				Version: sourceApi.GroupVersion.Version,
   210  			},
   211  			CanStartWithDigit: true,
   212  			MinLength:         1,
   213  			MaxLength:         100,
   214  			SpecialCharacters: false, //only hyphen
   215  		},
   216  		sourceApi.GitRepositoryKind: {
   217  			GV: schema.GroupVersion{
   218  				Group:   sourceApi.GroupVersion.Group,
   219  				Version: sourceApi.GroupVersion.Version,
   220  			},
   221  			CanStartWithDigit: true,
   222  			MinLength:         1,
   223  			MaxLength:         100,
   224  			SpecialCharacters: false, //only hyphen
   225  		},
   226  		sourceApi.HelmRepositoryKind: {
   227  			GV: schema.GroupVersion{
   228  				Group:   sourceApi.GroupVersion.Group,
   229  				Version: sourceApi.GroupVersion.Version,
   230  			},
   231  			CanStartWithDigit: true,
   232  			MinLength:         1,
   233  			MaxLength:         100,
   234  			SpecialCharacters: false, //only hyphen
   235  		},
   236  		sourceApi.HelmChartKind: {
   237  			GV: schema.GroupVersion{
   238  				Group:   sourceApi.GroupVersion.Group,
   239  				Version: sourceApi.GroupVersion.Version,
   240  			},
   241  			CanStartWithDigit: true,
   242  			MinLength:         1,
   243  			MaxLength:         100,
   244  			SpecialCharacters: false, //only hyphen
   245  		},
   246  		bannerApi.BannerKind: {
   247  			GV: schema.GroupVersion{
   248  				Group:   bannerApi.GroupVersion.Group,
   249  				Version: bannerApi.GroupVersion.Version,
   250  			},
   251  			CanStartWithDigit: true,
   252  			MinLength:         1,
   253  			MaxLength:         100,
   254  			SpecialCharacters: false,
   255  		},
   256  		clusterApi.ClusterKind: {
   257  			GV: schema.GroupVersion{
   258  				Group:   bannerApi.GroupVersion.Group,
   259  				Version: bannerApi.GroupVersion.Version,
   260  			},
   261  			CanStartWithDigit: true,
   262  			MinLength:         1,
   263  			MaxLength:         100,
   264  			SpecialCharacters: false,
   265  		},
   266  	}
   267  )
   268  
   269  // CanUseUUID checks if the provided resource can use uuid according to the naming requirements of that resource.
   270  func CanUseUUID(gvk schema.GroupVersionKind) (bool, error) {
   271  	v, k := gvk.ToAPIVersionAndKind()
   272  	if val, exists := resources[k]; exists {
   273  		switch val.GV.String() {
   274  		case v:
   275  			if val.MaxLength >= 36 && val.CanStartWithDigit {
   276  				return true, nil
   277  			}
   278  			return false, nil
   279  		default:
   280  			return false, ErrVersionNotSupported
   281  		}
   282  	}
   283  	return false, ErrGVKNotSupported
   284  }
   285  
   286  // CanUseHash checks if the provided resource can use a hash according to the naming requirements of that resource.
   287  func CanUseHash(gvk schema.GroupVersionKind) (bool, error) {
   288  	v, k := gvk.ToAPIVersionAndKind()
   289  	if val, exists := resources[k]; exists {
   290  		switch val.GV.String() {
   291  		case v:
   292  			if val.MaxLength >= 12 && val.CanStartWithDigit && val.SpecialCharacters {
   293  				return true, nil
   294  			}
   295  			return false, nil
   296  		default:
   297  			return false, ErrVersionNotSupported
   298  		}
   299  	}
   300  	return false, ErrGVKNotSupported
   301  }
   302  
   303  func SatisfiesRequirement(obj client.Object) (bool, error) {
   304  	return satisfiesRequirement(obj)
   305  }
   306  
   307  func satisfiesRequirement(obj client.Object) (bool, error) {
   308  	name := obj.GetName()
   309  	firstCharOfName := []rune(name[0:1])
   310  	gvk := obj.GetObjectKind().GroupVersionKind()
   311  	v, k := gvk.ToAPIVersionAndKind()
   312  	if val, exists := resources[k]; exists {
   313  		switch val.GV.String() {
   314  		case v:
   315  			return len(name) <= val.MaxLength && len(name) >= val.MinLength && (unicode.IsDigit(firstCharOfName[0]) && val.CanStartWithDigit), nil
   316  		default:
   317  			return false, ErrVersionNotSupported
   318  		}
   319  	}
   320  	return false, ErrGVKNotSupported
   321  }
   322  

View as plain text