Skip to content

Commit

Permalink
feat(site launch): Allow for ops to remove timed out domain associati…
Browse files Browse the repository at this point in the history
…ons (#720)

* style(env var): change naming of var

technically we mock both create and get calls, changing the var name to
reflect this

* fix(mockDomainAssociation): change wrong usage of env var

* feat(launchClient): Create Delete Domain calls + typing

* feat(launches Service ): call delete domain before create to remove ...

redundant associations
  • Loading branch information
kishore03109 authored Apr 20, 2023
1 parent 15f4863 commit bd577d7
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 2 deletions.
48 changes: 47 additions & 1 deletion src/services/identity/LaunchClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@ import {
GetDomainAssociationCommandInput as AmplifySDKGetDomainAssociationCommandInput,
GetDomainAssociationCommandOutput,
SubDomainSetting,
DeleteDomainAssociationCommandInput as AmplifySDKDeleteDomainAssociationCommandInput,
DeleteDomainAssociationCommand,
NotFoundException,
} from "@aws-sdk/client-amplify"
import { SubDomain } from "aws-sdk/clients/amplify"

import { config } from "@config/config"

import { AmplifyError } from "@root/types"

// stricter typing to interact with Amplify SDK
type CreateDomainAssociationCommandInput = {
[K in keyof AmplifySDKCreateDomainAssociationCommandInput]: NonNullable<
Expand All @@ -25,6 +30,19 @@ type GetDomainAssociationCommandInput = {
>
}

type DeleteDomainAssociationCommandInput = {
[K in keyof AmplifySDKDeleteDomainAssociationCommandInput]: NonNullable<
AmplifySDKDeleteDomainAssociationCommandInput[K]
>
}

export type AmplifyDomainNotFoundException = AmplifyError | NotFoundException

export const isAmplifyDomainNotFoundException = (
obj: unknown
): obj is AmplifyDomainNotFoundException =>
obj instanceof AmplifyError || obj instanceof NotFoundException

class LaunchClient {
private readonly amplifyClient: InstanceType<typeof AmplifyClient>

Expand Down Expand Up @@ -68,6 +86,14 @@ class LaunchClient {
domainName,
})

createDeleteDomainAssociationCommandInput = (
appId: string,
domainName: string
): DeleteDomainAssociationCommandInput => ({
appId,
domainName,
})

sendGetDomainAssociationCommand = (
input: GetDomainAssociationCommandInput
): Promise<GetDomainAssociationCommandOutput> => {
Expand Down Expand Up @@ -142,13 +168,33 @@ class LaunchClient {
return subDomains
}

async sendDeleteDomainAssociationCommand(
input: DeleteDomainAssociationCommandInput
): Promise<void> {
if (this.shouldMockAmplifyDomainCalls()) {
this.mockDeleteDomainAssociationOutput(input)
}
await this.amplifyClient.send(new DeleteDomainAssociationCommand(input))
}

mockDeleteDomainAssociationOutput(
input: DeleteDomainAssociationCommandInput
) {
if (!this.mockDomainAssociations.has(input.domainName)) {
throw new AmplifyError(
`NotFoundException: Domain association ${input.domainName} not found.`
)
}
this.mockDomainAssociations.delete(input.domainName)
}

private mockGetDomainAssociationOutput(
input: GetDomainAssociationCommandInput
): Promise<GetDomainAssociationCommandOutput> {
const isSubDomainCreated = true // this is a `get` call, assume domain has already been created
const subDomainSettings = this.mockDomainAssociations.get(input.domainName)
if (!subDomainSettings) {
throw new Error(
throw new AmplifyError(
`NotFoundException: Domain association ${input.domainName} not found.`
)
}
Expand Down
39 changes: 38 additions & 1 deletion src/services/identity/LaunchesService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import logger from "@logger/logger"
import { Deployment, Launch, Repo, User, Redirection } from "@database/models"
import { RedirectionTypes } from "@root/constants/constants"
import { AmplifyError } from "@root/types/index"
import LaunchClient from "@services/identity/LaunchClient"
import LaunchClient, {
isAmplifyDomainNotFoundException,
} from "@services/identity/LaunchClient"

export type SiteLaunchCreateParams = {
userId: number
Expand Down Expand Up @@ -159,6 +161,41 @@ export class LaunchesService {
throw siteIdResult.error
}

try {
// Check if association already exists
const getDomainAssociationCommandInput = this.launchClient.createGetDomainAssociationCommandInput(
appIdResult.value,
domainName
)

const getDomainAssociationResult = await this.launchClient.sendGetDomainAssociationCommand(
getDomainAssociationCommandInput
)
const hasDomainAssociationFailed =
getDomainAssociationResult?.domainAssociation?.domainStatus === "FAILED"
if (hasDomainAssociationFailed) {
// safe to delete and retry
const deleteDomainAssociationCommandInput = this.launchClient.createDeleteDomainAssociationCommandInput(
appIdResult.value,
domainName
)
await this.launchClient.sendDeleteDomainAssociationCommand(
deleteDomainAssociationCommandInput
)
}
} catch (error: unknown) {
const isExpectedNotFoundError = isAmplifyDomainNotFoundException(error)
if (!isExpectedNotFoundError) {
return err(
new AmplifyError(
`Unable to connect to Amplify for: ${repoName}, ${error}`,
repoName,
appIdResult.value
)
)
}
}

const launchAppOptions = this.launchClient.createDomainAssociationCommandInput(
appIdResult.value,
domainName,
Expand Down

0 comments on commit bd577d7

Please sign in to comment.