Merge pull request #1314 from balena-io/file-based-secrets

If a secrets file is not specified, read it from the data directory
This commit is contained in:
CameronDiver 2019-06-18 03:43:03 -07:00 committed by GitHub
commit 7b37c60e11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 66 additions and 16 deletions

View File

@ -1424,6 +1424,9 @@ Sample registry-secrets YAML file:
username: '_json_key' username: '_json_key'
password: '{escaped contents of the GCR keyfile.json file}' password: '{escaped contents of the GCR keyfile.json file}'
If an option is not specified, and a secrets.yml or secrets.json file exists in
the balena directory (usually $HOME/.balena), this file will be used instead.
Examples: Examples:
$ balena push myApp $ balena push myApp
@ -1459,7 +1462,9 @@ Don't use cache when building this project
#### --registry-secrets, -R <secrets.yml|.json> #### --registry-secrets, -R <secrets.yml|.json>
Path to a local YAML or JSON file containing Docker registry passwords used to pull base images Path to a local YAML or JSON file containing Docker registry passwords used to pull base images.
Note that if registry-secrets are not provided on the command line, a secrets configuration
file from the balena directory will be used (usually $HOME/.balena/secrets.yml|.json)
#### --nolive #### --nolive
@ -1566,6 +1571,9 @@ Sample registry-secrets YAML file:
username: '_json_key' username: '_json_key'
password: '{escaped contents of the GCR keyfile.json file}' password: '{escaped contents of the GCR keyfile.json file}'
If an option is not specified, and a secrets.yml or secrets.json file exists in
the balena directory (usually $HOME/.balena), this file will be used instead.
Examples: Examples:
$ balena build $ balena build
@ -1687,6 +1695,9 @@ Sample registry-secrets YAML file:
username: '_json_key' username: '_json_key'
password: '{escaped contents of the GCR keyfile.json file}' password: '{escaped contents of the GCR keyfile.json file}'
If an option is not specified, and a secrets.yml or secrets.json file exists in
the balena directory (usually $HOME/.balena), this file will be used instead.
Examples: Examples:
$ balena deploy myApp $ balena deploy myApp

View File

@ -101,6 +101,8 @@ module.exports =
action: (params, options, done) -> action: (params, options, done) ->
# compositions with many services trigger misleading warnings # compositions with many services trigger misleading warnings
require('events').defaultMaxListeners = 1000 require('events').defaultMaxListeners = 1000
sdk = (require('balena-sdk')).fromSharedOptions()
{ validateComposeOptions } = require('../utils/compose_ts') { validateComposeOptions } = require('../utils/compose_ts')
{ exitWithExpectedError } = require('../utils/patterns') { exitWithExpectedError } = require('../utils/patterns')
helpers = require('../utils/helpers') helpers = require('../utils/helpers')
@ -116,7 +118,7 @@ module.exports =
options.source ?= params.source options.source ?= params.source
delete params.source delete params.source
validateComposeOptions(options) validateComposeOptions(sdk, options)
{ application, arch, deviceType } = options { application, arch, deviceType } = options

View File

@ -180,6 +180,7 @@ module.exports =
action: (params, options, done) -> action: (params, options, done) ->
# compositions with many services trigger misleading warnings # compositions with many services trigger misleading warnings
require('events').defaultMaxListeners = 1000 require('events').defaultMaxListeners = 1000
sdk = (require('balena-sdk')).fromSharedOptions()
{ validateComposeOptions } = require('../utils/compose_ts') { validateComposeOptions } = require('../utils/compose_ts')
helpers = require('../utils/helpers') helpers = require('../utils/helpers')
Logger = require('../utils/logger') Logger = require('../utils/logger')
@ -198,7 +199,7 @@ module.exports =
appName = appName_raw || appName || options.application appName = appName_raw || appName || options.application
delete options.application delete options.application
validateComposeOptions(options) validateComposeOptions(sdk, options)
if not appName? if not appName?
throw new Error('Please specify the name of the application to deploy') throw new Error('Please specify the name of the application to deploy')

View File

