-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into benisrae/eks-fix-version-update
- Loading branch information
Showing
22 changed files
with
2,257 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
packages/@aws-cdk/aws-backup/lib/backupable-resources-collector.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import * as dynamodb from '@aws-cdk/aws-dynamodb'; | ||
import * as ec2 from '@aws-cdk/aws-ec2'; | ||
import * as efs from '@aws-cdk/aws-efs'; | ||
import * as rds from '@aws-cdk/aws-rds'; | ||
import { IAspect, IConstruct, Stack } from '@aws-cdk/core'; | ||
|
||
export class BackupableResourcesCollector implements IAspect { | ||
public readonly resources: string[] = []; | ||
|
||
public visit(node: IConstruct) { | ||
if (node instanceof efs.CfnFileSystem) { | ||
this.resources.push(Stack.of(node).formatArn({ | ||
service: 'elasticfilesystem', | ||
resource: 'file-system', | ||
resourceName: node.ref, | ||
})); | ||
} | ||
|
||
if (node instanceof dynamodb.CfnTable) { | ||
this.resources.push(Stack.of(node).formatArn({ | ||
service: 'dynamodb', | ||
resource: 'table', | ||
resourceName: node.ref, | ||
})); | ||
} | ||
|
||
if (node instanceof ec2.CfnInstance) { | ||
this.resources.push(Stack.of(node).formatArn({ | ||
service: 'ec2', | ||
resource: 'instance', | ||
resourceName: node.ref, | ||
})); | ||
} | ||
|
||
if (node instanceof ec2.CfnVolume) { | ||
this.resources.push(Stack.of(node).formatArn({ | ||
service: 'ec2', | ||
resource: 'volume', | ||
resourceName: node.ref, | ||
})); | ||
} | ||
|
||
if (node instanceof rds.CfnDBInstance) { | ||
this.resources.push(Stack.of(node).formatArn({ | ||
service: 'rds', | ||
resource: 'db', | ||
sep: ':', | ||
resourceName: node.ref, | ||
})); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,8 @@ | ||
export * from './vault'; | ||
export * from './plan'; | ||
export * from './rule'; | ||
export * from './selection'; | ||
export * from './resource'; | ||
|
||
// AWS::Backup CloudFormation Resources: | ||
export * from './backup.generated'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
import { Construct, IResource, Lazy, Resource } from '@aws-cdk/core'; | ||
import { CfnBackupPlan } from './backup.generated'; | ||
import { BackupPlanRule } from './rule'; | ||
import { BackupSelection, BackupSelectionOptions } from './selection'; | ||
import { BackupVault, IBackupVault } from './vault'; | ||
|
||
/** | ||
* A backup plan | ||
*/ | ||
export interface IBackupPlan extends IResource { | ||
/** | ||
* The identifier of the backup plan. | ||
* | ||
* @attribute | ||
*/ | ||
readonly backupPlanId: string; | ||
} | ||
|
||
/** | ||
* Properties for a BackupPlan | ||
*/ | ||
export interface BackupPlanProps { | ||
/** | ||
* The display name of the backup plan. | ||
* | ||
* @default - A CDK generated name | ||
*/ | ||
readonly backupPlanName?: string; | ||
|
||
/** | ||
* The backup vault where backups are stored | ||
* | ||
* @default - use the vault defined at the rule level. If not defined a new | ||
* common vault for the plan will be created | ||
*/ | ||
readonly backupVault?: IBackupVault; | ||
|
||
/** | ||
* Rules for the backup plan. Use `addRule()` to add rules after | ||
* instantiation. | ||
* | ||
* @default - use `addRule()` to add rules | ||
*/ | ||
readonly backupPlanRules?: BackupPlanRule[]; | ||
} | ||
|
||
/** | ||
* A backup plan | ||
*/ | ||
export class BackupPlan extends Resource implements IBackupPlan { | ||
/** | ||
* Import an existing backup plan | ||
*/ | ||
public static fromBackupPlanId(scope: Construct, id: string, backupPlanId: string): IBackupPlan { | ||
class Import extends Resource implements IBackupPlan { | ||
public readonly backupPlanId = backupPlanId; | ||
} | ||
return new Import(scope, id); | ||
} | ||
|
||
/** | ||
* Daily with 35 day retention | ||
*/ | ||
public static daily35DayRetention(scope: Construct, id: string, backupVault?: IBackupVault) { | ||
const plan = new BackupPlan(scope, id, { backupVault }); | ||
plan.addRule(BackupPlanRule.daily()); | ||
return plan; | ||
} | ||
|
||
/** | ||
* Daily and monthly with 1 year retention | ||
*/ | ||
public static dailyMonthly1YearRetention(scope: Construct, id: string, backupVault?: IBackupVault) { | ||
const plan = new BackupPlan(scope, id, { backupVault }); | ||
plan.addRule(BackupPlanRule.daily()); | ||
plan.addRule(BackupPlanRule.monthly1Year()); | ||
return plan; | ||
} | ||
|
||
/** | ||
* Daily, weekly and monthly with 5 year retention | ||
*/ | ||
public static dailyWeeklyMonthly5YearRetention(scope: Construct, id: string, backupVault?: IBackupVault) { | ||
const plan = new BackupPlan(scope, id, { backupVault }); | ||
plan.addRule(BackupPlanRule.daily()); | ||
plan.addRule(BackupPlanRule.weekly()); | ||
plan.addRule(BackupPlanRule.monthly5Year()); | ||
return plan; | ||
} | ||
|
||
/** | ||
* Daily, weekly and monthly with 7 year retention | ||
*/ | ||
public static dailyWeeklyMonthly7YearRetention(scope: Construct, id: string, backupVault?: IBackupVault) { | ||
const plan = new BackupPlan(scope, id, { backupVault }); | ||
plan.addRule(BackupPlanRule.daily()); | ||
plan.addRule(BackupPlanRule.weekly()); | ||
plan.addRule(BackupPlanRule.monthly7Year()); | ||
return plan; | ||
} | ||
|
||
public readonly backupPlanId: string; | ||
|
||
/** | ||
* The ARN of the backup plan | ||
* | ||
* @attribute | ||
*/ | ||
public readonly backupPlanArn: string; | ||
|
||
/** | ||
* Version Id | ||
* | ||
* @attribute | ||
*/ | ||
public readonly versionId: string; | ||
|
||
private readonly rules: CfnBackupPlan.BackupRuleResourceTypeProperty[] = []; | ||
private _backupVault?: IBackupVault; | ||
|
||
constructor(scope: Construct, id: string, props: BackupPlanProps = {}) { | ||
super(scope, id); | ||
|
||
const plan = new CfnBackupPlan(this, 'Resource', { | ||
backupPlan: { | ||
backupPlanName: props.backupPlanName || id, | ||
backupPlanRule: Lazy.anyValue({ produce: () => this.rules }, { omitEmptyArray: true }), | ||
}, | ||
}); | ||
|
||
this.backupPlanId = plan.attrBackupPlanId; | ||
this.backupPlanArn = plan.attrBackupPlanArn; | ||
this.versionId = plan.attrVersionId; | ||
|
||
this._backupVault = props.backupVault; | ||
|
||
for (const rule of props.backupPlanRules || []) { | ||
this.addRule(rule); | ||
} | ||
} | ||
|
||
/** | ||
* Adds a rule to a plan | ||
* | ||
* @param rule the rule to add | ||
*/ | ||
public addRule(rule: BackupPlanRule) { | ||
let vault: IBackupVault; | ||
if (rule.props.backupVault) { | ||
vault = rule.props.backupVault; | ||
} else if (this._backupVault) { | ||
vault = this._backupVault; | ||
} else { | ||
this._backupVault = new BackupVault(this, 'Vault'); | ||
vault = this._backupVault; | ||
} | ||
|
||
this.rules.push({ | ||
completionWindowMinutes: rule.props.completionWindow?.toMinutes(), | ||
lifecycle: (rule.props.deleteAfter || rule.props.moveToColdStorageAfter) && { | ||
deleteAfterDays: rule.props.deleteAfter?.toDays(), | ||
moveToColdStorageAfterDays: rule.props.moveToColdStorageAfter?.toDays(), | ||
}, | ||
ruleName: rule.props.ruleName ?? `${this.node.id}Rule${this.rules.length}`, | ||
scheduleExpression: rule.props.scheduleExpression?.expressionString, | ||
startWindowMinutes: rule.props.startWindow?.toMinutes(), | ||
targetBackupVault: vault.backupVaultName, | ||
}); | ||
} | ||
|
||
/** | ||
* The backup vault where backups are stored if not defined at | ||
* the rule level | ||
*/ | ||
public get backupVault(): IBackupVault { | ||
if (!this._backupVault) { | ||
// This cannot happen but is here to make TypeScript happy | ||
throw new Error('No backup vault!'); | ||
} | ||
|
||
return this._backupVault; | ||
} | ||
|
||
/** | ||
* Adds a selection to this plan | ||
*/ | ||
public addSelection(id: string, options: BackupSelectionOptions): BackupSelection { | ||
return new BackupSelection(this, id, { | ||
backupPlan: this, | ||
...options, | ||
}); | ||
} | ||
|
||
protected validate() { | ||
if (this.rules.length === 0) { | ||
return ['A backup plan must have at least 1 rule.']; | ||
} | ||
|
||
return []; | ||
} | ||
} |
Oops, something went wrong.