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:
mike12345567 2020-12-14 18:31:48 +00:00
parent 186fe1e8f1
commit 166bf153de
11 changed files with 149 additions and 6 deletions

View File

@ -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}

View File

@ -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

View File

@ -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)

View File

@ -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)
} }

View File

@ -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),
}
}

View File

@ -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()

View File

@ -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}`

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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)
}