@ -194,7 +194,9 @@ export const push: CommandDefinition<
alias: 'R', alias: 'R',
parameter: 'secrets.yml|.json', parameter: 'secrets.yml|.json',
description: stripIndent` description: stripIndent`
Path to a local YAML or JSON file containing Docker registry passwords used to pull base images`, Path to a local YAML or JSON file containing Docker registry passwords used to pull base images.
Note that if registry-secrets are not provided on the command line, a secrets configuration
file from the balena directory will be used (usually $HOME/.balena/secrets.yml|.json)`,
}, },
{ {
signature: 'nolive', signature: 'nolive',
@ -248,7 +250,7 @@ export const push: CommandDefinition<
const { exitIfNotLoggedIn, exitWithExpectedError } = await import( const { exitIfNotLoggedIn, exitWithExpectedError } = await import(
'../utils/patterns' '../utils/patterns'
); );
const { validateSpecifiedDockerfile, parseRegistrySecrets } = await import( const { validateSpecifiedDockerfile, getRegistrySecrets } = await import(
'../utils/compose_ts' '../utils/compose_ts'
); );
const { BuildError } = await import('../utils/device/errors'); const { BuildError } = await import('../utils/device/errors');
@ -269,9 +271,10 @@ export const push: CommandDefinition<
options.dockerfile, options.dockerfile,
); );
const registrySecrets = options['registry-secrets'] const registrySecrets = await getRegistrySecrets(
? await parseRegistrySecrets(options['registry-secrets']) sdk,
: {}; options['registry-secrets'],
);
const buildTarget = getBuildTarget(appOrDevice); const buildTarget = getBuildTarget(appOrDevice);
switch (buildTarget) { switch (buildTarget) {

View File

@ -21,6 +21,7 @@ import * as MultiBuild from 'resin-multibuild';
import { Readable } from 'stream'; import { Readable } from 'stream';
import * as tar from 'tar-stream'; import * as tar from 'tar-stream';
import { BalenaSDK } from 'balena-sdk';
import { DeviceInfo } from './device/api'; import { DeviceInfo } from './device/api';
import Logger = require('./logger'); import Logger = require('./logger');
@ -31,7 +32,34 @@ export interface RegistrySecrets {
}; };
} }
export async function parseRegistrySecrets( export async function getRegistrySecrets(
sdk: BalenaSDK,
inputFilename?: string,
): Promise<RegistrySecrets> {
const { fs } = await import('mz');
const Path = await import('path');
if (inputFilename != null) {
return await parseRegistrySecrets(inputFilename);
}
const directory = await sdk.settings.get('dataDirectory');
const potentialPaths = [
Path.join(directory, 'secrets.yml'),
Path.join(directory, 'secrets.yaml'),
Path.join(directory, 'secrets.json'),
];
for (const path of potentialPaths) {
if (await fs.exists(path)) {
return await parseRegistrySecrets(path);
}
}
return {};
}
async function parseRegistrySecrets(
secretsFilename: string, secretsFilename: string,
): Promise<RegistrySecrets> { ): Promise<RegistrySecrets> {
const { fs } = await import('mz'); const { fs } = await import('mz');
@ -63,12 +91,14 @@ export async function parseRegistrySecrets(
* This function is meant to be called very early on to validate users' input, * This function is meant to be called very early on to validate users' input,
* before any project loading / building / deploying. * before any project loading / building / deploying.
*/ */
export async function validateComposeOptions(options: { [opt: string]: any }) { export async function validateComposeOptions(
if (options['registry-secrets']) { sdk: BalenaSDK,
options['registry-secrets'] = await parseRegistrySecrets( options: { [opt: string]: any },
) {
options['registry-secrets'] = await getRegistrySecrets(
sdk,
options['registry-secrets'], options['registry-secrets'],
); );
}
} }
/** /**

View File

@ -43,4 +43,7 @@ Sample registry-secrets YAML file:
password: cze14 password: cze14
'eu.gcr.io': # Google Container Registry 'eu.gcr.io': # Google Container Registry
username: '_json_key' username: '_json_key'
password: '{escaped contents of the GCR keyfile.json file}'`; password: '{escaped contents of the GCR keyfile.json file}'
If an option is not specified, and a secrets.yml or secrets.json file exists in
the balena directory (usually $HOME/.balena), this file will be used instead.`;