Skip to content

chore(config-resolver): refactor regionInfo types to improve readability #2934

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/config-resolver/src/regionInfo/PartitionHash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* The hash of partition with the information specific to that partition.
* The information includes the list of regions belonging to that partition,
* and the hostname to be used for the partition.
*/
export type PartitionHash = {
[key: string]: { regions: string[]; regionRegex: string; hostname?: string; endpoint?: string };
};
7 changes: 7 additions & 0 deletions packages/config-resolver/src/regionInfo/RegionHash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { RegionInfo } from "@aws-sdk/types";

/**
* The hash of region with the information specific to that region.
* The information can include hostname, signingService and signingRegion.
*/
export type RegionHash = { [key: string]: Partial<Omit<RegionInfo, "partition" | "path">> };
Original file line number Diff line number Diff line change
@@ -1,47 +1,18 @@
import { getHostnameTemplate } from "./getHostnameTemplate";
import { getResolvedPartition, PartitionHash } from "./getResolvedPartition";

jest.mock("./getResolvedPartition");

const AWS_TEMPLATE = "{signingService}.{region}.amazonaws.com";

describe(getHostnameTemplate.name, () => {
const mockRegion = "mockRegion";
const mockPartition = "mockPartition";
const mockRegionRegex = "mockRegionRegex";
const mockHostname = "{region}.mockHostname.com";
const mockSigningService = "mockSigningService";

beforeEach(() => {
(getResolvedPartition as jest.Mock).mockReturnValue(mockPartition);
});

afterEach(() => {
expect(getResolvedPartition).toHaveBeenCalledTimes(1);
jest.clearAllMocks();
it("returns partitionHostname if present", () => {
expect(getHostnameTemplate(mockSigningService, { partitionHostname: mockHostname })).toEqual(mockHostname);
});

it("returns hostname template if present in partitionHash", () => {
const mockPartitionHash: PartitionHash = {
[mockPartition]: {
regions: [mockRegion, `${mockRegion}2`, `${mockRegion}3`],
regionRegex: mockRegionRegex,
hostname: mockHostname,
},
};

expect(
getHostnameTemplate(mockRegion, { signingService: mockSigningService, partitionHash: mockPartitionHash })
).toEqual(mockHostname);
expect(getResolvedPartition).toHaveBeenCalledWith(mockRegion, { partitionHash: mockPartitionHash });
});

it("returns default hostname template if not present in partitionHash", () => {
const mockPartitionHash: PartitionHash = {};

expect(
getHostnameTemplate(mockRegion, { signingService: mockSigningService, partitionHash: mockPartitionHash })
).toEqual(AWS_TEMPLATE.replace("{signingService}", mockSigningService));
expect(getResolvedPartition).toHaveBeenCalledWith(mockRegion, { partitionHash: mockPartitionHash });
it("returns default hostname template if partitionHostname is not present", () => {
expect(getHostnameTemplate(mockSigningService, {})).toEqual(
AWS_TEMPLATE.replace("{signingService}", mockSigningService)
);
});
});
14 changes: 4 additions & 10 deletions packages/config-resolver/src/regionInfo/getHostnameTemplate.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import { getResolvedPartition, GetResolvedPartitionOptions } from "./getResolvedPartition";

const AWS_TEMPLATE = "{signingService}.{region}.amazonaws.com";

export interface GetHostnameTemplateOptions extends GetResolvedPartitionOptions {
/**
* The name to be used while signing the service request.
*/
signingService: string;
export interface GetHostnameTemplateOptions {
partitionHostname?: string;
}

export const getHostnameTemplate = (region: string, { signingService, partitionHash }: GetHostnameTemplateOptions) =>
partitionHash[getResolvedPartition(region, { partitionHash })]?.hostname ??
AWS_TEMPLATE.replace("{signingService}", signingService);
export const getHostnameTemplate = (signingService: string, { partitionHostname }: GetHostnameTemplateOptions) =>
partitionHostname ?? AWS_TEMPLATE.replace("{signingService}", signingService);
55 changes: 27 additions & 28 deletions packages/config-resolver/src/regionInfo/getRegionInfo.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { getRegionInfo } from "./getRegionInfo";
import { getResolvedHostname, RegionHash } from "./getResolvedHostname";
import { getResolvedPartition, PartitionHash } from "./getResolvedPartition";
import { getResolvedHostname } from "./getResolvedHostname";
import { getResolvedPartition } from "./getResolvedPartition";
import { PartitionHash } from "./PartitionHash";
import { RegionHash } from "./RegionHash";

jest.mock("./getResolvedHostname");
jest.mock("./getResolvedPartition");
Expand Down Expand Up @@ -52,7 +54,7 @@ describe(getRegionInfo.name, () => {

const getMockResolvedPartitionOptions = (partitionHash) => ({ partitionHash });

const getMockResolvedHostnameOptions = (regionHash, getResolvedPartitionOptions) => ({
const getMockRegionInfoOptions = (regionHash, getResolvedPartitionOptions) => ({
...getResolvedPartitionOptions,
signingService: mockSigningService,
regionHash,
Expand All @@ -75,21 +77,20 @@ describe(getRegionInfo.name, () => {
const mockPartitionHash = getMockPartitionHash(regionCase);

const mockGetResolvedPartitionOptions = getMockResolvedPartitionOptions(mockPartitionHash);
const mockGetResolvedHostnameOptions = getMockResolvedHostnameOptions(
mockRegionHash,
mockGetResolvedPartitionOptions
);
const mockGetRegionInfoOptions = getMockRegionInfoOptions(mockRegionHash, mockGetResolvedPartitionOptions);

expect(getRegionInfo(mockRegion, mockGetResolvedHostnameOptions)).toEqual({
expect(getRegionInfo(mockRegion, mockGetRegionInfoOptions)).toEqual({
signingService: mockSigningService,
hostname: mockHostname,
partition: mockPartition,
});

expect(getResolvedHostname).toHaveBeenCalledWith(
getMockResolvedRegion(regionCase),
mockGetResolvedHostnameOptions
);
const mockResolvedRegion = getMockResolvedRegion(regionCase);
expect(getResolvedHostname).toHaveBeenCalledWith(mockResolvedRegion, {
signingService: mockSigningService,
regionHostname: mockGetRegionInfoOptions.regionHash[mockResolvedRegion]?.hostname,
partitionHostname: mockGetRegionInfoOptions.partitionHash[mockPartition]?.hostname,
});
expect(getResolvedPartition).toHaveBeenCalledWith(mockRegion, mockGetResolvedPartitionOptions);
});
});
Expand Down Expand Up @@ -121,10 +122,7 @@ describe(getRegionInfo.name, () => {
const mockPartitionHash = getMockPartitionHash(regionCase);

const mockGetResolvedPartitionOptions = getMockResolvedPartitionOptions(mockPartitionHash);
const mockGetResolvedHostnameOptions = getMockResolvedHostnameOptions(
mockRegionHash,
mockGetResolvedPartitionOptions
);
const mockGetRegionInfoOptions = getMockRegionInfoOptions(mockRegionHash, mockGetResolvedPartitionOptions);

const mockRegionHashWithSigningRegion = getMockRegionHashWithSigningRegion(
regionCase,
Expand All @@ -133,17 +131,19 @@ describe(getRegionInfo.name, () => {
);

expect(
getRegionInfo(mockRegion, { ...mockGetResolvedHostnameOptions, regionHash: mockRegionHashWithSigningRegion })
getRegionInfo(mockRegion, { ...mockGetRegionInfoOptions, regionHash: mockRegionHashWithSigningRegion })
).toEqual({
signingService: mockSigningService,
hostname: mockHostname,
partition: mockPartition,
signingRegion: mockSigningRegion,
});

expect(getResolvedHostname).toHaveBeenCalledWith(getMockResolvedRegion(regionCase), {
...mockGetResolvedHostnameOptions,
regionHash: mockRegionHashWithSigningRegion,
const mockResolvedRegion = getMockResolvedRegion(regionCase);
expect(getResolvedHostname).toHaveBeenCalledWith(mockResolvedRegion, {
signingService: mockSigningService,
regionHostname: mockGetRegionInfoOptions.regionHash[mockResolvedRegion]?.hostname,
partitionHostname: mockGetRegionInfoOptions.partitionHash[mockPartition]?.hostname,
});
expect(getResolvedPartition).toHaveBeenCalledWith(mockRegion, mockGetResolvedPartitionOptions);
});
Expand Down Expand Up @@ -176,10 +176,7 @@ describe(getRegionInfo.name, () => {
const mockPartitionHash = getMockPartitionHash(regionCase);

const mockGetResolvedPartitionOptions = getMockResolvedPartitionOptions(mockPartitionHash);
const mockGetResolvedHostnameOptions = getMockResolvedHostnameOptions(
mockRegionHash,
mockGetResolvedPartitionOptions
);
const mockGetRegionInfoOptions = getMockRegionInfoOptions(mockRegionHash, mockGetResolvedPartitionOptions);

const mockRegionHashWithSigningRegion = getMockRegionHashWithSigningService(
regionCase,
Expand All @@ -188,16 +185,18 @@ describe(getRegionInfo.name, () => {
);

expect(
getRegionInfo(mockRegion, { ...mockGetResolvedHostnameOptions, regionHash: mockRegionHashWithSigningRegion })
getRegionInfo(mockRegion, { ...mockGetRegionInfoOptions, regionHash: mockRegionHashWithSigningRegion })
).toEqual({
signingService: mockSigningServiceInRegionHash,
hostname: mockHostname,
partition: mockPartition,
});

expect(getResolvedHostname).toHaveBeenCalledWith(getMockResolvedRegion(regionCase), {
...mockGetResolvedHostnameOptions,
regionHash: mockRegionHashWithSigningRegion,
const mockResolvedRegion = getMockResolvedRegion(regionCase);
expect(getResolvedHostname).toHaveBeenCalledWith(mockResolvedRegion, {
signingService: mockSigningService,
regionHostname: mockGetRegionInfoOptions.regionHash[mockResolvedRegion]?.hostname,
partitionHostname: mockGetRegionInfoOptions.partitionHash[mockPartition]?.hostname,
});
expect(getResolvedPartition).toHaveBeenCalledWith(mockRegion, mockGetResolvedPartitionOptions);
});
Expand Down
20 changes: 14 additions & 6 deletions packages/config-resolver/src/regionInfo/getRegionInfo.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { RegionInfo } from "@aws-sdk/types";

import { getResolvedHostname, GetResolvedHostnameOptions, RegionHash } from "./getResolvedHostname";
import { getResolvedPartition, PartitionHash } from "./getResolvedPartition";
import { getResolvedHostname } from "./getResolvedHostname";
import { getResolvedPartition } from "./getResolvedPartition";
import { PartitionHash } from "./PartitionHash";
import { RegionHash } from "./RegionHash";

export { RegionHash, PartitionHash };

export interface GetRegionInfoOptions extends GetResolvedHostnameOptions {}
export interface GetRegionInfoOptions {
signingService: string;
regionHash: RegionHash;
partitionHash: PartitionHash;
}

export const getRegionInfo = (
region: string,
Expand All @@ -16,7 +20,11 @@ export const getRegionInfo = (
return {
partition,
signingService,
hostname: getResolvedHostname(resolvedRegion, { signingService, regionHash, partitionHash }),
hostname: getResolvedHostname(resolvedRegion, {
signingService,
regionHostname: regionHash[resolvedRegion]?.hostname,
partitionHostname: partitionHash[partition]?.hostname,
}),
...(regionHash[resolvedRegion]?.signingRegion && {
signingRegion: regionHash[resolvedRegion].signingRegion,
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,63 +1,40 @@
import { getHostnameTemplate } from "./getHostnameTemplate";
import { getResolvedHostname, RegionHash } from "./getResolvedHostname";
import { PartitionHash } from "./getResolvedPartition";
import { getResolvedHostname } from "./getResolvedHostname";

jest.mock("./getHostnameTemplate");

describe(getResolvedHostname.name, () => {
const mockSigningService = "mockSigningService";
const mockRegion = "mockRegion";
const mockPartition = "mockPartition";
const mockRegionRegex = "mockRegionRegex";
const mockHostname = "{region}.mockHostname.com";

afterEach(() => {
jest.clearAllMocks();
});

it("returns hostname if available in regionHash", () => {
const mockRegionHash: RegionHash = {
[mockRegion]: {
hostname: mockHostname,
},
};
const mockPartitionHash: PartitionHash = {};

expect(
getResolvedHostname(mockRegion, {
signingService: mockSigningService,
regionHash: mockRegionHash,
partitionHash: mockPartitionHash,
regionHostname: mockHostname,
})
).toBe(mockHostname);
expect(getHostnameTemplate).not.toHaveBeenCalled();
});

it("returns hostname from hostname template when not available in regionHash", () => {
const mockRegionHash: RegionHash = {};

(getHostnameTemplate as jest.Mock).mockReturnValue(mockHostname);

const mockPartitionHash: PartitionHash = {
[mockPartition]: {
regions: [mockRegion, `${mockRegion}2`, `${mockRegion}3`],
regionRegex: mockRegionRegex,
hostname: mockHostname,
},
};

expect(
getResolvedHostname(mockRegion, {
signingService: mockSigningService,
regionHash: mockRegionHash,
partitionHash: mockPartitionHash,
partitionHostname: mockHostname,
})
).toBe(mockHostname.replace("{region}", mockRegion));

expect(getHostnameTemplate).toHaveBeenCalledTimes(1);
expect(getHostnameTemplate).toHaveBeenCalledWith(mockRegion, {
signingService: mockSigningService,
partitionHash: mockPartitionHash,
expect(getHostnameTemplate).toHaveBeenCalledWith(mockSigningService, {
partitionHostname: mockHostname,
});
});
});
25 changes: 8 additions & 17 deletions packages/config-resolver/src/regionInfo/getResolvedHostname.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
import { RegionInfo } from "@aws-sdk/types";
import { getHostnameTemplate } from "./getHostnameTemplate";

import { getHostnameTemplate, GetHostnameTemplateOptions } from "./getHostnameTemplate";
import { GetResolvedPartitionOptions } from "./getResolvedPartition";

export type RegionHash = { [key: string]: Partial<Omit<RegionInfo, "partition" | "path">> };

export interface GetResolvedHostnameOptions extends GetHostnameTemplateOptions, GetResolvedPartitionOptions {
/**
* The hash of region with the information specific to that region.
* The information can include hostname, signingService and signingRegion.
*/
regionHash: RegionHash;
export interface GetResolvedHostnameOptions {
signingService: string;
regionHostname?: string;
partitionHostname?: string;
}

export const getResolvedHostname = (
region: string,
{ signingService, regionHash, partitionHash }: GetResolvedHostnameOptions
) =>
regionHash[region]?.hostname ??
getHostnameTemplate(region, { signingService, partitionHash }).replace("{region}", region);
resolvedRegion: string,
{ signingService, regionHostname, partitionHostname }: GetResolvedHostnameOptions
) => regionHostname ?? getHostnameTemplate(signingService, { partitionHostname }).replace("{region}", resolvedRegion);
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getResolvedPartition, PartitionHash } from "./getResolvedPartition";
import { getResolvedPartition } from "./getResolvedPartition";
import { PartitionHash } from "./PartitionHash";

describe(getResolvedPartition.name, () => {
const mockRegion = "mockRegion";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
export type PartitionHash = {
[key: string]: { regions: string[]; regionRegex: string; hostname?: string; endpoint?: string };
};
import { PartitionHash } from "./PartitionHash";

export interface GetResolvedPartitionOptions {
/**
* The hash of partition with the information specific to that partition.
* The information includes the list of regions belonging to that partition,
* and the hostname to be used for the partition.
*/
partitionHash: PartitionHash;
}

Expand Down
2 changes: 2 additions & 0 deletions packages/config-resolver/src/regionInfo/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from "./PartitionHash";
export * from "./RegionHash";
export * from "./getRegionInfo";