Skip to content

Commit

Permalink
fix(deadline): User Data execution on Worker Nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
Eugene Kozlov committed Nov 18, 2020
1 parent 9387f60 commit 0f526b5
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,20 @@
IVpc,
Port
)
from aws_cdk.aws_s3_assets import (
Asset
)

from aws_rfdk import (
HealthMonitor,
)
from aws_rfdk.deadline import (
InstanceUserDataProvider,
IRenderQueue,
WorkerInstanceFleet,
)

import os

@dataclass
class ComputeTierProps(StackProps):
Expand All @@ -43,6 +48,22 @@ class ComputeTierProps(StackProps):
# The bastion host to allow connection to Worker nodes.
bastion: Optional[BastionHostLinux] = None

class UserDataProvider(InstanceUserDataProvider):
def pre_cloud_watch_agent(self, host) -> None:
host.user_data.add_commands("echo preCloudWatchAgent")
def pre_deadline_configuration(self, host) -> None:
host.user_data.add_commands("echo preDeadlineConfiguration")
def post_worker_launch(self, host) -> None:
host.user_data.add_commands("echo postWorkerLaunch")
test_script=Asset(host.node.scope, "SampleAsset",
path=os.path.join(os.getcwd(), "..", "scripts", "configure_worker.sh")
)
test_script.grant_read(host)
local_path = host.user_data.add_s3_download_command(
bucket=test_script.bucket,
bucket_key=test_script.s3_object_key
)
host.user_data.add_execute_file_command(file_path=local_path)

