Skip to content

Commit f9da194

Browse files
adding support for listing environments. fixes #30 (#31)
1 parent 2501e95 commit f9da194

File tree

7 files changed

+301
-2
lines changed

7 files changed

+301
-2
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ $ aio config:set cloudmanager_programid 4
8484
* [`aio cloudmanager:get-current-execution PIPELINEID`](#aio-cloudmanagerget-current-execution-pipelineid)
8585
* [`aio cloudmanager:get-quality-gate-results PIPELINEID EXECUTIONID ACTION`](#aio-cloudmanagerget-quality-gate-results-pipelineid-executionid-action)
8686
* [`aio cloudmanager:list-current-executions`](#aio-cloudmanagerlist-current-executions)
87+
* [`aio cloudmanager:list-environments`](#aio-cloudmanagerlist-environments)
8788
* [`aio cloudmanager:list-pipelines`](#aio-cloudmanagerlist-pipelines)
8889
* [`aio cloudmanager:list-programs`](#aio-cloudmanagerlist-programs)
8990
* [`aio cloudmanager:start-execution PIPELINEID`](#aio-cloudmanagerstart-execution-pipelineid)
@@ -209,6 +210,21 @@ OPTIONS
209210

210211
_See code: [src/commands/cloudmanager/list-current-executions.js](https://github.com/adobe/aio-cli-plugin-cloudmanager/blob/v0.1.3/src/commands/cloudmanager/list-current-executions.js)_
211212

213+
## `aio cloudmanager:list-environments`
214+
215+
lists environments available in a Cloud Manager program
216+
217+
```
218+
USAGE
219+
$ aio cloudmanager:list-environments
220+
221+
OPTIONS
222+
-p, --programId=programId the programId. if not specified, defaults to 'cloudmanager_programid' config value
223+
-r, --passphrase=passphrase the passphrase for the private-key
224+
```
225+
226+
_See code: [src/commands/cloudmanager/list-environments.js](https://github.com/adobe/aio-cli-plugin-cloudmanager/blob/v0.1.3/src/commands/cloudmanager/list-environments.js)_
227+
212228
## `aio cloudmanager:list-pipelines`
213229

214230
lists pipelines available in a Cloud Manager program

src/client.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,31 @@ class Client {
245245
else throw new Error(`Cannot advance execution: ${res.url} (${res.status} ${res.statusText})`)
246246
})
247247
}
248+
249+
async _listEnvironments(path) {
250+
return this.get(path).then((res) => {
251+
if (res.ok) return res.json()
252+
else throw new Error(`Cannot retrieve environments: ${res.url} (${res.status} ${res.statusText})`)
253+
})
254+
}
255+
256+
async listEnvironments(programId) {
257+
const programs = await this.listPrograms();
258+
let program = programs.find(p => p.id === programId);
259+
if (!program) {
260+
throw new Error(`Could not find program ${programId}`)
261+
}
262+
program = await this.getProgram(program.link(rels.self).href)
263+
program = halfred.parse(program)
264+
265+
const result = await this._listEnvironments(program.link(rels.environments).href)
266+
let environments = result && halfred.parse(result).embeddedArray('environments')
267+
if (!environments) {
268+
throw new Error(`Could not find environments for program ${programId}`)
269+
}
270+
return environments
271+
}
272+
248273
}
249274

250275
module.exports = Client
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
Copyright 2019 Adobe. All rights reserved.
3+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License. You may obtain a copy
5+
of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
7+
Unless required by applicable law or agreed to in writing, software distributed under
8+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
OF ANY KIND, either express or implied. See the License for the specific language
10+
governing permissions and limitations under the License.
11+
*/
12+
13+
const { Command } = require('@oclif/command')
14+
const { accessToken: getAccessToken } = require('@adobe/aio-cli-plugin-jwt-auth')
15+
const { getApiKey, getOrgId, getProgramId } = require('../../cloudmanager-helpers')
16+
const { cli } = require('cli-ux')
17+
const Client = require('../../client')
18+
const commonFlags = require('../../common-flags')
19+
20+
async function _listEnvironments(programId, passphrase) {
21+
const apiKey = await getApiKey()
22+
const accessToken = await getAccessToken(passphrase)
23+
const orgId = await getOrgId()
24+
return new Client(orgId, accessToken, apiKey).listEnvironments(programId)
25+
}
26+
27+
class ListEnvironmentsCommand extends Command {
28+
async run() {
29+
const { flags } = this.parse(ListEnvironmentsCommand)
30+
31+
const programId = await getProgramId(flags)
32+
33+
let result
34+
35+
try {
36+
result = await this.listEnvironments(programId, flags.passphrase)
37+
} catch (error) {
38+
this.error(error.message)
39+
}
40+
41+
cli.table(result, {
42+
id: {
43+
header: "Environment Id"
44+
},
45+
name: {},
46+
type: {},
47+
description: {}
48+
}, {
49+
printLine: this.log
50+
})
51+
52+
return result
53+
}
54+
55+
async listEnvironments(programId, passphrase = null) {
56+
return _listEnvironments(programId, passphrase)
57+
}
58+
}
59+
60+
ListEnvironmentsCommand.description = 'lists environments available in a Cloud Manager program'
61+
62+
ListEnvironmentsCommand.flags = {
63+
...commonFlags.global,
64+
...commonFlags.programId
65+
}
66+
67+
module.exports = ListEnvironmentsCommand

src/constants.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ module.exports = {
1919
metrics: 'http://ns.adobe.com/adobecloud/rel/pipeline/metrics',
2020
cancel: 'http://ns.adobe.com/adobecloud/rel/pipeline/cancel',
2121
advance: 'http://ns.adobe.com/adobecloud/rel/pipeline/advance',
22-
executionId: 'http://ns.adobe.com/adobecloud/rel/execution/id'
22+
executionId: 'http://ns.adobe.com/adobecloud/rel/execution/id',
23+
environments: 'http://ns.adobe.com/adobecloud/rel/environments'
2324
},
2425
config: {
2526
programId: 'cloudmanager_programid'

src/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const GetQualityGateResults = require('./commands/cloudmanager/get-quality-gate-
1919
const CloudManagerCommand = require('./commands/cloudmanager')
2020
const CancelCurrentExecution = require('./commands/cloudmanager/cancel-current-execution')
2121
const AdvanceCurrentExecution = require('./commands/cloudmanager/advance-current-execution')
22+
const ListEnvironments = require('./commands/cloudmanager/list-environments')
2223

2324
module.exports = {
2425
'aaa': CloudManagerCommand, // needs to be first alphabetically
@@ -29,5 +30,6 @@ module.exports = {
2930
'list-current-executions': new ListCurrentExecutions().listCurrentExecutions,
3031
'get-quality-gate-results': new GetQualityGateResults().getQualityGateResults,
3132
'cancel-current-execution': new CancelCurrentExecution().cancelCurrentExecution,
32-
'advance-current-execution': new AdvanceCurrentExecution().advanceCurrentExecution
33+
'advance-current-execution': new AdvanceCurrentExecution().advanceCurrentExecution,
34+
'list-environments': new ListEnvironments().listEnvironments
3335
}

test/__mocks__/node-fetch.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ fetchMock.mock('https://cloudmanager.adobe.io/api/program/4', {
7373
},
7474
'http://ns.adobe.com/adobecloud/rel/pipelines': {
7575
href: '/api/program/4/pipelines'
76+
},
77+
'http://ns.adobe.com/adobecloud/rel/environments': {
78+
href: '/api/program/4/environments'
7679
}
7780
}
7881
})
@@ -81,6 +84,58 @@ fetchMock.mock('https://cloudmanager.adobe.io/api/program/4/pipelines', {
8184
pipelines: []
8285
}
8386
})
87+
fetchMock.mock('https://cloudmanager.adobe.io/api/program/4/environments', {
88+
"_embedded": {
89+
"environments": [
90+
{
91+
"_links": {
92+
"self": {
93+
"href": "/api/program/4/environment/1",
94+
"templated": false
95+
},
96+
"http://ns.adobe.com/adobecloud/rel/logs":{
97+
"href":"/api/program/4/environment/1884/logs?service={service}&name={name}&days={days}",
98+
"templated": true
99+
}
100+
},
101+
"id": "1",
102+
"programId": "4",
103+
"name": "TestProgram_prod",
104+
"description": "description for TestProgram_prod",
105+
"type": "prod"
106+
},
107+
{
108+
"_links": {
109+
"self": {
110+
"href": "/api/program/4/environment/2",
111+
"templated": false
112+
}
113+
},
114+
"id": "2",
115+
"programId": "4",
116+
"name": "TestProgram_stage",
117+
"description": "description for TestProgram_stage",
118+
"type": "stage"
119+
},
120+
{
121+
"_links": {
122+
"self": {
123+
"href": "/api/program/4/environment/3",
124+
"templated": false
125+
}
126+
},
127+
"id": "3",
128+
"programId": "4",
129+
"name": "TestProgram_dev",
130+
"description": "description for TestProgram_dev",
131+
"type": "dev"
132+
}
133+
]
134+
},
135+
"_totalNumberOfItems": 3
136+
137+
})
138+
84139
fetchMock.mock('https://cloudmanager.adobe.io/api/program/5', {
85140
id: "5",
86141
name: "test1",
@@ -91,6 +146,9 @@ fetchMock.mock('https://cloudmanager.adobe.io/api/program/5', {
91146
},
92147
'http://ns.adobe.com/adobecloud/rel/pipelines': {
93148
href: '/api/program/5/pipelines'
149+
},
150+
'http://ns.adobe.com/adobecloud/rel/environments': {
151+
href: '/api/program/5/environments'
94152
}
95153
}
96154
})
@@ -158,6 +216,11 @@ mockResponseWithMethod('https://cloudmanager.adobe.io/api/program/5/pipeline/5/e
158216
location: 'https://cloudmanager.adobe.io/api/program/4/pipeline/8555/execution/12742'
159217
}
160218
});
219+
fetchMock.mock('https://cloudmanager.adobe.io/api/program/5/environments', {
220+
_embedded: {
221+
environments: []
222+
}
223+
})
161224

162225
mockResponseWithMethod('https://cloudmanager.adobe.io/api/program/5/pipeline/6/execution', 'GET', require('./data/execution1000.json'))
163226
mockResponseWithMethod('https://cloudmanager.adobe.io/api/program/5/pipeline/6/execution', 'PUT', 412)
@@ -172,10 +235,14 @@ fetchMock.mock('https://cloudmanager.adobe.io/api/program/6', {
172235
},
173236
'http://ns.adobe.com/adobecloud/rel/pipelines': {
174237
href: '/api/program/6/pipelines'
238+
},
239+
'http://ns.adobe.com/adobecloud/rel/environments': {
240+
href: '/api/program/6/environments'
175241
}
176242
}
177243
})
178244
fetchMock.mock('https://cloudmanager.adobe.io/api/program/6/pipelines', 404)
245+
mockResponseWithMethod('https://cloudmanager.adobe.io/api/program/6/environments', 'GET', 404)
179246

180247
mockResponseWithMethod('https://cloudmanager.adobe.io/api/program/5/pipeline/7/execution/1001', 'GET', require('./data/execution1001.json'))
181248
mockResponseWithMethod('https://cloudmanager.adobe.io/api/program/5/pipeline/5/execution/1002', 'GET', 404)
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
Copyright 2019 Adobe. All rights reserved.
3+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License. You may obtain a copy
5+
of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
7+
Unless required by applicable law or agreed to in writing, software distributed under
8+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
OF ANY KIND, either express or implied. See the License for the specific language
10+
governing permissions and limitations under the License.
11+
*/
12+
13+
const { setStore } = require('@adobe/aio-cna-core-config')
14+
const ListEnvironmentsCommand = require('../../src/commands/cloudmanager/list-environments')
15+
16+
beforeEach(() => {
17+
setStore({})
18+
})
19+
20+
test('list-environments - missing arg', async () => {
21+
expect.assertions(2)
22+
23+
let runResult = ListEnvironmentsCommand.run([])
24+
await expect(runResult instanceof Promise).toBeTruthy()
25+
await expect(runResult).rejects.toSatisfy(err => err.message.indexOf("Program ID must be specified either as --programId flag or through cloudmanager_programid") === 0)
26+
})
27+
28+
test('list-environments - missing config', async () => {
29+
expect.assertions(2)
30+
31+
let runResult = ListEnvironmentsCommand.run(["--programId", "5"])
32+
await expect(runResult instanceof Promise).toBeTruthy()
33+
await expect(runResult).rejects.toEqual(new Error('missing config data: jwt-auth'))
34+
})
35+
36+
test('list-environments - failure', async () => {
37+
setStore({
38+
'jwt-auth': JSON.stringify({
39+
client_id: '1234',
40+
jwt_payload: {
41+
iss: "good"
42+
}
43+
}),
44+
'cloudmanager_programid': "6"
45+
})
46+
47+
expect.assertions(2)
48+
49+
let runResult = ListEnvironmentsCommand.run([])
50+
await expect(runResult instanceof Promise).toBeTruthy()
51+
await expect(runResult).rejects.toEqual(new Error('Cannot retrieve environments: https://cloudmanager.adobe.io/api/program/6/environments (404 Not Found)'))
52+
})
53+
54+
test('list-environments - success empty', async () => {
55+
setStore({
56+
'jwt-auth': JSON.stringify({
57+
client_id: '1234',
58+
jwt_payload: {
59+
iss: "good"
60+
}
61+
}),
62+
'cloudmanager_programid': "5"
63+
})
64+
65+
expect.assertions(2)
66+
67+
let runResult = ListEnvironmentsCommand.run([])
68+
await expect(runResult instanceof Promise).toBeTruthy()
69+
await expect(runResult).resolves.toEqual([])
70+
})
71+
72+
test('list-environments - success', async () => {
73+
setStore({
74+
'jwt-auth': JSON.stringify({
75+
client_id: '1234',
76+
jwt_payload: {
77+
iss: "good"
78+
}
79+
}),
80+
'cloudmanager_programid': "4"
81+
})
82+
83+
expect.assertions(2)
84+
85+
let runResult = ListEnvironmentsCommand.run([])
86+
await expect(runResult instanceof Promise).toBeTruthy()
87+
await expect(runResult).resolves.toMatchObject([{
88+
id: "1",
89+
name: "TestProgram_prod",
90+
type: "prod"
91+
},
92+
{
93+
id: "2",
94+
name: "TestProgram_stage",
95+
type: "stage"
96+
},
97+
{
98+
id: "3",
99+
name: "TestProgram_dev",
100+
type: "dev"
101+
}])
102+
})
103+
104+
105+
test('list-environments - bad program', async () => {
106+
setStore({
107+
'jwt-auth': JSON.stringify({
108+
client_id: '1234',
109+
jwt_payload: {
110+
iss: "good"
111+
}
112+
}),
113+
'cloudmanager_programid': "8"
114+
})
115+
116+
expect.assertions(2)
117+
118+
let runResult = ListEnvironmentsCommand.run([])
119+
await expect(runResult instanceof Promise).toBeTruthy()
120+
await expect(runResult).rejects.toEqual(new Error('Could not find program 8'))
121+
})

0 commit comments

Comments
 (0)