From 6f7b4ca9bdcf4409e5ca849246a410c6fd7cb82b Mon Sep 17 00:00:00 2001 From: michaelhtm <98621731+michaelhtm@users.noreply.github.com> Date: Mon, 11 Nov 2024 11:07:17 -0800 Subject: [PATCH] Change resource entrypoint from `name` to `id` This gives the perception that the entrypoint should be unique --- api/v1alpha1/resource_group.go | 2 +- config/crd/bases/kro.run_resourcegroups.yaml | 6 +- .../ec2-controller/ec2-controller.yaml | 12 +-- .../ec2-controller/ec2-crd-group.yaml | 34 +++---- .../eks-controller/eks-controller.yaml | 14 +-- .../eks-controller/eks-crd-group.yaml | 14 +-- .../iam-controller/iam-controller.yaml | 10 +-- .../iam-controller/iam-crd-group.yaml | 12 +-- examples/ack-eks-cluster/eks-cluster.yaml | 24 ++--- examples/ack-eks-cluster/eks-reused.yaml | 4 +- examples/application/rg.yaml | 8 +- examples/cachecluster/cachecluster.yaml | 8 +- .../cachecluster/simple-cachecluster.yaml | 2 +- examples/cel-functions/rg.yaml | 4 +- examples/core-dns/core-dns.yaml | 12 +-- .../clusters/rg/eks-w-vpc.yaml | 4 +- .../eks-cluster-mgmt/clusters/rg/eks.yaml | 16 ++-- .../eks-cluster-mgmt/clusters/rg/vpc.yaml | 26 +++--- examples/networkstack/network-stack.yaml | 10 +-- .../serverless-microservice/microservice.yaml | 36 ++++---- internal/cel/ast/inspector.go | 18 ++-- internal/cel/ast/inspector_test.go | 88 +++++++++---------- internal/cel/environment.go | 12 +-- internal/graph/builder.go | 42 ++++----- internal/graph/builder_test.go | 4 +- internal/graph/validation.go | 32 +++---- internal/graph/validation_test.go | 26 +++--- internal/runtime/runtime.go | 48 +++++----- internal/runtime/runtime_test.go | 2 +- internal/testutil/generator/resourcegroup.go | 4 +- test/integration/suites/core/recover_test.go | 6 +- .../suites/core/validation_test.go | 8 +- .../docs/docs/concepts/00-resource-groups.md | 2 +- .../02-deploy-a-resource-group.md | 6 +- website/docs/examples/ack-eks-cluster.md | 24 ++--- website/docs/examples/ack-networking-stack.md | 10 +-- .../docs/examples/ack-valkey-cachecluster.md | 8 +- website/docs/examples/deploying-controller.md | 14 +-- website/docs/examples/deploying-coredns.md | 12 +-- website/docs/examples/pod-rds-dbinstance.md | 4 +- website/docs/examples/web-app-ingress.md | 6 +- website/docs/examples/web-app.md | 4 +- 42 files changed, 319 insertions(+), 319 deletions(-) diff --git a/api/v1alpha1/resource_group.go b/api/v1alpha1/resource_group.go index fff41f8d..2a320ed3 100644 --- a/api/v1alpha1/resource_group.go +++ b/api/v1alpha1/resource_group.go @@ -81,7 +81,7 @@ type Validation struct { type Resource struct { // +kubebuilder:validation:Required - Name string `json:"name,omitempty"` + ID string `json:"id,omitempty"` // +kubebuilder:validation:Required Template runtime.RawExtension `json:"template,omitempty"` // +kubebuilder:validation:Optional diff --git a/config/crd/bases/kro.run_resourcegroups.yaml b/config/crd/bases/kro.run_resourcegroups.yaml index 0cf83251..18d7f8d7 100644 --- a/config/crd/bases/kro.run_resourcegroups.yaml +++ b/config/crd/bases/kro.run_resourcegroups.yaml @@ -71,12 +71,12 @@ spec: description: The resources that are part of the resourcegroup. items: properties: + id: + type: string includeWhen: items: type: string type: array - name: - type: string readyWhen: items: type: string @@ -85,7 +85,7 @@ spec: type: object x-kubernetes-preserve-unknown-fields: true required: - - name + - id - template type: object type: array diff --git a/examples/ack-controller/ec2-controller/ec2-controller.yaml b/examples/ack-controller/ec2-controller/ec2-controller.yaml index ceeedd7a..933aa305 100644 --- a/examples/ack-controller/ec2-controller/ec2-controller.yaml +++ b/examples/ack-controller/ec2-controller/ec2-controller.yaml @@ -37,7 +37,7 @@ spec: serviceAccount: name: string | default=ec2-controller-sa resources: - - name: ec2CRDGroup + - id: ec2CRDGroup template: apiVersion: kro.run/v1alpha1 kind: EC2CRDGroup @@ -45,7 +45,7 @@ spec: name: ${schema.spec.name}-crd-group spec: name: ${schema.spec.name}-crd-group - - name: ec2ControllerIamRole + - id: ec2ControllerIamRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -70,7 +70,7 @@ spec: } }] } - - name: serviceAccount + - id: serviceAccount template: apiVersion: v1 kind: ServiceAccount @@ -79,7 +79,7 @@ spec: namespace: ${schema.spec.namespace} annotations: eks.amazonaws.com/role-arn: ${ec2ControllerIamRole.status.ackResourceMetadata.arn} - - name: deployment + - id: deployment template: apiVersion: apps/v1 kind: Deployment @@ -138,7 +138,7 @@ spec: value: ${schema.spec.values.log.level} ports: - containerPort: 80 - - name: clusterRoleBinding + - id: clusterRoleBinding template: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding @@ -152,7 +152,7 @@ spec: - kind: ServiceAccount name: ${serviceAccount.metadata.name} namespace: ${serviceAccount.metadata.namespace} - - name: clusterRole + - id: clusterRole template: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole diff --git a/examples/ack-controller/ec2-controller/ec2-crd-group.yaml b/examples/ack-controller/ec2-controller/ec2-crd-group.yaml index 2d04b167..46393993 100644 --- a/examples/ack-controller/ec2-controller/ec2-crd-group.yaml +++ b/examples/ack-controller/ec2-controller/ec2-crd-group.yaml @@ -9,7 +9,7 @@ spec: spec: name: string | default=ec2CRDGroup resources: - - name: dhcpOptionsCRD + - id: dhcpOptionsCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -192,7 +192,7 @@ spec: storage: true subresources: status: {} - - name: elasticIPAddressCRD + - id: elasticIPAddressCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -378,7 +378,7 @@ spec: storage: true subresources: status: {} - - name: flowLogsCRD + - id: flowLogsCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -645,7 +645,7 @@ spec: storage: true subresources: status: {} - - name: instanceCRD + - id: instanceCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -1525,7 +1525,7 @@ spec: storage: true subresources: status: {} - - name: internetGatewayCRD + - id: internetGatewayCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -1727,7 +1727,7 @@ spec: storage: true subresources: status: {} - - name: natGatewayCRD + - id: natGatewayCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -2029,7 +2029,7 @@ spec: storage: true subresources: status: {} - - name: networkAclCRD + - id: networkAclCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -2265,7 +2265,7 @@ spec: storage: true subresources: status: {} - - name: routeTableCRD + - id: routeTableCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -2611,7 +2611,7 @@ spec: storage: true subresources: status: {} - - name: securityGroupCRD + - id: securityGroupCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -3039,7 +3039,7 @@ spec: storage: true subresources: status: {} - - name: subnetCRD + - id: subnetCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -3351,7 +3351,7 @@ spec: storage: true subresources: status: {} - - name: transitGatewayCRD + - id: transitGatewayCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -3533,7 +3533,7 @@ spec: storage: true subresources: status: {} - - name: vpcEndpointCRD + - id: vpcEndpointCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -3876,7 +3876,7 @@ spec: storage: true subresources: status: {} - - name: vpcEndpointServiceConfigurationCRD + - id: vpcEndpointServiceConfigurationCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -4103,7 +4103,7 @@ spec: storage: true subresources: status: {} - - name: vpcPeeringConnectionCRD + - id: vpcPeeringConnectionCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -4431,7 +4431,7 @@ spec: storage: true subresources: status: {} - - name: vpcCRD + - id: vpcCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -4723,7 +4723,7 @@ spec: storage: true subresources: status: {} - - name: adoptedResourceCRD + - id: adoptedResourceCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -4978,7 +4978,7 @@ spec: storage: true subresources: status: {} - - name: fieldExportCRD + - id: fieldExportCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition diff --git a/examples/ack-controller/eks-controller/eks-controller.yaml b/examples/ack-controller/eks-controller/eks-controller.yaml index 61ac97b9..8bae809c 100644 --- a/examples/ack-controller/eks-controller/eks-controller.yaml +++ b/examples/ack-controller/eks-controller/eks-controller.yaml @@ -40,7 +40,7 @@ spec: serviceAccount: name: string | default=eks-controller-sa resources: - - name: eksCRDGroup + - id: eksCRDGroup template: apiVersion: kro.run/v1alpha1 kind: EKSCRDGroup @@ -48,7 +48,7 @@ spec: name: ${schema.spec.name}-crd-group spec: name: ${schema.spec.name}-crd-group - - name: eksControllerIamPolicy + - id: eksControllerIamPolicy template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Policy @@ -75,7 +75,7 @@ spec: } ] } - - name: eksControllerIamRole + - id: eksControllerIamRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -100,7 +100,7 @@ spec: } }] } - - name: serviceAccount + - id: serviceAccount template: apiVersion: v1 kind: ServiceAccount @@ -109,7 +109,7 @@ spec: namespace: ${schema.spec.namespace} annotations: eks.amazonaws.com/role-arn : ${eksControllerIamRole.status.ackResourceMetadata.arn} - - name: deployment + - id: deployment template: apiVersion: apps/v1 kind: Deployment @@ -168,7 +168,7 @@ spec: value: ${schema.spec.values.log.level} ports: - containerPort: 80 - - name: clusterRoleBinding + - id: clusterRoleBinding template: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding @@ -182,7 +182,7 @@ spec: - kind: ServiceAccount name: ${serviceAccount.metadata.name} namespace: ${serviceAccount.metadata.namespace} - - name: clusterRole + - id: clusterRole template: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole diff --git a/examples/ack-controller/eks-controller/eks-crd-group.yaml b/examples/ack-controller/eks-controller/eks-crd-group.yaml index 5c6ec928..2f44162e 100644 --- a/examples/ack-controller/eks-controller/eks-crd-group.yaml +++ b/examples/ack-controller/eks-controller/eks-crd-group.yaml @@ -9,7 +9,7 @@ spec: spec: name: string | default=eksCRDGroup resources: - - name: accessEntryCRD + - id: accessEntryCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -273,7 +273,7 @@ spec: storage: true subresources: status: {} - - name: addonsCRD + - id: addonsCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -592,7 +592,7 @@ spec: storage: true subresources: status: {} - - name: clusterCRD + - id: clusterCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -1028,7 +1028,7 @@ spec: storage: true subresources: status: {} - - name: fargateProfilesCRD + - id: fargateProfilesCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -1279,7 +1279,7 @@ spec: storage: true subresources: status: {} - - name: identityProviderCRD + - id: identityProviderCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -1456,7 +1456,7 @@ spec: storage: true subresources: status: {} - - name: nodeGroupsCRD + - id: nodeGroupsCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -1929,7 +1929,7 @@ spec: storage: true subresources: status: {} - - name: podIdentityAssociationCRD + - id: podIdentityAssociationCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition diff --git a/examples/ack-controller/iam-controller/iam-controller.yaml b/examples/ack-controller/iam-controller/iam-controller.yaml index 3337102b..24bb01dc 100644 --- a/examples/ack-controller/iam-controller/iam-controller.yaml +++ b/examples/ack-controller/iam-controller/iam-controller.yaml @@ -33,7 +33,7 @@ spec: name: string | default=ack-iam-controller-sa roleArn: string | required=true resources: - - name: iamCRDGroup + - id: iamCRDGroup template: apiVersion: kro.run/v1alpha1 kind: IAMCRDGroup @@ -41,7 +41,7 @@ spec: name: ${schema.spec.name}-crd-group spec: name: ${schema.spec.name}-crd-group - - name: serviceAccount + - id: serviceAccount template: apiVersion: v1 kind: ServiceAccount @@ -50,7 +50,7 @@ spec: namespace: ${schema.spec.namespace} annotations: eks.amazonaws.com/role-arn: ${schema.spec.values.serviceAccount.roleArn} - - name: deployment + - id: deployment template: apiVersion: apps/v1 kind: Deployment @@ -109,7 +109,7 @@ spec: value: ${schema.spec.values.log.level} ports: - containerPort: 80 - - name: clusterRoleBinding + - id: clusterRoleBinding template: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding @@ -123,7 +123,7 @@ spec: - kind: ServiceAccount name: ${serviceAccount.metadata.name} namespace: ${serviceAccount.metadata.namespace} - - name: clusterRole + - id: clusterRole template: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole diff --git a/examples/ack-controller/iam-controller/iam-crd-group.yaml b/examples/ack-controller/iam-controller/iam-crd-group.yaml index f38ecbc1..1c46219f 100644 --- a/examples/ack-controller/iam-controller/iam-crd-group.yaml +++ b/examples/ack-controller/iam-controller/iam-crd-group.yaml @@ -9,7 +9,7 @@ spec: spec: name: string | default=iamCRDGroup resources: - - name: iamGroupCRD + - id: iamGroupCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -210,7 +210,7 @@ spec: storage: true subresources: status: {} - - name: iamInstanceProfileCRD + - id: iamInstanceProfileCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -427,7 +427,7 @@ spec: storage: true subresources: status: {} - - name: iamOpenIDConnectProviderCRD + - id: iamOpenIDConnectProviderCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -631,7 +631,7 @@ spec: storage: true subresources: status: {} - - name: iamPolicyCRD + - id: iamPolicyCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -920,7 +920,7 @@ spec: storage: true subresources: status: {} - - name: iamRoleCRD + - id: iamRoleCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -1241,7 +1241,7 @@ spec: storage: true subresources: status: {} - - name: iamUserCRD + - id: iamUserCRD template: apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition diff --git a/examples/ack-eks-cluster/eks-cluster.yaml b/examples/ack-eks-cluster/eks-cluster.yaml index f9ce8abf..8cbdd2cf 100644 --- a/examples/ack-eks-cluster/eks-cluster.yaml +++ b/examples/ack-eks-cluster/eks-cluster.yaml @@ -18,7 +18,7 @@ spec: clusterARN: ${cluster.status.ackResourceMetadata.arn} # resources resources: - - name: clusterVPC + - id: clusterVPC readyWhen: - ${clusterVPC.status.state == "available"} template: @@ -31,14 +31,14 @@ spec: - 192.168.0.0/16 enableDNSSupport: true enableDNSHostnames: true - - name: clusterElasticIPAddress + - id: clusterElasticIPAddress template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: ElasticIPAddress metadata: name: kro-cluster-eip spec: {} - - name: clusterInternetGateway + - id: clusterInternetGateway template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: InternetGateway @@ -46,7 +46,7 @@ spec: name: kro-cluster-igw spec: vpc: ${clusterVPC.status.vpcID} - - name: clusterRouteTable + - id: clusterRouteTable template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: RouteTable @@ -57,7 +57,7 @@ spec: routes: - destinationCIDRBlock: 0.0.0.0/0 gatewayID: ${clusterInternetGateway.status.internetGatewayID} - - name: clusterSubnetA + - id: clusterSubnetA readyWhen: - ${clusterSubnetA.status.state == "available"} template: @@ -72,7 +72,7 @@ spec: routeTables: - ${clusterRouteTable.status.routeTableID} mapPublicIPOnLaunch: true - - name: clusterSubnetB + - id: clusterSubnetB template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Subnet @@ -85,7 +85,7 @@ spec: routeTables: - ${clusterRouteTable.status.routeTableID} mapPublicIPOnLaunch: true - - name: clusterNATGateway + - id: clusterNATGateway template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: NATGateway @@ -94,7 +94,7 @@ spec: spec: subnetID: ${clusterSubnetB.status.subnetID} allocationID: ${clusterElasticIPAddress.status.allocationID} - - name: clusterRole + - id: clusterRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -118,7 +118,7 @@ spec: } ] } - - name: clusterNodeRole + - id: clusterNodeRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -144,7 +144,7 @@ spec: } ] } - - name: clusterAdminRole + - id: clusterAdminRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -172,7 +172,7 @@ spec: } ] } - - name: cluster + - id: cluster readyWhen: - ${cluster.status.status == "ACTIVE"} template: @@ -192,7 +192,7 @@ spec: subnetIDs: - ${clusterSubnetA.status.subnetID} - ${clusterSubnetB.status.subnetID} - - name: clusterNodeGroup + - id: clusterNodeGroup template: apiVersion: eks.services.k8s.aws/v1alpha1 kind: Nodegroup diff --git a/examples/ack-eks-cluster/eks-reused.yaml b/examples/ack-eks-cluster/eks-reused.yaml index 407f9387..0bec689b 100644 --- a/examples/ack-eks-cluster/eks-reused.yaml +++ b/examples/ack-eks-cluster/eks-reused.yaml @@ -15,7 +15,7 @@ spec: clusterARN2: ${cluster2.status.clusterARN} # resources resources: - - name: cluster1 + - id: cluster1 template: apiVersion: eks.services.k8s.aws/v1alpha1 kind: EKSCluster @@ -24,7 +24,7 @@ spec: spec: name: cluster1-${schema.spec.name} version: ${spc.version} - - name: cluster2 + - id: cluster2 template: apiVersion: eks.services.k8s.aws/v1alpha1 kind: EKSCluster diff --git a/examples/application/rg.yaml b/examples/application/rg.yaml index 51977dbe..ca2a7d96 100644 --- a/examples/application/rg.yaml +++ b/examples/application/rg.yaml @@ -23,7 +23,7 @@ spec: availableReplicas: ${deployment.status.availableReplicas} resources: - - name: deployment + - id: deployment readyWhen: - ${deployment.spec.replicas == deployment.status.availableReplicas} template: @@ -65,7 +65,7 @@ spec: value: ${schema.spec.s3bucket} restartPolicy: Always - - name: serviceaccount + - id: serviceaccount template: apiVersion: v1 kind: ServiceAccount @@ -73,7 +73,7 @@ spec: name: ${schema.spec.name} namespace: ${schema.spec.namespace} - - name: service + - id: service includeWhen: - ${schema.spec.service.enabled} template: @@ -91,7 +91,7 @@ spec: port: 80 targetPort: ${schema.spec.port} - - name: ingress + - id: ingress includeWhen: - ${schema.spec.ingress.enabled} template: diff --git a/examples/cachecluster/cachecluster.yaml b/examples/cachecluster/cachecluster.yaml index 45fd74f3..50de49e6 100644 --- a/examples/cachecluster/cachecluster.yaml +++ b/examples/cachecluster/cachecluster.yaml @@ -13,7 +13,7 @@ spec: subnets: ${cacheSubnetGroup.status.subnets} clusterARN: ${valkey.status.ackResourceMetadata.arn} resources: - - name: networkingStack + - id: networkingStack template: apiVersion: kro.run/v1alpha1 kind: NetworkingStack @@ -21,7 +21,7 @@ spec: name: ${schema.spec.name}-networking-stack spec: name: ${schema.spec.name}-networking-stack - - name: cacheSubnetGroup + - id: cacheSubnetGroup template: apiVersion: elasticache.services.k8s.aws/v1alpha1 kind: CacheSubnetGroup @@ -34,7 +34,7 @@ spec: - ${networkingStack.status.networkingInfo.subnetAZA} - ${networkingStack.status.networkingInfo.subnetAZB} - ${networkingStack.status.networkingInfo.subnetAZC} - - name: sg + - id: sg template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: SecurityGroup @@ -50,7 +50,7 @@ spec: ipProtocol: tcp ipRanges: - cidrIP: 0.0.0.0/0 - - name: valkey + - id: valkey template: apiVersion: elasticache.services.k8s.aws/v1alpha1 kind: CacheCluster diff --git a/examples/cachecluster/simple-cachecluster.yaml b/examples/cachecluster/simple-cachecluster.yaml index 1a55a872..ac3bca96 100644 --- a/examples/cachecluster/simple-cachecluster.yaml +++ b/examples/cachecluster/simple-cachecluster.yaml @@ -13,7 +13,7 @@ spec: csgARN: ${cacheSubnetGroup.status.ackResourceMetadata.arn} subnets: ${cacheSubnetGroup.status.subnets} resources: - - name: cacheSubnetGroup + - id: cacheSubnetGroup template: apiVersion: elasticache.services.k8s.aws/v1alpha1 kind: CacheSubnetGroup diff --git a/examples/cel-functions/rg.yaml b/examples/cel-functions/rg.yaml index 15ac848e..b9c3d763 100644 --- a/examples/cel-functions/rg.yaml +++ b/examples/cel-functions/rg.yaml @@ -13,7 +13,7 @@ spec: deploymentConditions: ${deployment.status.conditions} availableReplicas: ${deployment.status.availableReplicas * 10} resources: - - name: deployment + - id: deployment template: apiVersion: apps/v1 kind: Deployment @@ -41,7 +41,7 @@ spec: value: ${schema.spec.fullDNSName.split('.')[0]} - name: DNS_PARTIALS value: ${schema.spec.fullDNSName.split('.').slice(0, 1).join('.')} - - name: service + - id: service template: apiVersion: v1 kind: Service diff --git a/examples/core-dns/core-dns.yaml b/examples/core-dns/core-dns.yaml index 76682f0f..a42486b6 100644 --- a/examples/core-dns/core-dns.yaml +++ b/examples/core-dns/core-dns.yaml @@ -40,7 +40,7 @@ spec: serviceAccount: secrets: 'map[string]string | default={"name": "coredns-token-pvcnf"}' resources: - - name: clusterRole + - id: clusterRole template: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -71,7 +71,7 @@ spec: - nodes verbs: - get - - name: clusterRoleBinding + - id: clusterRoleBinding template: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding @@ -87,7 +87,7 @@ spec: - kind: ServiceAccount name: ${serviceAccount.metadata.name} namespace: ${serviceAccount.metadata.namespace} - - name: configMap + - id: configMap template: apiVersion: v1 kind: ConfigMap @@ -110,7 +110,7 @@ spec: reload loadbalance } - - name: deployment + - id: deployment template: apiVersion: apps/v1 kind: Deployment @@ -142,7 +142,7 @@ spec: items: - key: Corefile path: Corefile - - name: service + - id: service template: apiVersion: v1 kind: Service @@ -169,7 +169,7 @@ spec: selector: k8s-app: kube-dns sessionAffinity: None - - name: serviceAccount + - id: serviceAccount template: apiVersion: v1 kind: ServiceAccount diff --git a/examples/eks-cluster-mgmt/clusters/rg/eks-w-vpc.yaml b/examples/eks-cluster-mgmt/clusters/rg/eks-w-vpc.yaml index f3046947..e5d3270f 100644 --- a/examples/eks-cluster-mgmt/clusters/rg/eks-w-vpc.yaml +++ b/examples/eks-cluster-mgmt/clusters/rg/eks-w-vpc.yaml @@ -22,7 +22,7 @@ spec: k8sVersion: string nodesCount: integer resources: - - name: vpc + - id: vpc template: apiVersion: kro.run/v1alpha1 kind: Vpc @@ -37,7 +37,7 @@ spec: publicSubnet2Cidr: ${schema.spec.cidr.publicSubnet2Cidr} privateSubnet1Cidr: ${schema.spec.cidr.privateSubnet1Cidr} privateSubnet2Cidr: ${schema.spec.cidr.privateSubnet2Cidr} - - name: eks + - id: eks template: apiVersion: kro.run/v1alpha1 kind: EksCluster diff --git a/examples/eks-cluster-mgmt/clusters/rg/eks.yaml b/examples/eks-cluster-mgmt/clusters/rg/eks.yaml index b50437b7..4bbd9f93 100644 --- a/examples/eks-cluster-mgmt/clusters/rg/eks.yaml +++ b/examples/eks-cluster-mgmt/clusters/rg/eks.yaml @@ -23,7 +23,7 @@ spec: k8sVersion: string nodesCount: integer resources: - - name: clusterRole + - id: clusterRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -47,7 +47,7 @@ spec: } ] } - - name: nodeRole + - id: nodeRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -73,7 +73,7 @@ spec: } ] } - - name: ekscluster + - id: ekscluster template: apiVersion: eks.services.k8s.aws/v1alpha1 kind: Cluster @@ -92,7 +92,7 @@ spec: - ${schema.spec.subnets.controlplane.subnet1ID} - ${schema.spec.subnets.controlplane.subnet2ID} #version: ${schema.spec.k8sVersion} a bug needs to be fixed for this to work - - name: nodegroup + - id: nodegroup template: apiVersion: eks.services.k8s.aws/v1alpha1 kind: Nodegroup @@ -112,7 +112,7 @@ spec: minSize: 3 #${schema.spec.nodesCount} a bug needs to be fixed for this to work maxSize: 3 #${schema.spec.nodesCount} a bug needs to be fixed for this to work desiredSize: 3 #${schema.spec.nodesCount} a bug needs to be fixed for this to work - - name: argocdRole + - id: argocdRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -136,7 +136,7 @@ spec: } ] } - - name: argocdSecret + - id: argocdSecret template: apiVersion: v1 kind: Secret @@ -164,7 +164,7 @@ spec: "caData": "${ekscluster.status.certificateAuthority.data}" } } - - name: accessEntry + - id: accessEntry template: apiVersion: eks.services.k8s.aws/v1alpha1 kind: AccessEntry @@ -178,7 +178,7 @@ spec: type: "cluster" policyARN: "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy" principalARN: "${argocdRole.status.ackResourceMetadata.arn}" - - name: oidcProvider + - id: oidcProvider template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: OpenIDConnectProvider diff --git a/examples/eks-cluster-mgmt/clusters/rg/vpc.yaml b/examples/eks-cluster-mgmt/clusters/rg/vpc.yaml index e2580986..a9652bd1 100644 --- a/examples/eks-cluster-mgmt/clusters/rg/vpc.yaml +++ b/examples/eks-cluster-mgmt/clusters/rg/vpc.yaml @@ -25,7 +25,7 @@ spec: privateSubnet1ID: ${privateSubnet1.status.subnetID} privateSubnet2ID: ${privateSubnet2.status.subnetID} resources: # how to publish a field in the RG claim e.g. vpcID - - name: vpc + - id: vpc template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: VPC @@ -40,7 +40,7 @@ spec: tags: - key: "Name" value: ${schema.spec.name}-vpc - - name: internetGateway + - id: internetGateway template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: InternetGateway @@ -52,7 +52,7 @@ spec: tags: - key: "Name" value: ${schema.spec.name}-igw - - name: natGateway1 + - id: natGateway1 template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: NATGateway @@ -65,7 +65,7 @@ spec: tags: - key: "Name" value: ${schema.spec.name}-nat-gateway1 - - name: natGateway2 + - id: natGateway2 template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: NATGateway @@ -78,7 +78,7 @@ spec: tags: - key: "Name" value: ${schema.spec.name}-nat-gateway2 - - name: eip1 + - id: eip1 template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: ElasticIPAddress @@ -89,7 +89,7 @@ spec: tags: - key: "Name" value: ${schema.spec.name}-eip1 - - name: eip2 + - id: eip2 template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: ElasticIPAddress @@ -100,7 +100,7 @@ spec: tags: - key: "Name" value: ${schema.spec.name}-eip2 - - name: publicRoutetable + - id: publicRoutetable template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: RouteTable @@ -115,7 +115,7 @@ spec: tags: - key: "Name" value: ${schema.spec.name}-public-routetable - - name: privateRoutetable1 + - id: privateRoutetable1 template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: RouteTable @@ -130,7 +130,7 @@ spec: tags: - key: "Name" value: ${schema.spec.name}-private-routetable1 - - name: privateRoutetable2 + - id: privateRoutetable2 template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: RouteTable @@ -145,7 +145,7 @@ spec: tags: - key: "Name" value: ${schema.spec.name}-private-routetable2 - - name: publicSubnet1 + - id: publicSubnet1 template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Subnet @@ -164,7 +164,7 @@ spec: value: ${schema.spec.name}-public-subnet1 - key: kubernetes.io/role/elb value: '1' - - name: publicSubnet2 + - id: publicSubnet2 template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Subnet @@ -183,7 +183,7 @@ spec: value: ${schema.spec.name}-public-subnet2 - key: kubernetes.io/role/elb value: '1' - - name: privateSubnet1 + - id: privateSubnet1 template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Subnet @@ -201,7 +201,7 @@ spec: value: ${schema.spec.name}-private-subnet1 - key: kubernetes.io/role/internal-elb value: '1' - - name: privateSubnet2 + - id: privateSubnet2 template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Subnet diff --git a/examples/networkstack/network-stack.yaml b/examples/networkstack/network-stack.yaml index 986c0ec4..4a2a25e2 100644 --- a/examples/networkstack/network-stack.yaml +++ b/examples/networkstack/network-stack.yaml @@ -18,7 +18,7 @@ spec: securityGroup: ${securityGroup.status.id} # resources resources: - - name: vpc + - id: vpc template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: VPC @@ -29,7 +29,7 @@ spec: - 192.168.0.0/16 enableDNSHostnames: false enableDNSSupport: true - - name: subnetAZA + - id: subnetAZA template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Subnet @@ -39,7 +39,7 @@ spec: availabilityZone: us-west-2a cidrBlock: 192.168.0.0/18 vpcID: ${vpc.status.vpcID} - - name: subnetAZB + - id: subnetAZB template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Subnet @@ -49,7 +49,7 @@ spec: availabilityZone: us-west-2b cidrBlock: 192.168.64.0/18 vpcID: ${vpc.status.vpcID} - - name: subnetAZC + - id: subnetAZC template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Subnet @@ -59,7 +59,7 @@ spec: availabilityZone: us-west-2c cidrBlock: 192.168.128.0/18 vpcID: ${vpc.status.vpcID} - - name: securityGroup + - id: securityGroup template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: SecurityGroup diff --git a/examples/serverless-microservice/microservice.yaml b/examples/serverless-microservice/microservice.yaml index d7c7873a..3b660478 100644 --- a/examples/serverless-microservice/microservice.yaml +++ b/examples/serverless-microservice/microservice.yaml @@ -24,7 +24,7 @@ spec: resources: # Business logic data store (Amazon DynamoDB table) along with the permissiosn to access it (to be used by the AWS Lambda function that implements business logic) - - name: itemsTable + - id: itemsTable template: apiVersion: dynamodb.services.k8s.aws/v1alpha1 kind: Table @@ -39,7 +39,7 @@ spec: attributeType: S billingMode: PAY_PER_REQUEST tableName: ${schema.spec.namePrefix}-items-table - - name: lambdaDDBAccessPolicy + - id: lambdaDDBAccessPolicy template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Policy @@ -74,7 +74,7 @@ spec: } # Policy to be used by all AWS Lambda functions that allows publishing logs to Amazon CloudWatch - - name: lambdaBasicPolicy + - id: lambdaBasicPolicy template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Policy @@ -99,7 +99,7 @@ spec: } # Business logics Lambda - - name: logicLambdaRole + - id: logicLambdaRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -125,7 +125,7 @@ spec: policies: - ${lambdaBasicPolicy.status.ackResourceMetadata.arn} - ${lambdaDDBAccessPolicy.status.ackResourceMetadata.arn} - - name: logicLambda + - id: logicLambda template: apiVersion: lambda.services.k8s.aws/v1alpha1 kind: Function @@ -145,7 +145,7 @@ spec: role: ${logicLambdaRole.status.ackResourceMetadata.arn} # Lambda authorizer along with permissions required to retrieve password from AWS Secrets Manager - - name: lambdaSecretsAccessPolicy + - id: lambdaSecretsAccessPolicy template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Policy @@ -168,7 +168,7 @@ spec: } ] } - - name: authorizerLambdaRole + - id: authorizerLambdaRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -194,7 +194,7 @@ spec: policies: - ${lambdaBasicPolicy.status.ackResourceMetadata.arn} - ${lambdaSecretsAccessPolicy.status.ackResourceMetadata.arn} - - name: authorizerLambda + - id: authorizerLambda template: apiVersion: lambda.services.k8s.aws/v1alpha1 kind: Function @@ -215,7 +215,7 @@ spec: # ACK Lambda controller does not support Lambda resource policies typically used by API Gateway - https://github.com/aws-controllers-k8s/community/issues/1405 # API Gateway has to use role based permissions instead - - name: apigwLogicLambdaExecutionPolicy + - id: apigwLogicLambdaExecutionPolicy template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Policy @@ -236,7 +236,7 @@ spec: } ] } - - name: apigwLogicLambdaExecutionRole + - id: apigwLogicLambdaExecutionRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -261,7 +261,7 @@ spec: } policies: - ${apigwLogicLambdaExecutionPolicy.status.ackResourceMetadata.arn} - - name: apigwAuthorizerLambdaExecutionPolicy + - id: apigwAuthorizerLambdaExecutionPolicy template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Policy @@ -282,7 +282,7 @@ spec: } ] } - - name: apigwAuthorizerLambdaExecutionRole + - id: apigwAuthorizerLambdaExecutionRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -309,7 +309,7 @@ spec: - ${apigwAuthorizerLambdaExecutionPolicy.status.ackResourceMetadata.arn} # Amazon API Gateway HTTP API and associated resources - - name: apigw + - id: apigw template: apiVersion: apigatewayv2.services.k8s.aws/v1alpha1 kind: API @@ -318,7 +318,7 @@ spec: spec: name: ${schema.spec.namePrefix}-${schema.spec.api.apiName} protocolType: HTTP - - name: apigwLambdaIntegration + - id: apigwLambdaIntegration template: apiVersion: apigatewayv2.services.k8s.aws/v1alpha1 kind: Integration @@ -331,7 +331,7 @@ spec: integrationURI: "arn:aws:apigateway:${schema.spec.region}:lambda:path/2015-03-31/functions/${logicLambda.status.ackResourceMetadata.arn}/invocations" integrationMethod: POST payloadFormatVersion: "2.0" - - name: apigwItemsIdRoute + - id: apigwItemsIdRoute template: apiVersion: apigatewayv2.services.k8s.aws/v1alpha1 kind: Route @@ -343,7 +343,7 @@ spec: target: integrations/${apigwLambdaIntegration.status.integrationID} authorizationType: CUSTOM authorizerID: ${apigwAuthorizer.status.authorizerID} - - name: apigwItemsRoute + - id: apigwItemsRoute template: apiVersion: apigatewayv2.services.k8s.aws/v1alpha1 kind: Route @@ -355,7 +355,7 @@ spec: target: integrations/${apigwLambdaIntegration.status.integrationID} authorizationType: CUSTOM authorizerID: ${apigwAuthorizer.status.authorizerID} - - name: apigwDefaultStage + - id: apigwDefaultStage template: apiVersion: apigatewayv2.services.k8s.aws/v1alpha1 kind: Stage @@ -365,7 +365,7 @@ spec: apiID: ${apigw.status.apiID} stageName: "$default" autoDeploy: true - - name: apigwAuthorizer + - id: apigwAuthorizer template: apiVersion: apigatewayv2.services.k8s.aws/v1alpha1 kind: Authorizer diff --git a/internal/cel/ast/inspector.go b/internal/cel/ast/inspector.go index c88e92e4..fab117dc 100644 --- a/internal/cel/ast/inspector.go +++ b/internal/cel/ast/inspector.go @@ -25,10 +25,10 @@ import ( // ResourceDependency represents a resource and its accessed path within a CEL expression. // For example, in the expression "deployment.spec.replicas > 0", -// Name would be "deployment" and Path would be "deployment.spec.replicas" +// ID would be "deployment" and Path would be "deployment.spec.replicas" type ResourceDependency struct { - // Name is the root resource identifier (e.g "deployment", "service", "pod") - Name string + // ID is the root resource identifier (e.g "deployment", "service", "pod") + ID string // Path is the full access path including nested fields // For example: "deployment.spec.replicas" or "service.metadata.name" Path string @@ -51,10 +51,10 @@ type FunctionCall struct { // UnknownResource represents a resource reference in the expression that wasn't // declared in the known resources list. This helps identify potentially missing -// or misspelled resource names. +// or misspelled resource ids. type UnknownResource struct { - // Name is the undeclared resource identifier that was referenced - Name string + // ID is the undeclared resource identifier that was referenced + ID string // Path is the full access path that was attempted with this unknown resource // For example: "unknown_resource.field.subfield" Path string @@ -89,7 +89,7 @@ type Inspector struct { // env is the CEL evaluation environment containing type definitions and functions env *cel.Env - // resources is a set of known resource names that can be referenced in expressions + // resources is a set of known resource ids that can be referenced in expressions resources map[string]struct{} // functions is a set of known function names that can be called in expressions @@ -256,7 +256,7 @@ func (a *Inspector) inspectIdent(ident *exprpb.Expr_Ident, currentPath string) E } return ExpressionInspection{ ResourceDependencies: []ResourceDependency{{ - Name: ident.Name, + ID: ident.Name, Path: fullPath, }}, } @@ -269,7 +269,7 @@ func (a *Inspector) inspectIdent(ident *exprpb.Expr_Ident, currentPath string) E } return ExpressionInspection{ UnknownResources: []UnknownResource{{ - Name: ident.Name, + ID: ident.Name, Path: path, }}, } diff --git a/internal/cel/ast/inspector_test.go b/internal/cel/ast/inspector_test.go index 0e1d7368..c0560cda 100644 --- a/internal/cel/ast/inspector_test.go +++ b/internal/cel/ast/inspector_test.go @@ -32,7 +32,7 @@ func TestInspector_InspectionResults(t *testing.T) { resources: []string{"eksCluster"}, expression: `eksCluster.status.state == "ACTIVE"`, wantResources: []ResourceDependency{ - {Name: "eksCluster", Path: "eksCluster.status.state"}, + {ID: "eksCluster", Path: "eksCluster.status.state"}, }, }, { @@ -40,9 +40,9 @@ func TestInspector_InspectionResults(t *testing.T) { resources: []string{"bucket"}, expression: `bucket.spec.name == "my-bucket" && bucket.metadata.name == bucket.spec.name`, wantResources: []ResourceDependency{ - {Name: "bucket", Path: "bucket.metadata.name"}, - {Name: "bucket", Path: "bucket.spec.name"}, - {Name: "bucket", Path: "bucket.spec.name"}, + {ID: "bucket", Path: "bucket.metadata.name"}, + {ID: "bucket", Path: "bucket.spec.name"}, + {ID: "bucket", Path: "bucket.spec.name"}, }, }, @@ -52,7 +52,7 @@ func TestInspector_InspectionResults(t *testing.T) { functions: []string{"toLower"}, expression: `toLower(bucket.name)`, wantResources: []ResourceDependency{ - {Name: "bucket", Path: "bucket.name"}, + {ID: "bucket", Path: "bucket.name"}, }, wantFunctions: []FunctionCall{ {Name: "toLower"}, @@ -64,7 +64,7 @@ func TestInspector_InspectionResults(t *testing.T) { functions: []string{"max"}, expression: `max(deployment.spec.replicas, 5)`, wantResources: []ResourceDependency{ - {Name: "deployment", Path: "deployment.spec.replicas"}, + {ID: "deployment", Path: "deployment.spec.replicas"}, }, wantFunctions: []FunctionCall{ {Name: "max"}, @@ -76,8 +76,8 @@ func TestInspector_InspectionResults(t *testing.T) { functions: []string{}, expression: `list[0] || flags["enabled"]`, wantResources: []ResourceDependency{ - {Name: "list", Path: "list"}, - {Name: "flags", Path: "flags"}, + {ID: "list", Path: "list"}, + {ID: "flags", Path: "flags"}, }, wantFunctions: []FunctionCall{}, }, @@ -102,9 +102,9 @@ func TestInspector_InspectionResults(t *testing.T) { functions: []string{"validate"}, expression: `validate(conditions.ready || conditions.initialized && list[3])`, wantResources: []ResourceDependency{ - {Name: "list", Path: "list"}, - {Name: "conditions", Path: "conditions.ready"}, - {Name: "conditions", Path: "conditions.initialized"}, + {ID: "list", Path: "list"}, + {ID: "conditions", Path: "conditions.ready"}, + {ID: "conditions", Path: "conditions.initialized"}, }, wantFunctions: []FunctionCall{ {Name: "validate", Arguments: []string{ @@ -117,8 +117,8 @@ func TestInspector_InspectionResults(t *testing.T) { resources: []string{"eksCluster", "nodeGroup"}, expression: `eksCluster.spec.version == nodeGroup.spec.version`, wantResources: []ResourceDependency{ - {Name: "eksCluster", Path: "eksCluster.spec.version"}, - {Name: "nodeGroup", Path: "nodeGroup.spec.version"}, + {ID: "eksCluster", Path: "eksCluster.spec.version"}, + {ID: "nodeGroup", Path: "nodeGroup.spec.version"}, }, }, { @@ -126,8 +126,8 @@ func TestInspector_InspectionResults(t *testing.T) { resources: []string{"deployment", "eksCluster"}, expression: `deployment.metadata.namespace == "default" && eksCluster.spec.version == "1.31"`, wantResources: []ResourceDependency{ - {Name: "deployment", Path: "deployment.metadata.namespace"}, - {Name: "eksCluster", Path: "eksCluster.spec.version"}, + {ID: "deployment", Path: "deployment.metadata.namespace"}, + {ID: "eksCluster", Path: "eksCluster.spec.version"}, }, }, { @@ -136,8 +136,8 @@ func TestInspector_InspectionResults(t *testing.T) { functions: []string{"concat", "toLower"}, expression: `concat(toLower(eksCluster.spec.name), "-", bucket.spec.name)`, wantResources: []ResourceDependency{ - {Name: "eksCluster", Path: "eksCluster.spec.name"}, - {Name: "bucket", Path: "bucket.spec.name"}, + {ID: "eksCluster", Path: "eksCluster.spec.name"}, + {ID: "bucket", Path: "bucket.spec.name"}, }, wantFunctions: []FunctionCall{ {Name: "concat"}, @@ -150,7 +150,7 @@ func TestInspector_InspectionResults(t *testing.T) { functions: []string{"count"}, expression: `count(instances) > 0`, wantResources: []ResourceDependency{ - {Name: "instances", Path: "instances"}, + {ID: "instances", Path: "instances"}, }, wantFunctions: []FunctionCall{ {Name: "count"}, @@ -164,9 +164,9 @@ func TestInspector_InspectionResults(t *testing.T) { count(fargateProfile.spec.selectors) <= 5 && eksCluster.status.state == "ACTIVE"`, wantResources: []ResourceDependency{ - {Name: "fargateProfile", Path: "fargateProfile.spec.subnets"}, - {Name: "fargateProfile", Path: "fargateProfile.spec.selectors"}, - {Name: "eksCluster", Path: "eksCluster.status.state"}, + {ID: "fargateProfile", Path: "fargateProfile.spec.subnets"}, + {ID: "fargateProfile", Path: "fargateProfile.spec.selectors"}, + {ID: "eksCluster", Path: "eksCluster.status.state"}, }, wantFunctions: []FunctionCall{ {Name: "contains"}, @@ -182,9 +182,9 @@ func TestInspector_InspectionResults(t *testing.T) { contains(map(r.ipRanges, range, concat(range.cidr, "/", range.description)), "0.0.0.0/0"))`, wantResources: []ResourceDependency{ - {Name: "securityGroup", Path: "securityGroup.spec.vpcID"}, - {Name: "securityGroup", Path: "securityGroup.spec.rules"}, - {Name: "vpc", Path: "vpc.status.vpcID"}, + {ID: "securityGroup", Path: "securityGroup.spec.vpcID"}, + {ID: "securityGroup", Path: "securityGroup.spec.rules"}, + {ID: "vpc", Path: "vpc.status.vpcID"}, }, wantFunctions: []FunctionCall{ {Name: "concat"}, @@ -205,11 +205,11 @@ func TestInspector_InspectionResults(t *testing.T) { contains(map(iamRole.policies, p, p.actions), "eks:*") && size(vpc.subnets.filter(s, s.isPrivate)) >= 2`, wantResources: []ResourceDependency{ - {Name: "eksCluster", Path: "eksCluster.status.state"}, - {Name: "eksCluster", Path: "eksCluster.status.createdAt"}, - {Name: "nodeGroups", Path: "nodeGroups"}, - {Name: "iamRole", Path: "iamRole.policies"}, - {Name: "vpc", Path: "vpc.subnets"}, + {ID: "eksCluster", Path: "eksCluster.status.state"}, + {ID: "eksCluster", Path: "eksCluster.status.createdAt"}, + {ID: "nodeGroups", Path: "nodeGroups"}, + {ID: "iamRole", Path: "iamRole.policies"}, + {ID: "vpc", Path: "vpc.subnets"}, }, wantFunctions: []FunctionCall{ {Name: "contains"}, @@ -232,13 +232,13 @@ func TestInspector_InspectionResults(t *testing.T) { validateAddress(customer.shippingAddress) && calculateTax(order.total, customer.address.zipCode) > 0 || true`, wantResources: []ResourceDependency{ - {Name: "order", Path: "order.total"}, - {Name: "order", Path: "order.total"}, - {Name: "order", Path: "order.items"}, - {Name: "product", Path: "product.id"}, - {Name: "inventory", Path: "inventory.stock"}, - {Name: "customer", Path: "customer.shippingAddress"}, - {Name: "customer", Path: "customer.address.zipCode"}, + {ID: "order", Path: "order.total"}, + {ID: "order", Path: "order.total"}, + {ID: "order", Path: "order.items"}, + {ID: "product", Path: "product.id"}, + {ID: "inventory", Path: "inventory.stock"}, + {ID: "customer", Path: "customer.shippingAddress"}, + {ID: "customer", Path: "customer.address.zipCode"}, }, wantFunctions: []FunctionCall{ {Name: "validateAddress"}, @@ -252,7 +252,7 @@ func TestInspector_InspectionResults(t *testing.T) { functions: []string{}, expression: `pods.filter(p, p.status == "Running")`, wantResources: []ResourceDependency{ - {Name: "pods", Path: "pods"}, + {ID: "pods", Path: "pods"}, }, wantFunctions: []FunctionCall{ {Name: "map"}, @@ -372,7 +372,7 @@ func TestInspector_UnknownResourcesAndCalls(t *testing.T) { {Name: "unknownResource.someMethod"}, }, wantUnknownRes: []UnknownResource{ - {Name: "unknownResource", Path: "unknownResource"}, + {ID: "unknownResource", Path: "unknownResource"}, }, }, { @@ -385,7 +385,7 @@ func TestInspector_UnknownResourcesAndCalls(t *testing.T) { {Name: "unknown.method1().method2"}, }, wantUnknownRes: []UnknownResource{ - {Name: "unknown", Path: "unknown"}, + {ID: "unknown", Path: "unknown"}, }, }, { @@ -398,7 +398,7 @@ func TestInspector_UnknownResourcesAndCalls(t *testing.T) { i.type == 't2.micro' )`, wantResources: []ResourceDependency{ - {Name: "instances", Path: "instances"}, + {ID: "instances", Path: "instances"}, }, wantFunctions: []FunctionCall{ {Name: "map"}, @@ -412,8 +412,8 @@ func TestInspector_UnknownResourcesAndCalls(t *testing.T) { i.state == 'running' )`, wantResources: []ResourceDependency{ - {Name: "i", Path: "i.status"}, - {Name: "instances", Path: "instances"}, + {ID: "i", Path: "i.status"}, + {ID: "instances", Path: "instances"}, }, wantFunctions: []FunctionCall{ {Name: "map"}, @@ -426,7 +426,7 @@ func TestInspector_UnknownResourcesAndCalls(t *testing.T) { functions: []string{"processItems", "validate"}, expression: `processItems(bucket).validate()`, wantResources: []ResourceDependency{ - {Name: "bucket", Path: "bucket"}, + {ID: "bucket", Path: "bucket"}, }, wantFunctions: []FunctionCall{ {Name: "processItems"}, @@ -444,7 +444,7 @@ func TestInspector_UnknownResourcesAndCalls(t *testing.T) { {Name: "result.unknownFn().anotherUnknownFn"}, }, wantUnknownRes: []UnknownResource{ - {Name: "result", Path: "result"}, + {ID: "result", Path: "result"}, }, }, } diff --git a/internal/cel/environment.go b/internal/cel/environment.go index 0173ad97..78390e50 100644 --- a/internal/cel/environment.go +++ b/internal/cel/environment.go @@ -23,19 +23,19 @@ type EnvOption func(*envOptions) // envOptions holds all the configuration for the CEL environment. type envOptions struct { - // resourceNames will be converted to CEL variable declarations + // resourceIDs will be converted to CEL variable declarations // of type 'any'. // // TODO(a-hilaly): Add support for custom types. - resourceNames []string + resourceIDs []string // customDeclarations will be added to the CEL environment. customDeclarations []cel.EnvOption } -// WithResourceNames adds resource names that will be declared as CEL variables. -func WithResourceNames(names []string) EnvOption { +// WithResourceIDs adds resource ids that will be declared as CEL variables. +func WithResourceIDs(ids []string) EnvOption { return func(opts *envOptions) { - opts.resourceNames = append(opts.resourceNames, names...) + opts.resourceIDs = append(opts.resourceIDs, ids...) } } @@ -59,7 +59,7 @@ func DefaultEnvironment(options ...EnvOption) (*cel.Env, error) { ext.Strings(), } - for _, name := range opts.resourceNames { + for _, name := range opts.resourceIDs { declarations = append(declarations, cel.Variable(name, cel.AnyType)) } return cel.NewEnv(declarations...) diff --git a/internal/graph/builder.go b/internal/graph/builder.go index 8e90579f..ff508cea 100644 --- a/internal/graph/builder.go +++ b/internal/graph/builder.go @@ -145,9 +145,9 @@ func (b *Builder) NewResourceGroup(originalCR *v1alpha1.ResourceGroup) (*Graph, for _, rgResource := range rg.Spec.Resources { r, err := b.buildRGResource(rgResource, namespacedResources) if err != nil { - return nil, fmt.Errorf("failed to build resource '%v': %v", rgResource.Name, err) + return nil, fmt.Errorf("failed to build resource '%v': %v", rgResource.ID, err) } - resources[rgResource.Name] = r + resources[rgResource.ID] = r } // At this stage we have a superficial understanding of the resources that are @@ -251,25 +251,25 @@ func (b *Builder) buildRGResource(rgResource *v1alpha1.Resource, namespacedResou resourceObject := map[string]interface{}{} err := yaml.UnmarshalStrict(rgResource.Template.Raw, &resourceObject) if err != nil { - return nil, fmt.Errorf("failed to unmarshal resource %s: %w", rgResource.Name, err) + return nil, fmt.Errorf("failed to unmarshal resource %s: %w", rgResource.ID, err) } // 1. Check if it looks like a valid Kubernetes resource. err = validateKubernetesObjectStructure(resourceObject) if err != nil { - return nil, fmt.Errorf("resource %s is not a valid Kubernetes object: %v", rgResource.Name, err) + return nil, fmt.Errorf("resource %s is not a valid Kubernetes object: %v", rgResource.ID, err) } // 2. Based the GVK, we need to load the OpenAPI schema for the resource. gvk, err := metadata.ExtractGVKFromUnstructured(resourceObject) if err != nil { - return nil, fmt.Errorf("failed to extract GVK from resource %s: %w", rgResource.Name, err) + return nil, fmt.Errorf("failed to extract GVK from resource %s: %w", rgResource.ID, err) } // 3. Load the OpenAPI schema for the resource. resourceSchema, err := b.schemaResolver.ResolveSchema(gvk) if err != nil { - return nil, fmt.Errorf("failed to get schema for resource %s: %w", rgResource.Name, err) + return nil, fmt.Errorf("failed to get schema for resource %s: %w", rgResource.ID, err) } var emulatedResource *unstructured.Unstructured @@ -280,10 +280,10 @@ func (b *Builder) buildRGResource(rgResource *v1alpha1.Resource, namespacedResou if gvk.Group == "apiextensions.k8s.io" && gvk.Version == "v1" && gvk.Kind == "CustomResourceDefinition" { celExpressions, err := parser.ParseSchemalessResource(resourceObject) if err != nil { - return nil, fmt.Errorf("failed to parse schemaless resource %s: %w", rgResource.Name, err) + return nil, fmt.Errorf("failed to parse schemaless resource %s: %w", rgResource.ID, err) } if len(celExpressions) > 0 { - return nil, fmt.Errorf("failed, CEL expressions are not supported for CRDs, resource %s", rgResource.Name) + return nil, fmt.Errorf("failed, CEL expressions are not supported for CRDs, resource %s", rgResource.ID) } } else { @@ -291,13 +291,13 @@ func (b *Builder) buildRGResource(rgResource *v1alpha1.Resource, namespacedResou // CEL expressions. emulatedResource, err = b.resourceEmulator.GenerateDummyCR(gvk, resourceSchema) if err != nil { - return nil, fmt.Errorf("failed to generate dummy CR for resource %s: %w", rgResource.Name, err) + return nil, fmt.Errorf("failed to generate dummy CR for resource %s: %w", rgResource.ID, err) } // 5. Extract CEL fieldDescriptors from the schema. fieldDescriptors, err := parser.ParseResource(resourceObject, resourceSchema) if err != nil { - return nil, fmt.Errorf("failed to extract CEL expressions from schema for resource %s: %w", rgResource.Name, err) + return nil, fmt.Errorf("failed to extract CEL expressions from schema for resource %s: %w", rgResource.ID, err) } for _, fieldDescriptor := range fieldDescriptors { resourceVariables = append(resourceVariables, &variable.ResourceField{ @@ -324,7 +324,7 @@ func (b *Builder) buildRGResource(rgResource *v1alpha1.Resource, namespacedResou // Note that at this point we don't inject the dependencies into the resource. return &Resource{ - id: rgResource.Name, + id: rgResource.ID, gvr: metadata.GVKtoGVR(gvk), schema: resourceSchema, emulatedObject: emulatedResource, @@ -356,7 +356,7 @@ func (b *Builder) buildDependencyGraph( // We also want to allow users to refer to the instance spec in their expressions. resourceNames = append(resourceNames, "schema") - env, err := krocel.DefaultEnvironment(krocel.WithResourceNames(resourceNames)) + env, err := krocel.DefaultEnvironment(krocel.WithResourceIDs(resourceNames)) if err != nil { return nil, fmt.Errorf("failed to create CEL environment: %w", err) } @@ -465,7 +465,7 @@ func (b *Builder) buildInstanceResource( } resourceNames := maps.Keys(resources) - env, err := krocel.DefaultEnvironment(krocel.WithResourceNames(resourceNames)) + env, err := krocel.DefaultEnvironment(krocel.WithResourceIDs(resourceNames)) if err != nil { return nil, fmt.Errorf("failed to create CEL environment: %w", err) } @@ -552,7 +552,7 @@ func buildStatusSchema( // Inspection of the CEL expressions to infer the types of the status fields. resourceNames := maps.Keys(resources) - env, err := krocel.DefaultEnvironment(krocel.WithResourceNames(resourceNames)) + env, err := krocel.DefaultEnvironment(krocel.WithResourceIDs(resourceNames)) if err != nil { return nil, nil, fmt.Errorf("failed to create CEL environment: %w", err) } @@ -602,8 +602,8 @@ func validateCELExpressionContext(env *cel.Env, expression string, resources []s } // make sure that the expression refers to the resources defined in the resource group. for _, resource := range inspectionResult.ResourceDependencies { - if !slices.Contains(resources, resource.Name) { - return fmt.Errorf("expression refers to unknown resource: %s", resource.Name) + if !slices.Contains(resources, resource.ID) { + return fmt.Errorf("expression refers to unknown resource: %s", resource.ID) } } return nil @@ -654,9 +654,9 @@ func extractDependencies(env *cel.Env, expression string, resourceNames []string isStatic := true dependencies := make([]string, 0) for _, resource := range inspectionResult.ResourceDependencies { - if resource.Name != "schema" && !slices.Contains(dependencies, resource.Name) { + if resource.ID != "schema" && !slices.Contains(dependencies, resource.ID) { isStatic = false - dependencies = append(dependencies, resource.Name) + dependencies = append(dependencies, resource.ID) } } if len(inspectionResult.UnknownResources) > 0 { @@ -682,7 +682,7 @@ func validateResourceCELExpressions(resources map[string]*Resource, instance *Re resourceNames = append(resourceNames, "schema") conditionFieldNames := []string{"schema"} - env, err := krocel.DefaultEnvironment(krocel.WithResourceNames(resourceNames)) + env, err := krocel.DefaultEnvironment(krocel.WithResourceIDs(resourceNames)) if err != nil { return fmt.Errorf("failed to create CEL environment: %w", err) } @@ -731,7 +731,7 @@ func validateResourceCELExpressions(resources map[string]*Resource, instance *Re // I would also suggest separating the dryRuns of readyWhenExpressions // and the resourceExpressions. for _, readyWhenExpression := range resource.readyWhenExpressions { - fieldEnv, err := krocel.DefaultEnvironment(krocel.WithResourceNames([]string{resource.id})) + fieldEnv, err := krocel.DefaultEnvironment(krocel.WithResourceIDs([]string{resource.id})) if err != nil { return fmt.Errorf("failed to create CEL environment: %w", err) } @@ -762,7 +762,7 @@ func validateResourceCELExpressions(resources map[string]*Resource, instance *Re } for _, includeWhenExpression := range resource.includeWhenExpressions { - instanceEnv, err := krocel.DefaultEnvironment(krocel.WithResourceNames(resourceNames)) + instanceEnv, err := krocel.DefaultEnvironment(krocel.WithResourceIDs(resourceNames)) if err != nil { return fmt.Errorf("failed to create CEL environment: %w", err) } diff --git a/internal/graph/builder_test.go b/internal/graph/builder_test.go index 8090bbbe..64aab115 100644 --- a/internal/graph/builder_test.go +++ b/internal/graph/builder_test.go @@ -62,7 +62,7 @@ func TestGraphBuilder_Validation(t *testing.T) { errMsg: "schema not found", }, { - name: "invalid resource name with operator", + name: "invalid resource id with operator", resourceGroupOpts: []generator.ResourceGroupOption{ generator.WithSchema( "Test", "v1alpha1", @@ -71,7 +71,7 @@ func TestGraphBuilder_Validation(t *testing.T) { }, nil, ), - generator.WithResource("vpc-1", map[string]interface{}{ // Invalid name with operator + generator.WithResource("vpc-1", map[string]interface{}{ // Invalid id with operator "apiVersion": "ec2.services.k8s.aws/v1alpha1", "kind": "VPC", "metadata": map[string]interface{}{ diff --git a/internal/graph/validation.go b/internal/graph/validation.go index d5a7531d..77e4e9e4 100644 --- a/internal/graph/validation.go +++ b/internal/graph/validation.go @@ -65,9 +65,9 @@ var ( } ) -// isValidResourceName checks if the given name is a valid KRO resource name (loawercase) -func isValidResourceName(name string) bool { - return lowerCamelCaseRegex.MatchString(name) +// isValidResourceID checks if the given id is a valid KRO resource id (loawercase) +func isValidResourceID(id string) bool { + return lowerCamelCaseRegex.MatchString(id) } // isValidKindName checks if the given name is a valid KRO kind name (uppercase) @@ -91,7 +91,7 @@ func validateResourceGroupNamingConventions(rg *v1alpha1.ResourceGroup) error { if !isValidKindName(rg.Spec.Schema.Kind) { return fmt.Errorf("%s: kind '%s' is not a valid KRO kind name: must be UpperCamelCase", ErrNamingConvention, rg.Spec.Schema.Kind) } - err := validateResourceNames(rg) + err := validateResourceIDs(rg) if err != nil { return fmt.Errorf("%s: %w", ErrNamingConvention, err) } @@ -99,28 +99,28 @@ func validateResourceGroupNamingConventions(rg *v1alpha1.ResourceGroup) error { } // validateResource performs basic validation on a given resourcegroup. -// It checks that there are no duplicate resource names and that the -// resource names are conformant to the KRO naming convention. +// It checks that there are no duplicate resource ids and that the +// resource ids are conformant to the KRO naming convention. // // The KRO naming convention is as follows: -// - The name should start with a lowercase letter. -// - The name should only contain alphanumeric characters. +// - The id should start with a lowercase letter. +// - The id should only contain alphanumeric characters. // - does not contain any special characters, underscores, or hyphens. -func validateResourceNames(rg *v1alpha1.ResourceGroup) error { +func validateResourceIDs(rg *v1alpha1.ResourceGroup) error { seen := make(map[string]struct{}) for _, res := range rg.Spec.Resources { - if isKROReservedWord(res.Name) { - return fmt.Errorf("name %s is a reserved keyword in KRO", res.Name) + if isKROReservedWord(res.ID) { + return fmt.Errorf("id %s is a reserved keyword in KRO", res.ID) } - if !isValidResourceName(res.Name) { - return fmt.Errorf("name %s is not a valid KRO resource name: must be lower camelCase", res.Name) + if !isValidResourceID(res.ID) { + return fmt.Errorf("id %s is not a valid KRO resource id: must be lower camelCase", res.ID) } - if _, ok := seen[res.Name]; ok { - return fmt.Errorf("found duplicate resource name %s", res.Name) + if _, ok := seen[res.ID]; ok { + return fmt.Errorf("found duplicate resource IDs %s", res.ID) } - seen[res.Name] = struct{}{} + seen[res.ID] = struct{}{} } return nil } diff --git a/internal/graph/validation_test.go b/internal/graph/validation_test.go index 429441a8..f95c5e37 100644 --- a/internal/graph/validation_test.go +++ b/internal/graph/validation_test.go @@ -26,46 +26,46 @@ func TestValidateRGResourceNames(t *testing.T) { expectError bool }{ { - name: "Valid resource group resource names", + name: "Valid resource group resource ids", rg: &v1alpha1.ResourceGroup{ Spec: v1alpha1.ResourceGroupSpec{ Resources: []*v1alpha1.Resource{ - {Name: "validName1"}, - {Name: "validName2"}, + {ID: "validID1"}, + {ID: "validID2"}, }, }, }, expectError: false, }, { - name: "Duplicate resource names", + name: "Duplicate resource ids", rg: &v1alpha1.ResourceGroup{ Spec: v1alpha1.ResourceGroupSpec{ Resources: []*v1alpha1.Resource{ - {Name: "duplicateName"}, - {Name: "duplicateName"}, + {ID: "duplicateID"}, + {ID: "duplicateID"}, }, }, }, expectError: true, }, { - name: "Invalid resource name", + name: "Invalid resource ID", rg: &v1alpha1.ResourceGroup{ Spec: v1alpha1.ResourceGroupSpec{ Resources: []*v1alpha1.Resource{ - {Name: "Invalid_Name"}, + {ID: "Invalid_ID"}, }, }, }, expectError: true, }, { - name: "Reserved word as resource name", + name: "Reserved word as resource id", rg: &v1alpha1.ResourceGroup{ Spec: v1alpha1.ResourceGroupSpec{ Resources: []*v1alpha1.Resource{ - {Name: "spec"}, + {ID: "spec"}, }, }, }, @@ -75,9 +75,9 @@ func TestValidateRGResourceNames(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := validateResourceNames(tt.rg) + err := validateResourceIDs(tt.rg) if (err != nil) != tt.expectError { - t.Errorf("validateRGResourceNames() error = %v, expectError %v", err, tt.expectError) + t.Errorf("validateRGResourceIDs() error = %v, expectError %v", err, tt.expectError) } }) } @@ -118,7 +118,7 @@ func TestIsValidResourceName(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := isValidResourceName(tt.name); got != tt.expected { + if got := isValidResourceID(tt.name); got != tt.expected { t.Errorf("isValidResourceName(%q) = %v, want %v", tt.name, got, tt.expected) } }) diff --git a/internal/runtime/runtime.go b/internal/runtime/runtime.go index 94f91917..a30b889b 100644 --- a/internal/runtime/runtime.go +++ b/internal/runtime/runtime.go @@ -57,7 +57,7 @@ func NewResourceGroupRuntime( } // make sure to copy the variables and the dependencies, to avoid // modifying the original resource. - for name, resource := range resources { + for id, resource := range resources { // Process the resource variables. for _, variable := range resource.GetVariables() { for _, expr := range variable.Expressions { @@ -66,7 +66,7 @@ func NewResourceGroupRuntime( // NOTE(a-hilaly): This strikes me as an early optimization, but // it's a good one, i believe... We can always remove it if it's // too magical. - r.runtimeVariables[name] = append(r.runtimeVariables[name], ec) + r.runtimeVariables[id] = append(r.runtimeVariables[id], ec) continue } ees := &expressionEvaluationState{ @@ -74,7 +74,7 @@ func NewResourceGroupRuntime( Dependencies: variable.Dependencies, Kind: variable.Kind, } - r.runtimeVariables[name] = append(r.runtimeVariables[name], ees) + r.runtimeVariables[id] = append(r.runtimeVariables[id], ees) r.expressionsCache[expr] = ees } } @@ -92,7 +92,7 @@ func NewResourceGroupRuntime( for _, variable := range instance.GetVariables() { for _, expr := range variable.Expressions { if ec, seen := r.expressionsCache[expr]; seen { - // It is validated at the Graph level that the resource names + // It is validated at the Graph level that the resource ids // can't be `instance`. This is why. r.runtimeVariables["instance"] = append(r.runtimeVariables["instance"], ec) continue @@ -142,7 +142,7 @@ type ResourceGroupRuntime struct { // been successfully reconciled with the cluster state. resolvedResources map[string]*unstructured.Unstructured - // runtimeVariables maps resource names to their associated variables. + // runtimeVariables maps resource ids to their associated variables. // These variables are used in the synchronization process to resolve // dependencies and compute derived values for resources. runtimeVariables map[string][]*expressionEvaluationState @@ -173,30 +173,30 @@ func (rt *ResourceGroupRuntime) TopologicalOrder() []string { return rt.topologicalOrder } -// ResourceDescriptor returns the descriptor for a given resource name. +// ResourceDescriptor returns the descriptor for a given resource id. // -// It is the responsibility of the caller to ensure that the resource name +// It is the responsibility of the caller to ensure that the resource id // exists in the runtime. a.k.a the caller should use the TopologicalOrder -// to get the resource names. -func (rt *ResourceGroupRuntime) ResourceDescriptor(name string) ResourceDescriptor { - return rt.resources[name] +// to get the resource ids. +func (rt *ResourceGroupRuntime) ResourceDescriptor(id string) ResourceDescriptor { + return rt.resources[id] } // GetResource returns a resource so that it's either created or updated in // the cluster, it also returns the runtime state of the resource. Indicating // whether the resource variables are resolved or not, and whether the resource // readiness conditions are met or not. -func (rt *ResourceGroupRuntime) GetResource(name string) (*unstructured.Unstructured, ResourceState) { +func (rt *ResourceGroupRuntime) GetResource(id string) (*unstructured.Unstructured, ResourceState) { // Did the user set the resource? - r, ok := rt.resolvedResources[name] + r, ok := rt.resolvedResources[id] if ok { return r, ResourceStateResolved } // If not, can we process the resource? - resolved := rt.canProcessResource(name) + resolved := rt.canProcessResource(id) if resolved { - return rt.resources[name].Unstructured(), ResourceStateResolved + return rt.resources[id].Unstructured(), ResourceStateResolved } return nil, ResourceStateWaitingOnDependencies @@ -204,8 +204,8 @@ func (rt *ResourceGroupRuntime) GetResource(name string) (*unstructured.Unstruct // SetResource updates or sets a resource in the runtime. This is typically // called after a resource has been created or updated in the cluster. -func (rt *ResourceGroupRuntime) SetResource(name string, resource *unstructured.Unstructured) { - rt.resolvedResources[name] = resource +func (rt *ResourceGroupRuntime) SetResource(id string, resource *unstructured.Unstructured) { + rt.resolvedResources[id] = resource } // GetInstance returns the main instance object managed by this runtime. @@ -258,12 +258,12 @@ func (rt *ResourceGroupRuntime) Synchronize() (bool, error) { // propagateResourceVariables iterates over all resources and evaluates their // variables if all dependencies are resolved. func (rt *ResourceGroupRuntime) propagateResourceVariables() error { - for name := range rt.resources { - if rt.canProcessResource(name) { + for id := range rt.resources { + if rt.canProcessResource(id) { // evaluate the resource variables - err := rt.evaluateResourceExpressions(name) + err := rt.evaluateResourceExpressions(id) if err != nil { - return fmt.Errorf("failed to evaluate resource variables for %s: %w", name, err) + return fmt.Errorf("failed to evaluate resource variables for %s: %w", id, err) } } } @@ -302,7 +302,7 @@ func (rt *ResourceGroupRuntime) resourceVariablesResolved(resource string) bool // depending only on the initial configuration. This function is usually // called once during runtime initialization to set up the baseline state func (rt *ResourceGroupRuntime) evaluateStaticVariables() error { - env, err := krocel.DefaultEnvironment(krocel.WithResourceNames([]string{"schema"})) + env, err := krocel.DefaultEnvironment(krocel.WithResourceIDs([]string{"schema"})) if err != nil { return err } @@ -346,7 +346,7 @@ func (rt *ResourceGroupRuntime) evaluateDynamicVariables() error { // and are resolved after all the dependencies are resolved. resolvedResources := maps.Keys(rt.resolvedResources) - env, err := krocel.DefaultEnvironment(krocel.WithResourceNames(resolvedResources)) + env, err := krocel.DefaultEnvironment(krocel.WithResourceIDs(resolvedResources)) if err != nil { return err } @@ -474,7 +474,7 @@ func (rt *ResourceGroupRuntime) IsResourceReady(resourceID string) (bool, string // we should not expect errors here since we already compiled it // in the dryRun - env, err := krocel.DefaultEnvironment(krocel.WithResourceNames([]string{resourceID})) + env, err := krocel.DefaultEnvironment(krocel.WithResourceIDs([]string{resourceID})) if err != nil { return false, "", fmt.Errorf("failed creating new Environment: %w", err) } @@ -530,7 +530,7 @@ func (rt *ResourceGroupRuntime) WantToCreateResource(resourceID string) (bool, e // we should not expect errors here since we already compiled it // in the dryRun - env, err := krocel.DefaultEnvironment(krocel.WithResourceNames([]string{"schema"})) + env, err := krocel.DefaultEnvironment(krocel.WithResourceIDs([]string{"schema"})) if err != nil { return false, nil } diff --git a/internal/runtime/runtime_test.go b/internal/runtime/runtime_test.go index 55490817..562d4fa1 100644 --- a/internal/runtime/runtime_test.go +++ b/internal/runtime/runtime_test.go @@ -2463,7 +2463,7 @@ func Test_areDependenciesIgnored(t *testing.T) { } func setupTestEnv(names []string) (*cel.Env, error) { - return krocel.DefaultEnvironment(krocel.WithResourceNames(names)) + return krocel.DefaultEnvironment(krocel.WithResourceIDs(names)) } func Test_evaluateExpression(t *testing.T) { diff --git a/internal/testutil/generator/resourcegroup.go b/internal/testutil/generator/resourcegroup.go index 6ca1c728..50d72ac4 100644 --- a/internal/testutil/generator/resourcegroup.go +++ b/internal/testutil/generator/resourcegroup.go @@ -77,7 +77,7 @@ func WithSchema(kind, version string, spec, status map[string]interface{}) Resou // WithResource adds a resource to the ResourceGroup with the given name and definition // readyWhen and includeWhen expressions are optional. func WithResource( - name string, + id string, template map[string]interface{}, readyWhen []string, includeWhen []string, @@ -88,7 +88,7 @@ func WithResource( panic(err) } rg.Spec.Resources = append(rg.Spec.Resources, &krov1alpha1.Resource{ - Name: name, + ID: id, ReadyWhen: readyWhen, IncludeWhen: includeWhen, Template: runtime.RawExtension{ diff --git a/test/integration/suites/core/recover_test.go b/test/integration/suites/core/recover_test.go index eee8aafc..69456fbe 100644 --- a/test/integration/suites/core/recover_test.go +++ b/test/integration/suites/core/recover_test.go @@ -99,7 +99,7 @@ var _ = Describe("Recovery", func() { // Add resources with circular dependency rg.Spec.Resources = append(rg.Spec.Resources, &krov1alpha1.Resource{ - Name: "serviceA", + ID: "serviceA", Template: toRawExtension(map[string]interface{}{ "apiVersion": "v1", "kind": "Service", @@ -109,7 +109,7 @@ var _ = Describe("Recovery", func() { }), }, &krov1alpha1.Resource{ - Name: "serviceB", + ID: "serviceB", Template: toRawExtension(map[string]interface{}{ "apiVersion": "v1", "kind": "Service", @@ -145,7 +145,7 @@ var _ = Describe("Recovery", func() { // Replace with new valid resource rg.Spec.Resources = []*krov1alpha1.Resource{ { - Name: "itsapodnow", + ID: "itsapodnow", Template: toRawExtension(map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", diff --git a/test/integration/suites/core/validation_test.go b/test/integration/suites/core/validation_test.go index f26bb355..2cb882c1 100644 --- a/test/integration/suites/core/validation_test.go +++ b/test/integration/suites/core/validation_test.go @@ -45,7 +45,7 @@ var _ = Describe("Validation", func() { })).To(Succeed()) }) - Context("Resource Names", func() { + Context("Resource IDs", func() { It("should validate correct resource naming conventions", func() { rg := generator.NewResourceGroup("test-validation", generator.WithNamespace(namespace), @@ -74,7 +74,7 @@ var _ = Describe("Validation", func() { }, 10*time.Second, time.Second).Should(Succeed()) }) - It("should reject invalid resource names", func() { + It("should reject invalid resource IDs", func() { invalidNames := []string{ "MyResource", // Uppercase first letter "my_resource", // Contains underscore @@ -126,7 +126,7 @@ var _ = Describe("Validation", func() { } }) - It("should reject duplicate resource names", func() { + It("should reject duplicate resource IDs", func() { rg := generator.NewResourceGroup("test-validation-dup", generator.WithNamespace(namespace), generator.WithSchema( @@ -160,7 +160,7 @@ var _ = Describe("Validation", func() { } g.Expect(condition).ToNot(BeNil()) g.Expect(condition.Status).To(Equal(metav1.ConditionFalse)) - g.Expect(*condition.Reason).To(ContainSubstring("found duplicate resource name")) + g.Expect(*condition.Reason).To(ContainSubstring("found duplicate resource IDs")) }, 10*time.Second, time.Second).Should(Succeed()) }) }) diff --git a/website/docs/docs/concepts/00-resource-groups.md b/website/docs/docs/concepts/00-resource-groups.md index 0a61f9d9..ca91acdd 100644 --- a/website/docs/docs/concepts/00-resource-groups.md +++ b/website/docs/docs/concepts/00-resource-groups.md @@ -60,7 +60,7 @@ spec: # Define the resources kro will manage resources: - - name: resource1 + - id: resource1 # declare your resources along with default values and variables template: {} ``` diff --git a/website/docs/docs/getting-started/02-deploy-a-resource-group.md b/website/docs/docs/getting-started/02-deploy-a-resource-group.md index 2e0827ff..93c673ae 100644 --- a/website/docs/docs/getting-started/02-deploy-a-resource-group.md +++ b/website/docs/docs/getting-started/02-deploy-a-resource-group.md @@ -61,7 +61,7 @@ spec: # Define the resources this API will manage. resources: - - name: deployment + - id: deployment template: apiVersion: apps/v1 kind: Deployment @@ -83,7 +83,7 @@ spec: ports: - containerPort: 80 - - name: service + - id: service template: apiVersion: v1 kind: Service @@ -96,7 +96,7 @@ spec: port: 80 targetPort: 80 - - name: ingress + - id: ingress includeWhen: - ${schema.spec.ingress.enabled} # Only include if the user wants to create an Ingress template: diff --git a/website/docs/examples/ack-eks-cluster.md b/website/docs/examples/ack-eks-cluster.md index 651fe561..e3d7d245 100644 --- a/website/docs/examples/ack-eks-cluster.md +++ b/website/docs/examples/ack-eks-cluster.md @@ -25,7 +25,7 @@ spec: clusterARN: ${cluster.status.ackResourceMetadata.arn} # resources resources: - - name: clusterVPC + - id: clusterVPC readyWhen: - ${clusterVPC.status.state == "available"} template: @@ -38,14 +38,14 @@ spec: - 192.168.0.0/16 enableDNSSupport: true enableDNSHostnames: true - - name: clusterElasticIPAddress + - id: clusterElasticIPAddress template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: ElasticIPAddress metadata: name: kro-cluster-eip spec: {} - - name: clusterInternetGateway + - id: clusterInternetGateway template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: InternetGateway @@ -53,7 +53,7 @@ spec: name: kro-cluster-igw spec: vpc: ${clusterVPC.status.vpcID} - - name: clusterRouteTable + - id: clusterRouteTable template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: RouteTable @@ -64,7 +64,7 @@ spec: routes: - destinationCIDRBlock: 0.0.0.0/0 gatewayID: ${clusterInternetGateway.status.internetGatewayID} - - name: clusterSubnetA + - id: clusterSubnetA readyWhen: - ${clusterSubnetA.status.state == "available"} template: @@ -79,7 +79,7 @@ spec: routeTables: - ${clusterRouteTable.status.routeTableID} mapPublicIPOnLaunch: true - - name: clusterSubnetB + - id: clusterSubnetB template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Subnet @@ -92,7 +92,7 @@ spec: routeTables: - ${clusterRouteTable.status.routeTableID} mapPublicIPOnLaunch: true - - name: clusterNATGateway + - id: clusterNATGateway template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: NATGateway @@ -101,7 +101,7 @@ spec: spec: subnetID: ${clusterSubnetB.status.subnetID} allocationID: ${clusterElasticIPAddress.status.allocationID} - - name: clusterRole + - id: clusterRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -125,7 +125,7 @@ spec: } ] } - - name: clusterNodeRole + - id: clusterNodeRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -151,7 +151,7 @@ spec: } ] } - - name: clusterAdminRole + - id: clusterAdminRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -179,7 +179,7 @@ spec: } ] } - - name: cluster + - id: cluster readyWhen: - ${cluster.status.status == "ACTIVE"} template: @@ -199,7 +199,7 @@ spec: subnetIDs: - ${clusterSubnetA.status.subnetID} - ${clusterSubnetB.status.subnetID} - - name: clusterNodeGroup + - id: clusterNodeGroup template: apiVersion: eks.services.k8s.aws/v1alpha1 kind: Nodegroup diff --git a/website/docs/examples/ack-networking-stack.md b/website/docs/examples/ack-networking-stack.md index b86cc960..4270bad6 100644 --- a/website/docs/examples/ack-networking-stack.md +++ b/website/docs/examples/ack-networking-stack.md @@ -25,7 +25,7 @@ spec: securityGroup: ${securityGroup.status.id} # resources resources: - - name: vpc + - id: vpc template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: VPC @@ -36,7 +36,7 @@ spec: - 192.168.0.0/16 enableDNSHostnames: false enableDNSSupport: true - - name: subnetAZA + - id: subnetAZA template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Subnet @@ -46,7 +46,7 @@ spec: availabilityZone: us-west-2a cidrBlock: 192.168.0.0/18 vpcID: ${vpc.status.vpcID} - - name: subnetAZB + - id: subnetAZB template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Subnet @@ -56,7 +56,7 @@ spec: availabilityZone: us-west-2b cidrBlock: 192.168.64.0/18 vpcID: ${vpc.status.vpcID} - - name: subnetAZC + - id: subnetAZC template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: Subnet @@ -66,7 +66,7 @@ spec: availabilityZone: us-west-2c cidrBlock: 192.168.128.0/18 vpcID: ${vpc.status.vpcID} - - name: securityGroup + - id: securityGroup template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: SecurityGroup diff --git a/website/docs/examples/ack-valkey-cachecluster.md b/website/docs/examples/ack-valkey-cachecluster.md index 38b02a46..a139e84c 100644 --- a/website/docs/examples/ack-valkey-cachecluster.md +++ b/website/docs/examples/ack-valkey-cachecluster.md @@ -20,7 +20,7 @@ spec: subnets: ${cacheSubnetGroup.status.subnets} clusterARN: ${valkey.status.ackResourceMetadata.arn} resources: - - name: networkingStack + - id: networkingStack template: apiVersion: kro.run/v1alpha1 kind: NetworkingStack @@ -28,7 +28,7 @@ spec: name: ${schema.spec.name}-networking-stack spec: name: ${schema.spec.name}-networking-stack - - name: cacheSubnetGroup + - id: cacheSubnetGroup template: apiVersion: elasticache.services.k8s.aws/v1alpha1 kind: CacheSubnetGroup @@ -41,7 +41,7 @@ spec: - ${networkingStack.status.networkingInfo.subnetAZA} - ${networkingStack.status.networkingInfo.subnetAZB} - ${networkingStack.status.networkingInfo.subnetAZC} - - name: sg + - id: sg template: apiVersion: ec2.services.k8s.aws/v1alpha1 kind: SecurityGroup @@ -57,7 +57,7 @@ spec: ipProtocol: tcp ipRanges: - cidrIP: 0.0.0.0/0 - - name: valkey + - id: valkey template: apiVersion: elasticache.services.k8s.aws/v1alpha1 kind: CacheCluster diff --git a/website/docs/examples/deploying-controller.md b/website/docs/examples/deploying-controller.md index 084c3246..5c38f969 100644 --- a/website/docs/examples/deploying-controller.md +++ b/website/docs/examples/deploying-controller.md @@ -47,7 +47,7 @@ spec: serviceAccount: name: string | default=eks-controller-sa resources: - - name: eksCRDGroup + - id: eksCRDGroup template: apiVersion: kro.run/v1alpha1 kind: EKSCRDGroup @@ -55,7 +55,7 @@ spec: name: ${schema.spec.name}-crd-group spec: name: ${schema.spec.name}-crd-group - - name: eksControllerIamPolicy + - id: eksControllerIamPolicy template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Policy @@ -82,7 +82,7 @@ spec: } ] } - - name: eksControllerIamRole + - id: eksControllerIamRole template: apiVersion: iam.services.k8s.aws/v1alpha1 kind: Role @@ -107,7 +107,7 @@ spec: } }] } - - name: serviceAccount + - id: serviceAccount template: apiVersion: v1 kind: ServiceAccount @@ -116,7 +116,7 @@ spec: namespace: ${schema.spec.namespace} annotations: eks.amazonaws.com/role-arn : ${eksControllerIamRole.status.ackResourceMetadata.arn} - - name: deployment + - id: deployment template: apiVersion: apps/v1 kind: Deployment @@ -175,7 +175,7 @@ spec: value: ${schema.spec.values.log.level} ports: - containerPort: 80 - - name: clusterRoleBinding + - id: clusterRoleBinding template: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding @@ -189,7 +189,7 @@ spec: - kind: ServiceAccount name: ${serviceAccount.metadata.name} namespace: ${serviceAccount.metadata.namespace} - - name: clusterRole + - id: clusterRole template: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole diff --git a/website/docs/examples/deploying-coredns.md b/website/docs/examples/deploying-coredns.md index aa483f06..e99e4304 100644 --- a/website/docs/examples/deploying-coredns.md +++ b/website/docs/examples/deploying-coredns.md @@ -47,7 +47,7 @@ spec: serviceAccount: secrets: 'map[string]string | default={"name": "coredns-token-pvcnf"}' resources: - - name: clusterRole + - id: clusterRole template: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -78,7 +78,7 @@ spec: - nodes verbs: - get - - name: clusterRoleBinding + - id: clusterRoleBinding template: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding @@ -94,7 +94,7 @@ spec: - kind: ServiceAccount name: ${serviceAccount.metadata.name} namespace: ${serviceAccount.metadata.namespace} - - name: configMap + - id: configMap template: apiVersion: v1 kind: ConfigMap @@ -117,7 +117,7 @@ spec: reload loadbalance } - - name: deployment + - id: deployment template: apiVersion: apps/v1 kind: Deployment @@ -149,7 +149,7 @@ spec: items: - key: Corefile path: Corefile - - name: service + - id: service template: apiVersion: v1 kind: Service @@ -176,7 +176,7 @@ spec: selector: k8s-app: kube-dns sessionAffinity: None - - name: serviceAccount + - id: serviceAccount template: apiVersion: v1 kind: ServiceAccount diff --git a/website/docs/examples/pod-rds-dbinstance.md b/website/docs/examples/pod-rds-dbinstance.md index e200f72b..3cc93e79 100644 --- a/website/docs/examples/pod-rds-dbinstance.md +++ b/website/docs/examples/pod-rds-dbinstance.md @@ -22,7 +22,7 @@ spec: # Resources resources: - - name: dbinstance + - id: dbinstance definition: apiVersion: rds.saervices.k8s.aws/v1alpha1 kind: DBInstance @@ -35,7 +35,7 @@ spec: allocatedStorage: 20 dbInstanceClass: db.t3.micro - - name: pod + - id: pod definition: apiVersion: v1 kind: Pod diff --git a/website/docs/examples/web-app-ingress.md b/website/docs/examples/web-app-ingress.md index 4113aed7..ad054e39 100644 --- a/website/docs/examples/web-app-ingress.md +++ b/website/docs/examples/web-app-ingress.md @@ -28,7 +28,7 @@ spec: # Define the resources this API will manage. resources: - - name: deployment + - id: deployment template: apiVersion: apps/v1 kind: Deployment @@ -50,7 +50,7 @@ spec: ports: - containerPort: 80 - - name: service + - id: service template: apiVersion: v1 kind: Service @@ -63,7 +63,7 @@ spec: port: 80 targetPort: 80 - - name: ingress + - id: ingress includeWhen: - ${schema.spec.ingress.enabled} # Only include if the user wants to create an Ingress template: diff --git a/website/docs/examples/web-app.md b/website/docs/examples/web-app.md index d8ee2b73..747f2bdb 100644 --- a/website/docs/examples/web-app.md +++ b/website/docs/examples/web-app.md @@ -16,7 +16,7 @@ spec: spec: name: string resources: - - name: deployment + - id: deployment definition: apiVersion: apps/v1 kind: Deployment @@ -37,7 +37,7 @@ spec: image: nginx ports: - containerPort: 80 - - name: service + - id: service definition: apiVersion: v1 kind: Service