Skip to content

Commit eca838a

Browse files
committed
@aws-sdk/client-ssm / aws-sdk/clients/ssm@aws-lite/ssm
1 parent cf5b8b5 commit eca838a

File tree

7 files changed

+108
-167
lines changed

7 files changed

+108
-167
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
"author": "Brian LeRoux <b@brian.io>",
2626
"license": "Apache-2.0",
2727
"dependencies": {
28+
"@aws-lite/client": "^0.8.1",
29+
"@aws-lite/ssm": "^0.1.0",
2830
"cookie": "^0.5.0",
2931
"cookie-signature": "^1.2.1",
3032
"csrf": "^3.1.0",
@@ -42,7 +44,6 @@
4244
"@aws-sdk/client-dynamodb": "^3.319.0",
4345
"@aws-sdk/client-sns": "^3.319.0",
4446
"@aws-sdk/client-sqs": "^3.319.0",
45-
"@aws-sdk/client-ssm": "^3.319.0",
4647
"@aws-sdk/lib-dynamodb": "^3.319.0",
4748
"@smithy/node-http-handler": "^2.1.7",
4849
"@types/aws-lambda": "^8.10.119",

src/discovery/index.js

Lines changed: 44 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
let { isNode18, useAWS } = require('../lib')
2-
let ssm, ssmClient
1+
let { callbackify } = require('util')
2+
let { getAwsClient, useAWS } = require('../lib')
33

44
/**
55
* @param {string} type - events, queues, or tables
@@ -19,11 +19,7 @@ module.exports = function lookup (callback) {
1919
app = 'arc-app'
2020
}
2121

22-
let Path = `/${stack || toLogicalID(`${app}-${env}`)}`
23-
let Recursive = true
24-
let values = []
25-
let config
26-
22+
let config = {}
2723
if (local) {
2824
let port = 2222
2925
if (ARC_SANDBOX) {
@@ -34,71 +30,53 @@ module.exports = function lookup (callback) {
3430
port = ports._arc
3531
}
3632
config = {
37-
endpoint: `http://localhost:${port}/_arc/ssm`,
33+
endpointPrefix: '/_arc/ssm',
34+
host: `localhost`,
35+
port,
36+
protocol: 'http',
3837
region: AWS_REGION || 'us-west-2',
3938
}
4039
}
4140

42-
// shim v2 and v3
43-
if (!ssmClient) {
44-
if (isNode18) {
45-
let { SSMClient: SSM, GetParametersByPathCommand: cmd } = require('@aws-sdk/client-ssm')
46-
let GetParametersByPathCommand = cmd
47-
ssm = new SSM(config)
48-
ssmClient = (params, callback) => {
49-
let command = new GetParametersByPathCommand(params)
50-
return ssm.send(command, callback)
51-
}
52-
}
41+
getAwsClient(config, (err, client) => {
42+
if (err) callback(err)
5343
else {
54-
let SSM = require('aws-sdk/clients/ssm')
55-
ssm = new SSM(config)
56-
ssmClient = (params, callback) => {
57-
return ssm.getParametersByPath(params, callback)
58-
}
44+
let Path = `/${stack || toLogicalID(`${app}-${env}`)}`
45+
let GetParametersByPath = callbackify(client.ssm.GetParametersByPath)
46+
GetParametersByPath({ Path, paginate: true }, function done (err, result) {
47+
if (err && local &&
48+
err.message.includes('Inaccessible host') &&
49+
err.message.includes('localhost')) {
50+
let msg = 'Sandbox internal services are unavailable, please ensure Sandbox is running'
51+
callback(ReferenceError(msg))
52+
}
53+
else if (err) {
54+
callback(err)
55+
}
56+
else {
57+
let services = result.Parameters.reduce((a, b) => {
58+
let hierarchy = b.Name.split('/')
59+
hierarchy.shift() // leading slash
60+
hierarchy.shift() // stack name
61+
let type = hierarchy.shift() // i.e. tables, events, queues, plugins
62+
if (!a[type]) a[type] = {}
63+
let parent = a[type]
64+
let child, lastChild, lastParent
65+
/* eslint-disable-next-line */
66+
while (child = hierarchy.shift()) {
67+
if (!parent[child]) parent[child] = {}
68+
lastParent = parent
69+
parent = parent[child]
70+
lastChild = child
71+
}
72+
lastParent[lastChild] = b.Value
73+
return a
74+
}, {})
75+
callback(null, services)
76+
}
77+
})
5978
}
60-
}
61-
62-
function getParams (params) {
63-
ssmClient(params, function done (err, result) {
64-
if (err && local &&
65-
err.message.includes('Inaccessible host') &&
66-
err.message.includes('localhost')) {
67-
let msg = 'Sandbox internal services are unavailable, please ensure Sandbox is running'
68-
callback(ReferenceError(msg))
69-
}
70-
else if (err) {
71-
callback(err)
72-
}
73-
else if (result.NextToken) {
74-
values = values.concat(result.Parameters)
75-
getParams({ Path, Recursive, NextToken: result.NextToken })
76-
}
77-
else {
78-
values = values.concat(result.Parameters)
79-
let services = values.reduce((a, b) => {
80-
let hierarchy = b.Name.split('/')
81-
hierarchy.shift() // leading slash
82-
hierarchy.shift() // stack name
83-
let type = hierarchy.shift() // i.e. tables, events, queues, plugins
84-
if (!a[type]) a[type] = {}
85-
let parent = a[type]
86-
let child, lastChild, lastParent
87-
/* eslint-disable-next-line */
88-
while (child = hierarchy.shift()) {
89-
if (!parent[child]) parent[child] = {}
90-
lastParent = parent
91-
parent = parent[child]
92-
lastChild = child
93-
}
94-
lastParent[lastChild] = b.Value
95-
return a
96-
}, {})
97-
callback(null, services)
98-
}
99-
})
100-
}
101-
getParams({ Path, Recursive })
79+
})
10280
}
10381

