Skip to content

Commit

Permalink
chore(cli): reorganize CLI code (#19324)
Browse files Browse the repository at this point in the history
Reorganize CLI code so that the `aws-auth` and `plugin` directories can
be (mostly) airlifted out. Any dependencies it has on surrounding code
is encoded in the `_env.ts` source file, which will do foreign imports.

The plugin subsystem used to call the context provider subsystem
directly--that's now inverted so that you don't have to lift the context
provider system out with it.


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
rix0rrr committed Mar 17, 2022
1 parent 9e17e4d commit 16d293d
Show file tree
Hide file tree
Showing 28 changed files with 1,129 additions and 1,084 deletions.
2,030 changes: 1,015 additions & 1,015 deletions packages/aws-cdk/THIRD_PARTY_LICENSES

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions packages/aws-cdk/lib/api/aws-auth/_env.ts
@@ -0,0 +1,17 @@
/**
* This file exists to expose and centralize some features that the files in this module expect from the surrounding
* CLI.
*
* The calls will be forwarded to whatever logging system is the "official" logging system for this CLI.
*
* Centralizing in this way makes it easy to copy/paste this directory out and have a single place to
* break dependencies and replace these functions.
*/

export { debug, warning, trace } from '../../logging';

import { cdkCacheDir } from '../../util/directories';

export function accountCacheDir() {
return cdkCacheDir();
}
5 changes: 2 additions & 3 deletions packages/aws-cdk/lib/api/aws-auth/account-cache.ts
@@ -1,7 +1,6 @@
import * as path from 'path';
import * as fs from 'fs-extra';
import { debug } from '../../logging';
import { cdkCacheDir } from '../../util/directories';
import { accountCacheDir, debug } from './_env';
import { Account } from './sdk-provider';

/**
Expand All @@ -22,7 +21,7 @@ export class AccountAccessKeyCache {
* @param filePath Path to the cache file
*/
constructor(filePath?: string) {
this.cacheFile = filePath || path.join(cdkCacheDir(), 'accounts_partitions.json');
this.cacheFile = filePath || path.join(accountCacheDir(), 'accounts_partitions.json');
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/aws-cdk/lib/api/aws-auth/awscli-compatible.ts
Expand Up @@ -5,7 +5,7 @@ import * as util from 'util';
import * as AWS from 'aws-sdk';
import * as fs from 'fs-extra';
import * as promptly from 'promptly';
import { debug } from '../../logging';
import { debug } from './_env';
import { PatchedSharedIniFileCredentials } from './aws-sdk-inifile';
import { SharedIniFile } from './sdk_ini_file';

Expand Down
Expand Up @@ -9,4 +9,4 @@ export function cached<A extends object, B>(obj: A, sym: symbol, fn: () => B): B
(obj as any)[sym] = fn();
}
return (obj as any)[sym];
}
}
6 changes: 3 additions & 3 deletions packages/aws-cdk/lib/api/aws-auth/credential-plugins.ts
@@ -1,6 +1,6 @@
import { debug } from '../../logging';
import { PluginHost } from '../../plugin';
import { CredentialProviderSource, Mode } from './credentials';
import { CredentialProviderSource, PluginHost } from '../plugin';
import { debug } from './_env';
import { Mode } from './credentials';

