@fjall/deploy-core 2.13.0 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.minified +1 -1
- package/dist/src/aws/index.d.ts +6 -2
- package/dist/src/aws/index.js +1 -1
- package/dist/src/aws/organisations/accountGlobals.d.ts +40 -0
- package/dist/src/aws/organisations/accountGlobals.js +1 -0
- package/dist/src/aws/organisations/accounts.js +1 -1
- package/dist/src/aws/organisations/importedAccounts.d.ts +16 -0
- package/dist/src/aws/organisations/importedAccounts.js +1 -0
- package/dist/src/aws/organisations/index.d.ts +3 -1
- package/dist/src/aws/organisations/index.js +1 -1
- package/dist/src/aws/organisations/rootAccess.d.ts +27 -0
- package/dist/src/aws/organisations/rootAccess.js +3 -0
- package/dist/src/aws/organisations/serviceAccess.d.ts +6 -0
- package/dist/src/aws/organisations/serviceAccess.js +1 -1
- package/dist/src/aws/organisations/types.d.ts +12 -0
- package/dist/src/aws/organisations/types.js +1 -1
- package/dist/src/aws/sts/assumeRoot.d.ts +46 -0
- package/dist/src/aws/sts/assumeRoot.js +1 -0
- package/dist/src/aws/targetReadiness.d.ts +70 -0
- package/dist/src/aws/targetReadiness.js +1 -0
- package/dist/src/aws/targetSetAdvisory.d.ts +24 -0
- package/dist/src/aws/targetSetAdvisory.js +1 -0
- package/dist/src/index.d.ts +13 -13
- package/dist/src/index.js +1 -1
- package/dist/src/orchestration/applicationDeploy.js +1 -1
- package/dist/src/orchestration/applicationDestroy.js +1 -1
- package/dist/src/orchestration/cascadeDestroyHelpers.d.ts +12 -1
- package/dist/src/orchestration/cascadeDestroyHelpers.js +1 -1
- package/dist/src/orchestration/cascadeHelpers.d.ts +21 -6
- package/dist/src/orchestration/cascadeHelpers.js +1 -1
- package/dist/src/orchestration/contextHelpers.d.ts +17 -2
- package/dist/src/orchestration/contextHelpers.js +1 -1
- package/dist/src/orchestration/index.d.ts +8 -3
- package/dist/src/orchestration/index.js +1 -1
- package/dist/src/orchestration/organisationDeploy/cascadeExecution.d.ts +28 -0
- package/dist/src/orchestration/organisationDeploy/cascadeExecution.js +1 -0
- package/dist/src/orchestration/organisationDeploy/infraSteps.d.ts +40 -0
- package/dist/src/orchestration/organisationDeploy/infraSteps.js +1 -0
- package/dist/src/orchestration/organisationDeploy/orgCascadeDeploy.d.ts +8 -0
- package/dist/src/orchestration/organisationDeploy/orgCascadeDeploy.js +5 -0
- package/dist/src/orchestration/organisationDeploy/orgContext.d.ts +12 -0
- package/dist/src/orchestration/organisationDeploy/orgContext.js +1 -0
- package/dist/src/orchestration/organisationDeploy/resolveCascadeAccounts.d.ts +15 -0
- package/dist/src/orchestration/organisationDeploy/resolveCascadeAccounts.js +1 -0
- package/dist/src/orchestration/organisationDeploy/singleComponentDeploy.d.ts +11 -0
- package/dist/src/orchestration/organisationDeploy/singleComponentDeploy.js +1 -0
- package/dist/src/orchestration/organisationDeploy/trailReconciliation.d.ts +21 -0
- package/dist/src/orchestration/organisationDeploy/trailReconciliation.js +1 -0
- package/dist/src/orchestration/organisationDeploy.d.ts +1 -5
- package/dist/src/orchestration/organisationDeploy.js +1 -5
- package/dist/src/orchestration/organisationDestroy.d.ts +1 -1
- package/dist/src/orchestration/organisationDestroy.js +2 -2
- package/dist/src/orchestration/organisationSetup.d.ts +18 -2
- package/dist/src/orchestration/organisationSetup.js +1 -1
- package/dist/src/orchestration/stackCleanup/bucketOps.d.ts +54 -0
- package/dist/src/orchestration/stackCleanup/bucketOps.js +1 -0
- package/dist/src/orchestration/stackCleanup/failedStack.d.ts +34 -0
- package/dist/src/orchestration/stackCleanup/failedStack.js +1 -0
- package/dist/src/orchestration/stackCleanup/logging.d.ts +9 -0
- package/dist/src/orchestration/stackCleanup/logging.js +1 -0
- package/dist/src/orchestration/stackCleanup/messages.d.ts +16 -0
- package/dist/src/orchestration/stackCleanup/messages.js +1 -0
- package/dist/src/orchestration/stackCleanup/orphanSweep.d.ts +25 -0
- package/dist/src/orchestration/stackCleanup/orphanSweep.js +1 -0
- package/dist/src/orchestration/stackCleanup/preEmpty.d.ts +35 -0
- package/dist/src/orchestration/stackCleanup/preEmpty.js +1 -0
- package/dist/src/orchestration/stackCleanup/stackResources.d.ts +9 -0
- package/dist/src/orchestration/stackCleanup/stackResources.js +1 -0
- package/dist/src/orchestration/stackCleanup.d.ts +13 -40
- package/dist/src/orchestration/stackCleanup.js +1 -1
- package/dist/src/orchestration/trailMigration/memberTrailCleanup.js +1 -1
- package/dist/src/orchestration/unlock/scpRemediation.d.ts +15 -0
- package/dist/src/orchestration/unlock/scpRemediation.js +1 -0
- package/dist/src/orchestration/unlock/unlockBucket.d.ts +37 -0
- package/dist/src/orchestration/unlock/unlockBucket.js +1 -0
- package/dist/src/orchestration/unlock/unlockQueue.d.ts +43 -0
- package/dist/src/orchestration/unlock/unlockQueue.js +1 -0
- package/dist/src/services/application/ApplicationStackService.d.ts +9 -10
- package/dist/src/services/application/ApplicationStackService.js +1 -1
- package/dist/src/services/application/applicationStackHelpers.d.ts +13 -8
- package/dist/src/services/application/applicationStackHelpers.js +3 -3
- package/dist/src/steps/stepRegistry.js +1 -1
- package/dist/src/types/FjallState.d.ts +7 -0
- package/dist/src/types/FjallState.js +1 -1
- package/dist/src/types/callbacks.d.ts +43 -2
- package/dist/src/types/callbacks.js +1 -0
- package/dist/src/types/deploymentEventSchema.d.ts +9 -0
- package/dist/src/types/deploymentEventSchema.js +1 -1
- package/dist/src/types/index.d.ts +5 -10
- package/dist/src/types/index.js +1 -1
- package/dist/src/types/orgConfig.d.ts +8 -2
- package/dist/src/types/params.d.ts +12 -0
- package/dist/src/types/patternDetection.d.ts +0 -25
- package/dist/src/types/patternDetection.js +1 -1
- package/dist/src/types/stepDefinitions.d.ts +2 -0
- package/dist/src/types/stepDefinitions.js +1 -1
- package/package.json +6 -4
package/dist/.minified
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
148 files minified at 2026-06-12T01:12:37.959Z
|
package/dist/src/aws/index.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export type { AwsProvider, AwsProviderCredentials, AwsSdkClientConstructor } from "./AwsProvider.js";
|
|
2
2
|
export { SimpleAwsProvider } from "./SimpleAwsProvider.js";
|
|
3
|
-
export {
|
|
4
|
-
export type {
|
|
3
|
+
export { checkTargetReadiness, describeTargetReadinessReason, buildTargetUnreadyAdvisory } from "./targetReadiness.js";
|
|
4
|
+
export type { TargetReadinessAccount, TargetReadinessClients, TargetReadinessReason, TargetReadinessVerdict } from "./targetReadiness.js";
|
|
5
|
+
export { buildTargetSetUnreadyAdvisory } from "./targetSetAdvisory.js";
|
|
6
|
+
export type { TargetSetUnreadyAdvisoryParams } from "./targetSetAdvisory.js";
|
|
7
|
+
export { ensureOrganisationExists, describeOrganisation, enablePolicyTypes, enableServiceAccess, SERVICE_PRINCIPALS, enableRamSharing, activateTrustedAccess, enableIpamDelegatedAdmin, updateBackupGlobalSettings, listAccounts, findAccount, createAccount, ensureOrganisationalUnitsExist, placeAccountsInOUs, buildAccountToOUMap, activateCostAllocationTags, checkIdentityCentreStatus, extractErrorName, isOULeaf, registerSecurityDelegates, SECURITY_SERVICE_PRINCIPALS, enableCentralisedRootAccess, ROOT_ACCESS_FEATURES, RootAccessEnablementError } from "./organisations/index.js";
|
|
8
|
+
export type { OrgDetails, OUMap, OUTree, AccountPlacementResult, AccountInfo, IdentityCentreStatus, BackupGlobalSettings, CostAllocationTag, CreateAccountResult, RootAccessFeature, RootAccessEnablementSummary } from "./organisations/index.js";
|
|
5
9
|
export { CloudFormationEventMonitor } from "./utils/cloudformationEvents.js";
|
|
6
10
|
export type { AwsClientLike, EventLogWriter, EventFailureAnalyser, EventLogWriterFactory, EventMonitorDeps } from "./utils/cloudformationEvents.js";
|
package/dist/src/aws/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{SimpleAwsProvider as a}from"./SimpleAwsProvider.js";import{ensureOrganisationExists as
|
|
1
|
+
import{SimpleAwsProvider as a}from"./SimpleAwsProvider.js";import{checkTargetReadiness as s,describeTargetReadinessReason as o,buildTargetUnreadyAdvisory as n}from"./targetReadiness.js";import{buildTargetSetUnreadyAdvisory as c}from"./targetSetAdvisory.js";import{ensureOrganisationExists as d,describeOrganisation as A,enablePolicyTypes as u,enableServiceAccess as S,SERVICE_PRINCIPALS as E,enableRamSharing as g,activateTrustedAccess as R,enableIpamDelegatedAdmin as b,updateBackupGlobalSettings as m,listAccounts as p,findAccount as C,createAccount as T,ensureOrganisationalUnitsExist as I,placeAccountsInOUs as x,buildAccountToOUMap as y,activateCostAllocationTags as O,checkIdentityCentreStatus as U,extractErrorName as f,isOULeaf as v,registerSecurityDelegates as P,SECURITY_SERVICE_PRINCIPALS as _,enableCentralisedRootAccess as h,ROOT_ACCESS_FEATURES as k,RootAccessEnablementError as L}from"./organisations/index.js";import{CloudFormationEventMonitor as D}from"./utils/cloudformationEvents.js";export{D as CloudFormationEventMonitor,k as ROOT_ACCESS_FEATURES,L as RootAccessEnablementError,_ as SECURITY_SERVICE_PRINCIPALS,E as SERVICE_PRINCIPALS,a as SimpleAwsProvider,O as activateCostAllocationTags,R as activateTrustedAccess,y as buildAccountToOUMap,c as buildTargetSetUnreadyAdvisory,n as buildTargetUnreadyAdvisory,U as checkIdentityCentreStatus,s as checkTargetReadiness,T as createAccount,A as describeOrganisation,o as describeTargetReadinessReason,h as enableCentralisedRootAccess,b as enableIpamDelegatedAdmin,u as enablePolicyTypes,g as enableRamSharing,S as enableServiceAccess,d as ensureOrganisationExists,I as ensureOrganisationalUnitsExist,f as extractErrorName,C as findAccount,v as isOULeaf,p as listAccounts,x as placeAccountsInOUs,P as registerSecurityDelegates,m as updateBackupGlobalSettings};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type IAMClient } from "@aws-sdk/client-iam";
|
|
2
|
+
import { type Result } from "@fjall/generator";
|
|
3
|
+
import type { OrgConfig } from "../../types/orgConfig.js";
|
|
4
|
+
export declare const ACCOUNT_GLOBALS_ROLE_NAME = "FjallMonitoring";
|
|
5
|
+
/**
|
|
6
|
+
* Probe whether the fixed-name account globals exist in this account — the
|
|
7
|
+
* prerequisite for a non-primary-region deploy, which skips creating them.
|
|
8
|
+
* IAM is a global service, so a GetRole from any region answers it.
|
|
9
|
+
*
|
|
10
|
+
* The design-suggested OIDC provider is a confounded discriminator: the
|
|
11
|
+
* connect-time quick-create stack creates it before any deploy (false
|
|
12
|
+
* "exists"), and the account stack skips it under the fjallOidcConfigured /
|
|
13
|
+
* receivesDeployRole() gates even when the globals branch runs.
|
|
14
|
+
*
|
|
15
|
+
* Returns success(false) ONLY on NoSuchEntityException. Every other error
|
|
16
|
+
* (AccessDenied, throttling) propagates as failure — a mis-read "missing"
|
|
17
|
+
* refuses a legitimate deploy, a mis-read "exists" silently deploys an
|
|
18
|
+
* account that cannot work; neither may be guessed.
|
|
19
|
+
*
|
|
20
|
+
* Failure messages stay raw — callers mask at their output boundary.
|
|
21
|
+
*/
|
|
22
|
+
export declare function describeAccountGlobalsExist(client: IAMClient, abortSignal?: AbortSignal): Promise<Result<boolean>>;
|
|
23
|
+
/**
|
|
24
|
+
* Org-vs-solo shape discriminator shared by every guard-step advisory in the
|
|
25
|
+
* deploy flow (account globals, target readiness) — one drift here would
|
|
26
|
+
* render contradictory remediation for the same estate.
|
|
27
|
+
*/
|
|
28
|
+
export declare function hasOrganisationTierAccount(providerAccounts: OrgConfig["providerAccounts"] | undefined): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Deploy-primary-first advisory for a non-primary deploy whose primary-region
|
|
31
|
+
* globals are missing (AC2a.2). Shape-branched on whether the provider
|
|
32
|
+
* accounts carry a tier-organisation account: org estates remediate via the
|
|
33
|
+
* cascade, solo accounts by deploying the primary region directly.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildMissingAccountGlobalsAdvisory(params: {
|
|
36
|
+
target: string;
|
|
37
|
+
deployRegion: string;
|
|
38
|
+
primaryRegion: string;
|
|
39
|
+
providerAccounts?: OrgConfig["providerAccounts"];
|
|
40
|
+
}): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{GetRoleCommand as i}from"@aws-sdk/client-iam";import{success as n,failure as a}from"@fjall/generator";import{accountTier as c,getErrorMessage as s}from"@fjall/util";import{ACCOUNT_MONITORING_ROLE_NAME as l}from"@fjall/util/aws";import{composeSdkAbortSignal as u}from"./types.js";const t=l;async function f(o,e){try{return await o.send(new i({RoleName:t}),{abortSignal:u(e)}),n(!0)}catch(r){return r instanceof Error&&r.name==="NoSuchEntityException"?n(!1):a(new Error(`Failed to probe account globals (role "${t}"): ${s(r)}`))}}function p(o){return(o??[]).some(e=>c(e)==="organisation")}function A(o){const r=p(o.providerAccounts)?`run \`fjall deploy organisation\` to provision the primary region (${o.primaryRegion}), then retry this deploy`:`target the primary region (${o.primaryRegion}) and run \`fjall deploy account\`, then retry this deploy`;return`Cannot deploy "${o.target}" into ${o.deployRegion}: the account globals (fixed-name IAM resources such as the ${t} role) are created only in the primary region (${o.primaryRegion}) and were not found in this account. Nothing has been deployed. Deploy the primary region first: ${r}.`}export{t as ACCOUNT_GLOBALS_ROLE_NAME,A as buildMissingAccountGlobalsAdvisory,f as describeAccountGlobalsExist,p as hasOrganisationTierAccount};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ListAccountsCommand as
|
|
1
|
+
import{ListAccountsCommand as f,CreateAccountCommand as b,CreateAccountState as w,DescribeCreateAccountStatusCommand as $}from"@aws-sdk/client-organizations";import{success as A,failure as r}from"@fjall/generator";import{getErrorMessage as E}from"@fjall/util";import{extractErrorName as p,composeSdkAbortSignal as S,isAborted as m,SDK_TIMEOUT_MS as g,AWS_ERROR_NAMES as C}from"./types.js";import{sleepAbortable as h}from"../../util/sleepAbortable.js";async function x(o){try{const t=await o.send(new f({MaxResults:20}),{abortSignal:AbortSignal.timeout(g)});let e=t.Accounts??[],n=t.NextToken;for(;n;){const c=await o.send(new f({MaxResults:20,NextToken:n}),{abortSignal:AbortSignal.timeout(g)});e=e.concat(c.Accounts??[]),n=c.NextToken}return A(e)}catch(t){return p(t)===C.ORGS_NOT_IN_USE?r(new Error("AWS Organisations is not enabled for this account")):r(new Error(`Failed to list accounts: ${E(t)}`))}}async function _(o,t){const e=await x(o);return e.success?A(e.data.find(n=>n.Id===t)):e}async function O(o,t,e,n=180,c=5e3,a){if(m(a))return r(new Error(`Aborted: account creation for "${t}" cancelled by shutdown signal before starting`));try{let u;try{u=await o.send(new b({AccountName:t,Email:e}),{abortSignal:S(a)})}catch(i){const l=p(i);if(l===C.ACCESS_DENIED)return r(new Error(`Access denied when creating account "${t}". Ensure your credentials have organizations:CreateAccount permission.`));if(l==="DuplicateAccountException")return r(new Error(`An account with the email "${e}" already exists in the organisation.`));if(l==="FinalizingOrganizationException")return r(new Error("The organisation is still being initialised. Please wait and try again."));throw i}const d=u.CreateAccountStatus?.Id;if(!d)return r(new Error(`CreateAccount request for "${t}" did not return a status ID`));for(let i=0;i<n;i++){if(m(a))return r(new Error(`Aborted: account creation polling for "${t}" cancelled by shutdown signal \u2014 AWS request ${d} may still complete server-side`));const s=(await o.send(new $({CreateAccountRequestId:d}),{abortSignal:S(a)})).CreateAccountStatus;if(!s)return r(new Error(`No status returned for CreateAccount request ${d}`));if(s.State===w.SUCCEEDED)return s.AccountId?A({accountId:s.AccountId,accountName:t}):r(new Error(`Account creation succeeded but no account ID returned for "${t}"`));if(s.State===w.FAILED)return r(new Error(`Account creation failed for "${t}": ${s.FailureReason}`));await h(c,a)}return r(new Error(`Account creation for "${t}" timed out after ${n*c/1e3} seconds`))}catch(u){return r(new Error(`Failed to create account "${t}": ${E(u)}`))}}export{O as createAccount,_ as findAccount,x as listAccounts};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Account } from "@aws-sdk/client-organizations";
|
|
2
|
+
/**
|
|
3
|
+
* Member accounts that joined the organisation by invitation rather than
|
|
4
|
+
* being created inside it. AWS reports provenance as Account.JoinedMethod
|
|
5
|
+
* ("CREATED" | "INVITED"): an invited account existed standalone first, so
|
|
6
|
+
* it holds self-managed root credentials that centralised root access
|
|
7
|
+
* management takes over — the posture change AC2.8 warns about. The
|
|
8
|
+
* management account is excluded (central management never applies to it),
|
|
9
|
+
* as are non-ACTIVE accounts.
|
|
10
|
+
*/
|
|
11
|
+
export declare function selectImportedMemberAccounts(accounts: Account[], managementAccountId: string): Account[];
|
|
12
|
+
/**
|
|
13
|
+
* Warn-once copy for the enable-root-access phase (AC2.8). Shared so every
|
|
14
|
+
* adapter surfaces identical wording.
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatImportedAccountsWarning(imported: Account[]): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function i(n,t){return n.filter(e=>e.JoinedMethod==="INVITED"&&e.Id!==t&&(e.State??e.Status)==="ACTIVE")}const a=5;function l(n){const t=n.slice(0,a).map(o=>`${o.Name??"unnamed"} (${o.Id??"unknown id"})`).join(", "),e=n.length-a,r=e>0?`${t} and ${e} more`:t,s=n.length===1?"account":"accounts";return`Centralised root access now applies to ${n.length} imported member ${s} that joined this organisation by invitation and previously held self-managed root credentials: ${r}. Root credentials for these accounts are now centrally managed.`}export{l as formatImportedAccountsWarning,i as selectImportedMemberAccounts};
|
|
@@ -3,9 +3,10 @@ export { extractErrorName, isOULeaf } from "./types.js";
|
|
|
3
3
|
export type { BackupGlobalSettings } from "./backup.js";
|
|
4
4
|
export type { CostAllocationTag } from "./costAllocation.js";
|
|
5
5
|
export type { CreateAccountResult } from "./accounts.js";
|
|
6
|
+
export type { RootAccessFeature, RootAccessEnablementSummary } from "./rootAccess.js";
|
|
6
7
|
export { ensureOrganisationExists, describeOrganisation } from "./organisation.js";
|
|
7
8
|
export { enablePolicyTypes } from "./policies.js";
|
|
8
|
-
export { enableServiceAccess } from "./serviceAccess.js";
|
|
9
|
+
export { enableServiceAccess, SERVICE_PRINCIPALS } from "./serviceAccess.js";
|
|
9
10
|
export { enableRamSharing } from "./ram.js";
|
|
10
11
|
export { activateTrustedAccess } from "./trustedAccess.js";
|
|
11
12
|
export { enableIpamDelegatedAdmin } from "./ipam.js";
|
|
@@ -15,3 +16,4 @@ export { ensureOrganisationalUnitsExist, placeAccountsInOUs, buildAccountToOUMap
|
|
|
15
16
|
export { activateCostAllocationTags } from "./costAllocation.js";
|
|
16
17
|
export { checkIdentityCentreStatus } from "./identityCentre.js";
|
|
17
18
|
export { registerSecurityDelegates, SECURITY_SERVICE_PRINCIPALS } from "./delegatedAdmin.js";
|
|
19
|
+
export { enableCentralisedRootAccess, ROOT_ACCESS_FEATURES, RootAccessEnablementError } from "./rootAccess.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{extractErrorName as r,isOULeaf as o}from"./types.js";import{ensureOrganisationExists as
|
|
1
|
+
import{extractErrorName as r,isOULeaf as o}from"./types.js";import{ensureOrganisationExists as s,describeOrganisation as c}from"./organisation.js";import{enablePolicyTypes as i}from"./policies.js";import{enableServiceAccess as m,SERVICE_PRINCIPALS as l}from"./serviceAccess.js";import{enableRamSharing as f}from"./ram.js";import{activateTrustedAccess as u}from"./trustedAccess.js";import{enableIpamDelegatedAdmin as S}from"./ipam.js";import{updateBackupGlobalSettings as I}from"./backup.js";import{listAccounts as b,findAccount as d,createAccount as g}from"./accounts.js";import{ensureOrganisationalUnitsExist as T,placeAccountsInOUs as U,buildAccountToOUMap as P}from"./organisationalUnits.js";import{activateCostAllocationTags as y}from"./costAllocation.js";import{checkIdentityCentreStatus as L}from"./identityCentre.js";import{registerSecurityDelegates as h,SECURITY_SERVICE_PRINCIPALS as k}from"./delegatedAdmin.js";import{enableCentralisedRootAccess as V,ROOT_ACCESS_FEATURES as B,RootAccessEnablementError as F}from"./rootAccess.js";export{B as ROOT_ACCESS_FEATURES,F as RootAccessEnablementError,k as SECURITY_SERVICE_PRINCIPALS,l as SERVICE_PRINCIPALS,y as activateCostAllocationTags,u as activateTrustedAccess,P as buildAccountToOUMap,L as checkIdentityCentreStatus,g as createAccount,c as describeOrganisation,V as enableCentralisedRootAccess,S as enableIpamDelegatedAdmin,i as enablePolicyTypes,f as enableRamSharing,m as enableServiceAccess,s as ensureOrganisationExists,T as ensureOrganisationalUnitsExist,r as extractErrorName,d as findAccount,o as isOULeaf,b as listAccounts,U as placeAccountsInOUs,h as registerSecurityDelegates,I as updateBackupGlobalSettings};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type IAMClient } from "@aws-sdk/client-iam";
|
|
2
|
+
import { type Result } from "@fjall/generator";
|
|
3
|
+
export declare const ROOT_ACCESS_FEATURES: readonly ["RootCredentialsManagement", "RootSessions"];
|
|
4
|
+
export type RootAccessFeature = (typeof ROOT_ACCESS_FEATURES)[number];
|
|
5
|
+
export interface RootAccessEnablementSummary {
|
|
6
|
+
/** Features newly enabled by this call. */
|
|
7
|
+
enabled: RootAccessFeature[];
|
|
8
|
+
/** Features that were already enabled before this call. */
|
|
9
|
+
alreadyEnabled: RootAccessFeature[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Failure carrying the features that DID transition before the error, so the
|
|
13
|
+
* orchestrator's warn gate (AC2.8) fires on partial enablement too. On
|
|
14
|
+
* pre-flight (list) failures both arrays are empty — `alreadyEnabled` is
|
|
15
|
+
* unknown, and only `enabled` is load-bearing for the warn gate.
|
|
16
|
+
*/
|
|
17
|
+
export declare class RootAccessEnablementError extends Error {
|
|
18
|
+
readonly partialSummary: RootAccessEnablementSummary;
|
|
19
|
+
constructor(message: string, partialSummary: RootAccessEnablementSummary);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Enable centralised root access management for the organisation: root
|
|
23
|
+
* credentials management plus root sessions, via the management account's
|
|
24
|
+
* IAM client. Idempotent — features already enabled are skipped via the
|
|
25
|
+
* ListOrganizationsFeatures pre-flight, so a re-run is a converging no-op.
|
|
26
|
+
*/
|
|
27
|
+
export declare function enableCentralisedRootAccess(client: IAMClient, abortSignal?: AbortSignal): Promise<Result<RootAccessEnablementSummary, RootAccessEnablementError>>;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{ListOrganizationsFeaturesCommand as A,EnableOrganizationsRootCredentialsManagementCommand as C,EnableOrganizationsRootSessionsCommand as h}from"@aws-sdk/client-iam";import{success as R,failure as s}from"@fjall/generator";import{composeSdkAbortSignal as d,extractErrorName as u,isAccessDenied as E}from"./types.js";import{getErrorMessage as b,maskSensitiveOutput as p}from"@fjall/util";const w=["RootCredentialsManagement","RootSessions"],y={RootCredentialsManagement:{CommandClass:C,permission:"iam:EnableOrganizationsRootCredentialsManagement"},RootSessions:{CommandClass:h,permission:"iam:EnableOrganizationsRootSessions"}};class o extends Error{partialSummary;constructor(t,e){super(t),this.name="RootAccessEnablementError",this.partialSummary=e}}function g(a){return new o("Trusted access for iam.amazonaws.com is not enabled in Organizations. Re-run organisation setup \u2014 its enable-service-access phase enables it \u2014 or enable it manually (organizations:EnableAWSServiceAccess for iam.amazonaws.com) and retry enabling centralised root access.",a)}async function F(a,t){const e={enabled:[],alreadyEnabled:[]};let c;try{const n=await a.send(new A({}),{abortSignal:d(t)});c=new Set(n.EnabledFeatures??[])}catch(n){const i=u(n);return E(i)?s(new o("Access denied when listing organisation root-access features. Ensure your credentials have iam:ListOrganizationsFeatures permission.",e)):i==="ServiceAccessNotEnabledException"?s(g(e)):s(new o(`Failed to list organisation root-access features: ${p(b(n))}`,e))}const r=[];for(const n of w){if(c.has(n)){e.alreadyEnabled.push(n);continue}const{CommandClass:i,permission:f}=y[n];try{await a.send(new i({}),{abortSignal:d(t)}),e.enabled.push(n)}catch(l){const m=u(l);if(E(m)){const S=r.length>0?`${r.join("; ")}; `:"";return s(new o(`${S}Access denied when enabling ${n}. Ensure your credentials have ${f} permission.`,e))}if(m==="ServiceAccessNotEnabledException")return s(g(e));r.push(`${n}: ${p(b(l))}`)}}return r.length>0?s(new o(`Failed to enable centralised root access:
|
|
2
|
+
${r.join(`
|
|
3
|
+
`)}`,e)):R(e)}export{w as ROOT_ACCESS_FEATURES,o as RootAccessEnablementError,F as enableCentralisedRootAccess};
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { type OrganizationsClient } from "@aws-sdk/client-organizations";
|
|
2
2
|
import { type Result } from "@fjall/generator";
|
|
3
|
+
/**
|
|
4
|
+
* Canonical list of Organizations trusted-access service principals fjall
|
|
5
|
+
* enables. Consumers MUST import this rather than redeclaring it — a mirror
|
|
6
|
+
* list drifts silently when a principal is added here.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SERVICE_PRINCIPALS: readonly ["account.amazonaws.com", "sso.amazonaws.com", "ipam.amazonaws.com", "ram.amazonaws.com", "backup.amazonaws.com", "member.org.stacksets.cloudformation.amazonaws.com", "guardduty.amazonaws.com", "securityhub.amazonaws.com", "config.amazonaws.com", "inspector2.amazonaws.com", "access-analyzer.amazonaws.com", "cloudtrail.amazonaws.com", "iam.amazonaws.com"];
|
|
3
9
|
/**
|
|
4
10
|
* Enable AWS service access for all required service principals.
|
|
5
11
|
* Idempotent — enabling an already-enabled principal is a no-op.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EnableAWSServiceAccessCommand as n}from"@aws-sdk/client-organizations";import{success as s,failure as
|
|
1
|
+
import{EnableAWSServiceAccessCommand as n}from"@aws-sdk/client-organizations";import{success as s,failure as o}from"@fjall/generator";import{extractErrorName as m,SDK_TIMEOUT_MS as i,AWS_ERROR_NAMES as t}from"./types.js";import{getErrorMessage as e}from"@fjall/util";const w=["account.amazonaws.com","sso.amazonaws.com","ipam.amazonaws.com","ram.amazonaws.com","backup.amazonaws.com","member.org.stacksets.cloudformation.amazonaws.com","guardduty.amazonaws.com","securityhub.amazonaws.com","config.amazonaws.com","inspector2.amazonaws.com","access-analyzer.amazonaws.com","cloudtrail.amazonaws.com","iam.amazonaws.com"];async function z(c){try{for(const a of w)try{await c.send(new n({ServicePrincipal:a}),{abortSignal:AbortSignal.timeout(i)})}catch(r){if(m(r)===t.ACCESS_DENIED)return o(new Error(`Access denied when enabling service access for ${a}. Ensure your credentials have organizations:EnableAWSServiceAccess permission.`));throw new Error(`Service principal ${a}: ${e(r)}`,{cause:r})}return s(void 0)}catch(a){return o(new Error(`Failed to enable service access: ${e(a)}`))}}export{w as SERVICE_PRINCIPALS,z as enableServiceAccess};
|
|
@@ -50,8 +50,20 @@ export type OUTree = {
|
|
|
50
50
|
};
|
|
51
51
|
/** Returns true if the value is a list of account names (leaf node). */
|
|
52
52
|
export declare function isOULeaf(value: string[] | OUTree): value is string[];
|
|
53
|
+
/**
|
|
54
|
+
* Compose the per-request SDK timeout with an optional caller shutdown
|
|
55
|
+
* signal so SIGTERM is not stalled by an in-flight call (the
|
|
56
|
+
* `DeployParams.abortSignal` contract).
|
|
57
|
+
*/
|
|
58
|
+
export declare function composeSdkAbortSignal(abortSignal?: AbortSignal): AbortSignal;
|
|
59
|
+
export declare function isAborted(abortSignal?: AbortSignal): boolean;
|
|
53
60
|
/**
|
|
54
61
|
* Extract the error name from an AWS SDK error.
|
|
55
62
|
* AWS SDK v3 errors have a `name` property that identifies the error type.
|
|
56
63
|
*/
|
|
57
64
|
export declare function extractErrorName(error: unknown): string;
|
|
65
|
+
/**
|
|
66
|
+
* IAM, STS, and S3 surface denials as "AccessDenied"; Organizations and most
|
|
67
|
+
* other services throw "AccessDeniedException" — match both.
|
|
68
|
+
*/
|
|
69
|
+
export declare function isAccessDenied(errorName: string): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const o=3e4,e={ACCESS_DENIED:"AccessDeniedException",ACCOUNT_ALREADY_REGISTERED:"AccountAlreadyRegisteredException",ACCOUNT_NOT_FOUND:"AccountNotFoundException",CHILD_NOT_FOUND:"ChildNotFoundException",ORGS_NOT_IN_USE:"AWSOrganizationsNotInUseException"};function i(n){return Array.isArray(n)}function c(n){const t=AbortSignal.timeout(3e4);return n!==void 0?AbortSignal.any([n,t]):t}function r(n){return n?.aborted===!0}function E(n){return typeof n=="object"&&n!==null&&"name"in n&&typeof n.name=="string"?n.name:"UnknownError"}function A(n){return n==="AccessDenied"||n===e.ACCESS_DENIED}export{e as AWS_ERROR_NAMES,o as SDK_TIMEOUT_MS,c as composeSdkAbortSignal,E as extractErrorName,r as isAborted,A as isAccessDenied,i as isOULeaf};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type STSClient } from "@aws-sdk/client-sts";
|
|
2
|
+
import { type Result } from "@fjall/generator";
|
|
3
|
+
import type { AwsProviderCredentials } from "../AwsProvider.js";
|
|
4
|
+
/**
|
|
5
|
+
* The five AWS-managed root-task policies AssumeRoot accepts. Every root
|
|
6
|
+
* session is bounded by exactly one of these; arbitrary policies are
|
|
7
|
+
* rejected by STS, so the primitive rejects them before sending.
|
|
8
|
+
*/
|
|
9
|
+
export declare const ROOT_TASK_POLICY_ARNS: readonly ["arn:aws:iam::aws:policy/root-task/IAMAuditRootUserCredentials", "arn:aws:iam::aws:policy/root-task/IAMCreateRootUserPassword", "arn:aws:iam::aws:policy/root-task/IAMDeleteRootUserCredentials", "arn:aws:iam::aws:policy/root-task/S3UnlockBucketPolicy", "arn:aws:iam::aws:policy/root-task/SQSUnlockQueuePolicy"];
|
|
10
|
+
export type RootTaskPolicyArn = (typeof ROOT_TASK_POLICY_ARNS)[number];
|
|
11
|
+
export declare function isRootTaskPolicyArn(value: string): value is RootTaskPolicyArn;
|
|
12
|
+
/** AssumeRoot hard maximum session duration. */
|
|
13
|
+
export declare const MAX_ROOT_SESSION_SECONDS = 900;
|
|
14
|
+
export interface AssumeRootOptions {
|
|
15
|
+
/** Member account whose root principal the session acts as. */
|
|
16
|
+
targetAccountId: string;
|
|
17
|
+
/** One of the five AWS root-task policy ARNs bounding the session. */
|
|
18
|
+
taskPolicyArn: string;
|
|
19
|
+
/** Session duration in seconds, max 900. Omitted → AWS default (900). */
|
|
20
|
+
durationSeconds?: number;
|
|
21
|
+
/** Caller shutdown signal, composed with the per-call SDK timeout. */
|
|
22
|
+
abortSignal?: AbortSignal;
|
|
23
|
+
}
|
|
24
|
+
export interface RootTaskSession {
|
|
25
|
+
credentials: AwsProviderCredentials & {
|
|
26
|
+
expiration?: Date;
|
|
27
|
+
};
|
|
28
|
+
/** Identity STS records for the root session (CloudTrail audit trail). */
|
|
29
|
+
sourceIdentity?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Assume a member account's root principal for a bounded privileged task
|
|
33
|
+
* via STS AssumeRoot.
|
|
34
|
+
*
|
|
35
|
+
* Requires management-account or delegated-admin credentials with
|
|
36
|
+
* `sts:AssumeRoot`, centralised root access enabled on the organisation
|
|
37
|
+
* (RootCredentialsManagement), and a client pinned to a regional STS
|
|
38
|
+
* endpoint — AssumeRoot is not served by the global endpoint. The cascade
|
|
39
|
+
* role path (`assumeCascadeRole`) is structurally useless against a
|
|
40
|
+
* quarantine: a quarantine deny policy blocks every role principal, while
|
|
41
|
+
* an assume-root session bypasses member roles entirely.
|
|
42
|
+
*
|
|
43
|
+
* Returned credentials are credential VALUES — callers must never log
|
|
44
|
+
* them; error messages from this primitive are masked.
|
|
45
|
+
*/
|
|
46
|
+
export declare function assumeRootForTask(client: STSClient, options: AssumeRootOptions): Promise<Result<RootTaskSession>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{AssumeRootCommand as m}from"@aws-sdk/client-sts";import{success as S,failure as n}from"@fjall/generator";import{getErrorMessage as f,maskSensitiveOutput as A}from"@fjall/util";import{composeSdkAbortSignal as p,extractErrorName as w,isAccessDenied as y}from"../organisations/types.js";const d=["arn:aws:iam::aws:policy/root-task/IAMAuditRootUserCredentials","arn:aws:iam::aws:policy/root-task/IAMCreateRootUserPassword","arn:aws:iam::aws:policy/root-task/IAMDeleteRootUserCredentials","arn:aws:iam::aws:policy/root-task/S3UnlockBucketPolicy","arn:aws:iam::aws:policy/root-task/SQSUnlockQueuePolicy"],g=new Set(d);function k(t){return g.has(t)}const u=900,T=/^\d{12}$/;async function O(t,i){const{targetAccountId:r,taskPolicyArn:a,durationSeconds:o,abortSignal:l}=i;if(!T.test(r))return n(new Error(`Invalid target account id "${r}": expected a 12-digit AWS account id.`));if(!k(a))return n(new Error(`Task policy "${a}" is not an AWS root-task policy. AssumeRoot accepts only: ${d.join(", ")}.`));if(o!==void 0&&(!Number.isInteger(o)||o<1||o>u))return n(new Error(`Invalid durationSeconds ${o}: AssumeRoot sessions must be a whole number of seconds between 1 and ${u}.`));const c=await R(t);if(c===void 0||c==="")return n(new Error("AssumeRoot requires a regional STS endpoint, but the client has no resolvable region. Construct the STS client with an explicit region."));try{const s=await t.send(new m({TargetPrincipal:r,TaskPolicyArn:{arn:a},...o!==void 0&&{DurationSeconds:o}}),{abortSignal:p(l)}),e=s.Credentials;return e?.AccessKeyId===void 0||e.SecretAccessKey===void 0||e.SessionToken===void 0?n(new Error(`AssumeRoot for account ${r} returned no credentials.`)):S({credentials:{accessKeyId:e.AccessKeyId,secretAccessKey:e.SecretAccessKey,sessionToken:e.SessionToken,...e.Expiration!==void 0&&{expiration:e.Expiration}},...s.SourceIdentity!==void 0&&{sourceIdentity:s.SourceIdentity}})}catch(s){const e=w(s);return y(e)?n(new Error(`Access denied assuming root for account ${r}. Ensure the credentials belong to the management account (or the delegated admin) with sts:AssumeRoot permission, and that centralised root access management is enabled for the organisation.`)):n(new Error(`Failed to assume root for account ${r}: ${A(f(s))}`))}}async function R(t){try{const i=t.config.region;return typeof i=="function"?await i():i}catch{return}}export{u as MAX_ROOT_SESSION_SECONDS,d as ROOT_TASK_POLICY_ARNS,O as assumeRootForTask,k as isRootTaskPolicyArn};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type CloudFormationClient } from "@aws-sdk/client-cloudformation";
|
|
2
|
+
import { type EC2Client } from "@aws-sdk/client-ec2";
|
|
3
|
+
import { type Result } from "@fjall/generator";
|
|
4
|
+
import type { OrgConfig } from "../types/orgConfig.js";
|
|
5
|
+
export declare const ACCOUNT_STACK_NAME: string;
|
|
6
|
+
export type TargetReadinessReason = {
|
|
7
|
+
kind: "missing-account-stack";
|
|
8
|
+
stackName: string;
|
|
9
|
+
region: string;
|
|
10
|
+
} | {
|
|
11
|
+
kind: "missing-ipam-pool";
|
|
12
|
+
accountId: string;
|
|
13
|
+
region: string;
|
|
14
|
+
};
|
|
15
|
+
export type TargetReadinessVerdict = {
|
|
16
|
+
ready: true;
|
|
17
|
+
} | {
|
|
18
|
+
ready: false;
|
|
19
|
+
reasons: TargetReadinessReason[];
|
|
20
|
+
advisory: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Both clients carry the target account's credentials, but their regions
|
|
24
|
+
* differ: cloudFormation is scoped to the TARGET region (the Account stack
|
|
25
|
+
* lives where the deploy lands); ec2 is scoped to the IPAM HOME region (the
|
|
26
|
+
* platform stack's region) — RAM shares are created in the home region and
|
|
27
|
+
* `DescribeIpamPools` returns nothing for shared pools anywhere else.
|
|
28
|
+
*/
|
|
29
|
+
export interface TargetReadinessClients {
|
|
30
|
+
cloudFormation: CloudFormationClient;
|
|
31
|
+
ec2: EC2Client;
|
|
32
|
+
}
|
|
33
|
+
export interface TargetReadinessAccount {
|
|
34
|
+
id: string;
|
|
35
|
+
/** Provider-account name when resolved from org config; omit otherwise. */
|
|
36
|
+
name?: string;
|
|
37
|
+
}
|
|
38
|
+
export declare function describeTargetReadinessReason(reason: TargetReadinessReason): string;
|
|
39
|
+
/**
|
|
40
|
+
* Shape-branched remediation for an unready deploy target (AC2b.1). Org
|
|
41
|
+
* estates (a tier-organisation account in providerAccounts) remediate via the
|
|
42
|
+
* cascade, which provisions every account and creates the IPAM pool; solo
|
|
43
|
+
* accounts provision the target directly. The solo `target set` command embeds
|
|
44
|
+
* the derived `{accountName}-{regionAbbrev}` target name — the only form
|
|
45
|
+
* `target set` resolves — and degrades to `fjall target list` guidance when
|
|
46
|
+
* the account name could not be resolved from org config.
|
|
47
|
+
*/
|
|
48
|
+
export declare function buildTargetUnreadyAdvisory(params: {
|
|
49
|
+
accountId: string;
|
|
50
|
+
accountName?: string;
|
|
51
|
+
region: string;
|
|
52
|
+
reasons: TargetReadinessReason[];
|
|
53
|
+
providerAccounts?: OrgConfig["providerAccounts"];
|
|
54
|
+
}): string;
|
|
55
|
+
/**
|
|
56
|
+
* Probe whether a deploy target is provisioned before any AWS mutation:
|
|
57
|
+
* the fixed-name Account stack must exist in the target region (both shapes),
|
|
58
|
+
* and for org estates (a tier-organisation account in providerAccounts) the
|
|
59
|
+
* (account, region) IPAM pool must exist. Bootstrap is excluded — both deploy
|
|
60
|
+
* paths self-heal it.
|
|
61
|
+
*
|
|
62
|
+
* Missing resources return an unready verdict carrying structured reasons and
|
|
63
|
+
* the shape-branched advisory. Every probe error (AccessDenied, throttling,
|
|
64
|
+
* network) propagates as failure — a mis-read "unready" refuses a legitimate
|
|
65
|
+
* deploy, a mis-read "ready" lets a deploy fail mid-mutation; neither may be
|
|
66
|
+
* guessed (mirrors describeAccountGlobalsExist).
|
|
67
|
+
*
|
|
68
|
+
* Failure messages stay raw — callers mask at their output boundary.
|
|
69
|
+
*/
|
|
70
|
+
export declare function checkTargetReadiness(clients: TargetReadinessClients, account: TargetReadinessAccount, region: string, orgConfig?: OrgConfig, abortSignal?: AbortSignal): Promise<Result<TargetReadinessVerdict>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DescribeStacksCommand as N}from"@aws-sdk/client-cloudformation";import{DescribeIpamPoolsCommand as S}from"@aws-sdk/client-ec2";import{success as i,failure as c}from"@fjall/generator";import{accountTier as A,generateTargetName as g,getErrorMessage as E}from"@fjall/util";import{formatIpamPairTagValue as y,IPAM_OPERATIONS_POOL_TAG_KEY as O,STACK_NOT_FOUND_PATTERN as k}from"@fjall/util/aws";import{getOrganisationStackName as _,ORGANISATION_TYPES as R}from"../types/operations.js";import{hasOrganisationTierAccount as T}from"./organisations/accountGlobals.js";import{composeSdkAbortSignal as I,isAborted as P}from"./organisations/types.js";const m=_(R.ACCOUNT),w=new Set(["CREATE_FAILED","ROLLBACK_IN_PROGRESS","ROLLBACK_COMPLETE","ROLLBACK_FAILED","REVIEW_IN_PROGRESS","DELETE_IN_PROGRESS","DELETE_FAILED"]);function $(e){switch(e.kind){case"missing-account-stack":return`the ${e.stackName} stack was not found in ${e.region}`;case"missing-ipam-pool":return`no IPAM pool exists for account ${e.accountId} in ${e.region}`}}function L(e){const t=e.accountName??e.accountId,n=e.reasons.map($).join(" and "),o=e.accountName!==void 0?`run \`fjall target set ${g(e.accountName,e.region)}\` then \`fjall deploy account\`, then retry this deploy`:"run `fjall target list` to find the target name, `fjall target set <target>`, then `fjall deploy account`, then retry this deploy",r=T(e.providerAccounts)?"run `fjall deploy organisation` (the cascade provisions every account and creates the IPAM pool), then retry this deploy":o;return`Target "${t}" is not ready in ${e.region}: ${n}. Nothing has been deployed. Provision the target first: ${r}.`}function b(e){return e instanceof Error&&e.name==="ValidationError"&&e.message.includes(k)}async function C(e,t,n){try{const r=(await e.send(new N({StackName:m}),{abortSignal:I(n)})).Stacks?.[0]?.StackStatus;return i(r!==void 0&&!w.has(r))}catch(o){return b(o)?i(!1):c(new Error(`Failed to probe the ${m} stack in ${t}: ${E(o)}`))}}function v(e,t,n,o){return e.Locale!==n?!1:o.side==="owner"?(e.Tags??[]).some(r=>r.Key===O&&r.Value===o.pairTagValue):e.OwnerId===t?!1:o.platformAccountId===void 0||e.OwnerId===o.platformAccountId}async function x(e,t,n,o,r){try{let a;do{if(P(r))return c(new Error(`Aborted: IPAM pool probe for account ${t} in ${n} cancelled by shutdown signal`));const s=await e.send(new S({...a!==void 0&&{NextToken:a}}),{abortSignal:I(r)});if((s.IpamPools??[]).some(u=>v(u,t,n,o)))return i(!0);a=s.NextToken}while(a!==void 0);return i(!1)}catch(a){return c(new Error(`Failed to probe IPAM pools for account ${t} in ${n}: ${E(a)}`))}}async function B(e,t,n,o,r){const a=[],s=await C(e.cloudFormation,n,r);if(!s.success)return c(s.error);s.data||a.push({kind:"missing-account-stack",stackName:m,region:n});const d=o?.providerAccounts;if(T(d)){const u=(d??[]).find(l=>l.id===t.id),p=(d??[]).find(l=>A(l)==="platform")?.id,h=u!==void 0&&A(u)==="platform"?{side:"owner",pairTagValue:y(t.id,n)}:{side:"consumer",...p!==void 0&&{platformAccountId:p}},f=await x(e.ec2,t.id,n,h,r);if(!f.success)return c(f.error);f.data||a.push({kind:"missing-ipam-pool",accountId:t.id,region:n})}return a.length===0?i({ready:!0}):i({ready:!1,reasons:a,advisory:L({accountId:t.id,...t.name!==void 0&&{accountName:t.name},region:n,reasons:a,...o!==void 0&&{providerAccounts:o.providerAccounts}})})}export{m as ACCOUNT_STACK_NAME,L as buildTargetUnreadyAdvisory,B as checkTargetReadiness,$ as describeTargetReadinessReason};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { OrgConfig } from "../types/orgConfig.js";
|
|
2
|
+
import { type TargetReadinessReason } from "./targetReadiness.js";
|
|
3
|
+
/**
|
|
4
|
+
* Coupled to buildTargetUnreadyAdvisory at ./targetReadiness.ts — both open
|
|
5
|
+
* with the identical `Target "X" is not ready in <region>: <reasons>.`
|
|
6
|
+
* sentence built from describeTargetReadinessReason. Kept as a sibling module
|
|
7
|
+
* (not a shared-core refactor in targetReadiness.ts) only because that file
|
|
8
|
+
* carries concurrent in-flight changes; merge into a shared core when it is
|
|
9
|
+
* next touched.
|
|
10
|
+
*/
|
|
11
|
+
export interface TargetSetUnreadyAdvisoryParams {
|
|
12
|
+
accountId: string;
|
|
13
|
+
accountName?: string;
|
|
14
|
+
region: string;
|
|
15
|
+
reasons: TargetReadinessReason[];
|
|
16
|
+
providerAccounts?: OrgConfig["providerAccounts"];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Shape-branched advisory for `fjall target set` when the just-set target is
|
|
20
|
+
* unprovisioned (AC2c.1). Advisory only — the target has been saved
|
|
21
|
+
* regardless, so unlike the deploy-context advisory there is no "Nothing has
|
|
22
|
+
* been deployed." sentence and no retry tail.
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildTargetSetUnreadyAdvisory(params: TargetSetUnreadyAdvisoryParams): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{hasOrganisationTierAccount as t}from"./organisations/accountGlobals.js";import{describeTargetReadinessReason as r}from"./targetReadiness.js";function s(o){const n=o.accountName??o.accountId,e=o.reasons.map(r).join(" and "),i=t(o.providerAccounts)?"Run `fjall deploy organisation` \u2014 the cascade provisions every account and creates the IPAM pool":"Run `fjall deploy account` to provision it";return`Target "${n}" is not ready in ${o.region}: ${e}. ${i}.`}export{s as buildTargetSetUnreadyAdvisory};
|
package/dist/src/index.d.ts
CHANGED
|
@@ -11,23 +11,19 @@
|
|
|
11
11
|
* responsibility. deploy-core receives credentials and a working
|
|
12
12
|
* directory; it never reads credential files or writes to the terminal.
|
|
13
13
|
*/
|
|
14
|
-
export { DeploymentEventSchema, DEPLOYMENT_EVENT_TYPES, DEPLOYMENT_EVENT_RESOURCE_CATEGORIES, CASCADE_PHASES, CASCADE_ACCOUNT_STATUSES } from "./types/index.js";
|
|
14
|
+
export { DeploymentEventSchema, DEPLOYMENT_EVENT_TYPES, DEPLOYMENT_EVENT_RESOURCE_CATEGORIES, DEPLOYMENT_EVENT_STATUS_REASON_MAX, DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX, DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX, CASCADE_PHASES, CASCADE_ACCOUNT_STATUSES } from "./types/index.js";
|
|
15
15
|
export type { DeploymentEvent, DeploymentEventType, DeploymentEventResourceCategory, DeploymentEventCascadePhase, DeploymentEventCascadeAccountStatus } from "./types/index.js";
|
|
16
|
-
export type { AwsCredentials, DeployIdentity, DeployCallbacks, StepCompleteStatus, ProgressEvent, ProgressEventType, ResourceEvent, AwsAuthResult, CascadeDeploymentResult, CascadePhase, BuildPushStartEvent, BuildPushProgressEvent, BuildPushCompleteEvent, TaskDefRegisteredEvent, ECSCompleteEvent, MigrationsStartEvent, MigrationsCompleteEvent, TrailMigrationPhase, TrailMigrationStatus, TrailMigrationPhaseEvent, ApiClientInterface, EntitlementsData, DeployParams, DeployOptions, DeploymentType, DeployResult, DestroyParams, DestroyOptions, DestroyResult, OrgConfig, ProviderAccount, SSOSession, Entitlements } from "./types/index.js";
|
|
16
|
+
export type { AwsCredentials, DeployIdentity, DeployCallbacks, StepCompleteStatus, StackCleanupQuarantineDetail, StackCleanupRetainedBucketsDetail, ProgressEvent, ProgressEventType, ResourceEvent, AwsAuthResult, CascadeDeploymentResult, CascadePhase, BuildPushStartEvent, BuildPushProgressEvent, BuildPushCompleteEvent, TaskDefRegisteredEvent, ECSCompleteEvent, MigrationsStartEvent, MigrationsCompleteEvent, TrailMigrationPhase, TrailMigrationStatus, TrailMigrationPhaseEvent, ApiClientInterface, EntitlementsData, DeployParams, DeployOptions, DeploymentType, DeployResult, DestroyParams, DestroyOptions, DestroyResult, OrgConfig, ProviderAccount, RootAccessManagementMode, SSOSession, Entitlements } from "./types/index.js";
|
|
17
17
|
export type { AwsProvider, AwsProviderCredentials, AwsSdkClientConstructor } from "./aws/index.js";
|
|
18
18
|
export { SimpleAwsProvider } from "./aws/index.js";
|
|
19
|
-
export {
|
|
20
|
-
export type {
|
|
19
|
+
export { checkTargetReadiness, describeTargetReadinessReason, buildTargetUnreadyAdvisory, buildTargetSetUnreadyAdvisory } from "./aws/index.js";
|
|
20
|
+
export type { TargetReadinessAccount, TargetReadinessClients, TargetReadinessReason, TargetReadinessVerdict, TargetSetUnreadyAdvisoryParams } from "./aws/index.js";
|
|
21
|
+
export { ensureOrganisationExists, describeOrganisation, enablePolicyTypes, enableServiceAccess, SERVICE_PRINCIPALS, enableRamSharing, activateTrustedAccess, enableIpamDelegatedAdmin, updateBackupGlobalSettings, listAccounts, findAccount, createAccount, ensureOrganisationalUnitsExist, placeAccountsInOUs, buildAccountToOUMap, activateCostAllocationTags, checkIdentityCentreStatus, extractErrorName, isOULeaf, registerSecurityDelegates, SECURITY_SERVICE_PRINCIPALS, enableCentralisedRootAccess, ROOT_ACCESS_FEATURES, RootAccessEnablementError } from "./aws/index.js";
|
|
22
|
+
export type { OrgDetails, OUMap, OUTree, AccountPlacementResult, AccountInfo, IdentityCentreStatus, BackupGlobalSettings, CostAllocationTag, CreateAccountResult, RootAccessFeature, RootAccessEnablementSummary } from "./aws/index.js";
|
|
21
23
|
export { STEP_IDS, STEP_NAMES, INFRASTRUCTURE_STEP_NAMES, INFRA_STEP_NAME } from "./types/index.js";
|
|
22
24
|
export type { StepId, InfrastructureStepName, StepDefinition, StepDeploymentType, Operation, StepContext } from "./types/index.js";
|
|
23
25
|
export type { DeploymentContext, StepOutput, ApplicationDeploymentContext, CallerIdentity, StackOutput, StackOutputsRecord, ValidationResult, DetectionResult, ProgressCallbacks, ApplicationStack, OrganisationType, DeploymentOperation, ApplicationOperation, OrganisationOperation, DeployOrderOptions, ParallelDeployGroupKey, ParallelDestroyGroupKey, OpenNextPattern, AppResourceFlags, ParallelDeploymentResult, ParallelDeployGroup, ParallelOperation, ParallelOperationType, ParallelOperationState, ApplicationErrorType, StackDeploymentData, StackDeploymentOptions, ApplicationDeploymentData, ApplicationDestructionData, FjallStateFile, TemplateHashEntry } from "./types/index.js";
|
|
24
|
-
export { ProgressReporter, APPLICATION_STACKS, ORGANISATION_TYPES, APPLICATION_DEPLOY_ORDER, APPLICATION_DESTROY_ORDER, OPENNEXT_DEPLOY_ORDER, OPENNEXT_DESTROY_ORDER, PARALLEL_DEPLOY_GROUPS, PARALLEL_DESTROY_GROUPS, OPENNEXT_PARALLEL_GROUPS, PARALLEL_OPERATION_TYPES, isApplicationOperation, isOrganisationOperation, getParallelDeployGroups, getParallelDestroyGroups, getApplicationDeployOrder, getApplicationDestroyOrder, getApplicationStackName, getOrganisationStackName, isApplicationStack, getApplicationStepName, getApplicationStepId, toPascalCase, isOpenNextPattern, OPENNEXT_PATTERNS, deriveResourcesFromManifestStacks, STACK_NOT_FOUND_PATTERN, STACK_FAILED_STATE_PATTERN, CDK_NO_STACKS_MATCH, INFRASTRUCTURE_FILENAME, ApplicationError, wrapApplicationError, FjallStateFileSchema, readStateFile, writeStateFile, createEmptyState, deleteStateFile, updateTemplateHash, getStateFilePath, stubCallerIdentity } from "./types/index.js";
|
|
25
|
-
/** @deprecated Use FrameworkRegistry.resolve() instead */
|
|
26
|
-
export { detectPattern } from "./types/index.js";
|
|
27
|
-
/** @deprecated Use FrameworkRegistry.resolve() instead */
|
|
28
|
-
export { detectPayloadPattern } from "./types/index.js";
|
|
29
|
-
/** @deprecated Use FrameworkRegistry.resolve() instead */
|
|
30
|
-
export { detectDatabase } from "./types/index.js";
|
|
26
|
+
export { ProgressReporter, APPLICATION_STACKS, ORGANISATION_TYPES, APPLICATION_DEPLOY_ORDER, APPLICATION_DESTROY_ORDER, OPENNEXT_DEPLOY_ORDER, OPENNEXT_DESTROY_ORDER, PARALLEL_DEPLOY_GROUPS, PARALLEL_DESTROY_GROUPS, OPENNEXT_PARALLEL_GROUPS, PARALLEL_OPERATION_TYPES, isApplicationOperation, isOrganisationOperation, getParallelDeployGroups, getParallelDestroyGroups, getApplicationDeployOrder, getApplicationDestroyOrder, getApplicationStackName, getOrganisationStackName, isApplicationStack, isQuarantineDetail, isRetainedBucketsDetail, getApplicationStepName, getApplicationStepId, toPascalCase, isOpenNextPattern, OPENNEXT_PATTERNS, deriveResourcesFromManifestStacks, STACK_NOT_FOUND_PATTERN, STACK_FAILED_STATE_PATTERN, CDK_NO_STACKS_MATCH, INFRASTRUCTURE_FILENAME, ApplicationError, wrapApplicationError, FjallStateFileSchema, readStateFile, writeStateFile, createEmptyState, deleteStateFile, updateTemplateHash, getStateFilePath, stubCallerIdentity } from "./types/index.js";
|
|
31
27
|
export { CloudFormationEventMonitor } from "./aws/index.js";
|
|
32
28
|
export type { AwsClientLike, EventLogWriter, EventFailureAnalyser, EventLogWriterFactory, EventMonitorDeps } from "./aws/index.js";
|
|
33
29
|
export { CdkService, CdkArgumentBuilder, CdkProcessManager, CdkEventMonitor, startStackMonitoring, DEFAULT_DEPLOY_TIMEOUT_MS, isCdkError, formatInfrastructureError, getStructuralHint, getSourceContext, hasCdkDifferences, parseDiffOutput, CloudFormationService, CloudFormationError, EcsService, EcsError, EcsServiceResolver, type CfnExportsClient, TemplateHashService, TemplateHashError, type TemplateComparisonResult, CdkContextBuilder, emitProgress, PROGRESS_MESSAGES, parseBuildPhase, buildStepContextBuildConfig, convertCloudFormationOutputsToRecord, type CloudFormationOutput, ApplicationStackService } from "./services/index.js";
|
|
@@ -43,7 +39,7 @@ export { type Result, success, failure, isSuccess, isFailure } from "@fjall/gene
|
|
|
43
39
|
export { deploy } from "./orchestration/index.js";
|
|
44
40
|
export { destroy } from "./orchestration/index.js";
|
|
45
41
|
export { partitionAccounts } from "./orchestration/index.js";
|
|
46
|
-
export { buildRegionList, buildAccountRegionPairs } from "./orchestration/index.js";
|
|
42
|
+
export { buildRegionList, buildAccountRegionPairs, cascadeHomeRegion, cascadeOperationKey } from "./orchestration/index.js";
|
|
47
43
|
export type { AccountRegionPair } from "./orchestration/index.js";
|
|
48
44
|
export { projectScalarSummary, projectAccountRows } from "./orchestration/index.js";
|
|
49
45
|
export type { CascadeOutcomeResult, CascadeMemberOutcome, CascadePlatformOutcome, CascadeLedger, CascadeAccountRow, CascadePlatformRow, CascadeAccountProjection } from "./orchestration/index.js";
|
|
@@ -51,12 +47,16 @@ export { reconcileProviderAccounts, mergeReconciledProviderAccounts } from "./or
|
|
|
51
47
|
export type { ReconcileResult } from "./orchestration/index.js";
|
|
52
48
|
export { decideNextTransition, reconcileTrailMigration, decommissionMemberTrailStorage, ORG_TRAIL_BUCKET_OUTPUT_KEY, TRAIL_BUCKET_OUTPUT_KEY, TRAIL_KEY_ARN_OUTPUT_KEY } from "./orchestration/index.js";
|
|
53
49
|
export type { MemberTrailFacts, TrailMigrationTransition, TrailMigrationOutcome, DecommissionClients, DecommissionInput, DecommissionOutcome } from "./orchestration/index.js";
|
|
50
|
+
export { unlockBucket, unlockQueue } from "./orchestration/index.js";
|
|
51
|
+
export type { UnlockBucketInput, UnlockBucketReport, UnlockQueueInput, UnlockQueueReport } from "./orchestration/index.js";
|
|
54
52
|
export { verifyOrgTrailDelivery } from "./aws/cloudtrail/orgTrailDelivery.js";
|
|
55
53
|
export type { OrgTrailDeliveryReport, OrgTrailAccountDelivery } from "./aws/cloudtrail/orgTrailDelivery.js";
|
|
54
|
+
export { assumeRootForTask, isRootTaskPolicyArn, ROOT_TASK_POLICY_ARNS, MAX_ROOT_SESSION_SECONDS } from "./aws/sts/assumeRoot.js";
|
|
55
|
+
export type { RootTaskPolicyArn, AssumeRootOptions, RootTaskSession } from "./aws/sts/assumeRoot.js";
|
|
56
56
|
export { parseAccountsConfiguration, flattenAccountsToEnvironments, extractAllAccountNames, accountsConfigToOUTree, isStringArray, isAccountsConfig, isOuOnlyAccountBucket, OU_ONLY_ACCOUNT_BUCKETS } from "./orchestration/index.js";
|
|
57
57
|
export type { AccountsConfig } from "./orchestration/index.js";
|
|
58
58
|
export { runOpenNextBuild } from "./orchestration/index.js";
|
|
59
|
-
export { runOrganisationSetup } from "./orchestration/index.js";
|
|
59
|
+
export { runOrganisationSetup, ORG_SETUP_PHASES } from "./orchestration/index.js";
|
|
60
60
|
export type { OrgSetupPhase, OrgSetupCallbacks, OrgSetupConfig, OrgSetupResult, DockerProvider, DockerProgressCallback, DockerBuildParams, DockerBuildResult, ECRInitParams, ECRInitResult, TagImagesParams, TagImagesResult, TagByDigestParams, DomainDeployProvider, DomainConfig, DomainDeployResult, DeployServices } from "./orchestration/index.js";
|
|
61
61
|
export type { FrameworkBuilder, FrameworkDetection, BuildPlan, BuildCommand, BuildCallbacks, DetectionContext, BuildOptions } from "./types/index.js";
|
|
62
62
|
export { FrameworkRegistry, type ResolvedBuilder } from "./orchestration/index.js";
|
package/dist/src/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DeploymentEventSchema as t,DEPLOYMENT_EVENT_TYPES as o,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as i,
|
|
1
|
+
import{DeploymentEventSchema as t,DEPLOYMENT_EVENT_TYPES as o,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as i,DEPLOYMENT_EVENT_STATUS_REASON_MAX as a,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as s,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as E,CASCADE_PHASES as n,CASCADE_ACCOUNT_STATUSES as c}from"./types/index.js";import{SimpleAwsProvider as A}from"./aws/index.js";import{checkTargetReadiness as T,describeTargetReadinessReason as p,buildTargetUnreadyAdvisory as _,buildTargetSetUnreadyAdvisory as O}from"./aws/index.js";import{ensureOrganisationExists as R,describeOrganisation as m,enablePolicyTypes as d,enableServiceAccess as P,SERVICE_PRINCIPALS as C,enableRamSharing as N,activateTrustedAccess as f,enableIpamDelegatedAdmin as g,updateBackupGlobalSettings as x,listAccounts as D,findAccount as I,createAccount as L,ensureOrganisationalUnitsExist as U,placeAccountsInOUs as k,buildAccountToOUMap as y,activateCostAllocationTags as v,checkIdentityCentreStatus as M,extractErrorName as F,isOULeaf as Y,registerSecurityDelegates as b,SECURITY_SERVICE_PRINCIPALS as B,enableCentralisedRootAccess as h,ROOT_ACCESS_FEATURES as K,RootAccessEnablementError as G}from"./aws/index.js";import{STEP_IDS as H,STEP_NAMES as X,INFRASTRUCTURE_STEP_NAMES as w,INFRA_STEP_NAME as j}from"./types/index.js";import{ProgressReporter as q,APPLICATION_STACKS as z,ORGANISATION_TYPES as J,APPLICATION_DEPLOY_ORDER as W,APPLICATION_DESTROY_ORDER as Z,OPENNEXT_DEPLOY_ORDER as $,OPENNEXT_DESTROY_ORDER as ee,PARALLEL_DEPLOY_GROUPS as re,PARALLEL_DESTROY_GROUPS as te,OPENNEXT_PARALLEL_GROUPS as oe,PARALLEL_OPERATION_TYPES as ie,isApplicationOperation as ae,isOrganisationOperation as se,getParallelDeployGroups as Ee,getParallelDestroyGroups as ne,getApplicationDeployOrder as ce,getApplicationDestroyOrder as Se,getApplicationStackName as Ae,getOrganisationStackName as le,isApplicationStack as Te,isQuarantineDetail as pe,isRetainedBucketsDetail as _e,getApplicationStepName as Oe,getApplicationStepId as ue,toPascalCase as Re,isOpenNextPattern as me,OPENNEXT_PATTERNS as de,deriveResourcesFromManifestStacks as Pe,STACK_NOT_FOUND_PATTERN as Ce,STACK_FAILED_STATE_PATTERN as Ne,CDK_NO_STACKS_MATCH as fe,INFRASTRUCTURE_FILENAME as ge,ApplicationError as xe,wrapApplicationError as De,FjallStateFileSchema as Ie,readStateFile as Le,writeStateFile as Ue,createEmptyState as ke,deleteStateFile as ye,updateTemplateHash as ve,getStateFilePath as Me,stubCallerIdentity as Fe}from"./types/index.js";import{CloudFormationEventMonitor as be}from"./aws/index.js";import{CdkService as he,CdkArgumentBuilder as Ke,CdkProcessManager as Ge,CdkEventMonitor as Ve,startStackMonitoring as He,DEFAULT_DEPLOY_TIMEOUT_MS as Xe,isCdkError as we,formatInfrastructureError as je,getStructuralHint as Qe,getSourceContext as qe,hasCdkDifferences as ze,parseDiffOutput as Je,CloudFormationService as We,CloudFormationError as Ze,EcsService as $e,EcsError as er,EcsServiceResolver as rr,TemplateHashService as tr,TemplateHashError as or,CdkContextBuilder as ir,emitProgress as ar,PROGRESS_MESSAGES as sr,parseBuildPhase as Er,buildStepContextBuildConfig as nr,convertCloudFormationOutputsToRecord as cr,ApplicationStackService as Sr}from"./services/index.js";import{CdkError as lr}from"./types/errors/index.js";import{BaseServiceError as pr,ValidationError as _r,AuthError as Or,AwsError as ur,DeploymentError as Rr,NetworkError as mr,FileSystemError as dr,ConfigError as Pr,toServiceError as Cr}from"./types/errors/index.js";import{filterDangerousEnvVars as fr,maskSensitiveOutput as gr,parseShellArgs as xr,sleep as Dr}from"@fjall/util";import{hasDockerfile as Lr}from"./util/dockerfileDetection.js";import{createSequencedCallbacks as kr}from"./util/sequencedCallbacks.js";import{fileExists as vr}from"@fjall/util/fsHelpers";import{success as Fr,failure as Yr,isSuccess as br,isFailure as Br}from"@fjall/generator";import{deploy as Kr}from"./orchestration/index.js";import{destroy as Vr}from"./orchestration/index.js";import{partitionAccounts as Xr}from"./orchestration/index.js";import{buildRegionList as jr,buildAccountRegionPairs as Qr,cascadeHomeRegion as qr,cascadeOperationKey as zr}from"./orchestration/index.js";import{projectScalarSummary as Wr,projectAccountRows as Zr}from"./orchestration/index.js";import{reconcileProviderAccounts as et,mergeReconciledProviderAccounts as rt}from"./orchestration/index.js";import{decideNextTransition as ot,reconcileTrailMigration as it,decommissionMemberTrailStorage as at,ORG_TRAIL_BUCKET_OUTPUT_KEY as st,TRAIL_BUCKET_OUTPUT_KEY as Et,TRAIL_KEY_ARN_OUTPUT_KEY as nt}from"./orchestration/index.js";import{unlockBucket as St,unlockQueue as At}from"./orchestration/index.js";import{verifyOrgTrailDelivery as Tt}from"./aws/cloudtrail/orgTrailDelivery.js";import{assumeRootForTask as _t,isRootTaskPolicyArn as Ot,ROOT_TASK_POLICY_ARNS as ut,MAX_ROOT_SESSION_SECONDS as Rt}from"./aws/sts/assumeRoot.js";import{parseAccountsConfiguration as dt,flattenAccountsToEnvironments as Pt,extractAllAccountNames as Ct,accountsConfigToOUTree as Nt,isStringArray as ft,isAccountsConfig as gt,isOuOnlyAccountBucket as xt,OU_ONLY_ACCOUNT_BUCKETS as Dt}from"./orchestration/index.js";import{runOpenNextBuild as Lt}from"./orchestration/index.js";import{runOrganisationSetup as kt,ORG_SETUP_PHASES as yt}from"./orchestration/index.js";import{FrameworkRegistry as Mt}from"./orchestration/index.js";import{openNextBuilder as Yt,dockerBuilder as bt}from"./orchestration/index.js";import{StepRegistry as ht,getDestroyStepId as Kt}from"./steps/index.js";export{W as APPLICATION_DEPLOY_ORDER,Z as APPLICATION_DESTROY_ORDER,z as APPLICATION_STACKS,xe as ApplicationError,Sr as ApplicationStackService,Or as AuthError,ur as AwsError,pr as BaseServiceError,c as CASCADE_ACCOUNT_STATUSES,n as CASCADE_PHASES,fe as CDK_NO_STACKS_MATCH,Ke as CdkArgumentBuilder,ir as CdkContextBuilder,lr as CdkError,Ve as CdkEventMonitor,Ge as CdkProcessManager,he as CdkService,Ze as CloudFormationError,be as CloudFormationEventMonitor,We as CloudFormationService,Pr as ConfigError,Xe as DEFAULT_DEPLOY_TIMEOUT_MS,s as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,i as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,a as DEPLOYMENT_EVENT_STATUS_REASON_MAX,E as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,o as DEPLOYMENT_EVENT_TYPES,Rr as DeploymentError,t as DeploymentEventSchema,er as EcsError,$e as EcsService,rr as EcsServiceResolver,dr as FileSystemError,Ie as FjallStateFileSchema,Mt as FrameworkRegistry,ge as INFRASTRUCTURE_FILENAME,w as INFRASTRUCTURE_STEP_NAMES,j as INFRA_STEP_NAME,Rt as MAX_ROOT_SESSION_SECONDS,mr as NetworkError,$ as OPENNEXT_DEPLOY_ORDER,ee as OPENNEXT_DESTROY_ORDER,oe as OPENNEXT_PARALLEL_GROUPS,de as OPENNEXT_PATTERNS,J as ORGANISATION_TYPES,yt as ORG_SETUP_PHASES,st as ORG_TRAIL_BUCKET_OUTPUT_KEY,Dt as OU_ONLY_ACCOUNT_BUCKETS,re as PARALLEL_DEPLOY_GROUPS,te as PARALLEL_DESTROY_GROUPS,ie as PARALLEL_OPERATION_TYPES,sr as PROGRESS_MESSAGES,q as ProgressReporter,K as ROOT_ACCESS_FEATURES,ut as ROOT_TASK_POLICY_ARNS,G as RootAccessEnablementError,B as SECURITY_SERVICE_PRINCIPALS,C as SERVICE_PRINCIPALS,Ne as STACK_FAILED_STATE_PATTERN,Ce as STACK_NOT_FOUND_PATTERN,H as STEP_IDS,X as STEP_NAMES,A as SimpleAwsProvider,ht as StepRegistry,Et as TRAIL_BUCKET_OUTPUT_KEY,nt as TRAIL_KEY_ARN_OUTPUT_KEY,or as TemplateHashError,tr as TemplateHashService,_r as ValidationError,Nt as accountsConfigToOUTree,v as activateCostAllocationTags,f as activateTrustedAccess,_t as assumeRootForTask,Qr as buildAccountRegionPairs,y as buildAccountToOUMap,jr as buildRegionList,nr as buildStepContextBuildConfig,O as buildTargetSetUnreadyAdvisory,_ as buildTargetUnreadyAdvisory,qr as cascadeHomeRegion,zr as cascadeOperationKey,M as checkIdentityCentreStatus,T as checkTargetReadiness,cr as convertCloudFormationOutputsToRecord,L as createAccount,ke as createEmptyState,kr as createSequencedCallbacks,ot as decideNextTransition,at as decommissionMemberTrailStorage,ye as deleteStateFile,Kr as deploy,Pe as deriveResourcesFromManifestStacks,m as describeOrganisation,p as describeTargetReadinessReason,Vr as destroy,bt as dockerBuilder,ar as emitProgress,h as enableCentralisedRootAccess,g as enableIpamDelegatedAdmin,d as enablePolicyTypes,N as enableRamSharing,P as enableServiceAccess,R as ensureOrganisationExists,U as ensureOrganisationalUnitsExist,Ct as extractAllAccountNames,F as extractErrorName,Yr as failure,vr as fileExists,fr as filterDangerousEnvVars,I as findAccount,Pt as flattenAccountsToEnvironments,je as formatInfrastructureError,ce as getApplicationDeployOrder,Se as getApplicationDestroyOrder,Ae as getApplicationStackName,ue as getApplicationStepId,Oe as getApplicationStepName,Kt as getDestroyStepId,le as getOrganisationStackName,Ee as getParallelDeployGroups,ne as getParallelDestroyGroups,qe as getSourceContext,Me as getStateFilePath,Qe as getStructuralHint,ze as hasCdkDifferences,Lr as hasDockerfile,gt as isAccountsConfig,ae as isApplicationOperation,Te as isApplicationStack,we as isCdkError,Br as isFailure,Y as isOULeaf,me as isOpenNextPattern,se as isOrganisationOperation,xt as isOuOnlyAccountBucket,pe as isQuarantineDetail,_e as isRetainedBucketsDetail,Ot as isRootTaskPolicyArn,ft as isStringArray,br as isSuccess,D as listAccounts,gr as maskSensitiveOutput,rt as mergeReconciledProviderAccounts,Yt as openNextBuilder,dt as parseAccountsConfiguration,Er as parseBuildPhase,Je as parseDiffOutput,xr as parseShellArgs,Xr as partitionAccounts,k as placeAccountsInOUs,Zr as projectAccountRows,Wr as projectScalarSummary,Le as readStateFile,et as reconcileProviderAccounts,it as reconcileTrailMigration,b as registerSecurityDelegates,Lt as runOpenNextBuild,kt as runOrganisationSetup,Dr as sleep,He as startStackMonitoring,Fe as stubCallerIdentity,Fr as success,Re as toPascalCase,Cr as toServiceError,St as unlockBucket,At as unlockQueue,x as updateBackupGlobalSettings,ve as updateTemplateHash,Tt as verifyOrgTrailDelivery,De as wrapApplicationError,Ue as writeStateFile};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{join as
|
|
1
|
+
import{join as $}from"path";import{CloudFormationClient as q}from"@aws-sdk/client-cloudformation";import{EC2Client as z}from"@aws-sdk/client-ec2";import{success as U,failure as m}from"@fjall/generator";import{logger as E}from"@fjall/util/logger";import{maskSensitiveOutput as S,toPascalCase as Y}from"@fjall/util";import{parseDockerServicesFromManifest as J}from"@fjall/util/manifest";import{stubCallerIdentity as Q}from"../types/deployment/index.js";import{getApplicationDeployOrder as V,getApplicationStackName as X,getApplicationStepName as F,getApplicationStepId as H,APPLICATION_STACKS as j}from"../types/operations.js";import{CdkContextBuilder as Z}from"../services/supporting/CdkContextBuilder.js";import{buildParamsContext as ee,bootstrapOrFail as te}from"./contextHelpers.js";import{runDetectionPipeline as oe}from"./detectionPipeline.js";import{STEP_IDS as O,STEP_NAMES as re}from"../types/stepDefinitions.js";import{StepRegistry as ne}from"../steps/stepRegistry.js";import{checkTargetReadiness as ae}from"../aws/targetReadiness.js";import{cascadeHomeRegion as ie}from"./cascadeHelpers.js";import{withStepLifecycle as se}from"./stepLifecycle.js";import{DOCKER_BUILD_STEP_NAME as G,runDockerBuild as ce}from"./dockerBuildHelper.js";import{getParallelPhase2Stacks as de,deployParallelPhase as le,deployStackSequential as pe,runDockerPreCompute as ue,createBuildCallbacks as fe}from"./applicationDeployHelpers.js";import{deployCodeOnly as ge}from"./codeOnlyDeploy.js";const R="applicationDeploy";function me(i){const a=Object.entries(i);if(a.length===0)return;const r={};for(const[t,s]of a){const b=`${Y(t)}ImageTag`;r[b]=s}return r}async function Me(i,a,r){const{callbacks:t,options:s}=i,b=Date.now(),D=Z.buildDeploymentContext({deployType:"application",target:r.appName,path:r.path,region:a.awsProvider.getRegion(),callerIdentity:Q(a.awsProvider.getAccountId()),...ee({orgConfig:i.orgConfig,identity:i.identity,skipOidc:i.options?.skipOidc})},{verbose:s?.verbose,infraOnly:s?.infraOnly},i.orgConfig),p=a.frameworkRegistry.resolve({appPath:r.path});let w;const k=!!s?.imageTag;if(p&&!k){w=p.builder.plan({appPath:r.path},p.detection);const e=fe(t),o=await p.builder.build(r.path,w,e,{skipBuild:s?.skipBuild,infraOnly:s?.infraOnly});if(!o.success){const n=new Error(S(o.error.message));return t.onError?.(n),m(n)}}if(s?.deployOnly||k){t.onLog?.(k?`Rollback mode \u2014 rolling to image tag ${s?.imageTag}`:"Deploy-only mode \u2014 skipping infrastructure pipeline","info");const e=$(r.path,"cdk.out"),o=J(e),n=o.length>0,l=p?.detection.hasDockerfile===!0,d=n||l;E.debug(R,"Deploy-only branch entered",{isRollback:k,imageTag:s?.imageTag,appName:r.appName,appPath:r.path,cdkOutPath:e,dockerProviderAvailable:i.dockerProvider!==void 0,builderName:p?.builder.name,hasDockerfileFromManifest:n,hasDockerfileFromDisk:l,hasDockerfile:d,manifestDockerServiceCount:o.length,manifestDockerPaths:o.map(u=>u.docker.path)}),!n&&!l&&t.onLog?.("No Dockerfile detected via manifest or appPath \u2014 skipping Docker build. If this app uses a cross-repo Dockerfile, ensure a full deploy has run first to populate cdk.out/fjall-manifest.json.","warn");let f={};if(!k&&i.dockerProvider!==void 0&&d){E.debug(R,"Running Docker build before code-only deploy",{source:n?"manifest":"disk"});const u=await ce(i,a,r,t);if(!u.success)return m(u.error);f=u.data}else E.debug(R,"Skipping Docker build",{reason:k?"rollback":i.dockerProvider===void 0?"no dockerProvider":"no Dockerfile detected"});return ge(i,a,r,f)}t.onLog?.("Analysing infrastructure\u2026","info");const T=await oe(r,a,D,t);if(!T.success){const e=new Error(S(T.error.message));return t.onError?.(e),m(e)}const c=T.data;try{await t.onDetectionComplete?.({...c,builderName:p?.builder.name??"unknown"})}catch(e){const o=e instanceof Error?e.message:String(e),n=new Error(S(o));return t.onError?.(n),m(n)}const K={deploymentType:"application",operation:"deploy",deployOnly:!1,infraOnly:s?.infraOnly??!1,hasDockerfile:c.hasDockerfile,pattern:c.pattern,resources:c.resources,...p&&{builderName:p.builder.name}},N=ne.getSteps(K),A=N.findIndex(e=>e.id===O.TARGET_READINESS),I=await se(t,{stepId:O.TARGET_READINESS,stepName:re.TARGET_READINESS,...A>=0&&{stepIndex:A,totalSteps:N.length}},async()=>{if(s?.skipReadinessCheck)return t.onLog?.("Skipping target readiness check (--skip-readiness-check)","warn"),{kind:"skipped",data:void 0};const e=a.awsProvider.getAccountId(),o=i.orgConfig?.providerAccounts.find(f=>f.id===e)?.name,n=a.awsProvider.getCredentials(),l=ie(i.orgConfig),d=await ae({cloudFormation:a.awsProvider.getClient(q),ec2:new z({region:l,...n!==void 0&&{credentials:n}})},{id:e,...o!==void 0&&{name:o}},a.awsProvider.getRegion(),i.orgConfig,i.abortSignal);return d.success?d.data.ready?{kind:"completed",data:void 0}:{kind:"error",error:new Error(S(d.data.advisory))}:{kind:"error",error:new Error(S(d.error.message))}});if(!I.success)return I;const g=w?w.deployOrder:V({pattern:c.pattern,resources:c.resources}),h=g.length;if(!c.hasDifferences&&!s?.force){t.onLog?.("No infrastructure changes detected","info");const e=c.hasDockerfile&&i.dockerProvider!==void 0&&g.includes(j.COMPUTE);for(let n=0;n<g.length;n++){const l=g[n];e&&l===j.COMPUTE&&(t.onStepStart?.(O.DOCKER_OPERATIONS,G),t.onStepComplete?.(O.DOCKER_OPERATIONS,G,"skipped"));const d=H(l,"deploy"),f=F(l,"deploy");t.onStepStart?.(d,f,n,h),t.onStepComplete?.(d,f,"skipped",n,h)}const o=await a.stackService.resolveWebsiteUrl(r.appName);return U({target:r.appName,deploymentType:"application",outputs:o?{websiteUrl:o}:void 0,noChanges:!0,durationMs:Date.now()-b})}const v=await te(a,D,t);if(!v.success)return v;const C={},P=new Map;for(let e=0;e<g.length;e++){const o=g[e],n=X(r.appName,o),l=H(o,"deploy"),d=F(o,"deploy");if(!(c.stackChanges.get(n)??!0)&&!s?.force){t.onStepStart?.(l,d,e,h),t.onLog?.(`Skipping ${o} \u2014 no changes detected`,"info"),t.onStepComplete?.(l,d,"skipped",e,h);continue}const u=de(g,e,c.stackChanges,r.appName,s?.force);if(u.length>=2){const B=await le(u,r,a,D,t,e,h,c,C,P);if(!B.success)return m(B.error);e+=u.length-1;continue}const y=await ue(o,i,a,r,t,c.hasDockerfile);if(y!==null&&!y.success)return m(y.error);const W=y!==null&&y.success?y.data.contentHashTagsByService:{},L=me(W),x=await pe(o,a,D,t,e,h,C,L!==void 0?{parameters:L}:void 0);if(!x.success)return m(x.error);const M=c.currentHashes.get(n);M&&P.set(n,M)}if(P.size>0){const e=await a.hashService.updateStateAfterDeploy(r.path,P);if(!e.success){const o=S(e.error.message);E.debug(R,"Failed to update state file",{error:o}),t.onLog?.(`Warning: failed to update state file \u2014 next deploy may re-deploy unchanged stacks: ${o}`,"warn")}}const _=await a.stackService.resolveWebsiteUrl(r.appName);return _&&(C.websiteUrl=_),U({target:r.appName,deploymentType:"application",outputs:Object.keys(C).length>0?C:void 0,durationMs:Date.now()-b})}export{Me as deployApplication};
|