From d4e7851321ab3f173afd34ec8503bce4f827263b Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Tue, 3 Dec 2024 09:27:02 -0500 Subject: [PATCH 01/20] feat: [M3-8953] - OBJ Gen2 Updates --- packages/api-v4/src/object-storage/buckets.ts | 5 ++ .../AccessKeyTable/HostNameTableCell.tsx | 47 ++++++++++++------- .../ObjectStorage/BucketDetail/index.tsx | 6 +-- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/packages/api-v4/src/object-storage/buckets.ts b/packages/api-v4/src/object-storage/buckets.ts index d05db3855c8..c3be674f718 100644 --- a/packages/api-v4/src/object-storage/buckets.ts +++ b/packages/api-v4/src/object-storage/buckets.ts @@ -262,6 +262,11 @@ export const updateBucketAccess = ( setData(params, UpdateBucketAccessSchema) ); +/** + * getObjectStorageEndpoints + * + * Returns a list of Object Storage Endpoints. + */ export const getObjectStorageEndpoints = ({ filter, params }: RequestOptions) => Request>( setMethod('GET'), diff --git a/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx b/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx index 9a7924f6329..8dcfc392dd7 100644 --- a/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx +++ b/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx @@ -27,28 +27,39 @@ export const HostNameTableCell = (props: Props) => { if (!regionsLookup || !regionsData || !regions || regions.length === 0) { return None; } - const label = regionsLookup[storageKeyData.regions[0].id]?.label; - const s3Endpoint = storageKeyData?.regions[0]?.s3_endpoint; - const endpointType = storageKeyData?.regions[0]?.endpoint_type; + const formatEndpoint = (region: ObjectStorageKeyRegions) => { + const label = regionsLookup[region.id]?.label; + const endpointType = region.endpoint_type + ? ` (${region.endpoint_type})` + : ''; + return `${label}${endpointType}: ${region.s3_endpoint}`; + }; + + const firstRegion = regions[0]; + const formattedFirstEndpoint = formatEndpoint(firstRegion); + const allEndpoints = regions.map(formatEndpoint).join('\n'); return ( - {label} - {endpointType && ` (${endpointType})`}: {s3Endpoint}  - {storageKeyData?.regions?.length === 1 && ( - + {formattedFirstEndpoint}  + {regions.length === 1 && ( + )} - {storageKeyData.regions.length > 1 && ( - { - setHostNames(storageKeyData.regions); - setShowHostNamesDrawers(true); - }} - type="button" - > - and {storageKeyData.regions.length - 1} more... - + {regions.length > 1 && ( + <> + | +{regions.length - 1} regions |  + { + setHostNames(regions); + setShowHostNamesDrawers(true); + }} + type="button" + > + Show All + + )} + ); }; @@ -59,5 +70,5 @@ const StyledCopyIcon = styled(CopyTooltip)(({ theme }) => ({ top: 1, width: 12, }, - marginLeft: theme.spacing(), + marginLeft: theme.spacing(0.5), })); diff --git a/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx b/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx index be9f752b461..44c66c18085 100644 --- a/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx +++ b/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx @@ -64,7 +64,7 @@ export const BucketDetailLanding = React.memo((props: Props) => { const { endpoint_type } = bucket ?? {}; - const isSSLEnabled = endpoint_type !== 'E2' && endpoint_type !== 'E3'; + const isGen2Endpoint = endpoint_type === 'E2' || endpoint_type === 'E3'; const tabs = [ { @@ -75,7 +75,7 @@ export const BucketDetailLanding = React.memo((props: Props) => { routeName: `${props.match.url}/access`, title: 'Access', }, - ...(flags.objectStorageGen2?.enabled + ...(isGen2Endpoint ? [ { routeName: `${props.match.url}/properties`, @@ -83,7 +83,7 @@ export const BucketDetailLanding = React.memo((props: Props) => { }, ] : []), - ...(isSSLEnabled + ...(!isGen2Endpoint ? [ { routeName: `${props.match.url}/ssl`, From e03a55e7c454721ba6b5306629a87d0cf7860ffc Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Tue, 3 Dec 2024 09:49:53 -0500 Subject: [PATCH 02/20] Add changeset --- .../.changeset/pr-11355-upcoming-features-1733237339445.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 packages/manager/.changeset/pr-11355-upcoming-features-1733237339445.md diff --git a/packages/manager/.changeset/pr-11355-upcoming-features-1733237339445.md b/packages/manager/.changeset/pr-11355-upcoming-features-1733237339445.md new file mode 100644 index 00000000000..c4a32321844 --- /dev/null +++ b/packages/manager/.changeset/pr-11355-upcoming-features-1733237339445.md @@ -0,0 +1,6 @@ +--- +"@linode/manager": Upcoming Features +--- + +Updates Regions/S3 Hostnames interface to match new design guidelines with +improved visualization of multiple storage regions. ([#11355](https://github.com/linode/manager/pull/11355)) From 4d7799e618311f3d283565c77c538e328523dd5c Mon Sep 17 00:00:00 2001 From: Connie Liu Date: Tue, 3 Dec 2024 10:59:05 -0500 Subject: [PATCH 03/20] fix duplicate buckets landing page, may rework --- .../src/queries/object-storage/requests.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/manager/src/queries/object-storage/requests.ts b/packages/manager/src/queries/object-storage/requests.ts index 4176f7393c4..b7bf9d17996 100644 --- a/packages/manager/src/queries/object-storage/requests.ts +++ b/packages/manager/src/queries/object-storage/requests.ts @@ -166,8 +166,21 @@ export const getAllBucketsFromEndpoints = async ( return { buckets: [], errors: [] }; } + // Avoid multiple getBucket calls for the same region while also + // keeping some endpoint information in case of an error being + // returned for that region + const uniqueRegions: Set = new Set(); + const filteredEndpoints: ObjectStorageEndpoint[] = []; + + for (const endpoint of endpoints) { + if (!uniqueRegions.has(endpoint.region)) { + filteredEndpoints.push(endpoint); + } + uniqueRegions.add(endpoint.region); + } + const results = await Promise.all( - endpoints.map((endpoint) => + filteredEndpoints.map((endpoint) => getAll((params) => getBucketsInRegion(endpoint.region, params) )() @@ -187,7 +200,7 @@ export const getAllBucketsFromEndpoints = async ( } }); - if (errors.length === endpoints.length) { + if (errors.length === filteredEndpoints.length) { throw new Error('Unable to get Object Storage buckets.'); } From 15e7bef9e7f463f03e4b30cbf509a78ce746bb72 Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Tue, 3 Dec 2024 15:22:07 -0500 Subject: [PATCH 04/20] Update e2e tests --- .../core/objectStorage/bucket-details.spec.ts | 65 +++++++++++++++++++ .../ObjectStorage/BucketDetail/index.tsx | 2 +- 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 packages/manager/cypress/e2e/core/objectStorage/bucket-details.spec.ts diff --git a/packages/manager/cypress/e2e/core/objectStorage/bucket-details.spec.ts b/packages/manager/cypress/e2e/core/objectStorage/bucket-details.spec.ts new file mode 100644 index 00000000000..c7bf56f68be --- /dev/null +++ b/packages/manager/cypress/e2e/core/objectStorage/bucket-details.spec.ts @@ -0,0 +1,65 @@ +import { mockGetAccount } from 'support/intercepts/account'; +import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; +import { mockGetBucketsForRegion } from 'support/intercepts/object-storage'; +import { + accountFactory, + objectStorageBucketFactory, + regionFactory, +} from 'src/factories'; +import { randomLabel } from 'support/util/random'; + +describe('Object Storage Gen 1 Bucket Details Tabs', () => { + beforeEach(() => { + mockAppendFeatureFlags({ + objMultiCluster: true, + objectStorageGen2: { enabled: false }, + }).as('getFeatureFlags'); + mockGetAccount( + accountFactory.build({ + capabilities: ['Object Storage', 'Object Storage Access Key Regions'], + }) + ).as('getAccount'); + }); + + const mockRegion = regionFactory.build({ + capabilities: ['Object Storage'], + }); + + const mockBucket = objectStorageBucketFactory.build({ + label: randomLabel(), + region: mockRegion.id, + }); + + describe('Properties tab without required capabilities', () => { + beforeEach(() => { + mockGetAccount( + accountFactory.build({ + capabilities: ['Object Storage'], + }) + ).as('getAccount'); + mockAppendFeatureFlags({ + objMultiCluster: true, + objectStorageGen2: { enabled: false }, + }).as('getFeatureFlags'); + }); + + it(`confirms the Properties tab does not exist for users without 'Object Storage Endpoint Types' capability`, () => { + const { region, label } = mockBucket; + + mockGetBucketsForRegion(mockRegion.id, [mockBucket]).as( + 'getBucketsForRegion' + ); + + cy.visitWithLogin( + `/object-storage/buckets/${region}/${label}/properties` + ); + + cy.wait(['@getFeatureFlags', '@getAccount']); + + cy.wait(1000); + + // Confirm Properties tab is not visible + cy.findByText('Properties', { timeout: 15000 }).should('not.exist'); + }); + }); +}); diff --git a/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx b/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx index 44c66c18085..d63fee919a3 100644 --- a/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx +++ b/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx @@ -75,7 +75,7 @@ export const BucketDetailLanding = React.memo((props: Props) => { routeName: `${props.match.url}/access`, title: 'Access', }, - ...(isGen2Endpoint + ...(isObjectStorageGen2Enabled ? [ { routeName: `${props.match.url}/properties`, From 82da5de52176e67c5418be73b2f894f4b620869a Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Tue, 3 Dec 2024 15:28:34 -0500 Subject: [PATCH 05/20] Remove redundant beforeEach --- .../e2e/core/objectStorage/bucket-details.spec.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packages/manager/cypress/e2e/core/objectStorage/bucket-details.spec.ts b/packages/manager/cypress/e2e/core/objectStorage/bucket-details.spec.ts index c7bf56f68be..7243fe2c380 100644 --- a/packages/manager/cypress/e2e/core/objectStorage/bucket-details.spec.ts +++ b/packages/manager/cypress/e2e/core/objectStorage/bucket-details.spec.ts @@ -31,18 +31,6 @@ describe('Object Storage Gen 1 Bucket Details Tabs', () => { }); describe('Properties tab without required capabilities', () => { - beforeEach(() => { - mockGetAccount( - accountFactory.build({ - capabilities: ['Object Storage'], - }) - ).as('getAccount'); - mockAppendFeatureFlags({ - objMultiCluster: true, - objectStorageGen2: { enabled: false }, - }).as('getFeatureFlags'); - }); - it(`confirms the Properties tab does not exist for users without 'Object Storage Endpoint Types' capability`, () => { const { region, label } = mockBucket; From 0bd1c2c275140446240fbc490ec841cca05267c1 Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Tue, 3 Dec 2024 16:42:39 -0500 Subject: [PATCH 06/20] Small adjustment to request --- .../src/queries/object-storage/requests.ts | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/packages/manager/src/queries/object-storage/requests.ts b/packages/manager/src/queries/object-storage/requests.ts index b7bf9d17996..f9b3d8f0617 100644 --- a/packages/manager/src/queries/object-storage/requests.ts +++ b/packages/manager/src/queries/object-storage/requests.ts @@ -166,26 +166,29 @@ export const getAllBucketsFromEndpoints = async ( return { buckets: [], errors: [] }; } - // Avoid multiple getBucket calls for the same region while also - // keeping some endpoint information in case of an error being - // returned for that region - const uniqueRegions: Set = new Set(); - const filteredEndpoints: ObjectStorageEndpoint[] = []; + // Initialize a Map to group endpoints by region for better error handling and flexibility. + const endpointsByRegion = new Map(); for (const endpoint of endpoints) { - if (!uniqueRegions.has(endpoint.region)) { - filteredEndpoints.push(endpoint); - } - uniqueRegions.add(endpoint.region); + const existingEndpoint = endpointsByRegion.get(endpoint.region) || []; + + // Update the Map with the current endpoint, maintaining all endpoints per region. + endpointsByRegion.set(endpoint.region, [...existingEndpoint, endpoint]); } const results = await Promise.all( - filteredEndpoints.map((endpoint) => + Array.from(endpointsByRegion.entries()).map(([region, regionEndpoints]) => getAll((params) => - getBucketsInRegion(endpoint.region, params) + getBucketsInRegion(region, params) )() - .then((data) => ({ buckets: data.data, endpoint })) - .catch((error) => ({ endpoint, error })) + .then((data) => ({ + buckets: data.data, + endpoints: regionEndpoints, + })) + .catch((error) => ({ + endpoints: regionEndpoints, + error, + })) ) ); @@ -196,11 +199,14 @@ export const getAllBucketsFromEndpoints = async ( if ('buckets' in result) { buckets.push(...result.buckets); } else { - errors.push({ endpoint: result.endpoint, error: result.error }); + // For each endpoint in the region, log the error to provide detailed error information. + result.endpoints.forEach((endpoint) => { + errors.push({ endpoint, error: result.error }); + }); } }); - if (errors.length === filteredEndpoints.length) { + if (errors.length === endpoints.length) { throw new Error('Unable to get Object Storage buckets.'); } From bcbe0150e8b88861837971dc00e618655048e3ba Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Tue, 3 Dec 2024 18:05:56 -0500 Subject: [PATCH 07/20] fix access keys e2e test --- .../objectStorageGen2/bucket-access-keys-gen2.spec.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-access-keys-gen2.spec.ts b/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-access-keys-gen2.spec.ts index 2f47a3db22f..af9220d6585 100644 --- a/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-access-keys-gen2.spec.ts +++ b/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-access-keys-gen2.spec.ts @@ -59,12 +59,12 @@ describe('Object Storage gen2 access keys tests', () => { cy.findByText(mockAccessKey1.label).should('be.visible'); cy.findByText(mockAccessKey2.label).should('be.visible'); cy.findByText('US, Newark, NJ (E3): us-east.com').should('be.visible'); - cy.findByText('US, Atlanta, GA (E3): us-southeast.com').should( - 'be.visible' - ); - // confirm endpoint types are present in the drawer - cy.findByText('and 3 more...').should('be.visible').click(); + // Using contains since the text includes additional information, i.e. '| +2 regions | Show All' + cy.contains('US, Atlanta, GA (E3): us-southeast.com').should('be.visible'); + cy.contains('+3 regions').should('be.visible'); + cy.findByText('Show All').should('be.visible').click(); + ui.drawer .findByTitle('Regions / S3 Hostnames') .should('be.visible') From 7f40ea48f9fe79ee39080e6cdda427df2952d877 Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Tue, 3 Dec 2024 21:34:26 -0500 Subject: [PATCH 08/20] Fix bucket-create-gen2.spec.ts failing tests @linode/frontend-sdet --- .../objectStorageGen2/bucket-create-gen2.spec.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts b/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts index 068b97e9ccb..100cda5dbac 100644 --- a/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts +++ b/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-create-gen2.spec.ts @@ -233,9 +233,6 @@ describe('Object Storage Gen2 create bucket tests', () => { .click(); }); - // Wait for the newly 'created' mocked bucket to appear - cy.wait(['@getBuckets']); - // Confirm request body has expected data cy.wait('@createBucket').then((xhr) => { const requestPayload = xhr.request.body; @@ -356,9 +353,6 @@ describe('Object Storage Gen2 create bucket tests', () => { .click(); }); - // Wait for the newly 'created' mocked bucket to appear - cy.wait(['@getBuckets']); - // Confirm request body has expected data cy.wait('@createBucket').then((xhr) => { const requestPayload = xhr.request.body; @@ -483,9 +477,6 @@ describe('Object Storage Gen2 create bucket tests', () => { .click(); }); - // Wait for the newly 'created' mocked bucket to appear - cy.wait(['@getBuckets']); - // Confirm request body has expected data cy.wait('@createBucket').then((xhr) => { const requestPayload = xhr.request.body; @@ -608,9 +599,6 @@ describe('Object Storage Gen2 create bucket tests', () => { .click(); }); - // Wait for the newly 'created' mocked bucket to appear - cy.wait(['@getBuckets']); - // Confirm request body has expected data cy.wait('@createBucket').then((xhr) => { const requestPayload = xhr.request.body; From 7edebf9082d37389940be3c8b7e63c12fcd04d5e Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Wed, 4 Dec 2024 10:54:01 -0500 Subject: [PATCH 09/20] E2E review updates @cliu-akamai @AzureLatte --- .../core/objectStorage/bucket-details.spec.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/manager/cypress/e2e/core/objectStorage/bucket-details.spec.ts b/packages/manager/cypress/e2e/core/objectStorage/bucket-details.spec.ts index 7243fe2c380..fc2e75c90e7 100644 --- a/packages/manager/cypress/e2e/core/objectStorage/bucket-details.spec.ts +++ b/packages/manager/cypress/e2e/core/objectStorage/bucket-details.spec.ts @@ -1,6 +1,6 @@ import { mockGetAccount } from 'support/intercepts/account'; import { mockAppendFeatureFlags } from 'support/intercepts/feature-flags'; -import { mockGetBucketsForRegion } from 'support/intercepts/object-storage'; +import { ui } from 'support/ui'; import { accountFactory, objectStorageBucketFactory, @@ -34,20 +34,21 @@ describe('Object Storage Gen 1 Bucket Details Tabs', () => { it(`confirms the Properties tab does not exist for users without 'Object Storage Endpoint Types' capability`, () => { const { region, label } = mockBucket; - mockGetBucketsForRegion(mockRegion.id, [mockBucket]).as( - 'getBucketsForRegion' - ); - cy.visitWithLogin( `/object-storage/buckets/${region}/${label}/properties` ); cy.wait(['@getFeatureFlags', '@getAccount']); - cy.wait(1000); + // Confirm that expected tabs are visible. + ui.tabList.findTabByTitle('Objects').should('be.visible'); + ui.tabList.findTabByTitle('Access').should('be.visible'); + ui.tabList.findTabByTitle('SSL/TLS').should('be.visible'); + + // Confirm that "Properties" tab is absent. + cy.findByText('Properties').should('not.exist'); - // Confirm Properties tab is not visible - cy.findByText('Properties', { timeout: 15000 }).should('not.exist'); + // TODO Confirm "Not Found" notice is present. }); }); }); From 597f46b17c3cdf937557c4b40b3fb39ea6128897 Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Wed, 4 Dec 2024 12:02:32 -0500 Subject: [PATCH 10/20] Fix issue where properties content was overriding SSL for non-gen2 capability users @coliu-akamai --- .../manager/src/features/ObjectStorage/BucketDetail/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx b/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx index d63fee919a3..4b548d0594c 100644 --- a/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx +++ b/packages/manager/src/features/ObjectStorage/BucketDetail/index.tsx @@ -136,7 +136,7 @@ export const BucketDetailLanding = React.memo((props: Props) => { endpointType={endpoint_type} /> - {flags.objectStorageGen2?.enabled && bucket && ( + {isObjectStorageGen2Enabled && bucket && ( From 26170f4bb4b03c79651c73205a4a0446edd5482d Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Wed, 4 Dec 2024 12:49:09 -0500 Subject: [PATCH 11/20] Remove CORS from object drawers @bnussman-akamai --- .../features/ObjectStorage/BucketDetail/AccessSelect.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/manager/src/features/ObjectStorage/BucketDetail/AccessSelect.tsx b/packages/manager/src/features/ObjectStorage/BucketDetail/AccessSelect.tsx index 0322c90c196..b99630fae17 100644 --- a/packages/manager/src/features/ObjectStorage/BucketDetail/AccessSelect.tsx +++ b/packages/manager/src/features/ObjectStorage/BucketDetail/AccessSelect.tsx @@ -47,10 +47,10 @@ export const AccessSelect = React.memo((props: Props) => { const { close: closeDialog, isOpen, open: openDialog } = useOpenClose(); const label = capitalize(variant); + + // CORS is only available at a bucket level, not at an object level. const isCorsAvailable = - (variant === 'bucket' || variant === 'object') && - endpointType !== 'E2' && - endpointType !== 'E3'; + variant === 'bucket' && endpointType !== 'E2' && endpointType !== 'E3'; const { data: bucketAccessData, From 03297f6fdab52e8e81e0694663eed1cabf233cb7 Mon Sep 17 00:00:00 2001 From: Jaalah Ramos <125309814+jaalah-akamai@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:49:05 -0500 Subject: [PATCH 12/20] Update packages/manager/.changeset/pr-11355-upcoming-features-1733237339445.md Co-authored-by: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com> --- .../.changeset/pr-11355-upcoming-features-1733237339445.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/.changeset/pr-11355-upcoming-features-1733237339445.md b/packages/manager/.changeset/pr-11355-upcoming-features-1733237339445.md index c4a32321844..d333c0cc08a 100644 --- a/packages/manager/.changeset/pr-11355-upcoming-features-1733237339445.md +++ b/packages/manager/.changeset/pr-11355-upcoming-features-1733237339445.md @@ -2,5 +2,5 @@ "@linode/manager": Upcoming Features --- -Updates Regions/S3 Hostnames interface to match new design guidelines with +Update Regions/S3 Hostnames interface to match new design guidelines with improved visualization of multiple storage regions. ([#11355](https://github.com/linode/manager/pull/11355)) From ad14035d020eced37190fb64c6a8ee8c7156b4fa Mon Sep 17 00:00:00 2001 From: Jaalah Ramos <125309814+jaalah-akamai@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:49:26 -0500 Subject: [PATCH 13/20] Update packages/manager/.changeset/pr-11355-upcoming-features-1733237339445.md Co-authored-by: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com> --- .../.changeset/pr-11355-upcoming-features-1733237339445.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/.changeset/pr-11355-upcoming-features-1733237339445.md b/packages/manager/.changeset/pr-11355-upcoming-features-1733237339445.md index d333c0cc08a..efc8449385d 100644 --- a/packages/manager/.changeset/pr-11355-upcoming-features-1733237339445.md +++ b/packages/manager/.changeset/pr-11355-upcoming-features-1733237339445.md @@ -3,4 +3,4 @@ --- Update Regions/S3 Hostnames interface to match new design guidelines with -improved visualization of multiple storage regions. ([#11355](https://github.com/linode/manager/pull/11355)) +improved visualization of multiple storage regions ([#11355](https://github.com/linode/manager/pull/11355)) From 1edce89ee7c55c21b092aaf7b60eff3215e45e22 Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Wed, 4 Dec 2024 14:57:54 -0500 Subject: [PATCH 14/20] Remove double copy icon @dwiley-akamai --- .../AccessKeyTable/HostNameTableCell.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx b/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx index 8dcfc392dd7..59297fa165b 100644 --- a/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx +++ b/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx @@ -38,14 +38,12 @@ export const HostNameTableCell = (props: Props) => { const firstRegion = regions[0]; const formattedFirstEndpoint = formatEndpoint(firstRegion); const allEndpoints = regions.map(formatEndpoint).join('\n'); + const showMultipleRegions = regions.length > 1; return ( {formattedFirstEndpoint}  - {regions.length === 1 && ( - - )} - {regions.length > 1 && ( + {showMultipleRegions ? ( <> | +{regions.length - 1} regions |  { setHostNames(regions); setShowHostNamesDrawers(true); }} - type="button" > Show All + + ) : ( + )} - ); }; From 8755f08acc22a85295440a2c9a6407778ea550e4 Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Wed, 4 Dec 2024 15:08:37 -0500 Subject: [PATCH 15/20] Add changesets --- packages/manager/.changeset/pr-11355-fixed-1733342647044.md | 5 +++++ .../.changeset/pr-11355-upcoming-features-1733342861906.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 packages/manager/.changeset/pr-11355-fixed-1733342647044.md create mode 100644 packages/manager/.changeset/pr-11355-upcoming-features-1733342861906.md diff --git a/packages/manager/.changeset/pr-11355-fixed-1733342647044.md b/packages/manager/.changeset/pr-11355-fixed-1733342647044.md new file mode 100644 index 00000000000..3d158411d10 --- /dev/null +++ b/packages/manager/.changeset/pr-11355-fixed-1733342647044.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +Remove CORS toggle for Object Storage bucket objects ([#11355](https://github.com/linode/manager/pull/11355)) diff --git a/packages/manager/.changeset/pr-11355-upcoming-features-1733342861906.md b/packages/manager/.changeset/pr-11355-upcoming-features-1733342861906.md new file mode 100644 index 00000000000..fae08b95637 --- /dev/null +++ b/packages/manager/.changeset/pr-11355-upcoming-features-1733342861906.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Remove Properties tab visibility for users without Gen2 capabilities, and fix duplicate bucket display issue ([#11355](https://github.com/linode/manager/pull/11355)) From 0a0bfa50787105ffbb05ca0c155b5336b70d5acc Mon Sep 17 00:00:00 2001 From: Jaalah Ramos <125309814+jaalah-akamai@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:31:51 -0500 Subject: [PATCH 16/20] Update packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx Co-authored-by: Banks Nussman <115251059+bnussman-akamai@users.noreply.github.com> --- .../AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx b/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx index 59297fa165b..4938dbf7be8 100644 --- a/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx +++ b/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx @@ -45,7 +45,7 @@ export const HostNameTableCell = (props: Props) => { {formattedFirstEndpoint}  {showMultipleRegions ? ( <> - | +{regions.length - 1} regions |  + | +{regions.length - 1} {pluralize('region', 'regions', regions.length - 1)} |  { setHostNames(regions); From 915e201e67442e45a1b50888b160040ade5b3a31 Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Wed, 4 Dec 2024 15:34:37 -0500 Subject: [PATCH 17/20] Pluralize the regions --- .../AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx b/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx index 4938dbf7be8..e23ce7ea5ee 100644 --- a/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx +++ b/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.tsx @@ -5,6 +5,7 @@ import React from 'react'; import { CopyTooltip } from 'src/components/CopyTooltip/CopyTooltip'; import { TableCell } from 'src/components/TableCell'; import { useRegionsQuery } from 'src/queries/regions/regions'; +import { pluralize } from 'src/utilities/pluralize'; import { getRegionsByRegionId } from 'src/utilities/regions'; import type { ObjectStorageKey, ObjectStorageKeyRegions } from '@linode/api-v4'; @@ -45,7 +46,7 @@ export const HostNameTableCell = (props: Props) => { {formattedFirstEndpoint}  {showMultipleRegions ? ( <> - | +{regions.length - 1} {pluralize('region', 'regions', regions.length - 1)} |  + | + {pluralize('region', 'regions', regions.length - 1)} |  { setHostNames(regions); From d1d97d625138452976fcaf9cc44afbfaa05deaa0 Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Wed, 4 Dec 2024 15:40:28 -0500 Subject: [PATCH 18/20] Fix E2E based in pluralize --- .../e2e/core/objectStorageGen2/bucket-access-keys-gen2.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-access-keys-gen2.spec.ts b/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-access-keys-gen2.spec.ts index af9220d6585..057130a1a5f 100644 --- a/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-access-keys-gen2.spec.ts +++ b/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-access-keys-gen2.spec.ts @@ -62,7 +62,7 @@ describe('Object Storage gen2 access keys tests', () => { // Using contains since the text includes additional information, i.e. '| +2 regions | Show All' cy.contains('US, Atlanta, GA (E3): us-southeast.com').should('be.visible'); - cy.contains('+3 regions').should('be.visible'); + cy.contains('+ 3 regions').should('be.visible'); cy.findByText('Show All').should('be.visible').click(); ui.drawer From 2a0bb8c5dae95b9e5fe4dd171203abd1d5fe86b7 Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Wed, 4 Dec 2024 16:09:14 -0500 Subject: [PATCH 19/20] Fix unit tests --- .../AccessKeyTable/HostNameTableCell.test.tsx | 12 +++++++----- .../ObjectStorage/BucketDetail/AccessSelect.test.tsx | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.test.tsx b/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.test.tsx index 12188935e01..63a1a81ef19 100644 --- a/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.test.tsx +++ b/packages/manager/src/features/ObjectStorage/AccessKeyLanding/AccessKeyTable/HostNameTableCell.test.tsx @@ -81,17 +81,19 @@ describe('HostNameTableCell', () => { return HttpResponse.json(makeResourcePage([region])); }) ); - const { findByText } = renderWithTheme( + const { getByText } = renderWithTheme( ); - const hostname = await findByText('US, Newark, NJ: alpha.test.com'); - const moreButton = await findByText(/and\s+1\s+more\.\.\./); - await waitFor(() => expect(hostname).toBeInTheDocument()); - await expect(moreButton).toBeInTheDocument(); + await waitFor(() => { + expect(getByText('Newark', { exact: false })).toBeInTheDocument(); + expect(getByText('alpha.test.com', { exact: false })).toBeInTheDocument(); + expect(getByText(/\+ 1 region/, { exact: false })).toBeInTheDocument(); + expect(getByText('Show All', { exact: false })).toBeInTheDocument(); + }); }); }); diff --git a/packages/manager/src/features/ObjectStorage/BucketDetail/AccessSelect.test.tsx b/packages/manager/src/features/ObjectStorage/BucketDetail/AccessSelect.test.tsx index a02a5ea5b1f..77ad6bcf442 100644 --- a/packages/manager/src/features/ObjectStorage/BucketDetail/AccessSelect.test.tsx +++ b/packages/manager/src/features/ObjectStorage/BucketDetail/AccessSelect.test.tsx @@ -38,8 +38,8 @@ describe('AccessSelect', () => { ['bucket', 'E1', true], ['bucket', 'E2', false], ['bucket', 'E3', false], - ['object', 'E0', true], - ['object', 'E1', true], + ['object', 'E0', false], + ['object', 'E1', false], ['object', 'E2', false], ['object', 'E3', false], ])( From c67db0978461da135745cecf3ddc3e38251cce5a Mon Sep 17 00:00:00 2001 From: Jaalah Ramos Date: Wed, 4 Dec 2024 16:29:34 -0500 Subject: [PATCH 20/20] Fix e2e from removing toggle --- .../objectStorageGen2/bucket-object-gen2.spec.ts | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-object-gen2.spec.ts b/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-object-gen2.spec.ts index 4dbc46e3907..79778512a08 100644 --- a/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-object-gen2.spec.ts +++ b/packages/manager/cypress/e2e/core/objectStorageGen2/bucket-object-gen2.spec.ts @@ -84,8 +84,8 @@ describe('Object Storage Gen2 bucket object tests', () => { const ACLNotification = 'Private: Only you can download this Object'; - // For E0/E1, confirm CORS toggle and ACL selection are both present - // For E2/E3, confirm ACL and Cors are removed + // For E0/E1, ACL selection is present + // For E2/E3, confirm ACL is removed const checkBucketObjectDetailsDrawer = ( bucketFilename: string, endpointType: string @@ -95,16 +95,8 @@ describe('Object Storage Gen2 bucket object tests', () => { endpointType === 'Standard (E3)' || endpointType === 'Standard (E2)' ) { - ui.toggle.find().should('not.exist'); - cy.contains('CORS Enabled').should('not.exist'); cy.findByLabelText('Access Control List (ACL)').should('not.exist'); } else { - ui.toggle - .find() - .should('have.attr', 'data-qa-toggle', 'true') - .should('be.visible'); - cy.contains('CORS Enabled').should('be.visible'); - cy.contains(ACLNotification).should('not.exist'); // Verify that ACL selection show up as options cy.findByLabelText('Access Control List (ACL)') @@ -131,7 +123,7 @@ describe('Object Storage Gen2 bucket object tests', () => { }; /** - + */ it('can check Object details drawer with E0 endpoint type', () => { const endpointTypeE0 = 'Legacy (E0)';