/**
* Cache for credential providers.
Expand Down
34 changes: 3 additions & 31 deletions packages/aws-cdk/lib/api/aws-auth/credentials.ts
@@ -1,31 +1,3 @@
import * as aws from 'aws-sdk';

export enum Mode {
ForReading,
ForWriting
}

/**
*/
export interface CredentialProviderSource {
name: string;

/**
* Whether the credential provider is even online
*
* Guaranteed to be called before any of the other functions are called.
*/
isAvailable(): Promise<boolean>;

/**
* Whether the credential provider can provide credentials for the given account.
*/
canProvideCredentials(accountId: string): Promise<boolean>;

/**
* Construct a credential provider for the given account and the given access mode
*
* Guaranteed to be called only if canProvideCredentails() returned true at some point.
*/
getProvider(accountId: string, mode: Mode): Promise<aws.Credentials>;
}
// Re-export this here because it used to be here and I don't want
// to change imports too much.
export { Mode } from '../plugin';
8 changes: 4 additions & 4 deletions packages/aws-cdk/lib/api/aws-auth/sdk-provider.ts
Expand Up @@ -4,11 +4,11 @@ import * as cxapi from '@aws-cdk/cx-api';
import * as AWS from 'aws-sdk';
import type { ConfigurationOptions } from 'aws-sdk/lib/config-base';
import * as fs from 'fs-extra';
import { debug, warning } from '../../logging';
import { cached } from '../../util/functions';
import { CredentialPlugins } from '../aws-auth/credential-plugins';
import { Mode } from '../aws-auth/credentials';
import { debug, warning } from './_env';
import { AwsCliCompatible } from './awscli-compatible';
import { cached } from './cached';
import { CredentialPlugins } from './credential-plugins';
import { Mode } from './credentials';
import { ISDK, SDK } from './sdk';


Expand Down
4 changes: 2 additions & 2 deletions packages/aws-cdk/lib/api/aws-auth/sdk.ts
@@ -1,8 +1,8 @@
import * as AWS from 'aws-sdk';
import type { ConfigurationOptions } from 'aws-sdk/lib/config-base';
import { debug, trace } from '../../logging';
import { cached } from '../../util/functions';
import { debug, trace } from './_env';
import { AccountAccessKeyCache } from './account-cache';
import { cached } from './cached';
import { Account } from './sdk-provider';

// We need to map regions to domain suffixes, and the SDK already has a function to do this.
Expand Down
11 changes: 11 additions & 0 deletions packages/aws-cdk/lib/api/plugin/_env.ts
@@ -0,0 +1,11 @@
/**
* This file exists to expose and centralize some features that the files in this module expect from the surrounding
* CLI.
*
* The calls will be forwarded to whatever logging system is the "official" logging system for this CLI.
*
* Centralizing in this way makes it easy to copy/paste this directory out and have a single place to
* break dependencies and replace these functions.
*/

export { error } from '../../logging';
Expand Up @@ -4,4 +4,4 @@ export interface ContextProviderPlugin {

export function isContextProviderPlugin(x: unknown): x is ContextProviderPlugin {
return typeof x === 'object' && !!x && !!(x as any).getValue;
}
}
31 changes: 31 additions & 0 deletions packages/aws-cdk/lib/api/plugin/credential-provider-source.ts
@@ -0,0 +1,31 @@
import * as aws from 'aws-sdk';

export enum Mode {
ForReading,
ForWriting
}

/**
*/
export interface CredentialProviderSource {
name: string;

/**
* Whether the credential provider is even online
*
* Guaranteed to be called before any of the other functions are called.
*/
isAvailable(): Promise<boolean>;

/**
* Whether the credential provider can provide credentials for the given account.
*/
canProvideCredentials(accountId: string): Promise<boolean>;

/**
* Construct a credential provider for the given account and the given access mode
*
* Guaranteed to be called only if canProvideCredentails() returned true at some point.
*/
getProvider(accountId: string, mode: Mode): Promise<aws.Credentials>;
}
3 changes: 3 additions & 0 deletions packages/aws-cdk/lib/api/plugin/index.ts
@@ -0,0 +1,3 @@
export * from './plugin';
export * from './context-provider-plugin';
export * from './credential-provider-source';
@@ -1,10 +1,9 @@
import { inspect } from 'util';
import * as chalk from 'chalk';

import { CredentialProviderSource } from './api/aws-auth/credentials';
import { registerPluginContextProvider } from './context-providers';
import { ContextProviderPlugin, isContextProviderPlugin } from './context-providers/provider';
import { error } from './logging';
import { error } from './_env';
import { ContextProviderPlugin, isContextProviderPlugin } from './context-provider-plugin';
import { CredentialProviderSource } from './credential-provider-source';

