From 945eb1ace2d6c0619a77c8ba7f8e124b248208f9 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 29 Sep 2022 15:38:54 +0100 Subject: [PATCH] Updating to add an option for generating admin user credentials as part of hosting, adding a dev command to create a simple, pre-watching environment using all flags. --- packages/cli/package.json | 3 +- packages/cli/src/hosting/genUser.js | 17 +++++++++++ packages/cli/src/hosting/index.js | 6 ++++ packages/cli/src/hosting/init.js | 28 +++++++++++------ packages/cli/src/hosting/utils.js | 22 +++++++++++++- packages/cli/src/hosting/watch.js | 47 +++++++++++------------------ packages/cli/src/plugins/index.js | 23 +++++++++++++- packages/cli/yarn.lock | 5 +++ 8 files changed, 109 insertions(+), 42 deletions(-) create mode 100644 packages/cli/src/hosting/genUser.js diff --git a/packages/cli/package.json b/packages/cli/package.json index f8f7717c15..589bbd9a3b 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -46,7 +46,8 @@ "pouchdb-replication-stream": "1.2.9", "randomstring": "1.1.5", "tar": "6.1.11", - "yaml": "^2.1.1" + "yaml": "^2.1.1", + "find-free-port": "^2.0.0" }, "devDependencies": { "copyfiles": "^2.4.1", diff --git a/packages/cli/src/hosting/genUser.js b/packages/cli/src/hosting/genUser.js new file mode 100644 index 0000000000..b6e078c8bd --- /dev/null +++ b/packages/cli/src/hosting/genUser.js @@ -0,0 +1,17 @@ +const { success } = require("../utils") +const { updateDockerComposeService } = require("./utils") +const randomString = require("randomstring") + +exports.generateUser = async () => { + const email = "admin@admin.com" + const password = randomString.generate({ length: 6 }) + updateDockerComposeService(service => { + service.environment["BB_ADMIN_USER_EMAIL"] = email + service.environment["BB_ADMIN_USER_PASSWORD"] = password + }) + console.log( + success( + `User admin credentials configured, access with email: ${email} - password: ${password}` + ) + ) +} diff --git a/packages/cli/src/hosting/index.js b/packages/cli/src/hosting/index.js index 6f54d6b543..d8133c4959 100644 --- a/packages/cli/src/hosting/index.js +++ b/packages/cli/src/hosting/index.js @@ -5,6 +5,7 @@ const { start } = require("./start") const { stop } = require("./stop") const { status } = require("./status") const { update } = require("./update") +const { generateUser } = require("./genUser") const { watchPlugins } = require("./watch") const command = new Command(`${CommandWords.HOSTING}`) @@ -39,6 +40,11 @@ const command = new Command(`${CommandWords.HOSTING}`) "Add plugin directory watching to a Budibase install.", watchPlugins ) + .addSubOption( + "--gen-user", + "Create an admin user automatically as part of first start.", + generateUser + ) .addSubOption("--single", "Specify this with init to use the single image.") exports.command = command diff --git a/packages/cli/src/hosting/init.js b/packages/cli/src/hosting/init.js index 068e40fb2a..37dfe9b4db 100644 --- a/packages/cli/src/hosting/init.js +++ b/packages/cli/src/hosting/init.js @@ -6,10 +6,11 @@ const axios = require("axios") const { parseEnv } = require("../utils") const { checkDockerConfigured, downloadFiles } = require("./utils") const { watchPlugins } = require("./watch") +const { generateUser } = require("./genUser") const DO_USER_DATA_URL = "http://169.254.169.254/metadata/v1/user-data" -async function getInitConfig(type, isQuick) { +async function getInitConfig(type, isQuick, port) { const config = isQuick ? makeFiles.QUICK_CONFIG : {} if (type === InitTypes.DIGITAL_OCEAN) { try { @@ -24,17 +25,23 @@ async function getInitConfig(type, isQuick) { // don't need to handle error, just don't do anything } } + // override port + if (port) { + config[makeFiles.ConfigMap.MAIN_PORT] = port + } return config } exports.init = async opts => { - let type, isSingle, watchDir + let type, isSingle, watchDir, genUser, port if (typeof opts === "string") { type = opts } else { - type = opts.init - isSingle = opts.single - watchDir = opts.watchPluginDir + type = opts["init"] + isSingle = opts["single"] + watchDir = opts["watchPluginDir"] + genUser = opts["genUser"] + port = opts["port"] } const isQuick = type === InitTypes.QUICK || type === InitTypes.DIGITAL_OCEAN await checkDockerConfigured() @@ -50,14 +57,17 @@ exports.init = async opts => { captureEvent(AnalyticsEvents.SelfHostInit, { type, }) - const config = await getInitConfig(type, isQuick) + const config = await getInitConfig(type, isQuick, port) if (!isSingle) { await downloadFiles() await makeFiles.makeEnv(config) } else { await makeFiles.makeSingleCompose(config) - if (watchDir) { - await watchPlugins(watchDir) - } + } + if (watchDir) { + await watchPlugins(watchDir) + } + if (genUser) { + await generateUser() } } diff --git a/packages/cli/src/hosting/utils.js b/packages/cli/src/hosting/utils.js index d5047c8deb..952974ee83 100644 --- a/packages/cli/src/hosting/utils.js +++ b/packages/cli/src/hosting/utils.js @@ -1,7 +1,7 @@ const { lookpath } = require("lookpath") const fs = require("fs") const makeFiles = require("./makeFiles") -const { logErrorToFile, downloadFile } = require("../utils") +const { logErrorToFile, downloadFile, error } = require("../utils") const yaml = require("yaml") const ERROR_FILE = "docker-error.log" @@ -65,3 +65,23 @@ exports.getAppService = path => { } return { yaml, service } } + +exports.updateDockerComposeService = updateFn => { + const opts = ["docker-compose.yaml", "docker-compose.yml"] + const dockerFilePath = opts.find(name => fs.existsSync(name)) + if (!dockerFilePath) { + console.log(error("Unable to locate docker-compose YAML.")) + return + } + const { yaml: parsedYaml, service } = exports.getAppService(dockerFilePath) + if (!service) { + console.log( + error( + "Unable to locate service within compose file, is it a valid Budibase configuration?" + ) + ) + return + } + updateFn(service) + fs.writeFileSync(dockerFilePath, yaml.stringify(parsedYaml)) +} diff --git a/packages/cli/src/hosting/watch.js b/packages/cli/src/hosting/watch.js index 600c413955..fb51aa9ad8 100644 --- a/packages/cli/src/hosting/watch.js +++ b/packages/cli/src/hosting/watch.js @@ -1,8 +1,7 @@ const { resolve } = require("path") const fs = require("fs") -const yaml = require("yaml") const { error, success } = require("../utils") -const { getAppService } = require("./utils") +const { updateDockerComposeService } = require("./utils") exports.watchPlugins = async pluginPath => { const PLUGIN_PATH = "/plugins" @@ -16,32 +15,20 @@ exports.watchPlugins = async pluginPath => { ) return } - const opts = ["docker-compose.yaml", "docker-compose.yml"] - let dockerFilePath = opts.find(name => fs.existsSync(name)) - if (!dockerFilePath) { - console.log(error("Unable to locate docker-compose YAML.")) - return - } - const { yaml: parsedYaml, service } = getAppService(dockerFilePath) - if (!service) { - console.log( - error( - "Unable to locate service within compose file, is it a valid Budibase configuration?" - ) - ) - return - } - // set environment variable - service.environment["PLUGINS_DIR"] = PLUGIN_PATH - // add volumes to parsed yaml - if (!service.volumes) { - service.volumes = [] - } - const found = service.volumes.find(vol => vol.includes(PLUGIN_PATH)) - if (found) { - service.volumes.splice(service.volumes.indexOf(found), 1) - } - service.volumes.push(`${pluginPath}:${PLUGIN_PATH}`) - fs.writeFileSync(dockerFilePath, yaml.stringify(parsedYaml)) - console.log(success("Docker compose configuration has been updated!")) + updateDockerComposeService(service => { + // set environment variable + service.environment["PLUGINS_DIR"] = PLUGIN_PATH + // add volumes to parsed yaml + if (!service.volumes) { + service.volumes = [] + } + const found = service.volumes.find(vol => vol.includes(PLUGIN_PATH)) + if (found) { + service.volumes.splice(service.volumes.indexOf(found), 1) + } + service.volumes.push(`${pluginPath}:${PLUGIN_PATH}`) + }) + console.log( + success(`Docker compose configured to watch directory: ${pluginPath}`) + ) } diff --git a/packages/cli/src/plugins/index.js b/packages/cli/src/plugins/index.js index 66cca8c19d..1057ca9aaa 100644 --- a/packages/cli/src/plugins/index.js +++ b/packages/cli/src/plugins/index.js @@ -1,5 +1,5 @@ const Command = require("../structures/Command") -const { CommandWords, AnalyticsEvents } = require("../constants") +const { CommandWords, AnalyticsEvents, InitTypes } = require("../constants") const { getSkeleton, fleshOutSkeleton } = require("./skeleton") const questions = require("../questions") const fs = require("fs") @@ -9,6 +9,9 @@ const { runPkgCommand } = require("../exec") const { join } = require("path") const { success, error, info, moveDirectory } = require("../utils") const { captureEvent } = require("../events") +const fp = require("find-free-port") +const { init: hostingInit } = require("../hosting/init") +const { start: hostingStart } = require("../hosting/start") function checkInPlugin() { if (!fs.existsSync("package.json")) { @@ -141,6 +144,19 @@ async function watch() { } } +async function dev() { + const pluginDir = await questions.string("Directory to watch", "./") + const [port] = await fp(10000) + await hostingInit({ + init: InitTypes.QUICK, + single: true, + watchPluginDir: pluginDir, + genUser: true, + port, + }) + await hostingStart() +} + const command = new Command(`${CommandWords.PLUGIN}`) .addHelp( "Custom plugins for Budibase, init, build and verify your components and datasources with this tool." @@ -160,5 +176,10 @@ const command = new Command(`${CommandWords.PLUGIN}`) "Automatically build any changes to your plugin.", watch ) + .addSubOption( + "--dev", + "Run a development environment which automatically watches the current directory.", + dev + ) exports.command = command diff --git a/packages/cli/yarn.lock b/packages/cli/yarn.lock index e664e587e6..0850f94154 100644 --- a/packages/cli/yarn.lock +++ b/packages/cli/yarn.lock @@ -1113,6 +1113,11 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +find-free-port@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-free-port/-/find-free-port-2.0.0.tgz#4b22e5f6579eb1a38c41ac6bcb3efed1b6da9b1b" + integrity sha512-J1j8gfEVf5FN4PR5w5wrZZ7NYs2IvqsHcd03cAeQx3Ec/mo+lKceaVNhpsRKoZpZKbId88o8qh+dwUwzBV6WCg== + find-replace@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38"