Skip to content

Commit 2563648

Browse files
committed
Small simplifications
1 parent 5338f1d commit 2563648

File tree

2 files changed

+71
-57
lines changed

2 files changed

+71
-57
lines changed

packages/@aws-cdk/aws-ec2/lib/user-data.ts

+58-49
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ export interface MultipartBodyOptions {
296296
/**
297297
* `Content-Transfer-Encoding` header specifying part encoding.
298298
*
299-
* @default undefined - don't add this header
299+
* @default undefined - body is not encoded
300300
*/
301301
readonly transferEncoding?: string;
302302

@@ -312,6 +312,15 @@ export interface MultipartBodyOptions {
312312
* The base class for all classes which can be used as {@link MultipartUserData}.
313313
*/
314314
export abstract class MultipartBody {
315+
/**
316+
* Content type for shell scripts
317+
*/
318+
public static readonly SHELL_SCRIPT = 'text/x-shellscript; charset="utf-8"';
319+
320+
/**
321+
* Content type for boot hooks
322+
*/
323+
public static readonly CLOUD_BOOTHOOK = 'text/cloud-boothook; charset="utf-8"';
315324

316325
/**
317326
* Constructs the new `MultipartBody` wrapping existing `UserData`. Modification to `UserData` are reflected
@@ -336,83 +345,72 @@ export abstract class MultipartBody {
336345
return new MultipartBodyRaw(opts);
337346
}
338347

339-
protected static readonly DEFAULT_CONTENT_TYPE = 'text/x-shellscript; charset="utf-8"';
340-
341-
/** The body of this MIME part. */
342-
public abstract get body(): string | undefined;
343-
344-
/** `Content-Type` header of this part */
345-
public abstract get contentType(): string;
348+
public constructor() {
349+
}
346350

347351
/**
348-
* `Content-Transfer-Encoding` header specifying part encoding.
352+
* Render body part as the string.
349353
*
350-
* @default undefined - don't add this header
354+
* Subclasses should not add leading nor trailing new line characters (\r \n)
351355
*/
352-
public abstract get transferEncoding(): string | undefined;
356+
public abstract renderBodyPart(): string[];
357+
}
353358

354-
public constructor() {
359+
/**
360+
* The raw part of multi-part user data, which can be added to {@link MultipartUserData}.
361+
*/
362+
class MultipartBodyRaw extends MultipartBody {
363+
public constructor(private readonly props: MultipartBodyOptions) {
364+
super();
355365
}
356366

357367
/**
358368
* Render body part as the string.
359-
*
360-
* Subclasses should not add leading nor trailing new line characters (\r \n)
361369
*/
362-
public renderBodyPart(): string {
370+
public renderBodyPart(): string[] {
363371
const result: string[] = [];
364372

365-
result.push(`Content-Type: ${this.contentType}`);
373+
result.push(`Content-Type: ${this.props.contentType}`);
366374

367-
if (this.transferEncoding != null) {
368-
result.push(`Content-Transfer-Encoding: ${this.transferEncoding}`);
375+
if (this.props.transferEncoding != null) {
376+
result.push(`Content-Transfer-Encoding: ${this.props.transferEncoding}`);
369377
}
370378
// One line free after separator
371379
result.push('');
372380

373-
if (this.body != null) {
374-
result.push(this.body);
381+
if (this.props.body != null) {
382+
result.push(this.props.body);
375383
// The new line added after join will be consumed by encapsulating or closing boundary
376384
}
377385

378-
return result.join('\n');
379-
}
380-
}
381-
382-
/**
383-
* The raw part of multi-part user data, which can be added to {@link MultipartUserData}.
384-
*/
385-
class MultipartBodyRaw extends MultipartBody {
386-
public readonly body: string | undefined;
387-
public readonly contentType: string;
388-
public readonly transferEncoding: string | undefined;
389-
390-
public constructor(props: MultipartBodyOptions) {
391-
super();
392-
393-
this.body = props.body;
394-
this.contentType = props.contentType;
386+
return result;
395387
}
396388
}
397389

398390
/**
399391
* Wrapper for `UserData`.
400392
*/
401393
class MultipartBodyUserDataWrapper extends MultipartBody {
394+
private readonly contentType: string;
402395

403-
public readonly contentType: string;
404-
public readonly transferEncoding: string | undefined;
405-
406-
public constructor(public readonly userData: UserData, contentType?: string) {
396+
public constructor(private readonly userData: UserData, contentType?: string) {
407397
super();
408398

409-
this.contentType = contentType || MultipartBody.DEFAULT_CONTENT_TYPE;
410-
this.transferEncoding = 'base64';
399+
this.contentType = contentType || MultipartBody.SHELL_SCRIPT;
411400
}
412401

413-
public get body(): string {
414-
// Wrap rendered user data with Base64 function, in case data contains non ASCII characters
415-
return Fn.base64(this.userData.render());
402+
/**
403+
* Render body part as the string.
404+
*/
405+
public renderBodyPart(): string[] {
406+
const result: string[] = [];
407+
408+
result.push(`Content-Type: ${this.contentType}`);
409+
result.push('Content-Transfer-Encoding: base64');
410+
result.push('');
411+
result.push(Fn.base64(this.userData.render()));
412+
413+
return result;
416414
}
417415
}
418416

@@ -469,10 +467,21 @@ export class MultipartUserData extends UserData {
469467
/**
470468
* Adds a part to the list of parts.
471469
*/
472-
public addPart(part: MultipartBody): this {
470+
public addPart(part: MultipartBody) {
473471
this.parts.push(part);
472+
}
474473

475-
return this;
474+
/**
475+
* Adds a multipart part based on a UserData object
476+
*
477+
* This is the same as calling:
478+
*
479+
* ```ts
480+
* multiPart.addPart(MultipartBody.fromUserData(userData, contentType));
481+
* ```
482+
*/
483+
public addUserDataPart(userData: UserData, contentType?: string) {
484+
this.addPart(MultipartBody.fromUserData(userData, contentType));
476485
}
477486

478487
public render(): string {
@@ -491,7 +500,7 @@ export class MultipartUserData extends UserData {
491500
// Add parts - each part starts with boundary
492501
this.parts.forEach(part => {
493502
resultArchive.push(`--${boundary}`);
494-
resultArchive.push(part.renderBodyPart());
503+
resultArchive.push(...part.renderBodyPart());
495504
});
496505

497506
// Add closing boundary

packages/@aws-cdk/aws-ec2/test/userdata.test.ts

+13-8
Original file line numberDiff line numberDiff line change
@@ -275,22 +275,27 @@ nodeunitShim({
275275

276276
'Linux user rendering multipart headers'(test: Test) {
277277
// GIVEN
278+
const stack = new Stack();
278279
const linuxUserData = ec2.UserData.forLinux();
279280
linuxUserData.addCommands('echo "Hello world"');
280281

281282
// WHEN
282283
const defaultRender1 = ec2.MultipartBody.fromUserData(linuxUserData);
283284
const defaultRender2 = ec2.MultipartBody.fromUserData(linuxUserData, 'text/cloud-boothook; charset=\"utf-8\"');
284285

285-
const defaultRender3 = ec2.MultipartBody.fromUserData(linuxUserData);
286-
287286
// THEN
288-
test.equals(defaultRender1.contentType, 'text/x-shellscript; charset=\"utf-8\"');
289-
test.equals(defaultRender2.contentType, 'text/cloud-boothook; charset=\"utf-8\"');
290-
test.equals(defaultRender3.contentType, 'text/x-shellscript; charset=\"utf-8\"');
291-
292-
test.equals(defaultRender1.transferEncoding, 'base64');
293-
test.equals(defaultRender2.transferEncoding, 'base64');
287+
expect(stack.resolve(defaultRender1.renderBodyPart())).toEqual([
288+
'Content-Type: text/x-shellscript; charset=\"utf-8\"',
289+
'Content-Transfer-Encoding: base64',
290+
'',
291+
{ 'Fn::Base64': '#!/bin/bash\necho \"Hello world\"' },
292+
]);
293+
expect(stack.resolve(defaultRender2.renderBodyPart())).toEqual([
294+
'Content-Type: text/cloud-boothook; charset=\"utf-8\"',
295+
'Content-Transfer-Encoding: base64',
296+
'',
297+
{ 'Fn::Base64': '#!/bin/bash\necho \"Hello world\"' },
298+
]);
294299

295300
test.done();
296301
},

0 commit comments

Comments
 (0)