// This is a helper to take object data and break it into rows add(data, {joiner = this.joiner, sort = this.sort} = {}) { _.forEach(sort ? _.sortBy(_.keys(data)) : _.keys(data), key => { // Do some special things for arrays if (_.isArray(data[key])) data[key] = data[key].join(joiner); // Do something special for objects if (_.isObject(data[key])) data[key] = util.inspect(data[key], {compact: true}); // Do the normal push this.push([(chalk[this.keyColor](_.toUpper(key))), data[key]]); }); }
// Helper to set the LANDO_LOAD_KEYS var const getKeys = (keys = true) => { if (_.isArray(keys)) return keys.join(' '); return keys.toString(); }
_.mergeWith(old, ...fresh, (s, f) => { if (_.isArray(s)) return _.uniq(s.concat(f)); })
constructor(id, options = {}) { options = _.merge({}, config, options); // Make sure our command is an array if (!_.isArray(options.command)) options.command = [options.command]; options.command = options.command.join(' && '); // Build the goz const go = { image: `golang:${options.version}`, ports: (options.command !== 'tail -f /dev/null') ? ['80'] : [], command: `/bin/sh -c "${options.command}"`, }; // Send it downstream super(id, options, {services: _.set({}, options.name, go)}); }
/* * This event makes sure that tooling and event commands that are run against an app container * are run through /helpers/psh-exec.sh first so they get the needed envvars eg HOME, USER, and PLATFORM_* set */ lando.events.on('pre-command-runner', app => { if (_.get(app, 'config.recipe') === 'platformsh') { // This is a cheap way to get the list of platform appservers // @TODO: will node, python, etc appserver still use `web`? const appCache = lando.cache.get(`${app.name}.compose.cache`) || {}; const appservers = _(appCache.info).filter(info => info.meUser === 'web').map('service').value(); // Loop through the tooling _.forEach(app.config.tooling, (tooling, name) => { // Standardize and arrayify tooling const cmd = tooling.cmd ? tooling.cmd : tooling.name; const cmds = (!_.isArray(cmd)) ? [cmd] : cmd; // Reset tooling tooling.cmd = utils.setPshExec(cmds, tooling.service, appservers); }); // Loop through the events _.forEach(app.config.events, (event, name) => { app.config.events[name] = utils.setPshExec(event, 'app', appservers); }); } });
_.map(cmds, cmd => { // Discover the service const command = getCommand(cmd); const service = getService(cmd, data); // Validate the service if we can // @NOTE fast engine runs might not have this data yet if (app.services && !_.includes(app.services, service)) { throw new Error(`This app has no service called ${service}`); } // Add the build command return { id: `${app.project}_${service}_1`, cmd: ['/bin/sh', '-c', _.isArray(command) ? command.join(' ') : command], compose: app.compose, project: app.project, opts: { cstdio: ['inherit', 'pipe', 'pipe'], mode: 'attach', user: getUser(service, app.info), services: [service], }, }; })
// Go through each service _.forEach(services, service => { // Loop through all internal, legacy and user steps _.forEach(rootSteps.concat(buildSteps), section => { // If the service has build sections let's loop through and run some commands if (!_.isEmpty(_.get(app, `config.services.${service}.${section}`, []))) { // Run each command _.forEach(app.config.services[service][section], cmd => { const container = `${app.project}_${service}_1`; build.push({ id: container, cmd: ['/bin/sh', '-c', _.isArray(cmd) ? cmd.join(' ') : cmd], compose: app.compose, project: app.project, opts: { mode: 'attach', cstdio: ['inherit', 'pipe', 'pipe'], prestart, user: (_.includes(rootSteps, section)) ? 'root' : getUser(service, app.info), services: [service], }, }); }); } }); });
function saveHistory(event, cmds = []) { if(noAccessToHistory || historySize === 0 || !_.isArray(cmds) || cmds.length === 0 ) { return; } // remove adjacent duplicates history = _.uniq(history.concat(cmds), true); // trim history updateHistorySize(null, historySize); // rewrite fs.writeFile(HISTORY_FILE, JSON.stringify(history), (err) => { if(err) { noAccessToHistory = true; console.error(`Failed to write history file ${err.message}`); } }); }
constructor(id, options = {}) { options = _.merge({}, config, options); // Arrayify the hosts if needed if (!_.isArray(options.hosts)) options.hosts = [options.hosts]; // Switch to legacy command if needed if (semver.lt(`${options.version}.0`, '5.0.0')) options.command = '/run.sh phpmyadmin'; // Build the default stuff here const pma = { image: `phpmyadmin/phpmyadmin:${options.version}`, environment: { MYSQL_ROOT_PASSWORD: '', PMA_HOSTS: options.hosts.join(','), PMA_PORT: 3306, PMA_USER: 'root', PMA_PASSWORD: '', UPLOAD_LIMIT: 'NOLIMITS!', }, ports: ['80'], command: options.command, }; // Add some info options.info = {backends: options.hosts}; // Send it downstream super(id, options, {services: _.set({}, options.name, pma)}); }
constructor(id, options = {}, factory) { options = _.merge({}, config, options); if (!_.isArray(options.backends)) options.backends = [options.backends];
constructor(id, options = {}) { options = _.merge({}, config, options); if (!_.isArray(options.command)) options.command = [options.command]; options.command = options.command.join(' && ');
constructor(id, options = {}) { options = _.merge({}, config, options); // Make sure our command is an array if (!_.isArray(options.command)) options.command = [options.command]; options.command = options.command.join(' && '); // Build the nodez const dotnet = { image: `microsoft/dotnet:${options.version}-sdk`, environment: { PATH: options.path.join(':'), ASPNETCORE_URLS: `http://+:${options.port}`, }, ports: (options.command !== 'tail -f /dev/null') ? [options.port] : [], volumes: options.volumes, command: `/bin/sh -c "${options.command}"`, }; // Send it downstream super(id, options, {services: _.set({}, options.name, dotnet)}); }
constructor(id, options = {}) { options = _.merge({}, config, options); // Make sure our command is an array if (!_.isArray(options.command)) options.command = [options.command]; options.command = options.command.join(' && '); // Build the nodez const ruby = { image: `ruby:${options.version}`, environment: { PATH: options.path.join(':'), }, ports: (options.command !== 'tail -f /dev/null') ? [options.port] : [], volumes: options.volumes, command: `/bin/sh -c "${options.command}"`, }; // Add port to "moreHttpsPorts" options.moreHttpPorts.push(options.port); // Send it downstream super(id, options, {services: _.set({}, options.name, ruby)}); }
function mergeArrayConcatCustomizer(objValue, srcValue) { if (_.isArray(objValue)) { return objValue.concat(srcValue); } }
constructor(id, options = {}) { options = _.merge({}, config, options); // Make sure our command is an array if (!_.isArray(options.command)) options.command = [options.command]; options.command = options.command.join(' && '); // Build the nodez const python = { image: `python:${options.version}`, environment: { PATH: options.path.join(':'), PIP_USER: 'true', PYTHONUSERBASE: '/var/www/.local', }, ports: (options.command !== 'tail -f /dev/null') ? [options.port] : [], volumes: options.volumes, command: `/bin/sh -c "${options.command}"`, }; // Add port to "moreHttpsPorts" options.moreHttpPorts.push(options.port); // Send it downstream super(id, options, {services: _.set({}, options.name, python)}); }