diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/00-httpCreate-subscription/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/00-httpCreate-subscription/00-key.json new file mode 100644 index 0000000000..e7d8728dac --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/00-httpCreate-subscription/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/00-httpCreate-subscription/subscription.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/00-httpCreate-subscription/subscription.json new file mode 100644 index 0000000000..8d2fb61818 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/00-httpCreate-subscription/subscription.json @@ -0,0 +1,6 @@ +{ + "resourceId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7", + "state": "Registered", + "registrationDate": "2025-12-19T19:53:15+00:00", + "properties": null +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/01-httpCreate-basic-cluster/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/01-httpCreate-basic-cluster/00-key.json new file mode 100644 index 0000000000..e9508f1ffb --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/01-httpCreate-basic-cluster/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/01-httpCreate-basic-cluster/create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/01-httpCreate-basic-cluster/create-with-tags.json new file mode 100644 index 0000000000..93159ddf62 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/01-httpCreate-basic-cluster/create-with-tags.json @@ -0,0 +1,52 @@ +{ + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": {} + }, + "name": "create-with-tags", + "properties": { + "api": { + "visibility": "Public" + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "console": {}, + "dns": {}, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "version": { + "channelGroup": "stable" + } + }, + "tags": { + "one": "apple" + }, + "type": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/02-cosmosCompare-confirm-content/cluster-create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/02-cosmosCompare-confirm-content/cluster-create-with-tags.json new file mode 100644 index 0000000000..85e62da950 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/02-cosmosCompare-confirm-content/cluster-create-with-tags.json @@ -0,0 +1,83 @@ +{ + "_attachments": "attachments/", + "_etag": "\"00000000-0000-0000-7121-fd067c0501dc\"", + "_rid": "WZlNALYurecDAAAAAAAAAA==", + "_self": "dbs/WZlNAA==/colls/WZlNALYurec=/docs/WZlNALYurecDAAAAAAAAAA==/", + "_ts": 1766174370, + "id": "c893be2c-80b0-497f-8490-e3e5fd2b2cc4", + "partitionKey": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "properties": { + "activeOperationId": "7a4ed07a-47a1-4efb-966a-93a6316522a0", + "identity": { + "type": "UserAssigned" + }, + "internalId": "/api/clusters_mgmt/v1/clusters/f2jwkrlg2p", + "internalState": { + "internalAPI": { + "customerProperties": { + "api": { + "visibility": "Public" + }, + "autoscaling": { + "maxNodeProvisionTimeSeconds": 900, + "maxPodGracePeriodSeconds": 600, + "podPriorityThreshold": -10 + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "dns": {}, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "operatorsAuthentication": { + "userAssignedIdentities": {} + }, + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "version": { + "channelGroup": "stable" + } + }, + "location": "globals-are-evil", + "serviceProviderProperties": { + "api": {}, + "clusterServiceID": "", + "console": {}, + "dns": {}, + "platform": {} + } + } + }, + "provisioningState": "Accepted", + "resourceId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags", + "systemData": {}, + "tags": { + "one": "apple" + } + }, + "resourceType": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/02-cosmosCompare-confirm-content/operation-cluster-create-with-tags-create.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/02-cosmosCompare-confirm-content/operation-cluster-create-with-tags-create.json new file mode 100644 index 0000000000..eb5f621dbe --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/02-cosmosCompare-confirm-content/operation-cluster-create-with-tags-create.json @@ -0,0 +1,22 @@ +{ + "_attachments": "attachments/", + "_etag": "\"00000000-0000-0000-7121-fd067c0501dc\"", + "_rid": "WZlNALYurecCAAAAAAAAAA==", + "_self": "dbs/WZlNAA==/colls/WZlNALYurec=/docs/WZlNALYurecCAAAAAAAAAA==/", + "_ts": 1766174370, + "id": "7a4ed07a-47a1-4efb-966a-93a6316522a0", + "partitionKey": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "properties": { + "externalId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags", + "internalId": "/api/clusters_mgmt/v1/clusters/f2jwkrlg2p", + "lastTransitionTime": "2025-12-19T19:59:30.714826736Z", + "operationId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/providers/Microsoft.RedHatOpenShift/locations/globals-are-evil/hcpOperationStatuses/7a4ed07a-47a1-4efb-966a-93a6316522a0", + "request": "Create", + "resourceId": null, + "startTime": "2025-12-19T19:59:30.714826736Z", + "status": "Accepted", + "tenantId": "00000000-0000-0000-0000-000000000000" + }, + "resourceType": "Microsoft.RedHatOpenShift/hcpOperationStatuses", + "ttl": 604800 +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/02-cosmosCompare-confirm-content/subscription.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/02-cosmosCompare-confirm-content/subscription.json new file mode 100644 index 0000000000..eb217c3212 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/02-cosmosCompare-confirm-content/subscription.json @@ -0,0 +1,16 @@ +{ + "_attachments": "attachments/", + "_etag": "\"00000000-0000-0000-7121-fcdc980501dc\"", + "_rid": "WZlNALYurecBAAAAAAAAAA==", + "_self": "dbs/WZlNAA==/colls/WZlNALYurec=/docs/WZlNALYurecBAAAAAAAAAA==/", + "_ts": 1766174370, + "id": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "partitionKey": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "properties": { + "properties": null, + "registrationDate": "2025-12-19T19:53:15+00:00", + "resourceId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7", + "state": "Registered" + }, + "resourceType": "Microsoft.Resources/subscriptions" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/03-httpGet-basic-cluster/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/03-httpGet-basic-cluster/00-key.json new file mode 100644 index 0000000000..e9508f1ffb --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/03-httpGet-basic-cluster/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/03-httpGet-basic-cluster/create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/03-httpGet-basic-cluster/create-with-tags.json new file mode 100644 index 0000000000..ae8864936b --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/03-httpGet-basic-cluster/create-with-tags.json @@ -0,0 +1,56 @@ +{ + "identity": { + "type": "UserAssigned" + }, + "location": "globals-are-evil", + "name": "create-with-tags", + "properties": { + "api": { + "visibility": "Public" + }, + "autoscaling": { + "maxNodeProvisionTimeSeconds": 900, + "maxPodGracePeriodSeconds": 600, + "podPriorityThreshold": -10 + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "provisioningState": "Accepted", + "version": { + "channelGroup": "stable" + } + }, + "tags": { + "one": "apple" + }, + "type": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/04-httpList-clusters/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/04-httpList-clusters/00-key.json new file mode 100644 index 0000000000..56bf975f8b --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/04-httpList-clusters/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/dummy" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/04-httpList-clusters/create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/04-httpList-clusters/create-with-tags.json new file mode 100644 index 0000000000..ae8864936b --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/04-httpList-clusters/create-with-tags.json @@ -0,0 +1,56 @@ +{ + "identity": { + "type": "UserAssigned" + }, + "location": "globals-are-evil", + "name": "create-with-tags", + "properties": { + "api": { + "visibility": "Public" + }, + "autoscaling": { + "maxNodeProvisionTimeSeconds": 900, + "maxPodGracePeriodSeconds": 600, + "podPriorityThreshold": -10 + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "provisioningState": "Accepted", + "version": { + "channelGroup": "stable" + } + }, + "tags": { + "one": "apple" + }, + "type": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/05-listActiveOperations-cluster-create/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/05-listActiveOperations-cluster-create/00-key.json new file mode 100644 index 0000000000..7f2c44f66d --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/05-listActiveOperations-cluster-create/00-key.json @@ -0,0 +1,3 @@ +{ + "parentResourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/05-listActiveOperations-cluster-create/operation-cluster-create-with-tags-create.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/05-listActiveOperations-cluster-create/operation-cluster-create-with-tags-create.json new file mode 100644 index 0000000000..282111b8a9 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/05-listActiveOperations-cluster-create/operation-cluster-create-with-tags-create.json @@ -0,0 +1,11 @@ +{ + "resourceId": null, + "tenantId": "00000000-0000-0000-0000-000000000000", + "request": "Create", + "externalId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags", + "internalId": "/api/clusters_mgmt/v1/clusters/5c9qj7ft56", + "operationId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/providers/Microsoft.RedHatOpenShift/locations/globals-are-evil/hcpOperationStatuses/07314510-beb6-4379-902a-ab6452603265", + "startTime": "2025-12-19T20:41:44.99062756Z", + "lastTransitionTime": "2025-12-19T20:41:44.99062756Z", + "status": "Accepted" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/06-completeOperation-cluster-basic-cluster/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/06-completeOperation-cluster-basic-cluster/00-key.json new file mode 100644 index 0000000000..e9508f1ffb --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/06-completeOperation-cluster-basic-cluster/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/07-httpReplace-field/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/07-httpReplace-field/00-key.json new file mode 100644 index 0000000000..e9508f1ffb --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/07-httpReplace-field/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/07-httpReplace-field/create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/07-httpReplace-field/create-with-tags.json new file mode 100644 index 0000000000..0df62c39de --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/07-httpReplace-field/create-with-tags.json @@ -0,0 +1,57 @@ +{ + "identity": { + "type": "UserAssigned" + }, + "location": "globals-are-evil", + "name": "create-with-tags", + "properties": { + "api": { + "visibility": "Public" + }, + "autoscaling": { + "maxNodeProvisionTimeSeconds": 47, + "maxPodGracePeriodSeconds": 73, + "podPriorityThreshold": -6 + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "provisioningState": "Accepted", + "version": { + "channelGroup": "stable" + } + }, + "tags": { + "one": "apple", + "two": "banana" + }, + "type": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/08-httpGet-basic-cluster/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/08-httpGet-basic-cluster/00-key.json new file mode 100644 index 0000000000..e9508f1ffb --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/08-httpGet-basic-cluster/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/08-httpGet-basic-cluster/create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/08-httpGet-basic-cluster/create-with-tags.json new file mode 100644 index 0000000000..0df62c39de --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/08-httpGet-basic-cluster/create-with-tags.json @@ -0,0 +1,57 @@ +{ + "identity": { + "type": "UserAssigned" + }, + "location": "globals-are-evil", + "name": "create-with-tags", + "properties": { + "api": { + "visibility": "Public" + }, + "autoscaling": { + "maxNodeProvisionTimeSeconds": 47, + "maxPodGracePeriodSeconds": 73, + "podPriorityThreshold": -6 + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "provisioningState": "Accepted", + "version": { + "channelGroup": "stable" + } + }, + "tags": { + "one": "apple", + "two": "banana" + }, + "type": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/09-cosmosCompare-confirm-update/cluster-create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/09-cosmosCompare-confirm-update/cluster-create-with-tags.json new file mode 100644 index 0000000000..fce9a8cb94 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/create-current/09-cosmosCompare-confirm-update/cluster-create-with-tags.json @@ -0,0 +1,84 @@ +{ + "_attachments": "attachments/", + "_etag": "\"00000000-0000-0000-7121-fd067c0501dc\"", + "_rid": "WZlNALYurecDAAAAAAAAAA==", + "_self": "dbs/WZlNAA==/colls/WZlNALYurec=/docs/WZlNALYurecDAAAAAAAAAA==/", + "_ts": 1766174370, + "id": "c893be2c-80b0-497f-8490-e3e5fd2b2cc4", + "partitionKey": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "properties": { + "activeOperationId": "7a4ed07a-47a1-4efb-966a-93a6316522a0", + "identity": { + "type": "UserAssigned" + }, + "internalId": "/api/clusters_mgmt/v1/clusters/f2jwkrlg2p", + "internalState": { + "internalAPI": { + "customerProperties": { + "api": { + "visibility": "Public" + }, + "autoscaling": { + "maxNodeProvisionTimeSeconds": 47, + "maxPodGracePeriodSeconds": 73, + "podPriorityThreshold": -6 + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "dns": {}, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "operatorsAuthentication": { + "userAssignedIdentities": {} + }, + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "version": { + "channelGroup": "stable" + } + }, + "location": "globals-are-evil", + "serviceProviderProperties": { + "api": {}, + "clusterServiceID": "", + "console": {}, + "dns": {}, + "platform": {} + } + } + }, + "provisioningState": "Accepted", + "resourceId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags", + "systemData": {}, + "tags": { + "one": "apple", + "two": "banana" + } + }, + "resourceType": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/01-load-old-data/6b690bec-0c16-4ecb-8f67-781caf40bba7.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/01-load-old-data/6b690bec-0c16-4ecb-8f67-781caf40bba7.json new file mode 100644 index 0000000000..f722b276c8 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/01-load-old-data/6b690bec-0c16-4ecb-8f67-781caf40bba7.json @@ -0,0 +1,16 @@ +{ + "_attachments": "attachments/", + "_etag": "\"00000000-0000-0000-7e71-4b9c340501dc\"", + "_rid": "qr1CAKur9GQBAAAAAAAAAA==", + "_self": "dbs/qr1CAA==/colls/qr1CAKur9GQ=/docs/qr1CAKur9GQBAAAAAAAAAA==/", + "_ts": 1767637797, + "id": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "partitionKey": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "properties": { + "properties": null, + "registrationDate": "2025-12-19T19:53:15+00:00", + "resourceId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7", + "state": "Registered" + }, + "resourceType": "Microsoft.Resources/subscriptions" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/01-load-old-data/create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/01-load-old-data/create-with-tags.json new file mode 100644 index 0000000000..54123632d2 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/01-load-old-data/create-with-tags.json @@ -0,0 +1,83 @@ +{ + "_attachments": "attachments/", + "_etag": "\"00000000-0000-0000-7e71-4bc5740501dc\"", + "_rid": "qr1CAKur9GQDAAAAAAAAAA==", + "_self": "dbs/qr1CAA==/colls/qr1CAKur9GQ=/docs/qr1CAKur9GQDAAAAAAAAAA==/", + "_ts": 1767637798, + "id": "9462c9da-42ac-4606-ad99-84e4f3ec0977", + "partitionKey": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "properties": { + "activeOperationId": "90b2322c-2c26-47ca-b6f9-d9b1a8385cbc", + "identity": { + "type": "UserAssigned" + }, + "internalId": "/api/clusters_mgmt/v1/clusters/9p2sk955gj", + "internalState": { + "internalAPI": { + "customerProperties": { + "api": { + "visibility": "Public" + }, + "autoscaling": { + "maxNodeProvisionTimeSeconds": 900, + "maxPodGracePeriodSeconds": 600, + "podPriorityThreshold": -10 + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "dns": {}, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "operatorsAuthentication": { + "userAssignedIdentities": {} + }, + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "version": { + "channelGroup": "stable" + } + }, + "location": "globals-are-evil", + "serviceProviderProperties": { + "api": {}, + "clusterServiceID": "", + "console": {}, + "dns": {}, + "platform": {} + } + } + }, + "provisioningState": "Accepted", + "resourceId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags", + "systemData": {}, + "tags": { + "one": "apple" + } + }, + "resourceType": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/01-load-old-data/hcpoperationstatuses_Create_90b2322c-2c26-47ca-b6f9-d9b1a8385cbc.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/01-load-old-data/hcpoperationstatuses_Create_90b2322c-2c26-47ca-b6f9-d9b1a8385cbc.json new file mode 100644 index 0000000000..522e43878d --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/01-load-old-data/hcpoperationstatuses_Create_90b2322c-2c26-47ca-b6f9-d9b1a8385cbc.json @@ -0,0 +1,22 @@ +{ + "_attachments": "attachments/", + "_etag": "\"00000000-0000-0000-7e71-4bc4d00501dc\"", + "_rid": "qr1CAKur9GQCAAAAAAAAAA==", + "_self": "dbs/qr1CAA==/colls/qr1CAKur9GQ=/docs/qr1CAKur9GQCAAAAAAAAAA==/", + "_ts": 1767637798, + "id": "90b2322c-2c26-47ca-b6f9-d9b1a8385cbc", + "partitionKey": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "properties": { + "externalId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags", + "internalId": "/api/clusters_mgmt/v1/clusters/9p2sk955gj", + "lastTransitionTime": "2026-01-05T18:29:58.181047849Z", + "operationId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/providers/Microsoft.RedHatOpenShift/locations/globals-are-evil/hcpOperationStatuses/90b2322c-2c26-47ca-b6f9-d9b1a8385cbc", + "request": "Create", + "resourceId": null, + "startTime": "2026-01-05T18:29:58.181047849Z", + "status": "Accepted", + "tenantId": "00000000-0000-0000-0000-000000000000" + }, + "resourceType": "Microsoft.RedHatOpenShift/hcpOperationStatuses", + "ttl": 604800 +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/02-loadClusterService-old-data/0_.api.clusters_mgmt.v1.clusters.9p2sk955gj-autoscaler.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/02-loadClusterService-old-data/0_.api.clusters_mgmt.v1.clusters.9p2sk955gj-autoscaler.json new file mode 100644 index 0000000000..baf289a382 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/02-loadClusterService-old-data/0_.api.clusters_mgmt.v1.clusters.9p2sk955gj-autoscaler.json @@ -0,0 +1,10 @@ +{ + "href": "/api/clusters_mgmt/v1/clusters/9p2sk955gj", + "kind": "ClusterAutoscaler", + "max_node_provision_time": "15m", + "max_pod_grace_period": 600, + "pod_priority_threshold": -10, + "resource_limits": { + "max_nodes_total": 0 + } +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/02-loadClusterService-old-data/0_.api.clusters_mgmt.v1.clusters.9p2sk955gj-cluster.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/02-loadClusterService-old-data/0_.api.clusters_mgmt.v1.clusters.9p2sk955gj-cluster.json new file mode 100644 index 0000000000..88fd962a55 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/02-loadClusterService-old-data/0_.api.clusters_mgmt.v1.clusters.9p2sk955gj-cluster.json @@ -0,0 +1,90 @@ +{ + "api": { + "cidr_block_access": { + "allow": { + "mode": "allow_all" + } + }, + "listening": "external" + }, + "azure": { + "etcd_encryption": { + "data_encryption": { + "customer_managed": { + "encryption_type": "kms", + "kms": { + "active_key": { + "key_name": "encryptionKeyName", + "key_vault_name": "keyVaultName", + "key_version": "2024-12-01-preview" + } + } + }, + "key_management_mode": "customer_managed" + } + }, + "managed_resource_group_name": "managed-resource-group-name", + "network_security_group_resource_id": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "nodes_outbound_connectivity": { + "outbound_type": "load_balancer" + }, + "operators_authentication": { + "managed_identities": { + "control_plane_operators_managed_identities": {}, + "data_plane_operators_managed_identities": {}, + "managed_identities_data_plane_identity_url": "" + } + }, + "resource_group_name": "resourcegroupname", + "resource_name": "create-with-tags", + "subnet_resource_id": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet", + "subscription_id": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "tenant_id": "00000000-0000-0000-0000-000000000000" + }, + "ccs": { + "enabled": true, + "kind": "CCS" + }, + "cloud_provider": { + "id": "azure", + "kind": "CloudProvider" + }, + "flavour": { + "id": "osd-4", + "kind": "Flavour" + }, + "href": "/api/clusters_mgmt/v1/clusters/9p2sk955gj", + "hypershift": { + "enabled": true + }, + "id": "9p2sk955gj", + "image_registry": { + "state": "disabled" + }, + "kind": "Cluster", + "name": "create-with-tags", + "network": { + "host_prefix": 23, + "machine_cidr": "10.0.0.0/16", + "pod_cidr": "10.128.0.0/14", + "service_cidr": "172.30.0.0/16", + "type": "OVNKubernetes" + }, + "node_drain_grace_period": { + "unit": "minutes", + "value": 0 + }, + "product": { + "id": "aro", + "kind": "Product" + }, + "region": { + "id": "globals-are-evil", + "kind": "CloudRegion" + }, + "version": { + "channel_group": "stable", + "id": "", + "kind": "Version" + } +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/03-httpGet-basic-cluster/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/03-httpGet-basic-cluster/00-key.json new file mode 100644 index 0000000000..e9508f1ffb --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/03-httpGet-basic-cluster/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/03-httpGet-basic-cluster/create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/03-httpGet-basic-cluster/create-with-tags.json new file mode 100644 index 0000000000..ae8864936b --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/03-httpGet-basic-cluster/create-with-tags.json @@ -0,0 +1,56 @@ +{ + "identity": { + "type": "UserAssigned" + }, + "location": "globals-are-evil", + "name": "create-with-tags", + "properties": { + "api": { + "visibility": "Public" + }, + "autoscaling": { + "maxNodeProvisionTimeSeconds": 900, + "maxPodGracePeriodSeconds": 600, + "podPriorityThreshold": -10 + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "provisioningState": "Accepted", + "version": { + "channelGroup": "stable" + } + }, + "tags": { + "one": "apple" + }, + "type": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/04-httpList-clusters/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/04-httpList-clusters/00-key.json new file mode 100644 index 0000000000..56bf975f8b --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/04-httpList-clusters/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/dummy" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/04-httpList-clusters/create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/04-httpList-clusters/create-with-tags.json new file mode 100644 index 0000000000..ae8864936b --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/04-httpList-clusters/create-with-tags.json @@ -0,0 +1,56 @@ +{ + "identity": { + "type": "UserAssigned" + }, + "location": "globals-are-evil", + "name": "create-with-tags", + "properties": { + "api": { + "visibility": "Public" + }, + "autoscaling": { + "maxNodeProvisionTimeSeconds": 900, + "maxPodGracePeriodSeconds": 600, + "podPriorityThreshold": -10 + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "provisioningState": "Accepted", + "version": { + "channelGroup": "stable" + } + }, + "tags": { + "one": "apple" + }, + "type": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/04-listActiveOperations-cluster-create/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/04-listActiveOperations-cluster-create/00-key.json new file mode 100644 index 0000000000..7f2c44f66d --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/04-listActiveOperations-cluster-create/00-key.json @@ -0,0 +1,3 @@ +{ + "parentResourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/04-listActiveOperations-cluster-create/operation-cluster-create-with-tags-create.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/04-listActiveOperations-cluster-create/operation-cluster-create-with-tags-create.json new file mode 100644 index 0000000000..282111b8a9 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/04-listActiveOperations-cluster-create/operation-cluster-create-with-tags-create.json @@ -0,0 +1,11 @@ +{ + "resourceId": null, + "tenantId": "00000000-0000-0000-0000-000000000000", + "request": "Create", + "externalId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags", + "internalId": "/api/clusters_mgmt/v1/clusters/5c9qj7ft56", + "operationId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/providers/Microsoft.RedHatOpenShift/locations/globals-are-evil/hcpOperationStatuses/07314510-beb6-4379-902a-ab6452603265", + "startTime": "2025-12-19T20:41:44.99062756Z", + "lastTransitionTime": "2025-12-19T20:41:44.99062756Z", + "status": "Accepted" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/06-completeOperation-cluster-basic-cluster/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/06-completeOperation-cluster-basic-cluster/00-key.json new file mode 100644 index 0000000000..e9508f1ffb --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/06-completeOperation-cluster-basic-cluster/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/07-httpReplace-field/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/07-httpReplace-field/00-key.json new file mode 100644 index 0000000000..e9508f1ffb --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/07-httpReplace-field/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/07-httpReplace-field/create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/07-httpReplace-field/create-with-tags.json new file mode 100644 index 0000000000..0df62c39de --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/07-httpReplace-field/create-with-tags.json @@ -0,0 +1,57 @@ +{ + "identity": { + "type": "UserAssigned" + }, + "location": "globals-are-evil", + "name": "create-with-tags", + "properties": { + "api": { + "visibility": "Public" + }, + "autoscaling": { + "maxNodeProvisionTimeSeconds": 47, + "maxPodGracePeriodSeconds": 73, + "podPriorityThreshold": -6 + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "provisioningState": "Accepted", + "version": { + "channelGroup": "stable" + } + }, + "tags": { + "one": "apple", + "two": "banana" + }, + "type": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/08-httpGet-basic-cluster/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/08-httpGet-basic-cluster/00-key.json new file mode 100644 index 0000000000..e9508f1ffb --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/08-httpGet-basic-cluster/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/08-httpGet-basic-cluster/create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/08-httpGet-basic-cluster/create-with-tags.json new file mode 100644 index 0000000000..0df62c39de --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/08-httpGet-basic-cluster/create-with-tags.json @@ -0,0 +1,57 @@ +{ + "identity": { + "type": "UserAssigned" + }, + "location": "globals-are-evil", + "name": "create-with-tags", + "properties": { + "api": { + "visibility": "Public" + }, + "autoscaling": { + "maxNodeProvisionTimeSeconds": 47, + "maxPodGracePeriodSeconds": 73, + "podPriorityThreshold": -6 + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "provisioningState": "Accepted", + "version": { + "channelGroup": "stable" + } + }, + "tags": { + "one": "apple", + "two": "banana" + }, + "type": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} diff --git a/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/09-cosmosCompare-confirm-update/cluster-create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/09-cosmosCompare-confirm-update/cluster-create-with-tags.json new file mode 100644 index 0000000000..fce9a8cb94 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/Cluster/read-old-data/09-cosmosCompare-confirm-update/cluster-create-with-tags.json @@ -0,0 +1,84 @@ +{ + "_attachments": "attachments/", + "_etag": "\"00000000-0000-0000-7121-fd067c0501dc\"", + "_rid": "WZlNALYurecDAAAAAAAAAA==", + "_self": "dbs/WZlNAA==/colls/WZlNALYurec=/docs/WZlNALYurecDAAAAAAAAAA==/", + "_ts": 1766174370, + "id": "c893be2c-80b0-497f-8490-e3e5fd2b2cc4", + "partitionKey": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "properties": { + "activeOperationId": "7a4ed07a-47a1-4efb-966a-93a6316522a0", + "identity": { + "type": "UserAssigned" + }, + "internalId": "/api/clusters_mgmt/v1/clusters/f2jwkrlg2p", + "internalState": { + "internalAPI": { + "customerProperties": { + "api": { + "visibility": "Public" + }, + "autoscaling": { + "maxNodeProvisionTimeSeconds": 47, + "maxPodGracePeriodSeconds": 73, + "podPriorityThreshold": -6 + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "dns": {}, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "operatorsAuthentication": { + "userAssignedIdentities": {} + }, + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "version": { + "channelGroup": "stable" + } + }, + "location": "globals-are-evil", + "serviceProviderProperties": { + "api": {}, + "clusterServiceID": "", + "console": {}, + "dns": {}, + "platform": {} + } + } + }, + "provisioningState": "Accepted", + "resourceId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags", + "systemData": {}, + "tags": { + "one": "apple", + "two": "banana" + } + }, + "resourceType": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/00-httpCreate-subscription/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/00-httpCreate-subscription/00-key.json new file mode 100644 index 0000000000..e7d8728dac --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/00-httpCreate-subscription/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/00-httpCreate-subscription/subscription.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/00-httpCreate-subscription/subscription.json new file mode 100644 index 0000000000..8d2fb61818 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/00-httpCreate-subscription/subscription.json @@ -0,0 +1,6 @@ +{ + "resourceId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7", + "state": "Registered", + "registrationDate": "2025-12-19T19:53:15+00:00", + "properties": null +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/01-httpCreate-basic-cluster/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/01-httpCreate-basic-cluster/00-key.json new file mode 100644 index 0000000000..e9508f1ffb --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/01-httpCreate-basic-cluster/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/01-httpCreate-basic-cluster/create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/01-httpCreate-basic-cluster/create-with-tags.json new file mode 100644 index 0000000000..93159ddf62 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/01-httpCreate-basic-cluster/create-with-tags.json @@ -0,0 +1,52 @@ +{ + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": {} + }, + "name": "create-with-tags", + "properties": { + "api": { + "visibility": "Public" + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "console": {}, + "dns": {}, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "version": { + "channelGroup": "stable" + } + }, + "tags": { + "one": "apple" + }, + "type": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/02-completeOperation-cluster-basic-cluster/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/02-completeOperation-cluster-basic-cluster/00-key.json new file mode 100644 index 0000000000..e9508f1ffb --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/02-completeOperation-cluster-basic-cluster/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/03-httpCreate-basic-nodepool/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/03-httpCreate-basic-nodepool/00-key.json new file mode 100644 index 0000000000..0df6ff26e6 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/03-httpCreate-basic-nodepool/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags/nodePools/basic-node-pool" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/03-httpCreate-basic-nodepool/basic-node-pool.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/03-httpCreate-basic-nodepool/basic-node-pool.json new file mode 100644 index 0000000000..0db7827eb0 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/03-httpCreate-basic-nodepool/basic-node-pool.json @@ -0,0 +1,28 @@ +{ + "name": "basic-node-pool", + "properties": { + "autoRepair": true, + "autoScaling": { + "min": 1, + "max": 5 + }, + "labels": [ + { + "key": "label-ky", + "value": "label-value" + } + ], + "nodeDrainTimeoutMinutes": 2, + "platform": { + "vmSize": "large" + }, + "taints": [ + { + "effect": "NoExecute", + "key": "foo.com/key", + "value": "valid" + } + ] + }, + "type": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters/nodePools" +} diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/04-httpCreate-second-nodepool/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/04-httpCreate-second-nodepool/00-key.json new file mode 100644 index 0000000000..f8cd07a7c7 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/04-httpCreate-second-nodepool/00-key.json @@ -0,0 +1,3 @@ +{ + "resourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags/nodePools/node-pool-02" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/04-httpCreate-second-nodepool/second-node-pool.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/04-httpCreate-second-nodepool/second-node-pool.json new file mode 100644 index 0000000000..9022b8b5f4 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/04-httpCreate-second-nodepool/second-node-pool.json @@ -0,0 +1,28 @@ +{ + "name": "node-pool-02", + "properties": { + "autoRepair": true, + "autoScaling": { + "min": 1, + "max": 5 + }, + "labels": [ + { + "key": "label-ky", + "value": "label-value" + } + ], + "nodeDrainTimeoutMinutes": 2, + "platform": { + "vmSize": "large" + }, + "taints": [ + { + "effect": "NoExecute", + "key": "foo.com/key", + "value": "valid" + } + ] + }, + "type": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters/nodePools" +} diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/05-listActiveOperations-cluster-create/00-key.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/05-listActiveOperations-cluster-create/00-key.json new file mode 100644 index 0000000000..7f2c44f66d --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/05-listActiveOperations-cluster-create/00-key.json @@ -0,0 +1,3 @@ +{ + "parentResourceID": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/05-listActiveOperations-cluster-create/operation-nodepool-create-basic-nodepool.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/05-listActiveOperations-cluster-create/operation-nodepool-create-basic-nodepool.json new file mode 100644 index 0000000000..d0219d1877 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/05-listActiveOperations-cluster-create/operation-nodepool-create-basic-nodepool.json @@ -0,0 +1,11 @@ +{ + "resourceId": null, + "tenantId": "00000000-0000-0000-0000-000000000000", + "request": "Create", + "externalId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags/nodePools/basic-node-pool", + "internalId": "/api/clusters_mgmt/v1/clusters/lm9l7hfwqc/node_pools/kd4vt5d8gb", + "operationId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/providers/Microsoft.RedHatOpenShift/locations/globals-are-evil/hcpOperationStatuses/7c3de93c-ff5d-4865-a177-291549ba8020", + "startTime": "2025-12-19T21:03:42.649357713Z", + "lastTransitionTime": "2025-12-19T21:03:42.649357713Z", + "status": "Accepted" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/05-listActiveOperations-cluster-create/operation-nodepool-create-nodepool-02.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/05-listActiveOperations-cluster-create/operation-nodepool-create-nodepool-02.json new file mode 100644 index 0000000000..67732f3d5b --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/05-listActiveOperations-cluster-create/operation-nodepool-create-nodepool-02.json @@ -0,0 +1,11 @@ +{ + "resourceId": null, + "tenantId": "00000000-0000-0000-0000-000000000000", + "request": "Create", + "externalId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags/nodePools/node-pool-02", + "internalId": "/api/clusters_mgmt/v1/clusters/lm9l7hfwqc/node_pools/7sthr8c5f6", + "operationId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/providers/Microsoft.RedHatOpenShift/locations/globals-are-evil/hcpOperationStatuses/c1216e33-a694-4a65-a504-d821c30dc67c", + "startTime": "2025-12-19T21:03:42.924755264Z", + "lastTransitionTime": "2025-12-19T21:03:42.924755264Z", + "status": "Accepted" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/cluster-create-with-tags.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/cluster-create-with-tags.json new file mode 100644 index 0000000000..5f5190cd41 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/cluster-create-with-tags.json @@ -0,0 +1,83 @@ +{ + "_attachments": "attachments/", + "_etag": "\"00000000-0000-0000-7121-fd067c0501dc\"", + "_rid": "WZlNALYurecDAAAAAAAAAA==", + "_self": "dbs/WZlNAA==/colls/WZlNALYurec=/docs/WZlNALYurecDAAAAAAAAAA==/", + "_ts": 1766174370, + "id": "c893be2c-80b0-497f-8490-e3e5fd2b2cc4", + "partitionKey": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "properties": { + "activeOperationId": "7a4ed07a-47a1-4efb-966a-93a6316522a0", + "identity": { + "type": "UserAssigned" + }, + "internalId": "/api/clusters_mgmt/v1/clusters/f2jwkrlg2p", + "internalState": { + "internalAPI": { + "customerProperties": { + "api": { + "visibility": "Public" + }, + "autoscaling": { + "maxNodeProvisionTimeSeconds": 900, + "maxPodGracePeriodSeconds": 600, + "podPriorityThreshold": -10 + }, + "clusterImageRegistry": { + "state": "Disabled" + }, + "dns": {}, + "etcd": { + "dataEncryption": { + "customerManaged": { + "encryptionType": "KMS", + "kms": { + "activeKey": { + "name": "encryptionKeyName", + "vaultName": "keyVaultName", + "version": "2024-12-01-preview" + } + } + }, + "keyManagementMode": "CustomerManaged" + } + }, + "network": { + "hostPrefix": 23, + "machineCidr": "10.0.0.0/16", + "networkType": "OVNKubernetes", + "podCidr": "10.128.0.0/14", + "serviceCidr": "172.30.0.0/16" + }, + "platform": { + "managedResourceGroup": "managed-resource-group-name", + "networkSecurityGroupId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/networkSecurityGroups/nsg", + "operatorsAuthentication": { + "userAssignedIdentities": {} + }, + "outboundType": "LoadBalancer", + "subnetId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/bar/providers/Microsoft.Network/virtualNetworks/vnet/subnets/subnet" + }, + "version": { + "channelGroup": "stable" + } + }, + "location": "globals-are-evil", + "serviceProviderProperties": { + "api": {}, + "clusterServiceID": "", + "console": {}, + "dns": {}, + "platform": {} + } + } + }, + "provisioningState": "Succeeded", + "resourceId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags", + "systemData": {}, + "tags": { + "one": "apple" + } + }, + "resourceType": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/nodepool-basic-node-pool.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/nodepool-basic-node-pool.json new file mode 100644 index 0000000000..5d31a89753 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/nodepool-basic-node-pool.json @@ -0,0 +1,54 @@ +{ + "_attachments": "attachments/", + "_etag": "\"00000000-0000-0000-712b-4dda080501dc\"", + "_rid": "SdEpAPzZNVkFAAAAAAAAAA==", + "_self": "dbs/SdEpAA==/colls/SdEpAPzZNVk=/docs/SdEpAPzZNVkFAAAAAAAAAA==/", + "_ts": 1766178371, + "id": "23bd08bc-2ed3-40be-8c9e-7e005f8a421f", + "partitionKey": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "properties": { + "activeOperationId": "a7b69c90-242b-4a85-8187-0b3bd4979155", + "internalId": "/api/clusters_mgmt/v1/clusters/w9xhwccbjp/node_pools/k9xp9ghzh2", + "internalState": { + "internalAPI": { + "location": "globals-are-evil", + "properties": { + "autoRepair": true, + "autoScaling": { + "max": 5, + "min": 1 + }, + "labels": { + "label-ky": "label-value" + }, + "nodeDrainTimeoutMinutes": 2, + "platform": { + "enableEncryptionAtHost": false, + "osDisk": { + "diskStorageAccountType": "Premium_LRS", + "sizeGiB": 64 + }, + "vmSize": "large" + }, + "taints": [ + { + "effect": "NoExecute", + "key": "foo.com/key", + "value": "valid" + } + ], + "version": { + "channelGroup": "stable" + } + }, + "serviceProviderProperties": { + "clusterServiceID": "" + } + } + }, + "provisioningState": "Accepted", + "resourceId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags/nodePools/basic-node-pool", + "systemData": {} + }, + "resourceType": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters/nodePools" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/nodepool-node-pool-02.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/nodepool-node-pool-02.json new file mode 100644 index 0000000000..a24ff01fc8 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/nodepool-node-pool-02.json @@ -0,0 +1,54 @@ +{ + "_attachments": "attachments/", + "_etag": "\"00000000-0000-0000-712b-4e012c0501dc\"", + "_rid": "SdEpAPzZNVkHAAAAAAAAAA==", + "_self": "dbs/SdEpAA==/colls/SdEpAPzZNVk=/docs/SdEpAPzZNVkHAAAAAAAAAA==/", + "_ts": 1766178372, + "id": "405f85e0-9528-458d-abbf-b16e2319c833", + "partitionKey": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "properties": { + "activeOperationId": "0129e72d-1f34-4630-9c58-725bd97283c6", + "internalId": "/api/clusters_mgmt/v1/clusters/w9xhwccbjp/node_pools/7r9c4pvw4p", + "internalState": { + "internalAPI": { + "location": "globals-are-evil", + "properties": { + "autoRepair": true, + "autoScaling": { + "max": 5, + "min": 1 + }, + "labels": { + "label-ky": "label-value" + }, + "nodeDrainTimeoutMinutes": 2, + "platform": { + "enableEncryptionAtHost": false, + "osDisk": { + "diskStorageAccountType": "Premium_LRS", + "sizeGiB": 64 + }, + "vmSize": "large" + }, + "taints": [ + { + "effect": "NoExecute", + "key": "foo.com/key", + "value": "valid" + } + ], + "version": { + "channelGroup": "stable" + } + }, + "serviceProviderProperties": { + "clusterServiceID": "" + } + } + }, + "provisioningState": "Accepted", + "resourceId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags/nodePools/node-pool-02", + "systemData": {} + }, + "resourceType": "Microsoft.RedHatOpenShift/hcpOpenShiftClusters/nodePools" +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/operation-cluster-create-with-tags-create.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/operation-cluster-create-with-tags-create.json new file mode 100644 index 0000000000..fe78413921 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/operation-cluster-create-with-tags-create.json @@ -0,0 +1,22 @@ +{ + "_attachments": "attachments/", + "_etag": "\"00000000-0000-0000-7121-fd067c0501dc\"", + "_rid": "WZlNALYurecCAAAAAAAAAA==", + "_self": "dbs/WZlNAA==/colls/WZlNALYurec=/docs/WZlNALYurecCAAAAAAAAAA==/", + "_ts": 1766174370, + "id": "7a4ed07a-47a1-4efb-966a-93a6316522a0", + "partitionKey": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "properties": { + "externalId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/resourceGroups/resourceGroupName/providers/Microsoft.RedHatOpenShift/hcpOpenShiftClusters/create-with-tags", + "internalId": "/api/clusters_mgmt/v1/clusters/f2jwkrlg2p", + "lastTransitionTime": "2025-12-19T19:59:30.714826736Z", + "operationId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7/providers/Microsoft.RedHatOpenShift/locations/globals-are-evil/hcpOperationStatuses/7a4ed07a-47a1-4efb-966a-93a6316522a0", + "request": "Create", + "resourceId": null, + "startTime": "2025-12-19T19:59:30.714826736Z", + "status": "Succeeded", + "tenantId": "00000000-0000-0000-0000-000000000000" + }, + "resourceType": "Microsoft.RedHatOpenShift/hcpOperationStatuses", + "ttl": 604800 +} \ No newline at end of file diff --git a/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/subscription.json b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/subscription.json new file mode 100644 index 0000000000..eb217c3212 --- /dev/null +++ b/test-integration/frontend/artifacts/FrontendCRUD/NodePool/create-current/06-cosmosCompare-confirm-content/subscription.json @@ -0,0 +1,16 @@ +{ + "_attachments": "attachments/", + "_etag": "\"00000000-0000-0000-7121-fcdc980501dc\"", + "_rid": "WZlNALYurecBAAAAAAAAAA==", + "_self": "dbs/WZlNAA==/colls/WZlNALYurec=/docs/WZlNALYurecBAAAAAAAAAA==/", + "_ts": 1766174370, + "id": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "partitionKey": "6b690bec-0c16-4ecb-8f67-781caf40bba7", + "properties": { + "properties": null, + "registrationDate": "2025-12-19T19:53:15+00:00", + "resourceId": "/subscriptions/6b690bec-0c16-4ecb-8f67-781caf40bba7", + "state": "Registered" + }, + "resourceType": "Microsoft.Resources/subscriptions" +} \ No newline at end of file diff --git a/test-integration/frontend/frontend_crud_test.go b/test-integration/frontend/frontend_crud_test.go new file mode 100644 index 0000000000..e90aeb6a97 --- /dev/null +++ b/test-integration/frontend/frontend_crud_test.go @@ -0,0 +1,50 @@ +// Copyright 2025 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package frontend + +import ( + "context" + "io/fs" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/Azure/ARO-HCP/internal/api" + "github.com/Azure/ARO-HCP/test-integration/utils/databasemutationhelpers" + "github.com/Azure/ARO-HCP/test-integration/utils/integrationutils" +) + +func TestFrontendCRUD(t *testing.T) { + integrationutils.SkipIfNotSimulationTesting(t) + + ctx := context.Background() + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + allCRUDDirFS, err := fs.Sub(artifacts, "artifacts/FrontendCRUD") + require.NoError(t, err) + + crudSuiteDirs := api.Must(fs.ReadDir(allCRUDDirFS, ".")) + for _, crudSuiteDirEntry := range crudSuiteDirs { + crudSuiteDir := api.Must(fs.Sub(allCRUDDirFS, crudSuiteDirEntry.Name())) + t.Run(crudSuiteDirEntry.Name(), func(t *testing.T) { + testCRUDSuite( + ctx, + t, + databasemutationhelpers.NothingCRUDSpecializer{}, + crudSuiteDir) + }) + } +} diff --git a/test-integration/utils/controllertesthelpers/basic_controller.go b/test-integration/utils/controllertesthelpers/basic_controller.go index 6cea4f739a..5f80fe1030 100644 --- a/test-integration/utils/controllertesthelpers/basic_controller.go +++ b/test-integration/utils/controllertesthelpers/basic_controller.go @@ -61,19 +61,22 @@ func (tc *BasicControllerTest) RunTest(t *testing.T) { logger = tc.ControllerKey.AddLoggerValues(logger) ctx = utils.ContextWithLogger(ctx, logger) - cosmosTestInfo, err := integrationutils.NewCosmosFromTestingEnv(ctx) + cosmosTestInfo, err := integrationutils.NewCosmosFromTestingEnv(ctx, t) require.NoError(t, err) defer cosmosTestInfo.Cleanup(utils.ContextWithLogger(context.Background(), slogt.New(t, slogt.JSON()))) initialState, err := fs.Sub(testDir, path.Join("00-load-initial-state")) require.NoError(t, err) if fsMightContainFiles(initialState) { - loadInitialStateStep, err := databasemutationhelpers.NewLoadStep( + loadInitialStateStep, err := databasemutationhelpers.NewLoadCosmosStep( databasemutationhelpers.NewStepID(00, "load", "initial-state"), initialState, ) require.NoError(t, err) - loadInitialStateStep.RunTest(ctx, t, cosmosTestInfo.CosmosResourcesContainer()) + input := databasemutationhelpers.StepInput{ + CosmosContainer: cosmosTestInfo.CosmosResourcesContainer(), + } + loadInitialStateStep.RunTest(ctx, t, input) } controllerInstance, testMemory := tc.ControllerInitializerFn(ctx, t, cosmosTestInfo.DBClient) @@ -88,7 +91,10 @@ func (tc *BasicControllerTest) RunTest(t *testing.T) { endState, ) require.NoError(t, err) - verifyEndStateStep.RunTest(ctx, t, cosmosTestInfo.CosmosResourcesContainer()) + input := databasemutationhelpers.StepInput{ + CosmosContainer: cosmosTestInfo.CosmosResourcesContainer(), + } + verifyEndStateStep.RunTest(ctx, t, input) } tc.ControllerVerifierFn(ctx, t, controllerInstance, testMemory) diff --git a/test-integration/utils/databasemutationhelpers/per_resource_comparer.go b/test-integration/utils/databasemutationhelpers/per_resource_comparer.go new file mode 100644 index 0000000000..dce7f8b70f --- /dev/null +++ b/test-integration/utils/databasemutationhelpers/per_resource_comparer.go @@ -0,0 +1,89 @@ +// Copyright 2026 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package databasemutationhelpers + +import ( + "encoding/json" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" + + "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" +) + +func ResourceInstanceEquals(t *testing.T, expected, actual any) (string, bool) { + expectedBytes, err := json.Marshal(expected) + require.NoError(t, err) + actualBytes, err := json.Marshal(actual) + require.NoError(t, err) + + expectedMap := map[string]any{} + require.NoError(t, json.Unmarshal(expectedBytes, &expectedMap)) + actualMap := map[string]any{} + require.NoError(t, json.Unmarshal(actualBytes, &actualMap)) + + // clear the fields from TypedDocument (wrapper) that don't compare + for _, currMap := range []map[string]any{expectedMap, actualMap} { + unstructured.RemoveNestedField(currMap, "id") // TODO restore when names are predictable + unstructured.RemoveNestedField(currMap, "_rid") + unstructured.RemoveNestedField(currMap, "_self") + unstructured.RemoveNestedField(currMap, "_etag") + unstructured.RemoveNestedField(currMap, "_attachments") + unstructured.RemoveNestedField(currMap, "_ts") + + // this loops handles the cosmosObj possibility and the internalObj possibility + for _, possiblePrepend := range []string{"", "properties"} { + unstructured.RemoveNestedField(currMap, prepend(possiblePrepend, "lastTransitionTime")...) // operations + unstructured.RemoveNestedField(currMap, prepend(possiblePrepend, "startTime")...) // operations + unstructured.RemoveNestedField(currMap, prepend(possiblePrepend, "operationId")...) // operations + unstructured.RemoveNestedField(currMap, prepend(possiblePrepend, "activeOperationId")...) // cluster, nodepool, externalauth + unstructured.RemoveNestedField(currMap, prepend(possiblePrepend, "internalId")...) // cluster, nodepool, externalauth + unstructured.RemoveNestedField(currMap, prepend(possiblePrepend, "cosmosUID")...) // controllers + unstructured.RemoveNestedField(currMap, prepend(possiblePrepend, "serviceProviderProperties", "cosmosUID")...) // cluster, nodepool, externalauth + + // for controllers + expectedConditions, found, err := unstructured.NestedSlice(currMap, prepend(possiblePrepend, "internalState", "status", "conditions")...) + if found && err == nil { + for i := range expectedConditions { + delete(expectedConditions[i].(map[string]any), "lastTransitionTime") + } + if err := unstructured.SetNestedSlice(currMap, expectedConditions, prepend(possiblePrepend, "internalState", "status", "conditions")...); err != nil { + panic(err) + } + } + + actualConditions, found, err := unstructured.NestedSlice(currMap, prepend(possiblePrepend, "internalState", "status", "conditions")...) + if found && err == nil { + for i := range actualConditions { + delete(actualConditions[i].(map[string]any), "lastTransitionTime") + } + if err := unstructured.SetNestedSlice(currMap, actualConditions, prepend(possiblePrepend, "internalState", "status", "conditions")...); err != nil { + panic(err) + } + } + } + } + + return cmp.Diff(expectedMap, actualMap), equality.Semantic.DeepEqual(expectedMap, actualMap) +} + +func prepend(first string, rest ...string) []string { + if len(first) == 0 { + return rest + } + return append([]string{first}, rest...) +} diff --git a/test-integration/utils/databasemutationhelpers/per_resource_crud.go b/test-integration/utils/databasemutationhelpers/per_resource_crud.go index 7927a4f39c..f8a376c857 100644 --- a/test-integration/utils/databasemutationhelpers/per_resource_crud.go +++ b/test-integration/utils/databasemutationhelpers/per_resource_crud.go @@ -98,6 +98,27 @@ func (OperationCRUDSpecializer) WriteCosmosID(newObj, oldObj *api.Operation) { // the cosmosID is derived from the operationID } +type NothingCRUDSpecializer struct { +} + +var _ ResourceCRUDTestSpecializer[any] = &NothingCRUDSpecializer{} + +func (NothingCRUDSpecializer) ResourceCRUDFromKey(t *testing.T, cosmosContainer *azcosmos.ContainerClient, key CosmosCRUDKey) database.ResourceCRUD[any] { + panic("unsupported") +} + +func (NothingCRUDSpecializer) InstanceEquals(expected, actual *any) bool { + panic("unsupported") +} + +func (NothingCRUDSpecializer) NameFromInstance(obj *any) string { + panic("unsupported") +} + +func (NothingCRUDSpecializer) WriteCosmosID(newObj, oldObj *any) { + panic("unsupported") +} + type UntypedCRUDSpecializer struct { } diff --git a/test-integration/utils/databasemutationhelpers/per_resource_http.go b/test-integration/utils/databasemutationhelpers/per_resource_http.go new file mode 100644 index 0000000000..036042299f --- /dev/null +++ b/test-integration/utils/databasemutationhelpers/per_resource_http.go @@ -0,0 +1,264 @@ +// Copyright 2026 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package databasemutationhelpers + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + "path" + "strings" + + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + + "github.com/Azure/ARO-HCP/internal/api" + "github.com/Azure/ARO-HCP/internal/utils" + hcpsdk20240610preview "github.com/Azure/ARO-HCP/test/sdk/v20240610preview/resourcemanager/redhatopenshifthcp/armredhatopenshifthcp" +) + +type HTTPTestAccessor interface { + Get(ctx context.Context, resourceIDString string) (any, error) + List(ctx context.Context, parentResourceIDString string) ([]any, error) + CreateOrUpdate(ctx context.Context, resourceIDString string, content []byte) error + Patch(ctx context.Context, resourceIDString string, content []byte) error + Delete(ctx context.Context, resourceIDString string) error +} + +type frontendHTTPTestAccessor struct { + frontEndURL string + frontendClient *hcpsdk20240610preview.ClientFactory +} + +func newFrontendHTTPTestAccessor(frontEndURL string, frontendClient *hcpsdk20240610preview.ClientFactory) *frontendHTTPTestAccessor { + return &frontendHTTPTestAccessor{ + frontEndURL: frontEndURL, + frontendClient: frontendClient, + } +} + +var _ HTTPTestAccessor = &frontendHTTPTestAccessor{} + +func (c frontendHTTPTestAccessor) Get(ctx context.Context, resourceIDString string) (any, error) { + resourceID, err := azcorearm.ParseResourceID(resourceIDString) + if err != nil { + return nil, utils.TrackError(err) + } + + switch strings.ToLower(resourceID.ResourceType.String()) { + case strings.ToLower(api.ClusterResourceType.String()): + return c.frontendClient.NewHcpOpenShiftClustersClient().Get(ctx, resourceID.ResourceGroupName, resourceID.Name, nil) + + case strings.ToLower(api.NodePoolResourceType.String()): + return c.frontendClient.NewNodePoolsClient().Get(ctx, resourceID.ResourceGroupName, resourceID.Parent.Name, resourceID.Name, nil) + + case strings.ToLower(api.ExternalAuthResourceType.String()): + return c.frontendClient.NewExternalAuthsClient().Get(ctx, resourceID.ResourceGroupName, resourceID.Parent.Name, resourceID.Name, nil) + + default: + return "", utils.TrackError(fmt.Errorf("unknown resource type: %s", resourceID.ResourceType.String())) + } +} + +func (c frontendHTTPTestAccessor) List(ctx context.Context, parentResourceIDString string) ([]any, error) { + parentResourceID, err := azcorearm.ParseResourceID(parentResourceIDString) + if err != nil { + return nil, utils.TrackError(err) + } + + switch strings.ToLower(parentResourceID.ResourceType.String()) { + case strings.ToLower(api.ClusterResourceType.String()): + pager := c.frontendClient.NewHcpOpenShiftClustersClient().NewListByResourceGroupPager(parentResourceID.ResourceGroupName, nil) + ret := []any{} + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + return nil, utils.TrackError(err) + } + for i := range page.Value { + ret = append(ret, page.Value[i]) + } + } + return ret, nil + + case strings.ToLower(api.NodePoolResourceType.String()): + pager := c.frontendClient.NewNodePoolsClient().NewListByParentPager(parentResourceID.ResourceGroupName, parentResourceID.Name, nil) + ret := []any{} + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + return nil, utils.TrackError(err) + } + for i := range page.Value { + ret = append(ret, page.Value[i]) + } + } + return ret, nil + + case strings.ToLower(api.ExternalAuthResourceType.String()): + pager := c.frontendClient.NewExternalAuthsClient().NewListByParentPager(parentResourceID.ResourceGroupName, parentResourceID.Name, nil) + ret := []any{} + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + return nil, utils.TrackError(err) + } + for i := range page.Value { + ret = append(ret, page.Value[i]) + } + } + return ret, nil + + default: + return nil, utils.TrackError(fmt.Errorf("unknown resource type: %s", parentResourceID.ResourceType.String())) + } +} + +func (c frontendHTTPTestAccessor) CreateOrUpdate(ctx context.Context, resourceIDString string, content []byte) error { + resourceID, err := azcorearm.ParseResourceID(resourceIDString) + if err != nil { + return utils.TrackError(err) + } + + switch strings.ToLower(resourceID.ResourceType.String()) { + case strings.ToLower(api.ClusterResourceType.String()): + obj := hcpsdk20240610preview.HcpOpenShiftCluster{} + if err := json.Unmarshal(content, &obj); err != nil { + return utils.TrackError(err) + } + _, err := c.frontendClient.NewHcpOpenShiftClustersClient().BeginCreateOrUpdate(ctx, resourceID.ResourceGroupName, resourceID.Name, obj, nil) + if err != nil { + return utils.TrackError(err) + } + return nil + + case strings.ToLower(api.NodePoolResourceType.String()): + obj := hcpsdk20240610preview.NodePool{} + if err := json.Unmarshal(content, &obj); err != nil { + return utils.TrackError(err) + } + _, err := c.frontendClient.NewNodePoolsClient().BeginCreateOrUpdate(ctx, resourceID.ResourceGroupName, resourceID.Parent.Name, resourceID.Name, obj, nil) + if err != nil { + return utils.TrackError(err) + } + return nil + + case strings.ToLower(api.ExternalAuthResourceType.String()): + obj := hcpsdk20240610preview.ExternalAuth{} + if err := json.Unmarshal(content, &obj); err != nil { + return utils.TrackError(err) + } + _, err := c.frontendClient.NewExternalAuthsClient().BeginCreateOrUpdate(ctx, resourceID.ResourceGroupName, resourceID.Parent.Name, resourceID.Name, obj, nil) + if err != nil { + return utils.TrackError(err) + } + return nil + + case strings.ToLower(azcorearm.SubscriptionResourceType.String()): + fullURL := c.frontEndURL + path.Join("/subscriptions", resourceID.Name) + req, err := http.NewRequest("PUT", fullURL, bytes.NewReader(content)) + if err != nil { + return utils.TrackError(err) + } + req.Header.Set("Content-Type", "application/json") + response, err := http.DefaultClient.Do(req) + if err != nil { + return utils.TrackError(err) + } + if response.StatusCode != 200 { + return utils.TrackError(fmt.Errorf("expected 200 status code, got %d", response.StatusCode)) + } + //responseBytes, err := httputil.DumpResponse(response, true) + //if err != nil { + // return utils.TrackError(err) + //} + //fmt.Printf("%s", string(responseBytes)) + + return nil + + default: + return utils.TrackError(fmt.Errorf("unknown resource type: %s", resourceID.ResourceType.String())) + } +} + +func (c frontendHTTPTestAccessor) Patch(ctx context.Context, resourceIDString string, content []byte) error { + resourceID, err := azcorearm.ParseResourceID(resourceIDString) + if err != nil { + return utils.TrackError(err) + } + + switch strings.ToLower(resourceID.ResourceType.String()) { + case strings.ToLower(api.ClusterResourceType.String()): + obj := hcpsdk20240610preview.HcpOpenShiftClusterUpdate{} + if err := json.Unmarshal(content, &obj); err != nil { + return utils.TrackError(err) + } + _, err := c.frontendClient.NewHcpOpenShiftClustersClient().BeginUpdate(ctx, resourceID.ResourceGroupName, resourceID.Name, obj, nil) + if err != nil { + return utils.TrackError(err) + } + return nil + + case strings.ToLower(api.NodePoolResourceType.String()): + obj := hcpsdk20240610preview.NodePoolUpdate{} + if err := json.Unmarshal(content, &obj); err != nil { + return utils.TrackError(err) + } + _, err := c.frontendClient.NewNodePoolsClient().BeginUpdate(ctx, resourceID.ResourceGroupName, resourceID.Parent.Name, resourceID.Name, obj, nil) + if err != nil { + return utils.TrackError(err) + } + return nil + + case strings.ToLower(api.ExternalAuthResourceType.String()): + obj := hcpsdk20240610preview.ExternalAuthUpdate{} + if err := json.Unmarshal(content, &obj); err != nil { + return utils.TrackError(err) + } + _, err := c.frontendClient.NewExternalAuthsClient().BeginUpdate(ctx, resourceID.ResourceGroupName, resourceID.Parent.Name, resourceID.Name, obj, nil) + if err != nil { + return utils.TrackError(err) + } + return nil + + default: + return utils.TrackError(fmt.Errorf("unknown resource type: %s", resourceID.ResourceType.String())) + } +} + +func (c frontendHTTPTestAccessor) Delete(ctx context.Context, resourceIDString string) error { + resourceID, err := azcorearm.ParseResourceID(resourceIDString) + if err != nil { + return utils.TrackError(err) + } + + switch strings.ToLower(resourceID.ResourceType.String()) { + case strings.ToLower(api.ClusterResourceType.String()): + _, err := c.frontendClient.NewHcpOpenShiftClustersClient().BeginDelete(ctx, resourceID.ResourceGroupName, resourceID.Name, nil) + return utils.TrackError(err) + + case strings.ToLower(api.NodePoolResourceType.String()): + _, err := c.frontendClient.NewNodePoolsClient().BeginDelete(ctx, resourceID.ResourceGroupName, resourceID.Parent.Name, resourceID.Name, nil) + return utils.TrackError(err) + + case strings.ToLower(api.ExternalAuthResourceType.String()): + _, err := c.frontendClient.NewExternalAuthsClient().BeginDelete(ctx, resourceID.ResourceGroupName, resourceID.Parent.Name, resourceID.Name, nil) + return utils.TrackError(err) + + default: + return utils.TrackError(fmt.Errorf("unknown resource type: %s", resourceID.ResourceType.String())) + } +} diff --git a/test-integration/utils/databasemutationhelpers/per_resource_operation.go b/test-integration/utils/databasemutationhelpers/per_resource_operation.go new file mode 100644 index 0000000000..29b14a2b1e --- /dev/null +++ b/test-integration/utils/databasemutationhelpers/per_resource_operation.go @@ -0,0 +1,51 @@ +// Copyright 2026 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package databasemutationhelpers + +import ( + "context" + + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + + "github.com/Azure/ARO-HCP/internal/database" + "github.com/Azure/ARO-HCP/internal/utils" + "github.com/Azure/ARO-HCP/test-integration/utils/integrationutils" +) + +type OperationAccessor interface { + CompleteOperation(ctx context.Context, resourceIDString string) error +} + +type operationAccessor struct { + dbClient database.DBClient +} + +func newOperationAccessor(dbClient database.DBClient) *operationAccessor { + return &operationAccessor{dbClient: dbClient} +} + +var _ OperationAccessor = &operationAccessor{} + +func (c operationAccessor) CompleteOperation(ctx context.Context, resourceIDString string) error { + resourceID, err := azcorearm.ParseResourceID(resourceIDString) + if err != nil { + return utils.TrackError(err) + } + + if err := integrationutils.MarkOperationsCompleteForName(ctx, c.dbClient, resourceID.SubscriptionID, resourceID.Name); err != nil { + return utils.TrackError(err) + } + return nil +} diff --git a/test-integration/utils/databasemutationhelpers/resource_crud_test_util.go b/test-integration/utils/databasemutationhelpers/resource_crud_test_util.go index f7d9c57ec2..cc8a818928 100644 --- a/test-integration/utils/databasemutationhelpers/resource_crud_test_util.go +++ b/test-integration/utils/databasemutationhelpers/resource_crud_test_util.go @@ -24,13 +24,16 @@ import ( "strings" "testing" + "github.com/neilotoole/slogt" "github.com/stretchr/testify/require" "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" "github.com/Azure/ARO-HCP/internal/api" + "github.com/Azure/ARO-HCP/internal/database" "github.com/Azure/ARO-HCP/internal/utils" "github.com/Azure/ARO-HCP/test-integration/utils/integrationutils" + hcpsdk20240610preview "github.com/Azure/ARO-HCP/test/sdk/v20240610preview/resourcemanager/redhatopenshifthcp/armredhatopenshifthcp" ) type ResourceMutationTest struct { @@ -41,7 +44,7 @@ type ResourceMutationTest struct { type IntegrationTestStep interface { StepID() StepID - RunTest(ctx context.Context, t *testing.T, cosmosContainer *azcosmos.ContainerClient) + RunTest(ctx context.Context, t *testing.T, stepInput StepInput) } func NewResourceMutationTest[InternalAPIType any](ctx context.Context, specializer ResourceCRUDTestSpecializer[InternalAPIType], testName string, testDir fs.FS) (*ResourceMutationTest, error) { @@ -58,6 +61,7 @@ func NewResourceMutationTest[InternalAPIType any](ctx context.Context, specializ func readSteps[InternalAPIType any](ctx context.Context, testDir fs.FS, specializer ResourceCRUDTestSpecializer[InternalAPIType]) ([]IntegrationTestStep, error) { steps := []IntegrationTestStep{} + numLoadClusterServiceSteps := 0 testContent := api.Must(fs.ReadDir(testDir, ".")) for _, dirEntry := range testContent { filenameParts := strings.SplitN(dirEntry.Name(), "-", 3) @@ -72,30 +76,53 @@ func readSteps[InternalAPIType any](ctx context.Context, testDir fs.FS, speciali index := filenameParts[0] stepType := filenameParts[1] stepName, _ := strings.CutSuffix(filenameParts[2], ".json") + if stepType == "loadClusterService" { // eventually this goes away, so we'll be able to remove the ugly. for now prevent mistakes. + numLoadClusterServiceSteps++ + } - testStep, err := newStep(index, stepType, stepName, testDir, dirEntry.Name(), specializer) + testStep, err := NewStep(index, stepType, stepName, testDir, dirEntry.Name(), specializer) if err != nil { return nil, fmt.Errorf("failed to create new step %q: %w", dirEntry.Name(), err) } steps = append(steps, testStep) } + if numLoadClusterServiceSteps > 1 { + return nil, fmt.Errorf("more than one step found for loadClusterService. Refactor to do it once or make it possible to load more than once") + } sort.Sort(byIndex(steps)) return steps, nil } func (tt *ResourceMutationTest) RunTest(t *testing.T) { - testInfo, err := integrationutils.NewCosmosFromTestingEnv(t.Context()) + ctx := t.Context() + ctx, cancel := context.WithCancel(ctx) + defer cancel() + ctx = utils.ContextWithLogger(ctx, slogt.New(t, slogt.JSON())) + + frontend, testInfo, err := integrationutils.NewFrontendFromTestingEnv(ctx, t) require.NoError(t, err) defer testInfo.Cleanup(context.Background()) + go frontend.Run(ctx, ctx.Done()) + + // create anything and round trip anything for cluster-service + err = integrationutils.TrivialPassThroughClusterServiceMock(t, testInfo, nil) + require.NoError(t, err) + stepInput := StepInput{ + CosmosContainer: testInfo.CosmosResourcesContainer(), + DBClient: testInfo.DBClient, + FrontendClient: testInfo.Get20240610ClientFactory, + FrontendURL: testInfo.FrontendURL, + FrontendTestInfo: testInfo, + } for _, step := range tt.steps { t.Logf("Running step %s", step.StepID()) - step.RunTest(t.Context(), t, testInfo.CosmosResourcesContainer()) + step.RunTest(t.Context(), t, stepInput) } } -func newStep[InternalAPIType any](indexString, stepType, stepName string, testDir fs.FS, path string, specializer ResourceCRUDTestSpecializer[InternalAPIType]) (IntegrationTestStep, error) { +func NewStep[InternalAPIType any](indexString, stepType, stepName string, testDir fs.FS, path string, specializer ResourceCRUDTestSpecializer[InternalAPIType]) (IntegrationTestStep, error) { itoInt, err := strconv.Atoi(indexString) if err != nil { return nil, fmt.Errorf("failed to convert %s to int: %w", indexString, err) @@ -107,8 +134,11 @@ func newStep[InternalAPIType any](indexString, stepType, stepName string, testDi } switch stepType { - case "load": - return NewLoadStep(stepID, stepDir) + case "load", "loadCosmos": + return NewLoadCosmosStep(stepID, stepDir) + + case "loadClusterService": + return NewLoadClusterServiceStep(stepID, stepDir) case "cosmosCompare": return NewCosmosCompareStep(stepID, stepDir) @@ -146,6 +176,18 @@ func newStep[InternalAPIType any](indexString, stepType, stepName string, testDi case "untypedDelete": return newUntypedDeleteStep(stepID, stepDir) + case "httpGet": + return newHTTPGetStep(stepID, stepDir) + + case "httpList": + return newHTTPListStep(stepID, stepDir) + + case "httpCreate", "httpReplace": + return newHTTPCreateStep(stepID, stepDir) + + case "completeOperation": + return newCompleteOperationStep(stepID, stepDir) + default: return nil, fmt.Errorf("unknown step type: %s", stepType) } @@ -210,3 +252,36 @@ func readResourcesInDir[InternalAPIType any](dir fs.FS) ([]*InternalAPIType, err return resources, nil } + +func readRawBytesInDir(dir fs.FS) ([][]byte, error) { + contents := [][]byte{} + testContent := api.Must(fs.ReadDir(dir, ".")) + for _, dirEntry := range testContent { + if dirEntry.Name() == "00-key.json" { // standard filenames to skip + continue + } + if dirEntry.Name() == "expected-error.txt" { // standard filenames to skip + continue + } + if !strings.HasSuffix(dirEntry.Name(), ".json") { // we can only understand JSON + continue + } + + currContent, err := fs.ReadFile(dir, dirEntry.Name()) + if err != nil { + return nil, fmt.Errorf("failed to read expected.json: %w", err) + } + contents = append(contents, currContent) + } + + return contents, nil +} + +type StepInput struct { + CosmosContainer *azcosmos.ContainerClient + DBClient database.DBClient + FrontendClient func(subscriptionID string) *hcpsdk20240610preview.ClientFactory + FrontendURL string + + FrontendTestInfo *integrationutils.FrontendIntegrationTestInfo +} diff --git a/test-integration/utils/databasemutationhelpers/step_completeoperation.go b/test-integration/utils/databasemutationhelpers/step_completeoperation.go new file mode 100644 index 0000000000..6659cde21a --- /dev/null +++ b/test-integration/utils/databasemutationhelpers/step_completeoperation.go @@ -0,0 +1,58 @@ +// Copyright 2025 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package databasemutationhelpers + +import ( + "context" + "encoding/json" + "fmt" + "io/fs" + "testing" + + "github.com/stretchr/testify/require" +) + +type completeOperationStep struct { + stepID StepID + key FrontendResourceKey +} + +func newCompleteOperationStep(stepID StepID, stepDir fs.FS) (*completeOperationStep, error) { + keyBytes, err := fs.ReadFile(stepDir, "00-key.json") + if err != nil { + return nil, fmt.Errorf("failed to read key.json: %w", err) + } + var key FrontendResourceKey + if err := json.Unmarshal(keyBytes, &key); err != nil { + return nil, fmt.Errorf("failed to unmarshal key.json: %w", err) + } + + return &completeOperationStep{ + stepID: stepID, + key: key, + }, nil +} + +var _ IntegrationTestStep = &completeOperationStep{} + +func (l *completeOperationStep) StepID() StepID { + return l.stepID +} + +func (l *completeOperationStep) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { + accessor := newOperationAccessor(stepInput.DBClient) + err := accessor.CompleteOperation(ctx, l.key.ResourceID) + require.NoError(t, err) +} diff --git a/test-integration/utils/databasemutationhelpers/step_cosmoscompare.go b/test-integration/utils/databasemutationhelpers/step_cosmoscompare.go index 0f17bfb2ac..9277af9a62 100644 --- a/test-integration/utils/databasemutationhelpers/step_cosmoscompare.go +++ b/test-integration/utils/databasemutationhelpers/step_cosmoscompare.go @@ -20,7 +20,6 @@ import ( "io/fs" "testing" - "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/require" "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" @@ -53,14 +52,14 @@ func (l *cosmosCompare) StepID() StepID { return l.stepID } -func (l *cosmosCompare) RunTest(ctx context.Context, t *testing.T, cosmosContainer *azcosmos.ContainerClient) { +func (l *cosmosCompare) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { // Query all documents in the container querySQL := "SELECT * FROM c" queryOptions := &azcosmos.QueryOptions{ QueryParameters: []azcosmos.QueryParameter{}, } - queryPager := cosmosContainer.NewQueryItemsPager(querySQL, azcosmos.PartitionKey{}, queryOptions) + queryPager := stepInput.CosmosContainer.NewQueryItemsPager(querySQL, azcosmos.PartitionKey{}, queryOptions) allActual := []*database.TypedDocument{} for queryPager.More() { @@ -76,16 +75,16 @@ func (l *cosmosCompare) RunTest(ctx context.Context, t *testing.T, cosmosContain } } - typedDocumentSpecializer := UntypedCRUDSpecializer{} for _, currExpected := range l.expectedContent { found := false currDiffs := []string{} for _, currActual := range allActual { - if typedDocumentSpecializer.InstanceEquals(currExpected, currActual) { + diff, equals := ResourceInstanceEquals(t, currExpected, currActual) + if equals { found = true break } - currDiffs = append(currDiffs, cmp.Diff(stringifyResource(currExpected), stringifyResource(currActual))) + currDiffs = append(currDiffs, diff) } if !found { t.Log(stringifyResource(allActual)) diff --git a/test-integration/utils/databasemutationhelpers/step_create.go b/test-integration/utils/databasemutationhelpers/step_create.go index 4b8e2fa592..47ab569fac 100644 --- a/test-integration/utils/databasemutationhelpers/step_create.go +++ b/test-integration/utils/databasemutationhelpers/step_create.go @@ -22,8 +22,6 @@ import ( "testing" "github.com/stretchr/testify/require" - - "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" ) type createStep[InternalAPIType any] struct { @@ -63,8 +61,8 @@ func (l *createStep[InternalAPIType]) StepID() StepID { return l.stepID } -func (l *createStep[InternalAPIType]) RunTest(ctx context.Context, t *testing.T, cosmosContainer *azcosmos.ContainerClient) { - controllerCRUDClient := l.specializer.ResourceCRUDFromKey(t, cosmosContainer, l.key) +func (l *createStep[InternalAPIType]) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { + controllerCRUDClient := l.specializer.ResourceCRUDFromKey(t, stepInput.CosmosContainer, l.key) for _, resource := range l.resources { _, err := controllerCRUDClient.Create(ctx, resource, nil) diff --git a/test-integration/utils/databasemutationhelpers/step_delete.go b/test-integration/utils/databasemutationhelpers/step_delete.go index e90777a616..e6bcf81df2 100644 --- a/test-integration/utils/databasemutationhelpers/step_delete.go +++ b/test-integration/utils/databasemutationhelpers/step_delete.go @@ -24,8 +24,6 @@ import ( "testing" "github.com/stretchr/testify/require" - - "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" ) type CosmosDeleteKey struct { @@ -72,8 +70,8 @@ func (l *deleteStep[InternalAPIType]) StepID() StepID { return l.stepID } -func (l *deleteStep[InternalAPIType]) RunTest(ctx context.Context, t *testing.T, cosmosContainer *azcosmos.ContainerClient) { - controllerCRUDClient := l.specializer.ResourceCRUDFromKey(t, cosmosContainer, l.key.CosmosCRUDKey) +func (l *deleteStep[InternalAPIType]) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { + controllerCRUDClient := l.specializer.ResourceCRUDFromKey(t, stepInput.CosmosContainer, l.key.CosmosCRUDKey) err := controllerCRUDClient.Delete(ctx, l.key.DeleteResourceName) switch { case len(l.expectedError) > 0: diff --git a/test-integration/utils/databasemutationhelpers/step_get.go b/test-integration/utils/databasemutationhelpers/step_get.go index c9fadfe715..9c93a04886 100644 --- a/test-integration/utils/databasemutationhelpers/step_get.go +++ b/test-integration/utils/databasemutationhelpers/step_get.go @@ -24,8 +24,6 @@ import ( "testing" "github.com/stretchr/testify/require" - - "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" ) type getStep[InternalAPIType any] struct { @@ -85,8 +83,8 @@ func (l *getStep[InternalAPIType]) StepID() StepID { return l.stepID } -func (l *getStep[InternalAPIType]) RunTest(ctx context.Context, t *testing.T, cosmosContainer *azcosmos.ContainerClient) { - controllerCRUDClient := l.specializer.ResourceCRUDFromKey(t, cosmosContainer, l.key) +func (l *getStep[InternalAPIType]) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { + controllerCRUDClient := l.specializer.ResourceCRUDFromKey(t, stepInput.CosmosContainer, l.key) resourceName := l.specializer.NameFromInstance(l.expectedResource) actualController, err := controllerCRUDClient.Get(ctx, resourceName) switch { diff --git a/test-integration/utils/databasemutationhelpers/step_getbyid.go b/test-integration/utils/databasemutationhelpers/step_getbyid.go index ac78603c7e..59c4e02d82 100644 --- a/test-integration/utils/databasemutationhelpers/step_getbyid.go +++ b/test-integration/utils/databasemutationhelpers/step_getbyid.go @@ -24,8 +24,6 @@ import ( "testing" "github.com/stretchr/testify/require" - - "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" ) type GetByIDCRUDKey struct { @@ -91,8 +89,8 @@ func (l *getByIDStep[InternalAPIType]) StepID() StepID { return l.stepID } -func (l *getByIDStep[InternalAPIType]) RunTest(ctx context.Context, t *testing.T, cosmosContainer *azcosmos.ContainerClient) { - controllerCRUDClient := l.specializer.ResourceCRUDFromKey(t, cosmosContainer, l.key.CosmosCRUDKey) +func (l *getByIDStep[InternalAPIType]) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { + controllerCRUDClient := l.specializer.ResourceCRUDFromKey(t, stepInput.CosmosContainer, l.key.CosmosCRUDKey) actualController, err := controllerCRUDClient.GetByID(ctx, l.key.CosmosID) switch { case len(l.expectedError) > 0: diff --git a/test-integration/utils/databasemutationhelpers/step_httpcreate.go b/test-integration/utils/databasemutationhelpers/step_httpcreate.go new file mode 100644 index 0000000000..d2439b3b4c --- /dev/null +++ b/test-integration/utils/databasemutationhelpers/step_httpcreate.go @@ -0,0 +1,74 @@ +// Copyright 2025 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package databasemutationhelpers + +import ( + "context" + "encoding/json" + "fmt" + "io/fs" + "testing" + + "github.com/stretchr/testify/require" + + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + + "github.com/Azure/ARO-HCP/internal/api" +) + +type httpCreateStep struct { + stepID StepID + key FrontendResourceKey + + resources [][]byte +} + +func newHTTPCreateStep(stepID StepID, stepDir fs.FS) (*httpCreateStep, error) { + keyBytes, err := fs.ReadFile(stepDir, "00-key.json") + if err != nil { + return nil, fmt.Errorf("failed to read key.json: %w", err) + } + var key FrontendResourceKey + if err := json.Unmarshal(keyBytes, &key); err != nil { + return nil, fmt.Errorf("failed to unmarshal key.json: %w", err) + } + + resources, err := readRawBytesInDir(stepDir) + if err != nil { + return nil, fmt.Errorf("failed to read resource in dir: %w", err) + } + + return &httpCreateStep{ + stepID: stepID, + key: key, + resources: resources, + }, nil +} + +var _ IntegrationTestStep = &httpCreateStep{} + +func (l *httpCreateStep) StepID() StepID { + return l.stepID +} + +func (l *httpCreateStep) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { + subscriptionID := api.Must(azcorearm.ParseResourceID(l.key.ResourceID)).SubscriptionID + accessor := newFrontendHTTPTestAccessor(stepInput.FrontendURL, stepInput.FrontendClient(subscriptionID)) + + for _, resource := range l.resources { + err := accessor.CreateOrUpdate(ctx, l.key.ResourceID, resource) + require.NoError(t, err) + } +} diff --git a/test-integration/utils/databasemutationhelpers/step_httpget.go b/test-integration/utils/databasemutationhelpers/step_httpget.go new file mode 100644 index 0000000000..4ec3c196e7 --- /dev/null +++ b/test-integration/utils/databasemutationhelpers/step_httpget.go @@ -0,0 +1,109 @@ +// Copyright 2025 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package databasemutationhelpers + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io/fs" + "strings" + "testing" + + "github.com/stretchr/testify/require" + + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + + "github.com/Azure/ARO-HCP/internal/api" +) + +type FrontendResourceKey struct { + ResourceID string `json:"resourceId"` +} + +type httpGetStep struct { + stepID StepID + key FrontendResourceKey + + expectedResource map[string]any + expectedError string +} + +func newHTTPGetStep(stepID StepID, stepDir fs.FS) (*httpGetStep, error) { + keyBytes, err := fs.ReadFile(stepDir, "00-key.json") + if err != nil { + return nil, fmt.Errorf("failed to read key.json: %w", err) + } + var key FrontendResourceKey + if err := json.Unmarshal(keyBytes, &key); err != nil { + return nil, fmt.Errorf("failed to unmarshal key.json: %w", err) + } + + expectedErrorBytes, err := fs.ReadFile(stepDir, "expected-error.txt") + if err != nil && !errors.Is(err, fs.ErrNotExist) { + return nil, fmt.Errorf("failed to read expected-error.txt: %w", err) + } + expectedError := strings.TrimSpace(string(expectedErrorBytes)) + + var expectedResource map[string]any + expectedResources, err := readResourcesInDir[map[string]any](stepDir) + if err != nil { + return nil, fmt.Errorf("failed to read resource in dir: %w", err) + } + switch len(expectedResources) { + case 0: + case 1: + expectedResource = *expectedResources[0] + default: + return nil, fmt.Errorf("cannot expect more than one resource") + } + + if len(expectedError) == 0 && expectedResource == nil { + return nil, fmt.Errorf("must expect either error and value") + } + + return &httpGetStep{ + stepID: stepID, + key: key, + expectedResource: expectedResource, + expectedError: expectedError, + }, nil +} + +var _ IntegrationTestStep = &httpGetStep{} + +func (l *httpGetStep) StepID() StepID { + return l.stepID +} + +func (l *httpGetStep) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { + resourceID := api.Must(azcorearm.ParseResourceID(l.key.ResourceID)) + subscriptionID := resourceID.SubscriptionID + accessor := newFrontendHTTPTestAccessor(stepInput.FrontendURL, stepInput.FrontendClient(subscriptionID)) + actual, err := accessor.Get(ctx, l.key.ResourceID) + switch { + case len(l.expectedError) > 0: + require.ErrorContains(t, err, l.expectedError) + return + default: + require.NoError(t, err) + } + + if diff, equals := ResourceInstanceEquals(t, l.expectedResource, actual); !equals { + t.Logf("actual:\n%v", stringifyResource(actual)) + t.Error(diff) + } +} diff --git a/test-integration/utils/databasemutationhelpers/step_httplist.go b/test-integration/utils/databasemutationhelpers/step_httplist.go new file mode 100644 index 0000000000..e3454c7949 --- /dev/null +++ b/test-integration/utils/databasemutationhelpers/step_httplist.go @@ -0,0 +1,109 @@ +// Copyright 2025 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package databasemutationhelpers + +import ( + "context" + "encoding/json" + "fmt" + "io/fs" + "testing" + + "github.com/stretchr/testify/require" + + azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + + "github.com/Azure/ARO-HCP/internal/api" +) + +type httpListStep struct { + stepID StepID + key FrontendResourceKey + + expectedResources []*map[string]any +} + +func newHTTPListStep(stepID StepID, stepDir fs.FS) (*httpListStep, error) { + keyBytes, err := fs.ReadFile(stepDir, "00-key.json") + if err != nil { + return nil, fmt.Errorf("failed to read key.json: %w", err) + } + var key FrontendResourceKey + if err := json.Unmarshal(keyBytes, &key); err != nil { + return nil, fmt.Errorf("failed to unmarshal key.json: %w", err) + } + + expectedResources, err := readResourcesInDir[map[string]any](stepDir) + if err != nil { + return nil, fmt.Errorf("failed to read resource in dir: %w", err) + } + + return &httpListStep{ + stepID: stepID, + key: key, + expectedResources: expectedResources, + }, nil +} + +var _ IntegrationTestStep = &httpListStep{} + +func (l *httpListStep) StepID() StepID { + return l.stepID +} + +func (l *httpListStep) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { + resourceID := api.Must(azcorearm.ParseResourceID(l.key.ResourceID)) + subscriptionID := resourceID.SubscriptionID + accessor := newFrontendHTTPTestAccessor(stepInput.FrontendURL, stepInput.FrontendClient(subscriptionID)) + actualResources, err := accessor.List(ctx, l.key.ResourceID) + require.NoError(t, err) + + if len(l.expectedResources) != len(actualResources) { + t.Logf("actual:\n%v", stringifyResource(actualResources)) + } + + require.Equal(t, len(l.expectedResources), len(actualResources), "unexpected number of resources") + // all the expected must be present + for i, expected := range l.expectedResources { + found := false + for _, actual := range actualResources { + _, equals := ResourceInstanceEquals(t, expected, actual) + if equals { + found = true + break + } + } + if !found { + t.Logf("actual:\n%v", stringifyResource(actualResources)) + } + require.True(t, found, "expected resource not found: %d", i) + } + + // all the actual must be expected + for i, actual := range actualResources { + found := false + for _, expected := range l.expectedResources { + _, equals := ResourceInstanceEquals(t, expected, actual) + if equals { + found = true + break + } + } + if !found { + t.Logf("expected:\n%v", stringifyResource(l.expectedResources)) + } + require.True(t, found, "actual resource not found: %d", i) + } +} diff --git a/test-integration/utils/databasemutationhelpers/step_list.go b/test-integration/utils/databasemutationhelpers/step_list.go index c7405cc417..9ed6578343 100644 --- a/test-integration/utils/databasemutationhelpers/step_list.go +++ b/test-integration/utils/databasemutationhelpers/step_list.go @@ -22,8 +22,6 @@ import ( "testing" "github.com/stretchr/testify/require" - - "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" ) type listStep[InternalAPIType any] struct { @@ -63,8 +61,8 @@ func (l *listStep[InternalAPIType]) StepID() StepID { return l.stepID } -func (l *listStep[InternalAPIType]) RunTest(ctx context.Context, t *testing.T, cosmosContainer *azcosmos.ContainerClient) { - controllerCRUDClient := l.specializer.ResourceCRUDFromKey(t, cosmosContainer, l.key) +func (l *listStep[InternalAPIType]) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { + controllerCRUDClient := l.specializer.ResourceCRUDFromKey(t, stepInput.CosmosContainer, l.key) actualControllersIterator, err := controllerCRUDClient.List(ctx, nil) require.NoError(t, err) diff --git a/test-integration/utils/databasemutationhelpers/step_list_active_operations.go b/test-integration/utils/databasemutationhelpers/step_list_active_operations.go index 4d2ecc2ff5..57d04a7692 100644 --- a/test-integration/utils/databasemutationhelpers/step_list_active_operations.go +++ b/test-integration/utils/databasemutationhelpers/step_list_active_operations.go @@ -24,7 +24,6 @@ import ( "github.com/stretchr/testify/require" azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" "github.com/Azure/ARO-HCP/internal/api" "github.com/Azure/ARO-HCP/internal/database" @@ -65,11 +64,11 @@ func (l *listActiveOperationsStep) StepID() StepID { return l.stepID } -func (l *listActiveOperationsStep) RunTest(ctx context.Context, t *testing.T, cosmosContainer *azcosmos.ContainerClient) { +func (l *listActiveOperationsStep) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { parentResourceID, err := azcorearm.ParseResourceID(l.key.ParentResourceID) require.NoError(t, err) - operationsCRUD := database.NewOperationCRUD(cosmosContainer, parentResourceID.SubscriptionID) + operationsCRUD := database.NewOperationCRUD(stepInput.CosmosContainer, parentResourceID.SubscriptionID) actualControllersIterator := operationsCRUD.ListActiveOperations(nil) require.NoError(t, err) @@ -89,11 +88,12 @@ func (l *listActiveOperationsStep) RunTest(ctx context.Context, t *testing.T, co for _, expected := range l.expectedOperations { found := false for _, actual := range actualControllers { - if specializer.InstanceEquals(expected, actual) { + diff, equals := ResourceInstanceEquals(t, expected, actual) + if equals { found = true break } - //t.Log(cmp.Diff(stringifyResource(expected), stringifyResource(actual))) + t.Log(diff) } if !found { t.Logf("actual:\n%v", stringifyResource(actualControllers)) @@ -105,10 +105,12 @@ func (l *listActiveOperationsStep) RunTest(ctx context.Context, t *testing.T, co for _, actual := range actualControllers { found := false for _, expected := range l.expectedOperations { - if specializer.InstanceEquals(expected, actual) { + diff, equals := ResourceInstanceEquals(t, expected, actual) + if equals { found = true break } + t.Log(diff) } if !found { t.Logf("expected:\n%v", stringifyResource(l.expectedOperations)) diff --git a/test-integration/utils/databasemutationhelpers/step_load.go b/test-integration/utils/databasemutationhelpers/step_load.go deleted file mode 100644 index 255e227408..0000000000 --- a/test-integration/utils/databasemutationhelpers/step_load.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2025 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package databasemutationhelpers - -import ( - "context" - "fmt" - "io/fs" - "strings" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" - - "github.com/Azure/ARO-HCP/internal/api" - "github.com/Azure/ARO-HCP/test-integration/utils/integrationutils" -) - -type loadStep struct { - stepID StepID - - contents [][]byte -} - -func NewLoadStep(stepID StepID, stepDir fs.FS) (*loadStep, error) { - - contents := [][]byte{} - testContent := api.Must(fs.ReadDir(stepDir, ".")) - for _, dirEntry := range testContent { - if dirEntry.Name() == "00-key.json" { // standard filenames to skip - continue - } - if dirEntry.Name() == "expected-error.txt" { // standard filenames to skip - continue - } - if !strings.HasSuffix(dirEntry.Name(), ".json") { // we can only understand JSON - continue - } - - currContent, err := fs.ReadFile(stepDir, dirEntry.Name()) - if err != nil { - return nil, fmt.Errorf("failed to read expected.json: %w", err) - } - contents = append(contents, currContent) - } - - return &loadStep{ - stepID: stepID, - contents: contents, - }, nil -} - -var _ IntegrationTestStep = &loadStep{} - -func (l *loadStep) StepID() StepID { - return l.stepID -} - -func (l *loadStep) RunTest(ctx context.Context, t *testing.T, cosmosContainer *azcosmos.ContainerClient) { - for _, content := range l.contents { - err := integrationutils.LoadCosmosContent(ctx, cosmosContainer, content) - require.NoError(t, err, "failed to load cosmos content: %v", string(content)) - } -} diff --git a/test-integration/utils/databasemutationhelpers/step_load_clusterservice.go b/test-integration/utils/databasemutationhelpers/step_load_clusterservice.go new file mode 100644 index 0000000000..34f7369f2c --- /dev/null +++ b/test-integration/utils/databasemutationhelpers/step_load_clusterservice.go @@ -0,0 +1,51 @@ +// Copyright 2025 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package databasemutationhelpers + +import ( + "context" + "io/fs" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/Azure/ARO-HCP/test-integration/utils/integrationutils" +) + +type loadClusterServiceStep struct { + stepID StepID + + clusterServiceContent fs.FS +} + +func NewLoadClusterServiceStep(stepID StepID, clusterServiceContent fs.FS) (*loadClusterServiceStep, error) { + return &loadClusterServiceStep{ + stepID: stepID, + clusterServiceContent: clusterServiceContent, + }, nil +} + +var _ IntegrationTestStep = &loadClusterServiceStep{} + +func (l *loadClusterServiceStep) StepID() StepID { + return l.stepID +} + +func (l *loadClusterServiceStep) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { + if stepInput.FrontendTestInfo == nil { + t.Fatal("FrontendTestInfo must not be nil in loadClusterServiceStep, probably using from the wrong kind of test") + } + require.NoError(t, integrationutils.TrivialPassThroughClusterServiceMock(t, stepInput.FrontendTestInfo, l.clusterServiceContent)) +} diff --git a/test-integration/utils/databasemutationhelpers/step_load_cosmos.go b/test-integration/utils/databasemutationhelpers/step_load_cosmos.go new file mode 100644 index 0000000000..80d89a14c2 --- /dev/null +++ b/test-integration/utils/databasemutationhelpers/step_load_cosmos.go @@ -0,0 +1,57 @@ +// Copyright 2025 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package databasemutationhelpers + +import ( + "context" + "io/fs" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/Azure/ARO-HCP/internal/utils" + "github.com/Azure/ARO-HCP/test-integration/utils/integrationutils" +) + +type loadCosmosStep struct { + stepID StepID + + contents [][]byte +} + +func NewLoadCosmosStep(stepID StepID, stepDir fs.FS) (*loadCosmosStep, error) { + contents, err := readRawBytesInDir(stepDir) + if err != nil { + return nil, utils.TrackError(err) + } + + return &loadCosmosStep{ + stepID: stepID, + contents: contents, + }, nil +} + +var _ IntegrationTestStep = &loadCosmosStep{} + +func (l *loadCosmosStep) StepID() StepID { + return l.stepID +} + +func (l *loadCosmosStep) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { + for _, content := range l.contents { + err := integrationutils.LoadCosmosContent(ctx, stepInput.CosmosContainer, content) + require.NoError(t, err, "failed to load cosmos content: %v", string(content)) + } +} diff --git a/test-integration/utils/databasemutationhelpers/step_replace.go b/test-integration/utils/databasemutationhelpers/step_replace.go index a7a227ecad..35cd5aa529 100644 --- a/test-integration/utils/databasemutationhelpers/step_replace.go +++ b/test-integration/utils/databasemutationhelpers/step_replace.go @@ -22,8 +22,6 @@ import ( "testing" "github.com/stretchr/testify/require" - - "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" ) type replaceStep[InternalAPIType any] struct { @@ -63,8 +61,8 @@ func (l *replaceStep[InternalAPIType]) StepID() StepID { return l.stepID } -func (l *replaceStep[InternalAPIType]) RunTest(ctx context.Context, t *testing.T, cosmosContainer *azcosmos.ContainerClient) { - resourceCRUDClient := l.specializer.ResourceCRUDFromKey(t, cosmosContainer, l.key) +func (l *replaceStep[InternalAPIType]) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { + resourceCRUDClient := l.specializer.ResourceCRUDFromKey(t, stepInput.CosmosContainer, l.key) for _, resource := range l.resources { // find the existing to set the UID for an replace to replace instead of creating a new record. diff --git a/test-integration/utils/databasemutationhelpers/step_untypeddelete.go b/test-integration/utils/databasemutationhelpers/step_untypeddelete.go index a7b7243b84..e73e4124e2 100644 --- a/test-integration/utils/databasemutationhelpers/step_untypeddelete.go +++ b/test-integration/utils/databasemutationhelpers/step_untypeddelete.go @@ -26,7 +26,6 @@ import ( "github.com/stretchr/testify/require" azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" "github.com/Azure/ARO-HCP/internal/api" "github.com/Azure/ARO-HCP/internal/database" @@ -76,11 +75,11 @@ func (l *untypedDeleteStep) StepID() StepID { return l.stepID } -func (l *untypedDeleteStep) RunTest(ctx context.Context, t *testing.T, cosmosContainer *azcosmos.ContainerClient) { +func (l *untypedDeleteStep) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { parentResourceID, err := azcorearm.ParseResourceID(l.key.ParentResourceID) require.NoError(t, err) - untypedCRUD := database.NewUntypedCRUD(cosmosContainer, *parentResourceID) + untypedCRUD := database.NewUntypedCRUD(stepInput.CosmosContainer, *parentResourceID) for _, childKey := range l.key.Descendents { childResourceType, err := azcorearm.ParseResourceType(childKey.ResourceType) require.NoError(t, err) diff --git a/test-integration/utils/databasemutationhelpers/step_untypedget.go b/test-integration/utils/databasemutationhelpers/step_untypedget.go index 8c462e58c7..4f8b1fff8d 100644 --- a/test-integration/utils/databasemutationhelpers/step_untypedget.go +++ b/test-integration/utils/databasemutationhelpers/step_untypedget.go @@ -26,7 +26,6 @@ import ( "github.com/stretchr/testify/require" azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" "github.com/Azure/ARO-HCP/internal/database" ) @@ -88,11 +87,11 @@ func (l *untypedGetStep) StepID() StepID { return l.stepID } -func (l *untypedGetStep) RunTest(ctx context.Context, t *testing.T, cosmosContainer *azcosmos.ContainerClient) { +func (l *untypedGetStep) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { parentResourceID, err := azcorearm.ParseResourceID(l.key.ParentResourceID) require.NoError(t, err) - untypedCRUD := database.NewUntypedCRUD(cosmosContainer, *parentResourceID) + untypedCRUD := database.NewUntypedCRUD(stepInput.CosmosContainer, *parentResourceID) for _, childKey := range l.key.Descendents { childResourceType, err := azcorearm.ParseResourceType(childKey.ResourceType) require.NoError(t, err) diff --git a/test-integration/utils/databasemutationhelpers/step_untypedlist.go b/test-integration/utils/databasemutationhelpers/step_untypedlist.go index 81541ecda8..f3dd72ab58 100644 --- a/test-integration/utils/databasemutationhelpers/step_untypedlist.go +++ b/test-integration/utils/databasemutationhelpers/step_untypedlist.go @@ -24,7 +24,6 @@ import ( "github.com/stretchr/testify/require" azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" "github.com/Azure/ARO-HCP/internal/database" ) @@ -66,11 +65,11 @@ func (l *untypedListStep) StepID() StepID { return l.stepID } -func (l *untypedListStep) RunTest(ctx context.Context, t *testing.T, cosmosContainer *azcosmos.ContainerClient) { +func (l *untypedListStep) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { parentResourceID, err := azcorearm.ParseResourceID(l.key.ParentResourceID) require.NoError(t, err) - untypedCRUD := database.NewUntypedCRUD(cosmosContainer, *parentResourceID) + untypedCRUD := database.NewUntypedCRUD(stepInput.CosmosContainer, *parentResourceID) for _, childKey := range l.key.Descendents { childResourceType, err := azcorearm.ParseResourceType(childKey.ResourceType) require.NoError(t, err) diff --git a/test-integration/utils/databasemutationhelpers/step_untypedlistrecursive.go b/test-integration/utils/databasemutationhelpers/step_untypedlistrecursive.go index 4a5508155e..e0888af000 100644 --- a/test-integration/utils/databasemutationhelpers/step_untypedlistrecursive.go +++ b/test-integration/utils/databasemutationhelpers/step_untypedlistrecursive.go @@ -24,7 +24,6 @@ import ( "github.com/stretchr/testify/require" azcorearm "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" "github.com/Azure/ARO-HCP/internal/database" ) @@ -77,11 +76,11 @@ func (l *untypedListRecursiveStep) StepID() StepID { return l.stepID } -func (l *untypedListRecursiveStep) RunTest(ctx context.Context, t *testing.T, cosmosContainer *azcosmos.ContainerClient) { +func (l *untypedListRecursiveStep) RunTest(ctx context.Context, t *testing.T, stepInput StepInput) { parentResourceID, err := azcorearm.ParseResourceID(l.key.ParentResourceID) require.NoError(t, err) - untypedCRUD := database.NewUntypedCRUD(cosmosContainer, *parentResourceID) + untypedCRUD := database.NewUntypedCRUD(stepInput.CosmosContainer, *parentResourceID) for _, childKey := range l.key.Descendents { childResourceType, err := azcorearm.ParseResourceType(childKey.ResourceType) require.NoError(t, err) diff --git a/test-integration/utils/integrationutils/cosmos_testinfo.go b/test-integration/utils/integrationutils/cosmos_testinfo.go index 05242b2d0b..b874d03909 100644 --- a/test-integration/utils/integrationutils/cosmos_testinfo.go +++ b/test-integration/utils/integrationutils/cosmos_testinfo.go @@ -24,8 +24,10 @@ import ( "io/fs" "net/http" "os" + "path" "path/filepath" "strings" + "testing" "github.com/google/uuid" @@ -43,7 +45,7 @@ import ( "github.com/Azure/ARO-HCP/internal/utils" ) -func NewCosmosFromTestingEnv(ctx context.Context) (*CosmosIntegrationTestInfo, error) { +func NewCosmosFromTestingEnv(ctx context.Context, t *testing.T) (*CosmosIntegrationTestInfo, error) { cosmosClient, err := createCosmosClientFromEnv() if err != nil { return nil, err @@ -59,7 +61,7 @@ func NewCosmosFromTestingEnv(ctx context.Context) (*CosmosIntegrationTestInfo, e } testInfo := &CosmosIntegrationTestInfo{ - ArtifactsDir: getArtifactDir(), + ArtifactsDir: path.Join(getArtifactDir(), t.Name()), CosmosDatabaseClient: cosmosDatabaseClient, DBClient: dbClient, CosmosClient: cosmosClient, diff --git a/test-integration/utils/integrationutils/frontend_testinfo.go b/test-integration/utils/integrationutils/frontend_testinfo.go index 9afae23147..5bd8b8fc52 100644 --- a/test-integration/utils/integrationutils/frontend_testinfo.go +++ b/test-integration/utils/integrationutils/frontend_testinfo.go @@ -171,11 +171,11 @@ func (s *FrontendIntegrationTestInfo) saveClusterServiceMockData(ctx context.Con return nil } -// adds mock data for later inclusion in artifacts -func (s *FrontendIntegrationTestInfo) AddMockData(dataName string, data map[string][]any) error { - if _, ok := s.mockData[dataName]; ok { - return fmt.Errorf("mock data for %q already exists", dataName) +func (s *FrontendIntegrationTestInfo) GetOrCreateMockData(dataName string) map[string][]any { + if existing, ok := s.mockData[dataName]; ok { + return existing } - s.mockData[dataName] = data - return nil + newData := map[string][]any{} + s.mockData[dataName] = newData + return newData } diff --git a/test-integration/utils/integrationutils/mutation_test_utils.go b/test-integration/utils/integrationutils/mutation_test_utils.go index bcc778c6d1..bb35760804 100644 --- a/test-integration/utils/integrationutils/mutation_test_utils.go +++ b/test-integration/utils/integrationutils/mutation_test_utils.go @@ -43,14 +43,12 @@ import ( ) func TrivialPassThroughClusterServiceMock(t *testing.T, testInfo *FrontendIntegrationTestInfo, initialDataDir fs.FS) error { - internalIDToCluster := map[string][]any{} - internalIDToAutoscaler := map[string][]any{} - internalIDToExternalAuth := map[string][]any{} - internalIDToNodePool := map[string][]any{} + internalIDToCluster := testInfo.GetOrCreateMockData(t.Name() + "_clusters") + internalIDToExternalAuth := testInfo.GetOrCreateMockData(t.Name() + "_externalAuths") + internalIDToNodePool := testInfo.GetOrCreateMockData(t.Name() + "_nodePools") + internalIDToAutoscaler := testInfo.GetOrCreateMockData(t.Name() + "_autoscalers") if initialDataDir != nil { - // TODO a full directory scan would probably make some kinds of testing easier - dirContent, err := fs.ReadDir(initialDataDir, ".") if err != nil { return fmt.Errorf("failed to read dir: %w", err) @@ -79,23 +77,49 @@ func TrivialPassThroughClusterServiceMock(t *testing.T, testInfo *FrontendIntegr return fmt.Errorf("duplicate cluster: %s", obj.HREF()) } internalIDToCluster[obj.HREF()] = []any{obj} - internalIDToAutoscaler[obj.HREF()] = []any{obj} case strings.HasSuffix(dirEntry.Name(), "-external-auth.json"): + obj, err := arohcpv1alpha1.UnmarshalExternalAuth(fileContent) + if err != nil { + return fmt.Errorf("failed to unmarshal nodepool: %w", err) + } + if _, exists := internalIDToExternalAuth[obj.HREF()]; exists { + return fmt.Errorf("duplicate nodepool: %s", obj.HREF()) + } + internalIDToExternalAuth[obj.HREF()] = []any{obj} + case strings.HasSuffix(dirEntry.Name(), "-node-pool.json"): + obj, err := arohcpv1alpha1.UnmarshalNodePool(fileContent) + if err != nil { + return fmt.Errorf("failed to unmarshal nodepool: %w", err) + } + if _, exists := internalIDToNodePool[obj.HREF()]; exists { + return fmt.Errorf("duplicate nodepool: %s", obj.HREF()) + } + internalIDToNodePool[obj.HREF()] = []any{obj} + + case strings.HasSuffix(dirEntry.Name(), "-autoscaler.json"): + obj, err := arohcpv1alpha1.UnmarshalClusterAutoscaler(fileContent) + if err != nil { + return fmt.Errorf("failed to unmarshal cluster: %w", err) + } + if _, exists := internalIDToAutoscaler[obj.HREF()]; exists { + return fmt.Errorf("duplicate autoscaler: %s", obj.HREF()) + } + internalIDToAutoscaler[obj.HREF()] = []any{obj} + default: return fmt.Errorf("unknown file %s", dirEntry.Name()) } } } - require.NoError(t, testInfo.AddMockData(t.Name()+"_clusters", internalIDToCluster)) testInfo.MockClusterServiceClient.EXPECT().PostCluster(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, clusterBuilder *csarhcpv1alpha1.ClusterBuilder, autoscalerBuilder *csarhcpv1alpha1.ClusterAutoscalerBuilder) (*csarhcpv1alpha1.Cluster, error) { justID := rand.String(10) internalID := "/api/clusters_mgmt/v1/clusters/" + justID if autoscalerBuilder != nil { - autoscaler, err := autoscalerBuilder.Build() + autoscaler, err := autoscalerBuilder.HREF(internalID).Build() if err != nil { return nil, err } @@ -126,13 +150,13 @@ func TrivialPassThroughClusterServiceMock(t *testing.T, testInfo *FrontendIntegr internalIDToCluster[id.String()] = append(internalIDToCluster[id.String()], ret) return ret, nil }).AnyTimes() - testInfo.MockClusterServiceClient.EXPECT().UpdateClusterAutoscaler(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, id ocm.InternalID, builder *arohcpv1alpha1.ClusterAutoscalerBuilder) (*arohcpv1alpha1.ClusterAutoscaler, error) { - ret, err := builder.Build() + testInfo.MockClusterServiceClient.EXPECT().UpdateClusterAutoscaler(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, internalID ocm.InternalID, builder *arohcpv1alpha1.ClusterAutoscalerBuilder) (*arohcpv1alpha1.ClusterAutoscaler, error) { + ret, err := builder.HREF(internalID.String()).Build() if err != nil { return nil, err } - internalIDToAutoscaler[id.String()] = append(internalIDToAutoscaler[id.String()], ret) + internalIDToAutoscaler[internalID.String()] = append(internalIDToAutoscaler[internalID.String()], ret) return ret, nil }).AnyTimes() testInfo.MockClusterServiceClient.EXPECT().GetCluster(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, id ocm.InternalID) (*csarhcpv1alpha1.Cluster, error) { @@ -150,7 +174,6 @@ func TrivialPassThroughClusterServiceMock(t *testing.T, testInfo *FrontendIntegr return ocm.NewSimpleClusterListIterator(allObjs, nil) }).AnyTimes() - require.NoError(t, testInfo.AddMockData(t.Name()+"_externalAuths", internalIDToExternalAuth)) testInfo.MockClusterServiceClient.EXPECT().PostExternalAuth(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, clusterID ocm.InternalID, builder *arohcpv1alpha1.ExternalAuthBuilder) (*arohcpv1alpha1.ExternalAuth, error) { justID := rand.String(10) builder.ID(justID) @@ -193,7 +216,6 @@ func TrivialPassThroughClusterServiceMock(t *testing.T, testInfo *FrontendIntegr return ocm.NewSimpleExternalAuthListIterator(allObjs, nil) }).AnyTimes() - require.NoError(t, testInfo.AddMockData(t.Name()+"_nodePools", internalIDToNodePool)) testInfo.MockClusterServiceClient.EXPECT().PostNodePool(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, clusterID ocm.InternalID, builder *arohcpv1alpha1.NodePoolBuilder) (*arohcpv1alpha1.NodePool, error) { justID := rand.String(10) nodePoolInternalID := clusterID.String() + "/node_pools/" + justID diff --git a/test-integration/utils/integrationutils/utils.go b/test-integration/utils/integrationutils/utils.go index ba03a0e063..c4c53a61e2 100644 --- a/test-integration/utils/integrationutils/utils.go +++ b/test-integration/utils/integrationutils/utils.go @@ -63,7 +63,7 @@ func getArtifactDir() string { } func NewFrontendFromTestingEnv(ctx context.Context, t *testing.T) (*frontend.Frontend, *FrontendIntegrationTestInfo, error) { - cosmosTestEnv, err := NewCosmosFromTestingEnv(ctx) + cosmosTestEnv, err := NewCosmosFromTestingEnv(ctx, t) if err != nil { return nil, nil, err } @@ -94,7 +94,7 @@ func NewFrontendFromTestingEnv(ctx context.Context, t *testing.T) (*frontend.Fro aroHCPFrontend := frontend.NewFrontend(logger, listener, metricsListener, metricsRegistry, cosmosTestEnv.DBClient, clusterServiceClient, noOpAuditClient) testInfo := &FrontendIntegrationTestInfo{ CosmosIntegrationTestInfo: cosmosTestEnv, - ArtifactsDir: artifactDir, + ArtifactsDir: cosmosTestEnv.ArtifactsDir, mockData: make(map[string]map[string][]any), MockClusterServiceClient: clusterServiceClient, FrontendURL: fmt.Sprintf("http://%s", listener.Addr().String()),