Repository: ratify-project/ratify (go)

Issue:
Switch `name` field in CRDs to `type`
### What would you like to be added?

Ratify has introduced new `type` field for CLI scenarios of verifier allowing for multiple instances of same verifier with unique config to exist at once. Right now, the `type` field used in CLI maps to the `name` field in CRD and the uniquely identifier `name` in CLI is equivalent to CRDs `metadata.name`. Moving forward, we should switch `name` field to `type` in CRDs. 

This will require:
- introducing `Type` field to all CRD spec of store, verifier, and policy
- support both `Name` and `Type` field until v2.0
- update all docs spec to use `type` and add deprecation warning in spec to `name` field.

### Anything else you would like to add?

_No response_

### Are you willing to submit PRs to contribute to this feature?

- [ ] Yes, I am willing to implement it.

Pull request:
chore:  update CRD and related code to enable `type` field
# Description

## What this PR does / why we need it:

updated CRDs and related code; enabled `type` field

## Which issue(s) this PR fixes *(optional, using `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when the PR gets merged)*:
Fixes #1285

## Type of change

Please delete options that are not relevant.

- [ ] Helm Chart Change (any edit/addition/update that is necessary for changes merged to the `main` branch)
- [ ] This change requires a documentation update

# How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Please also list any relevant details for your test configuration