10482
function toLogicalID (str) {

src/lib/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ let sandboxVersionAtLeast = require('./_sandbox-version')
44
let isNode18 = Number(process.version.replace('v', '').split('.')[0]) >= 18
55

66
let nonLocalEnvs = [ 'staging', 'production' ]
7+
8+
function getAwsClient (params, callback) {
9+
let { callbackify } = require('util')
10+
let _awsLite = require('@aws-lite/client')
11+
let awsLite = callbackify(_awsLite)
12+
awsLite(params, callback)
13+
}
14+
715
function useAWS () {
816
let { ARC_ENV, ARC_LOCAL, ARC_SANDBOX } = process.env
917
// Testing is always local
@@ -15,6 +23,7 @@ function useAWS () {
1523
}
1624

1725
module.exports = {
26+
getAwsClient,
1827
getPorts,
1928
isNode18,
2029
sandboxVersionAtLeast,

test/integration/discovery-test.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
let { join } = require('path')
2+
let test = require('tape')
3+
let sandbox = require('@architect/sandbox')
4+
let cwd = process.cwd()
5+
let mock = join(cwd, 'test', 'mock', 'project')
6+
let discovery = require('../../src/discovery')
7+
8+
test('Set up env', async t => {
9+
t.plan(2)
10+
await sandbox.start({ cwd: mock, quiet: true })
11+
t.pass('Set up ARC_APP_NAME env var')
12+
t.pass('Sandbox started')
13+
})
14+
15+
test('discovery should parse hierarchical SSM parameters into a service map object', t => {
16+
t.plan(6)
17+
discovery((err, services) => {
18+
t.notOk(err, 'No error passed to callback')
19+
t.equal(services.tables['arc-sessions'], 'test-only-staging-arc-sessions', 'Table value set up in correct place of service map')
20+
t.equal(services.tables.things, 'test-only-staging-things', 'Table value set up in correct place of service map')
21+
22+
// Check deeper depths
23+
t.ok(services.services.cloudwatch.metrics, 'Deeply nested object exists')
24+
t.equal(services.services.cloudwatch.metrics.foo, 'bar', 'variable has correct value')
25+
t.ok(services.services.cloudwatch.metrics.fiz, 'buz', 'variable has correct value')
26+
})
27+
})
28+
29+
test('Teardown', async t => {
30+
t.plan(1)
31+
await sandbox.end()
32+
t.pass('Sandbox ended')
33+
})

test/mock/project/app.arc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
@app
22
test-only
33

4+
@plugins
5+
services
6+
47
@http
58
get /http-session
69
get /http-async-session
@@ -22,3 +25,5 @@ async-queue
2225
arc-sessions
2326
_idx *String
2427
_ttl TTL
28+
things
29+
thing *String
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module.exports = {
2+
deploy: {
3+
services: async () => {
4+
return {
5+
tables: {
6+
stuff: 'so-very-much-stuff'
7+
},
8+
'cloudwatch/metrics': {
9+
foo: 'bar',
10+
fiz: 'buz',
11+
}
12+
}
13+
}
14+
}
15+
}

test/unit/src/discovery/index-test.js

Lines changed: 0 additions & 100 deletions
This file was deleted.

0 commit comments

Comments
 (0)