Skip to content

Commit

Permalink
aws-sdk@aws-lite/*
Browse files Browse the repository at this point in the history
Disable unit tests that rely on `aws-sdk` + `aws-sdk-mock`
  • Loading branch information
ryanblock committed Jan 6, 2024
1 parent 36e6f4c commit 2309b3d
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 216 deletions.
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
"dependencies": {
"@architect/inventory": "~3.6.0",
"@architect/utils": "~3.1.9",
"@aws-lite/client": "~0.13.3",
"@aws-lite/cloudformation": "~0.0.1",
"@aws-lite/cloudwatch-logs": "~0.0.2",
"@aws-lite/s3": "~0.1.8",
"@aws-lite/ssm": "~0.2.2",
"aws-sdk": "^2.1363.0",
"minimist": "~1.2.8",
"run-parallel": "~1.2.0",
Expand Down
97 changes: 38 additions & 59 deletions src/_delete-bucket.js
Original file line number Diff line number Diff line change
@@ -1,83 +1,62 @@
let aws = require('aws-sdk')
let waterfall = require('run-waterfall')

module.exports = function deleteBucketContents ({ bucket }, callback) {

let region = process.env.AWS_REGION
let s3 = new aws.S3({ region })

let objects = []
module.exports = function deleteBucketContents ({ aws, bucket: Bucket }, callback) {
let bucketExists = false
function ensureBucket (callback) {
s3.headBucket({ Bucket: bucket }, function done (err) {
if (err) bucketExists = false
else bucketExists = true
callback(null)
})
}

function collectObjects (ContinuationToken, callback) {
s3.listObjectsV2({
Bucket: bucket,
ContinuationToken
}, function done (err, result) {
if (err) {
callback(err)
}
else {
objects = objects.concat(result.Contents)
if (result.IsTruncated) {
collectObjects(result.NextContinuationToken, callback)
}
else {
callback(null, objects.map(item => ({ Key: item.Key })))
}
}
})
function collectObjects (callback) {
aws.s3.ListObjectsV2({ Bucket, paginate: true })
.then(result => {
let { Contents } = result
let objectsToDelete = Contents.map(({ Key }) => ({ Key })).filter(Boolean)
callback(null, objectsToDelete)
})
.catch(err => callback(err))
}

function deleteObjects (objs, callback) {
let batch = objs.splice(0, 1000) // S3.deleteObjects supports up to 1k keys
s3.deleteObjects({
Bucket: bucket,
Delete: {
Objects: batch
}
},
function done (err) {
if (err) callback(err)
else if (objs.length) {
deleteObjects(objs, callback)
}
else callback()
function deleteObjects (objectsToDelete, callback) {
let Objects = objectsToDelete.splice(0, 1000) // S3.deleteObjects supports up to 1k keys
aws.s3.DeleteObjects({
Bucket,
Delete: { Objects },
})
.then(() => {
if (objectsToDelete.length) {
deleteObjects(objectsToDelete, callback)
}
else callback()
})
.catch(err => callback(err))
}

waterfall([
function checkBucketExists (callback) {
ensureBucket(callback)
aws.s3.HeadBucket({ Bucket })
.then(() => {
bucketExists = true
callback()
})
.catch(() => callback())
},

function maybeCollectObjectsInBucket (callback) {
if (bucketExists) collectObjects(null, callback)
else callback(null, [])
if (bucketExists) {
collectObjects(callback)
}
else callback(null, false)
},

function maybeDeleteBucketObjects (stuffToDelete, callback) {
if (bucketExists && Array.isArray(stuffToDelete) && stuffToDelete.length > 0) {
deleteObjects(stuffToDelete, callback)
}
else {
callback()
function maybeDeleteBucketObjects (objectsToDelete, callback) {
if (bucketExists && objectsToDelete.length) {
deleteObjects(objectsToDelete, callback)
}
else callback()
},

function maybeDeleteBucket (callback) {
if (bucketExists) {
s3.deleteBucket({ Bucket: bucket }, function (err) {
if (err) callback(err)
else callback()
})
aws.s3.DeleteBucket({ Bucket })
.then(() => callback())
.catch(err => callback(err))
}
else callback()
}
Expand Down
66 changes: 29 additions & 37 deletions src/_delete-logs.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,33 @@
let aws = require('aws-sdk')

module.exports = function deleteLogs ({ StackName, update }, callback) {
let cloudwatch = new aws.CloudWatchLogs()
let logGroups = []
function getLogs (nextToken, cb) {
let params = {
logGroupNamePrefix: `/aws/lambda/${StackName}-`
}
if (nextToken) params.nextToken = nextToken
cloudwatch.describeLogGroups(params, function (err, data) {
if (err) cb(err)
else {
data.logGroups.forEach(l => {
logGroups.push(l.logGroupName)
})
if (data.nextToken) getLogs(data.nextToken, cb)
else cb()
module.exports = function deleteLogs ({ aws, StackName, update }, callback) {
aws.cloudwatchlogs.DescribeLogGroups({
logGroupNamePrefix: `/aws/lambda/${StackName}-`,
paginate: true,
})
.then(data => {
if (data?.logGroups?.length) {
let logGroups = data.logGroups.map(({ logGroupName }) => logGroupName)
deleter(aws, logGroups, update, callback)
}
else callback()
})
}
getLogs(null, function (err) {
if (err) callback(err)
else if (logGroups.length) {
let timer = 0
let numComplete = 0
logGroups.forEach(log => {
timer += 400 // max of about 2-3 transactions per second :/
let params = { logGroupName: log }
setTimeout(function delayedDelete () {
cloudwatch.deleteLogGroup(params, function (err /* , data */) {
if (err) update.warn(err)
numComplete++
if (logGroups.length === numComplete) callback()
})
}, timer)
})
}
else callback()
.catch(err => callback(err))
}