class ComputeTier(Stack):
"""
Expand Down Expand Up @@ -78,6 +99,7 @@ def __init__(self, scope: Construct, stack_id: str, *, props: ComputeTierProps,
worker_machine_image=props.worker_machine_image,
health_monitor=self.health_monitor,
key_name=props.key_pair_name,
user_data_provider=UserDataProvider()
)

if props.bastion:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mkdir test_dir
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
} from '@aws-cdk/aws-ec2';
import * as cdk from '@aws-cdk/core';
import {
IHost,
InstanceUserDataProvider,
IRenderQueue,
IWorkerFleet,
WorkerInstanceFleet,
Expand All @@ -19,6 +21,8 @@ import {
HealthMonitor,
IHealthMonitor,
} from 'aws-rfdk';
import { Asset } from '@aws-cdk/aws-s3-assets';
import * as path from 'path'

/**
* Properties for {@link ComputeTier}.
Expand Down Expand Up @@ -50,6 +54,33 @@ export interface ComputeTierProps extends cdk.StackProps {
readonly bastion?: BastionHostLinux;
}

class UserDataProvider extends InstanceUserDataProvider {
preCloudWatchAgent(host: IHost): void {
host.userData.addCommands('echo preCloudWatchAgent');
}
preDeadlineConfiguration(host: IHost): void {
host.userData.addCommands('echo preDeadlineConfiguration');
}
postWorkerLaunch(host: IHost): void {
host.userData.addCommands('echo postWorkerLaunch');
if (host.node.scope != undefined) {
const testScript = new Asset(
host.node.scope as cdk.Construct,
'SampleAsset',
{path: path.join(__dirname, '..', 'configure_worker.sh')},
);
testScript.grantRead(host);
const localPath = host.userData.addS3DownloadCommand({
bucket: testScript.bucket,
bucketKey: testScript.s3ObjectKey,
});
host.userData.addExecuteFileCommand({
filePath: localPath,
})
}
}
}

/**
* The computer tier consists of raw compute power. For a Deadline render farm,
* this will be the fleet of Worker nodes that render Deadline jobs.
Expand Down Expand Up @@ -88,6 +119,7 @@ export class ComputeTier extends cdk.Stack {
workerMachineImage: props.workerMachineImage,
healthMonitor: this.healthMonitor,
keyName: props.keyPairName,
userDataProvider: new UserDataProvider(),
});

if (props.bastion) {
Expand Down
26 changes: 25 additions & 1 deletion packages/aws-rfdk/lib/deadline/lib/worker-configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,26 @@ import {
Version,
} from './version';

/**
* Provider for adding user data scripts
*/
export interface IInstanceUserDataProvider {
// Method that is invoked before configuration Cloud Watch Agent.
preCloudWatchAgent(host: IHost): void;
// Method that is invoked before Deadline worker and renderqueue configuration .
preDeadlineConfiguration(host: IHost): void;
// Method that is invoked after all configuration is done and worker started.
postWorkerLaunch(host: IHost): void;
}

export class InstanceUserDataProvider implements IInstanceUserDataProvider{
preCloudWatchAgent(_host: IHost): void {
}
preDeadlineConfiguration(_host: IHost): void {
}
postWorkerLaunch(_host: IHost): void {
}
}
/**
* Configuration settings for Deadline Workers
*/
Expand Down Expand Up @@ -86,6 +106,8 @@ export interface WorkerInstanceConfigurationProps {
* @default The Worker is assigned the default settings as outlined in the WorkerSettings interface.
*/
readonly workerSettings?: WorkerSettings;

readonly userDataProvider?: IInstanceUserDataProvider;
}

/**
Expand All @@ -105,12 +127,14 @@ export interface WorkerInstanceConfigurationProps {
export class WorkerInstanceConfiguration extends Construct {
constructor(scope: Construct, id: string, props: WorkerInstanceConfigurationProps) {
super(scope, id);

props.userDataProvider?.preCloudWatchAgent(props.worker);
if (props.cloudwatchLogSettings) {
this.configureCloudWatchLogStream(props.worker, id, props.cloudwatchLogSettings);
}
props.userDataProvider?.preDeadlineConfiguration(props.worker);
props.renderQueue?.configureClientInstance({ host: props.worker});
this.configureWorkerSettings(props.worker, id, props.workerSettings);
props.userDataProvider?.postWorkerLaunch(props.worker);
}

/**
Expand Down
4 changes: 4 additions & 0 deletions packages/aws-rfdk/lib/deadline/lib/worker-fleet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import {
} from './render-queue';
import { Version } from './version';
import {
IInstanceUserDataProvider,
WorkerInstanceConfiguration,
WorkerSettings,
} from './worker-configuration';
Expand Down Expand Up @@ -189,6 +190,8 @@ export interface WorkerInstanceFleetProps extends WorkerSettings {
* @default The default devices of the provided ami will be used.
*/
readonly blockDevices?: BlockDevice[];

readonly userDataProvider?: IInstanceUserDataProvider;
}

/**
Expand Down Expand Up @@ -449,6 +452,7 @@ export class WorkerInstanceFleet extends WorkerInstanceFleetBase {
},
renderQueue: props.renderQueue,
workerSettings: props,
userDataProvider: props.userDataProvider,
});

// Updating the user data with successful cfn-signal commands.
Expand Down
4 changes: 2 additions & 2 deletions packages/aws-rfdk/lib/deadline/test/asset-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ export const RQ_CONNECTION_ASSET = {
};

export const VERSION_QUERY_ASSET = {
Bucket: stringLike('AssetParameters*S3Bucket6ABF873D'),
Key: stringLike('AssetParameters*S3VersionKey5A5FE29C'),
Bucket: stringLike('AssetParameters*S3Bucket978C4A04'),
Key: stringLike('AssetParameters*S3VersionKeyFFE15274'),
};
38 changes: 38 additions & 0 deletions packages/aws-rfdk/lib/deadline/test/worker-fleet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ import {
escapeTokenRegex,
} from '../../core/test/token-regex-helpers';
import {
IHost,
InstanceUserDataProvider,
IRenderQueue,
RenderQueue,
Repository,
Expand Down Expand Up @@ -92,12 +94,18 @@ beforeEach(() => {

test('default worker fleet is created correctly', () => {
// WHEN
class userDataProvider extends InstanceUserDataProvider{
preCloudWatchAgent(host: IHost) {
host.userData.addCommands('mkdir test_dir');
}
}
const fleet = new WorkerInstanceFleet(wfstack, 'workerFleet', {
vpc,
workerMachineImage: new GenericWindowsImage({
'us-east-1': 'ami-any',
}),
renderQueue,
userDataProvider: new userDataProvider(),
});

// THEN
Expand Down Expand Up @@ -1461,6 +1469,36 @@ describe('HealthMonitor Tests', () => {
TargetType: 'instance',
}));
});

test('UserData is added', () => {
// WHEN
class UserDataProvider extends InstanceUserDataProvider {
preCloudWatchAgent(host: IHost): void {
host.userData.addCommands('echo preCloudWatchAgent');
}
preDeadlineConfiguration(host: IHost): void {
host.userData.addCommands('echo preDeadlineConfiguration');
}
postWorkerLaunch(host: IHost): void {
host.userData.addCommands('echo postWorkerLaunch');
}
}
const fleet = new WorkerInstanceFleet(wfstack, 'workerFleet', {
vpc,
workerMachineImage: new GenericWindowsImage({
'us-east-1': 'ami-any',
}),
renderQueue,
healthMonitor,
userDataProvider: new UserDataProvider(),
});
const userData = fleet.fleet.userData.render();

// THEN
expect(userData).toContain('echo preCloudWatchAgent');
expect(userData).toContain('echo preDeadlineConfiguration');
expect(userData).toContain('echo postWorkerLaunch');
});
});

describe('tagging', () => {
Expand Down
11 changes: 11 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10460,6 +10460,17 @@ ts-node@^8.0.2:
source-map-support "^0.5.17"
yn "3.1.1"

ts-node@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.0.0.tgz#e7699d2a110cc8c0d3b831715e417688683460b3"
integrity sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==
dependencies:
arg "^4.1.0"
diff "^4.0.1"
make-error "^1.1.1"
source-map-support "^0.5.17"
yn "3.1.1"

tsame@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/tsame/-/tsame-2.0.1.tgz#70410ddbefcd29c61e2d68549b3347b0444d613f"
Expand Down

0 comments on commit 0f526b5

Please sign in to comment.