- [X] CI test
- [X] [AKS test](https://github.com/junczhu/ratify/actions/runs/10787285448)
![image](https://github.com/user-attachments/assets/27a05657-b398-49ea-a3d4-16b04e6dd12d)
# Checklist:

- [ ] Does the affected code have corresponding tests?
- [ ] Are the changes documented, not just with inline documentation, but also with conceptual documentation such as an overview of a new feature, or task-based documentation like a tutorial? Consider if this change should be announced on your project blog.
- [ ] Does this introduce breaking changes that would require an announcement or bumping the major version?
- [ ] Do all new files have appropriate license header?

# Post Merge Requirements
- [ ] MAINTAINERS: manually trigger the "Publish Package" workflow after merging any PR that indicates `Helm Chart Change`


Patch:
diff --git a/api/unversioned/keymanagementprovider_types.go b/api/unversioned/keymanagementprovider_types.go
index 9b3a77d..b347b96 100644
--- a/api/unversioned/keymanagementprovider_types.go
+++ b/api/unversioned/keymanagementprovider_types.go
@@ -32,6 +32,10 @@ type KeyManagementProviderSpec struct {
 	// Name of the key management provider
 	Type string `json:"type,omitempty"`
 
+	// Refresh interval for fetching the certificate/key files from the provider. Only for providers that are refreshable. The value is in the format of "1h30m" where "h" means hour and "m" means minute. Valid time units are units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
+	// +kubebuilder:default=""
+	RefreshInterval string `json:"refreshInterval,omitempty"`
+
 	// Parameters of the key management provider
 	Parameters runtime.RawExtension `json:"parameters,omitempty"`
 }
diff --git a/api/unversioned/namespacedkeymanagementprovider_types.go b/api/unversioned/namespacedkeymanagementprovider_types.go
index 70dcf55..cdccfe7 100644
--- a/api/unversioned/namespacedkeymanagementprovider_types.go
+++ b/api/unversioned/namespacedkeymanagementprovider_types.go
@@ -33,6 +33,10 @@ type NamespacedKeyManagementProviderSpec struct {
 	// Name of the key management provider
 	Type string `json:"type,omitempty"`
 
+	// Refresh interval for fetching the certificate/key files from the provider. Only for providers that are refreshable. The value is in the format of "1h30m" where "h" means hour and "m" means minute. Valid time units are units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
+	// +kubebuilder:default=""
+	RefreshInterval string `json:"refreshInterval,omitempty"`
+
 	// +kubebuilder:pruning:PreserveUnknownFields
 	// Parameters of the key management provider
 	Parameters runtime.RawExtension `json:"parameters,omitempty"`
diff --git a/api/unversioned/namespacedverifier_types.go b/api/unversioned/namespacedverifier_types.go
index 7e196a2..994e9d1 100644
--- a/api/unversioned/namespacedverifier_types.go
+++ b/api/unversioned/namespacedverifier_types.go
@@ -27,19 +27,22 @@ type NamespacedVerifierSpec struct {
 	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
 	// Important: Run "make" to regenerate code after modifying this file
 
-	// Name of the verifier
+	// Name of the verifier. Deprecated
 	Name string `json:"name"`
 
+	// Type of the verifier. Optional
+	Type string `json:"type,omitempty"`
+
 	// Version of the verifier plugin. Optional
 	Version string `json:"version,omitempty"`
 
 	// The type of artifact this verifier handles
 	ArtifactTypes string `json:"artifactTypes"`
 
-	// # Optional. URL/file path
+	// URL/file path. Optional
 	Address string `json:"address,omitempty"`
 
-	// OCI Artifact source to download the plugin from, optional
+	// OCI Artifact source to download the plugin from. Optional
 	Source *PluginSource `json:"source,omitempty"`
 
 	// Parameters for this verifier
diff --git a/api/unversioned/verifier_types.go b/api/unversioned/verifier_types.go
index 74b8bdf..fbdd69b 100644
--- a/api/unversioned/verifier_types.go
+++ b/api/unversioned/verifier_types.go
@@ -26,19 +26,22 @@ import (
 type VerifierSpec struct {
 	// Important: Run "make" to regenerate code after modifying this file
 
-	// Name of the verifier
+	// Name of the verifier. Deprecated
 	Name string `json:"name,omitempty"`
 
+	// Type of the verifier. Optional
+	Type string `json:"type,omitempty"`
+
 	// Version of the verifier plugin. Optional
 	Version string `json:"version,omitempty"`
 
 	// The type of artifact this verifier handles
 	ArtifactTypes string `json:"artifactTypes,omitempty"`
 
-	// # Optional. URL/file path
+	// URL/file path. Optional
 	Address string `json:"address,omitempty"`
 
-	// OCI Artifact source to download the plugin from, optional
+	// OCI Artifact source to download the plugin from. Optional
 	Source *PluginSource `json:"source,omitempty"`
 
 	// Parameters for this verifier
diff --git a/api/v1alpha1/zz_generated.conversion.go b/api/v1alpha1/zz_generated.conversion.go
index 467a815..9be9f81 100644
--- a/api/v1alpha1/zz_generated.conversion.go
+++ b/api/v1alpha1/zz_generated.conversion.go
@@ -642,6 +642,7 @@ func Convert_v1alpha1_VerifierSpec_To_unversioned_VerifierSpec(in *VerifierSpec,
 
 func autoConvert_unversioned_VerifierSpec_To_v1alpha1_VerifierSpec(in *unversioned.VerifierSpec, out *VerifierSpec, s conversion.Scope) error {
 	out.Name = in.Name
+	// WARNING: in.Type requires manual conversion: does not exist in peer-type
 	// WARNING: in.Version requires manual conversion: does not exist in peer-type
 	out.ArtifactTypes = in.ArtifactTypes
 	out.Address = in.Address
diff --git a/api/v1beta1/namespacedverifier_types.go b/api/v1beta1/namespacedverifier_types.go
index 31e1c8e..17809a4 100644
--- a/api/v1beta1/namespacedverifier_types.go
+++ b/api/v1beta1/namespacedverifier_types.go
@@ -29,19 +29,22 @@ type NamespacedVerifierSpec struct {
 	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
 	// Important: Run "make" to regenerate code after modifying this file
 
-	// Name of the verifier
+	// Name of the verifier. Deprecated
 	Name string `json:"name"`
 
+	// Type of the verifier. Optional
+	Type string `json:"type,omitempty"`
+
 	// Version of the verifier plugin. Optional
 	Version string `json:"version,omitempty"`
 
 	// The type of artifact this verifier handles
 	ArtifactTypes string `json:"artifactTypes"`
 
-	// # Optional. URL/file path
+	// URL/file path. Optional
 	Address string `json:"address,omitempty"`
 
-	// OCI Artifact source to download the plugin from, optional
+	// OCI Artifact source to download the plugin from. Optional
 	Source *PluginSource `json:"source,omitempty"`
 
 	// +kubebuilder:pruning:PreserveUnknownFields
diff --git a/api/v1beta1/verifier_types.go b/api/v1beta1/verifier_types.go
index 5d4bf09..b273a48 100644
--- a/api/v1beta1/verifier_types.go
+++ b/api/v1beta1/verifier_types.go
@@ -25,19 +25,22 @@ import (
 type VerifierSpec struct {
 	// Important: Run "make install-crds" to regenerate code after modifying this file
 
-	// Name of the verifier
+	// Name of the verifier. Deprecated
 	Name string `json:"name"`
 
+	// Type of the verifier. Optional
+	Type string `json:"type,omitempty"`
+
 	// Version of the verifier plugin. Optional
 	Version string `json:"version,omitempty"`
 
 	// The type of artifact this verifier handles
 	ArtifactTypes string `json:"artifactTypes"`
 
-	// # Optional. URL/file path
+	// URL/file path. Optional
 	Address string `json:"address,omitempty"`
 
-	// OCI Artifact source to download the plugin from, optional
+	// OCI Artifact source to download the plugin from. Optional
 	Source *PluginSource `json:"source,omitempty"`
 
 	// +kubebuilder:pruning:PreserveUnknownFields
diff --git a/api/v1beta1/zz_generated.conversion.go b/api/v1beta1/zz_generated.conversion.go
index fafb65b..0b69afa 100644
--- a/api/v1beta1/zz_generated.conversion.go
+++ b/api/v1beta1/zz_generated.conversion.go
@@ -569,6 +569,7 @@ func Convert_unversioned_KeyManagementProviderList_To_v1beta1_KeyManagementProvi
 
 func autoConvert_v1beta1_KeyManagementProviderSpec_To_unversioned_KeyManagementProviderSpec(in *KeyManagementProviderSpec, out *unversioned.KeyManagementProviderSpec, s conversion.Scope) error {
 	out.Type = in.Type
+	out.RefreshInterval = in.RefreshInterval
 	out.Parameters = in.Parameters
 	return nil
 }
@@ -580,6 +581,7 @@ func Convert_v1beta1_KeyManagementProviderSpec_To_unversioned_KeyManagementProvi
 
 func autoConvert_unversioned_KeyManagementProviderSpec_To_v1beta1_KeyManagementProviderSpec(in *unversioned.KeyManagementProviderSpec, out *KeyManagementProviderSpec, s conversion.Scope) error {
 	out.Type = in.Type
+	out.RefreshInterval = in.RefreshInterval
 	out.Parameters = in.Parameters
 	return nil
 }
@@ -673,6 +675,7 @@ func Convert_unversioned_NamespacedKeyManagementProviderList_To_v1beta1_Namespac
 
 func autoConvert_v1beta1_NamespacedKeyManagementProviderSpec_To_unversioned_NamespacedKeyManagementProviderSpec(in *NamespacedKeyManagementProviderSpec, out *unversioned.NamespacedKeyManagementProviderSpec, s conversion.Scope) error {
 	out.Type = in.Type
+	out.RefreshInterval = in.RefreshInterval
 	out.Parameters = in.Parameters
 	return nil
 }
@@ -684,6 +687,7 @@ func Convert_v1beta1_NamespacedKeyManagementProviderSpec_To_unversioned_Namespac
 
 func autoConvert_unversioned_NamespacedKeyManagementProviderSpec_To_v1beta1_NamespacedKeyManagementProviderSpec(in *unversioned.NamespacedKeyManagementProviderSpec, out *NamespacedKeyManagementProviderSpec, s conversion.Scope) error {
 	out.Type = in.Type
+	out.RefreshInterval = in.RefreshInterval
 	out.Parameters = in.Parameters
 	return nil
 }
@@ -983,6 +987,7 @@ func Convert_unversioned_NamespacedVerifierList_To_v1beta1_NamespacedVerifierLis
 
 func autoConvert_v1beta1_NamespacedVerifierSpec_To_unversioned_NamespacedVerifierSpec(in *NamespacedVerifierSpec, out *unversioned.NamespacedVerifierSpec, s conversion.Scope) error {
 	out.Name = in.Name
+	out.Type = in.Type
 	out.Version = in.Version
 	out.ArtifactTypes = in.ArtifactTypes
 	out.Address = in.Address
@@ -998,6 +1003,7 @@ func Convert_v1beta1_NamespacedVerifierSpec_To_unversioned_NamespacedVerifierSpe
 
 func autoConvert_unversioned_NamespacedVerifierSpec_To_v1beta1_NamespacedVerifierSpec(in *unversioned.NamespacedVerifierSpec, out *NamespacedVerifierSpec, s conversion.Scope) error {
 	out.Name = in.Name
+	out.Type = in.Type
 	out.Version = in.Version
 	out.ArtifactTypes = in.ArtifactTypes
 	out.Address = in.Address
@@ -1319,6 +1325,7 @@ func Convert_unversioned_VerifierList_To_v1beta1_VerifierList(in *unversioned.Ve
 
 func autoConvert_v1beta1_VerifierSpec_To_unversioned_VerifierSpec(in *VerifierSpec, out *unversioned.VerifierSpec, s conversion.Scope) error {
 	out.Name = in.Name
+	out.Type = in.Type
 	out.Version = in.Version
 	out.ArtifactTypes = in.ArtifactTypes
 	out.Address = in.Address
@@ -1334,6 +1341,7 @@ func Convert_v1beta1_VerifierSpec_To_unversioned_VerifierSpec(in *VerifierSpec,
 
 func autoConvert_unversioned_VerifierSpec_To_v1beta1_VerifierSpec(in *unversioned.VerifierSpec, out *VerifierSpec, s conversion.Scope) error {
 	out.Name = in.Name
+	out.Type = in.Type
 	out.Version = in.Version
 	out.ArtifactTypes = in.ArtifactTypes
 	out.Address = in.Address
diff --git a/config/crd/bases/config.ratify.deislabs.io_namespacedverifiers.yaml b/config/crd/bases/config.ratify.deislabs.io_namespacedverifiers.yaml
index 784bcb5..b61b077 100644
--- a/config/crd/bases/config.ratify.deislabs.io_namespacedverifiers.yaml
+++ b/config/crd/bases/config.ratify.deislabs.io_namespacedverifiers.yaml
@@ -48,20 +48,20 @@ spec:
             description: NamespacedVerifierSpec defines the desired state of NamespacedVerifier
             properties:
               address:
-                description: '# Optional. URL/file path'
+                description: URL/file path. Optional
                 type: string
               artifactTypes:
                 description: The type of artifact this verifier handles
                 type: string
               name:
-                description: Name of the verifier
+                description: Name of the verifier. Deprecated
                 type: string
               parameters:
                 description: Parameters for this verifier
                 type: object
                 x-kubernetes-preserve-unknown-fields: true
               source:
-                description: OCI Artifact source to download the plugin from, optional
+                description: OCI Artifact source to download the plugin from. Optional
                 properties:
                   artifact:
                     description: OCI Artifact source to download the plugin from
@@ -72,6 +72,9 @@ spec:
                     type: object
                     x-kubernetes-preserve-unknown-fields: true
                 type: object
+              type:
+                description: Type of the verifier. Optional
+                type: string
               version:
                 description: Version of the verifier plugin. Optional
                 type: string
diff --git a/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml b/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml
index a23d981..8d08f76 100644
--- a/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml
+++ b/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml
@@ -107,20 +107,20 @@ spec:
             description: VerifierSpec defines the desired state of Verifier
             properties:
               address:
-                description: '# Optional. URL/file path'
+                description: URL/file path. Optional
                 type: string
               artifactTypes:
                 description: The type of artifact this verifier handles
                 type: string
               name:
-                description: Name of the verifier
+                description: Name of the verifier. Deprecated
                 type: string
               parameters:
                 description: Parameters for this verifier
                 type: object
                 x-kubernetes-preserve-unknown-fields: true
               source:
-                description: OCI Artifact source to download the plugin from, optional
+                description: OCI Artifact source to download the plugin from. Optional
                 properties:
                   artifact:
                     description: OCI Artifact source to download the plugin from
@@ -131,6 +131,9 @@ spec:
                     type: object
                     x-kubernetes-preserve-unknown-fields: true
                 type: object
+              type:
+                description: Type of the verifier. Optional
+                type: string
               version:
                 description: Version of the verifier plugin. Optional
                 type: string
diff --git a/pkg/controllers/clusterresource/verifier_controller.go b/pkg/controllers/clusterresource/verifier_controller.go
index c8c8cd8..f752fa1 100644
--- a/pkg/controllers/clusterresource/verifier_controller.go
+++ b/pkg/controllers/clusterresource/verifier_controller.go
@@ -85,7 +85,7 @@ func (r *VerifierReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
 
 // creates a verifier reference from CR spec and add verifier to map
 func verifierAddOrReplace(spec configv1beta1.VerifierSpec, objectName string) error {
-	verifierConfig, err := cutils.SpecToVerifierConfig(spec.Parameters.Raw, objectName, spec.Name, spec.ArtifactTypes, spec.Source)
+	verifierConfig, err := cutils.SpecToVerifierConfig(spec.Parameters.Raw, objectName, cutils.GetVerifierType(spec), spec.ArtifactTypes, spec.Source)
 	if err != nil {
 		errMsg := fmt.Sprintf("Unable to apply cluster-wide resource %s of Verifier kind", objectName)
 		logrus.Error(err, errMsg)
diff --git a/pkg/controllers/namespaceresource/verifier_controller.go b/pkg/controllers/namespaceresource/verifier_controller.go
index 4b19b61..a2926ef 100644
--- a/pkg/controllers/namespaceresource/verifier_controller.go
+++ b/pkg/controllers/namespaceresource/verifier_controller.go
@@ -84,7 +84,7 @@ func (r *VerifierReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
 
 // creates a verifier reference from CRD spec and add store to map
 func verifierAddOrReplace(spec configv1beta1.NamespacedVerifierSpec, objectName string, namespace string) error {
-	verifierConfig, err := cutils.SpecToVerifierConfig(spec.Parameters.Raw, objectName, spec.Name, spec.ArtifactTypes, spec.Source)
+	verifierConfig, err := cutils.SpecToVerifierConfig(spec.Parameters.Raw, objectName, cutils.GetVerifierType(spec), spec.ArtifactTypes, spec.Source)
 	if err != nil {
 		errMsg := fmt.Sprintf("Unable to apply the resource %s of NamespacedVerifier kind in the namespace %s", objectName, namespace)
 		logrus.Error(err, errMsg)
diff --git a/pkg/controllers/utils/verifier.go b/pkg/controllers/utils/verifier.go
index e65a059..43a9e85 100644
--- a/pkg/controllers/utils/verifier.go
+++ b/pkg/controllers/utils/verifier.go
@@ -72,3 +72,22 @@ func SpecToVerifierConfig(raw []byte, verifierName, verifierType, artifactTypes
 
 	return verifierConfig, nil
 }
+
+// GetVerifierType returns verifier type and is backward compatible with the deprecated name field
+func GetVerifierType(verifierSpec interface{}) string {
+	switch spec := verifierSpec.(type) {
+	case configv1beta1.VerifierSpec:
+		if spec.Type == "" {
+			return spec.Name
+		}
+		return spec.Type
+	case configv1beta1.NamespacedVerifierSpec:
+		if spec.Type == "" {
+			return spec.Name
+		}
+		return spec.Type
+	default:
+		logrus.Error("unable to assert verifierSpec type", spec)
+	}
+	return ""
+}


Test patch:
diff --git a/pkg/controllers/utils/verifier_test.go b/pkg/controllers/utils/verifier_test.go
index 8ccf9a6..349653a 100644
--- a/pkg/controllers/utils/verifier_test.go
+++ b/pkg/controllers/utils/verifier_test.go
@@ -119,3 +119,46 @@ func TestSpecToVerifierConfig(t *testing.T) {
 func resetVerifierMap() {
 	controllers.NamespacedVerifiers = verifiers.NewActiveVerifiers()
 }
+
+func TestGetType(t *testing.T) {
+	tests := []struct {
+		name     string
+		input    interface{}
+		expected string
+	}{
+		{
+			name:     "cluster verifier spec with name",
+			input:    configv1beta1.VerifierSpec{Name: "clusterV"},
+			expected: "clusterV",
+		},
+		{
+			name:     "cluster verifier spec with type",
+			input:    configv1beta1.VerifierSpec{Type: "clusterV"},
+			expected: "clusterV",
+		},
+		{
+			name:     "namespaced verifier spec with name",
+			input:    configv1beta1.NamespacedVerifierSpec{Name: "namespacedV"},
+			expected: "namespacedV",
+		},
+		{
+			name:     "namespaced verifier spec with type",
+			input:    configv1beta1.NamespacedVerifierSpec{Type: "namespacedV"},
+			expected: "namespacedV",
+		},
+		{
+			name:     "verifier spec with no name or type",
+			input:    "",
+			expected: "",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			output := GetVerifierType(tt.input)
+			if tt.expected != output {
+				t.Fatalf("GetType() expected %v, actual %v", tt.expected, output)
+			}
+		})
+	}
+}