/**
* The basic contract for plug-ins to adhere to::
Expand Down Expand Up @@ -50,6 +49,8 @@ export class PluginHost {
*/
public readonly credentialProviderSources = new Array<CredentialProviderSource>();

public readonly contextProviderPlugins: Record<string, ContextProviderPlugin> = {};

constructor() {
if (PluginHost.instance && PluginHost.instance !== this) {
throw new Error('New instances of PluginHost must not be built. Use PluginHost.instance instead!');
Expand Down Expand Up @@ -87,6 +88,7 @@ export class PluginHost {
* @param source a new CredentialProviderSource to register.
*/
public registerCredentialProviderSource(source: CredentialProviderSource) {
// Forward to the right credentials-related plugin host
this.credentialProviderSources.push(source);
}

Expand Down Expand Up @@ -126,6 +128,6 @@ export class PluginHost {
if (!isContextProviderPlugin(provider)) {
throw new Error(`Object you gave me does not look like a ContextProviderPlugin: ${inspect(provider)}`);
}
registerPluginContextProvider(pluginProviderName, provider);
this.contextProviderPlugins[pluginProviderName] = provider;
}
}
2 changes: 1 addition & 1 deletion packages/aws-cdk/lib/cli.ts
Expand Up @@ -10,6 +10,7 @@ import { CloudFormationDeployments } from '../lib/api/cloudformation-deployments
import { StackSelector } from '../lib/api/cxapp/cloud-assembly';
import { CloudExecutable } from '../lib/api/cxapp/cloud-executable';
import { execProgram } from '../lib/api/cxapp/exec';
import { PluginHost } from '../lib/api/plugin';
import { ToolkitInfo } from '../lib/api/toolkit-info';
import { StackActivityProgress } from '../lib/api/util/cloudformation/stack-activity-monitor';
import { CdkToolkit } from '../lib/cdk-toolkit';
Expand All @@ -20,7 +21,6 @@ import { RequireApproval } from '../lib/diff';
import { availableInitLanguages, cliInit, printAvailableTemplates } from '../lib/init';
import { data, debug, error, print, setLogLevel } from '../lib/logging';
import { displayNotices, refreshNotices } from '../lib/notices';
import { PluginHost } from '../lib/plugin';
import { Command, Configuration, Settings } from '../lib/settings';
import * as version from '../lib/version';

Expand Down
2 changes: 1 addition & 1 deletion packages/aws-cdk/lib/context-providers/ami.ts
Expand Up @@ -2,8 +2,8 @@ import * as cxschema from '@aws-cdk/cloud-assembly-schema';
import * as cxapi from '@aws-cdk/cx-api';
import { Mode } from '../api/aws-auth/credentials';
import { SdkProvider } from '../api/aws-auth/sdk-provider';
import { ContextProviderPlugin } from '../api/plugin';
import { debug, print } from '../logging';
import { ContextProviderPlugin } from './provider';

/**
* Plugin to search AMIs for the current account
Expand Down
Expand Up @@ -2,8 +2,8 @@ import * as cxschema from '@aws-cdk/cloud-assembly-schema';
import * as cxapi from '@aws-cdk/cx-api';
import { Mode } from '../api/aws-auth/credentials';
import { SdkProvider } from '../api/aws-auth/sdk-provider';
import { ContextProviderPlugin } from '../api/plugin';
import { debug } from '../logging';
import { ContextProviderPlugin } from './provider';

/**
* Plugin to retrieve the Availability Zones for the current account
Expand Down
@@ -1,8 +1,8 @@
import * as cxapi from '@aws-cdk/cx-api';
import { Mode } from '../api/aws-auth/credentials';
import { SdkProvider } from '../api/aws-auth/sdk-provider';
import { ContextProviderPlugin } from '../api/plugin';
import { debug } from '../logging';
import { ContextProviderPlugin } from './provider';

/**
* Plugin to retrieve the Availability Zones for an endpoint service
Expand Down
2 changes: 1 addition & 1 deletion packages/aws-cdk/lib/context-providers/hosted-zones.ts
Expand Up @@ -2,8 +2,8 @@ import * as cxschema from '@aws-cdk/cloud-assembly-schema';
import * as cxapi from '@aws-cdk/cx-api';
import { Mode } from '../api/aws-auth/credentials';
import { SdkProvider } from '../api/aws-auth/sdk-provider';
import { ContextProviderPlugin } from '../api/plugin';
import { debug } from '../logging';
import { ContextProviderPlugin } from './provider';

export class HostedZoneContextProviderPlugin implements ContextProviderPlugin {

Expand Down
21 changes: 16 additions & 5 deletions packages/aws-cdk/lib/context-providers/index.ts
@@ -1,6 +1,8 @@
import * as cxschema from '@aws-cdk/cloud-assembly-schema';
import * as cxapi from '@aws-cdk/cx-api';
import { SdkProvider } from '../api';
import { PluginHost } from '../api/plugin';
import { ContextProviderPlugin } from '../api/plugin/context-provider-plugin';
import { replaceEnvPlaceholders } from '../api/util/placeholders';
import { debug } from '../logging';
import { Context, TRANSIENT_CONTEXT_KEY } from '../settings';
Expand All @@ -10,7 +12,6 @@ import { EndpointServiceAZContextProviderPlugin } from './endpoint-service-avail
import { HostedZoneContextProviderPlugin } from './hosted-zones';
import { KeyContextProviderPlugin } from './keys';
import { LoadBalancerContextProviderPlugin, LoadBalancerListenerContextProviderPlugin } from './load-balancers';
import { ContextProviderPlugin } from './provider';
import { SecurityGroupContextProviderPlugin } from './security-groups';
import { SSMContextProviderPlugin } from './ssm-parameters';
import { VpcNetworkContextProviderPlugin } from './vpcs';
Expand All @@ -35,10 +36,20 @@ export async function provideContextValues(
? `${PLUGIN_PROVIDER_PREFIX}:${(missingContext.props as cxschema.PluginContextQuery).pluginName}`
: missingContext.provider;

const factory = availableContextProviders[providerName];
if (!factory) {
// eslint-disable-next-line max-len
throw new Error(`Unrecognized context provider name: ${missingContext.provider}. You might need to update the toolkit to match the version of the construct library.`);
let factory;
if (providerName.startsWith(`${PLUGIN_PROVIDER_PREFIX}:`)) {
const plugin = PluginHost.instance.contextProviderPlugins[providerName.substring(PLUGIN_PROVIDER_PREFIX.length + 1)];
if (!plugin) {
// eslint-disable-next-line max-len
throw new Error(`Unrecognized plugin context provider name: ${missingContext.provider}.`);
}
factory = () => plugin;
} else {
factory = availableContextProviders[providerName];
if (!factory) {
// eslint-disable-next-line max-len
throw new Error(`Unrecognized context provider name: ${missingContext.provider}. You might need to update the toolkit to match the version of the construct library.`);
}
}

const provider = factory(sdk);
Expand Down
2 changes: 1 addition & 1 deletion packages/aws-cdk/lib/context-providers/keys.ts
Expand Up @@ -4,8 +4,8 @@ import * as AWS from 'aws-sdk';
import { PromiseResult } from 'aws-sdk/lib/request';
import { Mode } from '../api/aws-auth/credentials';
import { SdkProvider } from '../api/aws-auth/sdk-provider';
import { ContextProviderPlugin } from '../api/plugin';
import { debug } from '../logging';
import { ContextProviderPlugin } from './provider';

export class KeyContextProviderPlugin implements ContextProviderPlugin {

Expand Down
2 changes: 1 addition & 1 deletion packages/aws-cdk/lib/context-providers/load-balancers.ts
Expand Up @@ -3,7 +3,7 @@ import * as cxapi from '@aws-cdk/cx-api';
import * as AWS from 'aws-sdk';
import { Mode } from '../api/aws-auth/credentials';
import { SdkProvider } from '../api/aws-auth/sdk-provider';
import { ContextProviderPlugin } from './provider';
import { ContextProviderPlugin } from '../api/plugin';

/**
* Provides load balancer context information.
Expand Down
2 changes: 1 addition & 1 deletion packages/aws-cdk/lib/context-providers/security-groups.ts
Expand Up @@ -3,7 +3,7 @@ import * as cxapi from '@aws-cdk/cx-api';
import * as AWS from 'aws-sdk';
import { Mode } from '../api/aws-auth/credentials';
import { SdkProvider } from '../api/aws-auth/sdk-provider';
import { ContextProviderPlugin } from './provider';
import { ContextProviderPlugin } from '../api/plugin';

export class SecurityGroupContextProviderPlugin implements ContextProviderPlugin {
constructor(private readonly aws: SdkProvider) {
Expand Down
2 changes: 1 addition & 1 deletion packages/aws-cdk/lib/context-providers/ssm-parameters.ts
Expand Up @@ -3,8 +3,8 @@ import * as cxapi from '@aws-cdk/cx-api';
import * as AWS from 'aws-sdk';
import { Mode } from '../api/aws-auth/credentials';
import { SdkProvider } from '../api/aws-auth/sdk-provider';
import { ContextProviderPlugin } from '../api/plugin';
import { debug } from '../logging';
import { ContextProviderPlugin } from './provider';

/**
* Plugin to read arbitrary SSM parameter names
Expand Down
2 changes: 1 addition & 1 deletion packages/aws-cdk/lib/context-providers/vpcs.ts
Expand Up @@ -3,8 +3,8 @@ import * as cxapi from '@aws-cdk/cx-api';
import * as AWS from 'aws-sdk';
import { Mode } from '../api/aws-auth/credentials';
import { SdkProvider } from '../api/aws-auth/sdk-provider';
import { ContextProviderPlugin } from '../api/plugin';
import { debug } from '../logging';
import { ContextProviderPlugin } from './provider';

export class VpcNetworkContextProviderPlugin implements ContextProviderPlugin {

Expand Down
1 change: 0 additions & 1 deletion packages/aws-cdk/lib/index.ts
@@ -1,3 +1,2 @@
export * from './api';
export * from './plugin';
export { cli } from './cli';
2 changes: 1 addition & 1 deletion packages/aws-cdk/test/api/sdk-provider.test.ts
Expand Up @@ -5,8 +5,8 @@ import type { ConfigurationOptions } from 'aws-sdk/lib/config-base';
import * as promptly from 'promptly';
import * as uuid from 'uuid';
import { ISDK, Mode, SDK, SdkProvider } from '../../lib/api/aws-auth';
import { PluginHost } from '../../lib/api/plugin';
import * as logging from '../../lib/logging';
import { PluginHost } from '../../lib/plugin';
import * as bockfs from '../bockfs';
import { withMocked } from '../util';
import { FakeSts, RegisterRoleOptions, RegisterUserOptions } from './fake-sts';
Expand Down
2 changes: 1 addition & 1 deletion packages/aws-cdk/test/context-providers/generic.test.ts
@@ -1,4 +1,4 @@
import { PluginHost } from '../../lib';
import { PluginHost } from '../../lib/api/plugin';
import * as contextproviders from '../../lib/context-providers';
import { Context, TRANSIENT_CONTEXT_KEY } from '../../lib/settings';
import { MockSdkProvider } from '../util/mock-sdk';
Expand Down

0 comments on commit 16d293d

Please sign in to comment.