WIP - starting to work on deployment and hosting so that they don't use static URLs anymore to reach assets, instead using environment variables to determine what to use.
This commit is contained in:
parent
186fe1e8f1
commit
166bf153de
|
@ -10,6 +10,7 @@ services:
|
||||||
environment:
|
environment:
|
||||||
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
|
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
|
||||||
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
|
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
|
||||||
|
MINIO_URL: http://minio-service:9000
|
||||||
SELF_HOSTED: 1
|
SELF_HOSTED: 1
|
||||||
COUCH_DB_URL: http://${COUCH_DB_USER}:${COUCH_DB_PASSWORD}@couchdb-service:5984
|
COUCH_DB_URL: http://${COUCH_DB_USER}:${COUCH_DB_PASSWORD}@couchdb-service:5984
|
||||||
BUDIBASE_ENVIRONMENT: ${BUDIBASE_ENVIRONMENT}
|
BUDIBASE_ENVIRONMENT: ${BUDIBASE_ENVIRONMENT}
|
||||||
|
|
|
@ -3,4 +3,5 @@ MINIO_SECRET_KEY=budibase
|
||||||
COUCH_DB_PASSWORD=budibase
|
COUCH_DB_PASSWORD=budibase
|
||||||
COUCH_DB_USER=budibase
|
COUCH_DB_USER=budibase
|
||||||
BUDIBASE_ENVIRONMENT=PRODUCTION
|
BUDIBASE_ENVIRONMENT=PRODUCTION
|
||||||
|
HOSTING_URL="http://localhost:4001"
|
||||||
LOGO_URL=https://logoipsum.com/logo/logo-15.svg
|
LOGO_URL=https://logoipsum.com/logo/logo-15.svg
|
||||||
|
|
|
@ -150,6 +150,9 @@ exports.create = async function(ctx) {
|
||||||
name: ctx.request.body.name,
|
name: ctx.request.body.name,
|
||||||
template: ctx.request.body.template,
|
template: ctx.request.body.template,
|
||||||
instance: instance,
|
instance: instance,
|
||||||
|
deployment: {
|
||||||
|
type: "cloud",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
const instanceDb = new CouchDB(appId)
|
const instanceDb = new CouchDB(appId)
|
||||||
await instanceDb.put(newApplication)
|
await instanceDb.put(newApplication)
|
||||||
|
|
|
@ -20,7 +20,7 @@ exports.postDeployment = async function() {
|
||||||
exports.deploy = async function(deployment) {
|
exports.deploy = async function(deployment) {
|
||||||
const appId = deployment.getAppId()
|
const appId = deployment.getAppId()
|
||||||
var objClient = new AWS.S3({
|
var objClient = new AWS.S3({
|
||||||
endpoint: "http://localhost:9000",
|
endpoint: env.MINIO_URL,
|
||||||
s3ForcePathStyle: true, // needed with minio?
|
s3ForcePathStyle: true, // needed with minio?
|
||||||
signatureVersion: "v4",
|
signatureVersion: "v4",
|
||||||
params: {
|
params: {
|
||||||
|
@ -46,6 +46,7 @@ exports.deploy = async function(deployment) {
|
||||||
exports.replicateDb = async function(deployment) {
|
exports.replicateDb = async function(deployment) {
|
||||||
const appId = deployment.getAppId()
|
const appId = deployment.getAppId()
|
||||||
const localDb = new PouchDB(appId)
|
const localDb = new PouchDB(appId)
|
||||||
|
|
||||||
const remoteDb = new CouchDB(`${env.COUCH_DB_URL}/${appId}`)
|
const remoteDb = new CouchDB(`${env.COUCH_DB_URL}/${appId}`)
|
||||||
return performReplication(localDb, remoteDb)
|
return performReplication(localDb, remoteDb)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
const CouchDB = require("../../db")
|
||||||
|
const { BUILDER_CONFIG_DB, HOSTING_DOC } = require("../../constants")
|
||||||
|
const {
|
||||||
|
getHostingInfo,
|
||||||
|
HostingTypes,
|
||||||
|
getAppServerUrl,
|
||||||
|
} = require("../../utilities/builder/hosting")
|
||||||
|
|
||||||
|
exports.fetchInfo = async ctx => {
|
||||||
|
ctx.body = {
|
||||||
|
types: Object.values(HostingTypes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.save = async ctx => {
|
||||||
|
const db = new CouchDB(BUILDER_CONFIG_DB)
|
||||||
|
const { type, appServerUrl, objectStoreUrl, useHttps } = ctx.request.body
|
||||||
|
if (type === HostingTypes.CLOUD) {
|
||||||
|
ctx.throw(400, "Cannot update Cloud hosting information")
|
||||||
|
}
|
||||||
|
await db.put({
|
||||||
|
_id: HOSTING_DOC,
|
||||||
|
type,
|
||||||
|
appServerUrl,
|
||||||
|
objectStoreUrl,
|
||||||
|
useHttps,
|
||||||
|
})
|
||||||
|
ctx.body = "Hosting information saved successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.fetch = async ctx => {
|
||||||
|
ctx.body = await getHostingInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.fetchUrls = async ctx => {
|
||||||
|
ctx.body = {
|
||||||
|
appServer: getAppServerUrl(ctx.appId),
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,22 @@ const setBuilderToken = require("../../../utilities/builder/setBuilderToken")
|
||||||
const fileProcessor = require("../../../utilities/fileProcessor")
|
const fileProcessor = require("../../../utilities/fileProcessor")
|
||||||
const env = require("../../../environment")
|
const env = require("../../../environment")
|
||||||
|
|
||||||
|
function appServerUrl(appId) {
|
||||||
|
if (env.SELF_HOSTED) {
|
||||||
|
return env.HOSTING_URL
|
||||||
|
} else {
|
||||||
|
return `https://${appId}.app.budi.live`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function objectStoreUrl() {
|
||||||
|
if (env.SELF_HOSTED) {
|
||||||
|
return env.MINIO_URL
|
||||||
|
} else {
|
||||||
|
return "https://cdn.app.budi.live/assets"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// this was the version before we started versioning the component library
|
// this was the version before we started versioning the component library
|
||||||
const COMP_LIB_BASE_APP_VERSION = "0.2.5"
|
const COMP_LIB_BASE_APP_VERSION = "0.2.5"
|
||||||
|
|
||||||
|
@ -148,6 +164,7 @@ exports.serveApp = async function(ctx) {
|
||||||
title: appInfo.name,
|
title: appInfo.name,
|
||||||
production: env.CLOUD,
|
production: env.CLOUD,
|
||||||
appId: ctx.params.appId,
|
appId: ctx.params.appId,
|
||||||
|
appServerUrl: appServerUrl(ctx.params.appId),
|
||||||
})
|
})
|
||||||
|
|
||||||
const template = handlebars.compile(
|
const template = handlebars.compile(
|
||||||
|
@ -166,8 +183,9 @@ exports.serveAttachment = async function(ctx) {
|
||||||
const attachmentsPath = resolve(budibaseAppsDir(), appId, "attachments")
|
const attachmentsPath = resolve(budibaseAppsDir(), appId, "attachments")
|
||||||
|
|
||||||
// Serve from CloudFront
|
// Serve from CloudFront
|
||||||
|
// TODO: need to replace this with link to self hosted object store
|
||||||
if (env.CLOUD) {
|
if (env.CLOUD) {
|
||||||
const S3_URL = `https://cdn.app.budi.live/assets/${appId}/attachments/${ctx.file}`
|
const S3_URL = join(objectStoreUrl(), appId, "attachments", ctx.file)
|
||||||
const response = await fetch(S3_URL)
|
const response = await fetch(S3_URL)
|
||||||
const body = await response.text()
|
const body = await response.text()
|
||||||
ctx.set("Content-Type", response.headers.get("Content-Type"))
|
ctx.set("Content-Type", response.headers.get("Content-Type"))
|
||||||
|
@ -213,7 +231,14 @@ exports.serveComponentLibrary = async function(ctx) {
|
||||||
componentLib += `-${COMP_LIB_BASE_APP_VERSION}`
|
componentLib += `-${COMP_LIB_BASE_APP_VERSION}`
|
||||||
}
|
}
|
||||||
const S3_URL = encodeURI(
|
const S3_URL = encodeURI(
|
||||||
`https://${appId}.app.budi.live/assets/${componentLib}/${ctx.query.library}/dist/index.js`
|
join(
|
||||||
|
appServerUrl(appId),
|
||||||
|
"assets",
|
||||||
|
componentLib,
|
||||||
|
ctx.query.library,
|
||||||
|
"dist",
|
||||||
|
"index.js"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
const response = await fetch(S3_URL)
|
const response = await fetch(S3_URL)
|
||||||
const body = await response.text()
|
const body = await response.text()
|
||||||
|
|
|
@ -4,12 +4,11 @@
|
||||||
|
|
||||||
export let appId
|
export let appId
|
||||||
export let production
|
export let production
|
||||||
|
export let appServerUrl
|
||||||
export const PRODUCTION_ASSETS_URL = `https://${appId}.app.budi.live`
|
|
||||||
|
|
||||||
function publicPath(path) {
|
function publicPath(path) {
|
||||||
if (production) {
|
if (production) {
|
||||||
return `${PRODUCTION_ASSETS_URL}/assets/${appId}/${path}`
|
return `${appServerUrl}/assets/${appId}/${path}`
|
||||||
}
|
}
|
||||||
|
|
||||||
return `/assets/${path}`
|
return `/assets/${path}`
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
const Router = require("@koa/router")
|
||||||
|
const controller = require("../controllers/hosting")
|
||||||
|
const authorized = require("../../middleware/authorized")
|
||||||
|
const { BUILDER } = require("../../utilities/security/permissions")
|
||||||
|
|
||||||
|
const router = Router()
|
||||||
|
|
||||||
|
router
|
||||||
|
.fetch("/api/hosting/info", authorized(BUILDER), controller.fetchInfo)
|
||||||
|
.fetch("/api/hosting", authorized(BUILDER), controller.fetch)
|
||||||
|
.post("/api/hosting", authorized(BUILDER), controller.save)
|
||||||
|
|
||||||
|
module.exports = router
|
|
@ -41,3 +41,5 @@ const USERS_TABLE_SCHEMA = {
|
||||||
|
|
||||||
exports.AuthTypes = AuthTypes
|
exports.AuthTypes = AuthTypes
|
||||||
exports.USERS_TABLE_SCHEMA = USERS_TABLE_SCHEMA
|
exports.USERS_TABLE_SCHEMA = USERS_TABLE_SCHEMA
|
||||||
|
exports.BUILDER_CONFIG_DB = "builder-config-db"
|
||||||
|
exports.HOSTING_DOC = "hosting-doc"
|
||||||
|
|
|
@ -39,6 +39,8 @@ module.exports = {
|
||||||
// self hosting features
|
// self hosting features
|
||||||
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
|
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
|
||||||
MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
|
MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
|
||||||
|
MINIO_URL: process.MINIO_URL,
|
||||||
|
HOSTING_URL: process.HOSTING_URL,
|
||||||
LOGO_URL: process.env.LOGO_URL,
|
LOGO_URL: process.env.LOGO_URL,
|
||||||
_set(key, value) {
|
_set(key, value) {
|
||||||
process.env[key] = value
|
process.env[key] = value
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
const CouchDB = require("../../db")
|
||||||
|
const { BUILDER_CONFIG_DB, HOSTING_DOC } = require("../../constants")
|
||||||
|
const { join } = require("path")
|
||||||
|
|
||||||
|
function getProtocol(hostingInfo) {
|
||||||
|
return hostingInfo.useHttps ? "https://" : "http://"
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.HostingTypes = {
|
||||||
|
CLOUD: "cloud",
|
||||||
|
SELF: "self",
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getHostingInfo = async () => {
|
||||||
|
const db = new CouchDB(BUILDER_CONFIG_DB)
|
||||||
|
let doc
|
||||||
|
try {
|
||||||
|
doc = await db.get(HOSTING_DOC)
|
||||||
|
} catch (err) {
|
||||||
|
// don't write this doc, want to be able to update these default props
|
||||||
|
// for our servers with a new release without needing to worry about state of
|
||||||
|
// PouchDB in peoples installations
|
||||||
|
doc = {
|
||||||
|
_id: HOSTING_DOC,
|
||||||
|
type: exports.HostingTypes.CLOUD,
|
||||||
|
appServerUrl: "app.budi.live",
|
||||||
|
objectStoreUrl: "cdn.app.budi.live",
|
||||||
|
templatesUrl: "prod-budi-templates.s3-eu-west-1.amazonaws.com",
|
||||||
|
useHttps: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return doc
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getAppServerUrl = async (appId) => {
|
||||||
|
const hostingInfo = await exports.getHostingInfo()
|
||||||
|
const protocol = getProtocol(hostingInfo)
|
||||||
|
let url
|
||||||
|
if (hostingInfo.type === "cloud") {
|
||||||
|
url = `${protocol}${appId}.${hostingInfo.appServerUrl}`
|
||||||
|
} else {
|
||||||
|
url = `${protocol}${hostingInfo.appServerUrl}`
|
||||||
|
}
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getTemplatesUrl = async (appId, type, name) => {
|
||||||
|
const hostingInfo = await exports.getHostingInfo()
|
||||||
|
const protocol = getProtocol(hostingInfo)
|
||||||
|
let path
|
||||||
|
if (type && name) {
|
||||||
|
path = join("templates", type, `${name}.tar.gz`)
|
||||||
|
} else {
|
||||||
|
path = "manifest.json"
|
||||||
|
}
|
||||||
|
return join(`${protocol}${hostingInfo.templatesUrl}`, path)
|
||||||
|
}
|
Loading…
Reference in New Issue