function deleter (aws, logGroups, update, callback) {
let timer = 0
let numComplete = 0
logGroups.forEach(log => {
timer += 400 // max of about 2-3 transactions per second :/
setTimeout(function delayedDelete () {
aws.cloudwatchlogs.DeleteLogGroup({ logGroupName: log })
.then(() => {
numComplete++
if (logGroups.length === numComplete) callback()
})
.catch(err => {
numComplete++
update.warn(err)
})
}, timer)
})
}
76 changes: 35 additions & 41 deletions src/_ssm.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,62 @@
let aws = require('aws-sdk')
let parallel = require('run-parallel')

/**
*
*/
module.exports = {
getDeployBucket: function getDeployBucket (appname, callback) {
let region = process.env.AWS_REGION
let ssm = new aws.SSM({ region })
ssm.getParameter({
getDeployBucket: function getDeployBucket (aws, appname, callback) {
aws.ssm.GetParameter({
Name: `/${appname}/deploy/bucket`,
WithDecryption: true
}, function (err, data) {
if (err && err.code !== 'ParameterNotFound') callback(err)
else callback(null, (data && data.Parameter && data.Parameter.Value ? data.Parameter.Value : null))
})
.then(data => {
let value = data?.Parameter?.Value ? data.Parameter.Value : null
callback(null, value)
})
.catch(err => {
if (err && err.code !== 'ParameterNotFound') callback(err)
else callback()
})
},
deleteAll: function deleteAll (appname, env, callback) {
let region = process.env.AWS_REGION
let ssm = new aws.SSM({ region })

// set up for recursive retrieval of all parameters associated to the app
// since SSM only support max 10 param retrieval at a time
let results = {}
function collectByPath (rootPath, NextToken, cb) {
if (!results[rootPath]) results[rootPath] = []
let query = {
deleteAll: function deleteAll (aws, appname, env, callback) {
let Names = []
function collectByPath (rootPath, cb) {
aws.ssm.GetParametersByPath({
Path: rootPath,
Recursive: true,
MaxResults: 10
}
if (NextToken) query.NextToken = NextToken
ssm.getParametersByPath(query, function (err, data) {
// if the parameters are gone, that's fine too
if (err && err.code !== 'ParameterNotFound') cb(err)
else {
if (data && data.Parameters && data.Parameters.length) {
results[rootPath] = results[rootPath].concat(data.Parameters.map(param => param.Name))
if (data.NextToken) collectByPath(rootPath, data.NextToken, cb)
else cb(null, results[rootPath])
}
else cb(null, results[rootPath])
}
paginate: true
})
.then(data => {
if (data?.Parameters?.length) {
Names.push(...data.Parameters.map(({ Name }) => Name))
}
cb()
})
.catch(err => {
if (err && err.code !== 'ParameterNotFound') cb(err)
else cb()
})
}

// destroy all SSM Parameters associated to app; a few formats:
// /<app-name>/deploy/bucket - deployment bucket
// /<app-name>/<env>/* - environment variables via `arc env`
let paths = [ `/${appname}/${env}`, `/${appname}/deploy` ]
parallel(paths.map(path => collectByPath.bind(null, path, null)), function paramsCollected (err, res) {
let ops = [ `/${appname}/${env}`, `/${appname}/deploy` ]
.map(path => collectByPath.bind(null, path))

parallel(ops, (err) => {
if (err) callback(err)
else {
// combine all the various parameters by different path names into a single array
let Names = res.reduce((aggregate, current) => aggregate.concat(current), [])
function deleteThings () {
if (Names.length) {
// >10 SSM params in a call will fail
let chunk = Names.splice(0, 10)
ssm.deleteParameters({ Names: chunk }, function deleteParameters (err) {
if (err) callback(err)
else if (!Names.length) callback()
else deleteThings()
})
aws.ssm.DeleteParameters({ Names: chunk })
.then(() => {
if (!Names.length) callback()
else deleteThings()
})
.catch(err => callback(err))
}
else callback()
}
Expand Down
Loading

0 comments on commit 2309b3d

Please sign in to comment.