Skip to content
This repository has been archived by the owner on Nov 12, 2019. It is now read-only.

Commit

Permalink
refactored handleRequestSpotInstanceResponse directly into requestSpo…
Browse files Browse the repository at this point in the history
…tInstance API Handler (#22)
  • Loading branch information
petemoore authored and jhford committed Jul 26, 2017
1 parent 739cced commit 9d33c6d
Show file tree
Hide file tree
Showing 3 changed files with 340 additions and 238 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/.nyc_output/
/coverage/
/node_modules/
/user-config.yml
109 changes: 45 additions & 64 deletions lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ api.declare({
}, 'KeyName requirement not met');
return res.reportError('InputError', 'LaunchSpecification is invalid!');
}

assert(keyName === LaunchSpecification.KeyName);

let valid = await this.lsChecker.check({
launchSpecification: LaunchSpecification,
region: Region,
});

if (!valid) {
return res.reportError('InputError', 'LaunchSpecification is invalid!');
}
Expand Down Expand Up @@ -128,15 +128,49 @@ api.declare({
}
}

assert(Array.isArray(result.SpotInstanceRequests));
assert(result.SpotInstanceRequests.length === 1);

let [spotRequest] = result.SpotInstanceRequests;

let id = spotRequest.SpotInstanceRequestId;
let instanceType = LaunchSpecification.InstanceType;
let imageId = LaunchSpecification.ImageId;
let az = LaunchSpecification.Placement.AvailabilityZone;
let requestState = spotRequest.State;
let status = spotRequest.Status.Code;
let created = new Date(spotRequest.CreateTime);

let opts = {
workerType,
region: Region,
az,
instanceType,
imageId,
id,
state: requestState,
status,
created,
};

log.debug(opts, 'inserting spot request into database');

try {
await handleRequestSpotInstanceResponse({
state: this.state,
region: Region,
response: result,
await tagResources({
runaws: this.runaws,
ec2: this.ec2[Region],
keyPrefix: this.keyPrefix,
ec2: this.ec2,
ids: [id],
workerType,
});
} catch (err) {
log.warn({err}, 'Error while tagging, ignoring');
}

try {
await this.state.insertSpotRequest(opts);

log.debug(opts, 'finished inserting spot request into database');
res.status(204).end();
} catch (err) {
// https://www.postgresql.org/docs/9.6/static/errcodes-appendix.html
Expand Down Expand Up @@ -257,7 +291,7 @@ function createPubKeyHash(pubKey) {
keyData = crypto.createHash('sha256').update(keyData).digest('hex');
return keyData.slice(0, 7);
};

function createKeyPairName(prefix, pubKey, workerName) {
assert(typeof prefix === 'string');
// We want to support the case where we're still using a config setting
Expand Down Expand Up @@ -299,7 +333,7 @@ api.declare({
let keyName = createKeyPairName(this.keyPrefix, this.instancePubKey, workerType);

if (!req.satisfies({workerType: workerType})) { return undefined; }

if (knownKeyPairs.includes(keyName)) {
return res.status(204).end();
}
Expand Down Expand Up @@ -341,7 +375,7 @@ api.declare({
let keyName = createKeyPairName(this.keyPrefix, this.instancePubKey, workerType);

if (!req.satisfies({workerType: workerType})) { return undefined; }

await Promise.all(this.regions.map(async region => {
let keyPairs = await this.runaws(this.ec2[region], 'describeKeyPairs', {
Filters: [{
Expand All @@ -360,59 +394,6 @@ api.declare({
res.status(204).end();
});

/**
* Handle the output of the requestSpotInstance method. The response property
* should be just the raw object that the method returned. This is split out here
* so that we can use the same logic for imports and calls to the EC2 api made
* from the api
*/
async function handleRequestSpotInstanceResponse({state, region, response, runaws, ec2, keyPrefix}) {
assert(typeof region === 'string');
assert(typeof response === 'object');
assert(Array.isArray(response.SpotInstanceRequests));
assert(response.SpotInstanceRequests.length === 1);
let [spotRequest] = response.SpotInstanceRequests;

let id = spotRequest.SpotInstanceRequestId;
let workerType = spotRequest.LaunchSpecification.KeyName.split(':')[1];
let instanceType = spotRequest.LaunchSpecification.InstanceType;
let imageId = spotRequest.LaunchSpecification.ImageId;
let az = spotRequest.LaunchSpecification.Placement.AvailabilityZone;
let requestState = spotRequest.State;
let status = spotRequest.Status.Code;
let created = new Date(spotRequest.CreateTime);

let opts = {
workerType,
region,
az,
instanceType,
imageId,
id,
state: requestState,
status,
created,
};

log.info(opts, 'inserting spot request into database');

try {
await tagResources({
runaws,
ec2: ec2[region],
keyPrefix: keyPrefix,
ids: [id],
workerType,
});
} catch (err) {
log.warn({err}, 'Error while tagging, ignoring');
}

await state.insertSpotRequest(opts);

log.info(opts, 'finished inserting spot request into database');
}

// NOTE Idempotency is being enforced by the database for the import operation.
// I guess this is a problem because we could have a situation where the first
// call to this API succeeds but the client doesn't get the response and so
Expand Down
Loading

0 comments on commit 9d33c6d

Please sign in to comment.