Skip to content

Commit 9ad5b34

Browse files
feat(variables): support JSON input on stdin and files. fixes #150 (#153)
1 parent 6e75d08 commit 9ad5b34

File tree

4 files changed

+382
-4
lines changed

4 files changed

+382
-4
lines changed

README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,12 @@ OPTIONS
381381
-v, --variable=variable variable values in KEY VALUE format
382382
-y, --yaml output in yaml format
383383
384+
--jsonFile=jsonFile if set, read variables from a JSON array provided as a file; variables set through
385+
--variable or --secret flag will take precedence
386+
387+
--jsonStdin if set, read variables from a JSON array provided as standard input; variables set
388+
through --variable or --secret flag will take precedence
389+
384390
ALIASES
385391
$ aio cloudmanager:set-environment-variables
386392
```
@@ -592,6 +598,12 @@ OPTIONS
592598
-v, --variable=variable variable values in KEY VALUE format
593599
-y, --yaml output in yaml format
594600
601+
--jsonFile=jsonFile if set, read variables from a JSON array provided as a file; variables set through
602+
--variable or --secret flag will take precedence
603+
604+
--jsonStdin if set, read variables from a JSON array provided as standard input; variables set
605+
through --variable or --secret flag will take precedence
606+
595607
ALIASES
596608
$ aio cloudmanager:set-pipeline-variables
597609
```
@@ -703,6 +715,37 @@ ALIASES
703715
_See code: [src/commands/cloudmanager/program/list-pipelines.js](https://github.com/adobe/aio-cli-plugin-cloudmanager/blob/0.17.0/src/commands/cloudmanager/program/list-pipelines.js)_
704716
<!-- commandsstop -->
705717

718+
# Variables From Standard Input
719+
720+
The `environment:set-variables` and `pipeline:set-variables` commands allow for variables to be passed both as flags to the command and as a JSON array provided as standard input or as a file. The objects in this array are expected to have a `name`, `value`, and `type` keys following the same syntax as the Cloud Manager API. Deleting a variable can be done by passing an empty `value`. For example, given a file named `variables.json` that contains this:
721+
722+
```
723+
[
724+
{
725+
"name" : "MY_VARIABLE",
726+
"value" : "something",
727+
"type" : "string"
728+
},
729+
{
730+
"name" : "MY_SECRET_VARIABLE",
731+
"value" : "shhhh",
732+
"type" : "secretString"
733+
}
734+
]
735+
```
736+
737+
This can be passed to the `pipeline:set-variables` command using a shell command of
738+
739+
```
740+
$ cat variables.json | aio cloudmanager:pipeline:set-variables 1 --jsonStdin
741+
```
742+
743+
Or
744+
745+
```
746+
$ aio cloudmanager:pipeline:set-variables 1 --jsonFile variables.json
747+
```
748+
706749
# Development
707750

708751
For development, it is useful to use `aio plugins:link` to link to a local clone of this repository rather than a specific npm module, e.g.

src/base-variables-command.js

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,16 @@ OF ANY KIND, either express or implied. See the License for the specific languag
1010
governing permissions and limitations under the License.
1111
*/
1212

13+
const { promisify } = require('util')
14+
const fs = require('fs')
15+
1316
const { Command } = require('@oclif/command')
1417
const { cli } = require('cli-ux')
1518
const { flags } = require('@oclif/command')
1619
const { getProgramId, createKeyValueObjectFromFlag, getOutputFormat } = require('./cloudmanager-helpers')
1720
const commonFlags = require('./common-flags')
21+
const { getPipedData } = require('@adobe/aio-lib-core-config')
22+
const _ = require('lodash')
1823

1924
class BaseVariablesCommand extends Command {
2025
outputTable (result, flags) {
@@ -34,7 +39,7 @@ class BaseVariablesCommand extends Command {
3439

3540
const currentVariablesList = await this.getVariables(programId, args, flags.passphrase)
3641

37-
const variables = this.prepareVariableList(flags, currentVariablesList)
42+
const variables = await this.prepareVariableList(flags, currentVariablesList)
3843

3944
if (variables.length > 0) {
4045
cli.action.start('setting variables')
@@ -56,7 +61,7 @@ class BaseVariablesCommand extends Command {
5661
return result
5762
}
5863

59-
prepareVariableList (flags, currentVariablesList) {
64+
async prepareVariableList (flags, currentVariablesList) {
6065
const currentVariableTypes = {}
6166
currentVariablesList.forEach(variable => (currentVariableTypes[variable.name] = variable.type))
6267

@@ -97,8 +102,42 @@ class BaseVariablesCommand extends Command {
97102
})
98103
}
99104

105+
if (flags.jsonStdin) {
106+
const rawStdinData = await getPipedData()
107+
this.loadVariablesFromJson(rawStdinData, currentVariableTypes, variables)
108+
} else if (flags.jsonFile) {
109+
const getFileData = promisify(fs.readFile)
110+
const rawFileData = await getFileData(flags.jsonFile)
111+
this.loadVariablesFromJson(rawFileData, currentVariableTypes, variables)
112+
}
113+
100114
return variables
101115
}
116+
117+
loadVariablesFromJson (rawData, currentVariableTypes, variables) {
118+
let data
119+
try {
120+
data = JSON.parse(rawData)
121+
} catch (e) {
122+
this.error('Unable to parse variables from provided data.')
123+
}
124+
if (!_.isArray(data)) {
125+
this.error('Provided variables input was not an array.')
126+
}
127+
data.forEach(item => {
128+
if (item.name && !_.isUndefined(item.value)) {
129+
if (!item.type) {
130+
item.type = 'string'
131+
}
132+
if (currentVariableTypes[item.name] && !item.value) {
133+
item.type = currentVariableTypes[item.name]
134+
}
135+
if (!variables.find(variable => variable.name === item.name)) {
136+
variables.push(item)
137+
}
138+
}
139+
})
140+
}
102141
}
103142

104143
BaseVariablesCommand.setterFlags = {
@@ -117,6 +156,14 @@ BaseVariablesCommand.setterFlags = {
117156
description: 'variables/secrets to delete',
118157
multiple: true
119158
}),
159+
jsonStdin: flags.boolean({
160+
default: false,
161+
description: 'if set, read variables from a JSON array provided as standard input; variables set through --variable or --secret flag will take precedence'
162+
}),
163+
jsonFile: flags.string({
164+
description: 'if set, read variables from a JSON array provided as a file; variables set through --variable or --secret flag will take precedence',
165+
exclusive: ['jsonStdin']
166+
}),
120167
...commonFlags.outputFormat
121168
}
122169

test/__mocks__/@adobe/aio-lib-core-config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ let mockStore = {}
1414

1515
module.exports = {
1616
get: jest.fn(k => mockStore[k]),
17-
setStore: (s) => (mockStore = s)
17+
setStore: (s) => (mockStore = s),
18+
getPipedData: jest.fn()
1819
}

0 commit comments

Comments
 (0)