diff --git a/baseimage/createCaasImage b/baseimage/createCaasImage deleted file mode 100755 index 2bf7a70d4..000000000 --- a/baseimage/createCaasImage +++ /dev/null @@ -1,179 +0,0 @@ -#!/bin/bash - -set -eu -o pipefail - -assertNotEmpty() { - : "${!1:? "$1 is not set."}" -} - -readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -readonly SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd)" -export JSON="${SOURCE_DIR}/node_modules/.bin/json" - -revision=$(git rev-parse HEAD) -box_name="" -server_id="" -server_ip="" -destroy_server="yes" -deploy_env="dev" - -# Only GNU getopt supports long options. OS X comes bundled with the BSD getopt -# brew install gnu-getopt to get the GNU getopt on OS X -[[ $(uname -s) == "Darwin" ]] && GNU_GETOPT="/usr/local/opt/gnu-getopt/bin/getopt" || GNU_GETOPT="getopt" -readonly GNU_GETOPT - -args=$(${GNU_GETOPT} -o "" -l "revision:,regions:,size:,name:,no-destroy,env:" -n "$0" -- "$@") -eval set -- "${args}" - -while true; do - case "$1" in - --env) deploy_env="$2"; shift 2;; - --revision) revision="$2"; shift 2;; - --name) box_name="$2"; destroy_server="no"; shift 2;; - --no-destroy) destroy_server="no"; shift 2;; - --) break;; - *) echo "Unknown option $1"; exit 1;; - esac -done - -echo "Creating digitalocean image" -if [[ "${deploy_env}" == "staging" ]]; then - assertNotEmpty DIGITAL_OCEAN_TOKEN_STAGING - export DIGITAL_OCEAN_TOKEN="${DIGITAL_OCEAN_TOKEN_STAGING}" -elif [[ "${deploy_env}" == "dev" ]]; then - assertNotEmpty DIGITAL_OCEAN_TOKEN_DEV - export DIGITAL_OCEAN_TOKEN="${DIGITAL_OCEAN_TOKEN_DEV}" -elif [[ "${deploy_env}" == "prod" ]]; then - assertNotEmpty DIGITAL_OCEAN_TOKEN_PROD - export DIGITAL_OCEAN_TOKEN="${DIGITAL_OCEAN_TOKEN_PROD}" -else - echo "No such env ${deploy_env}." - exit 1 -fi - -vps="/bin/bash ${SCRIPT_DIR}/digitalocean.sh" - -readonly ssh_keys="${HOME}/.ssh/id_rsa_caas_${deploy_env}" -readonly scp202="scp -P 202 -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i ${ssh_keys}" -readonly scp22="scp -o ConnectTimeout=10 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i ${ssh_keys}" - -readonly ssh202="ssh -p 202 -o IdentitiesOnly=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i ${ssh_keys}" -readonly ssh22="ssh -o IdentitiesOnly=yes -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i ${ssh_keys}" - -if [[ ! -f "${ssh_keys}" ]]; then - echo "caas ssh key is missing at ${ssh_keys} (pick it up from secrets repo)" - exit 1 -fi - -function get_pretty_revision() { - local git_rev="$1" - local sha1=$(git rev-parse --short "${git_rev}" 2>/dev/null) - - echo "${sha1}" -} - -now=$(date "+%Y-%m-%d-%H%M%S") -pretty_revision=$(get_pretty_revision "${revision}") - -if [[ -z "${box_name}" ]]; then - # if you change this, change the regexp is appstore/janitor.js - box_name="box-${deploy_env}-${pretty_revision}-${now}" # remove slashes - - # create a new server if no name given - if ! caas_ssh_key_id=$($vps get_ssh_key_id "caas"); then - echo "Could not query caas ssh key" - exit 1 - fi - echo "Detected caas ssh key id: ${caas_ssh_key_id}" - - echo "Creating Server with name [${box_name}]" - if ! server_id=$($vps create ${caas_ssh_key_id} ${box_name}); then - echo "Failed to create server" - exit 1 - fi - echo "Created server with id: ${server_id}" - - # If we run scripts overenthusiastically without the wait, setup script randomly fails - echo -n "Waiting 120 seconds for server creation" - for i in $(seq 1 24); do - echo -n "." - sleep 5 - done - echo "" -else - if ! server_id=$($vps get_id "${box_name}"); then - echo "Could not determine id from name" - exit 1 - fi - echo "Reusing server with id: ${server_id}" - - $vps power_on "${server_id}" -fi - -# Query until we get an IP -while true; do - echo "Trying to get the server IP" - if server_ip=$($vps get_ip "${server_id}"); then - echo "Server IP : [${server_ip}]" - break - fi - echo "Timedout, trying again in 10 seconds" - sleep 10 -done - -while true; do - echo "Trying to copy init script to server" - if $scp22 "${SCRIPT_DIR}/initializeBaseUbuntuImage.sh" root@${server_ip}:.; then - break - fi - echo "Timedout, trying again in 30 seconds" - sleep 30 -done - -echo "Copying infra_version.js" -$scp22 "${SCRIPT_DIR}/../src/infra_version.js" root@${server_ip}:. - -echo "Copying box source" -cd "${SOURCE_DIR}" -git archive --format=tar HEAD | $ssh22 "root@${server_ip}" "cat - > /tmp/box.tar.gz" - -echo "Executing init script" -if ! $ssh22 "root@${server_ip}" "/bin/bash /root/initializeBaseUbuntuImage.sh caas"; then - echo "Init script failed" - exit 1 -fi - -echo "Shutting down server with id : ${server_id}" -$ssh22 "root@${server_ip}" "shutdown -f now" || true # shutdown sometimes terminates ssh connection immediately making this command fail - -# wait 10 secs for actual shutdown -echo "Waiting for 10 seconds for server to shutdown" -sleep 30 - -echo "Powering off server" -if ! $vps power_off "${server_id}"; then - echo "Could not power off server" - exit 1 -fi - -snapshot_name="box-${deploy_env}-${pretty_revision}-${now}" -echo "Snapshotting as ${snapshot_name}" -if ! image_id=$($vps snapshot "${server_id}" "${snapshot_name}"); then - echo "Could not snapshot and get image id" - exit 1 -fi - -if [[ "${destroy_server}" == "yes" ]]; then - echo "Destroying server" - if ! $vps destroy "${server_id}"; then - echo "Could not destroy server" - exit 1 - fi -else - echo "Skipping server destroy" -fi - -echo "Transferring image ${image_id} to other regions" -$vps transfer_image_to_all_regions "${image_id}" - -echo "Done." diff --git a/src/routes/test/caas-test.js b/src/routes/test/caas-test.js deleted file mode 100644 index 47b3f59d8..000000000 --- a/src/routes/test/caas-test.js +++ /dev/null @@ -1,172 +0,0 @@ -/* global it:false */ -/* global describe:false */ -/* global xdescribe:false */ -/* global before:false */ -/* global after:false */ - -'use strict'; - -var appdb = require('../../appdb.js'), - async = require('async'), - config = require('../../config.js'), - database = require('../../database.js'), - domains = require('../../domains.js'), - expect = require('expect.js'), - locker = require('../../locker.js'), - nock = require('nock'), - superagent = require('superagent'), - server = require('../../server.js'), - settings = require('../../settings.js'), - settingsdb = require('../../settingsdb.js'), - shell = require('../../shell.js'); - -const SERVER_URL = 'http://localhost:' + config.get('port'); -const USERNAME = 'superadmin'; -const PASSWORD = 'Foobar?1337'; -const EMAIL ='silly@me.com'; - -const DOMAIN_0 = { - domain: 'example-backups-test.com', - zoneName: 'example-backups-test.com', - config: {}, - provider: 'noop', - fallbackCertificate: null, - tlsConfig: { provider: 'fallback' } -}; - -let AUDIT_SOURCE = { ip: '1.2.3.4' }; - -var token = null, ownerId = null; -var gSudoOriginal = null; -function injectShellMock() { - gSudoOriginal = shell.sudo; - shell.sudo = function (tag, options, callback) { callback(null); }; -} - -function restoreShellMock() { - shell.sudo = gSudoOriginal; -} - -function setup(done) { - nock.cleanAll(); - config._reset(); - config.set('provider', 'caas'); - - async.series([ - server.start.bind(server), - - database._clear, - - settingsdb.set.bind(null, settings.CAAS_CONFIG_KEY, JSON.stringify({ boxId: 'BOX_ID', token: 'ACCESS_TOKEN2' })), - domains.add.bind(null, DOMAIN_0.domain, DOMAIN_0, AUDIT_SOURCE), - - function createAdmin(callback) { - var scope1 = nock(config.apiServerOrigin()).get('/api/v1/caas/boxes/BOX_ID/setup/verify?setupToken=somesetuptoken').reply(200, {}); - var scope2 = nock(config.apiServerOrigin()).post('/api/v1/caas/boxes/BOX_ID/setup/done?setupToken=somesetuptoken').reply(201, {}); - - superagent.post(SERVER_URL + '/api/v1/cloudron/activate') - .query({ setupToken: 'somesetuptoken' }) - .send({ username: USERNAME, password: PASSWORD, email: EMAIL }) - .end(function (error, result) { - expect(result).to.be.ok(); - expect(result.statusCode).to.eql(201); - expect(scope1.isDone()).to.be.ok(); - expect(scope2.isDone()).to.be.ok(); - - // stash token for further use - ownerId = result.body.userId; - token = result.body.token; - - callback(); - }); - }, - - function addApp(callback) { - var manifest = { version: '0.0.1', manifestVersion: 1, dockerImage: 'foo', healthCheckPath: '/', httpPort: 3, title: 'ok', addons: { } }; - appdb.add('appid', 'appStoreId', manifest, 'location', DOMAIN_0.domain, ownerId, [ ] /* portBindings */, { }, callback); - }, - - function createSettings(callback) { - settings.setBackupConfig({ provider: 'filesystem', backupFolder: '/tmp', format: 'tgz' }, callback); - } - ], done); -} - -function cleanup(done) { - database._clear(function (error) { - expect(!error).to.be.ok(); - - server.stop(done); - }); -} - -describe('Caas', function () { - describe('activate', function () { - before(setup); - after(cleanup); - - it('fails due to missing setupToken', function (done) { - superagent.post(SERVER_URL + '/api/v1/cloudron/activate') - .send({ username: '', password: 'somepassword', email: 'admin@foo.bar' }) - .end(function (error, result) { - expect(result.statusCode).to.equal(400); - done(); - }); - }); - - // note that while the server itself returns 503, the cloudron gets activated. this is just the way it is - it('fails due to internal server error on appstore side', function (done) { - var scope = nock(config.apiServerOrigin()).get('/api/v1/caas/boxes/BOX_ID/setup/verify?setupToken=somesetuptoken').reply(500, { message: 'this is wrong' }); - - superagent.post(SERVER_URL + '/api/v1/cloudron/activate') - .query({ setupToken: 'somesetuptoken' }) - .send({ username: 'someuser', password: 'strong#A3asdf', email: 'admin@foo.bar' }) - .end(function (error, result) { - expect(result.statusCode).to.equal(424); - expect(scope.isDone()).to.be.ok(); - done(); - }); - }); - - xit('succeeds', function (done) { - var scope1 = nock(config.apiServerOrigin()).get('/api/v1/caas/boxes/BOX_ID/setup/verify?setupToken=somesetuptoken').reply(200, {}); - var scope2 = nock(config.apiServerOrigin()).post('/api/v1/caas/boxes/BOX_ID/setup/done?setupToken=somesetuptoken').reply(201, {}); - - superagent.post(SERVER_URL + '/api/v1/cloudron/activate') - .query({ setupToken: 'somesetuptoken' }) - .send({ username: 'someuser', password: 'ADSF#asd546', email: 'admin@foo.bar', displayName: 'tester' }) - .end(function (error, result) { - console.dir(error); - expect(result.statusCode).to.equal(201); - expect(scope1.isDone()).to.be.ok(); - expect(scope2.isDone()).to.be.ok(); - done(); - }); - }); - }); - - describe('Backups API', function () { - var scope1 = nock(config.apiServerOrigin()).post('/api/v1/caas/boxes/BOX_ID/awscredentials?token=BACKUP_TOKEN') - .reply(201, { credentials: { AccessKeyId: 'accessKeyId', SecretAccessKey: 'secretAccessKey' } }, { 'Content-Type': 'application/json' }); - - before(setup); - after(cleanup); - - it('calls the appstore after backup is done', function (done) { - superagent.post(SERVER_URL + '/api/v1/backups/create') - .query({ access_token: token }) - .end(function (error, result) { - expect(result.statusCode).to.equal(202); - - function checkAppstoreServerCalled() { - if (scope1.isDone()) return done(); - - setTimeout(checkAppstoreServerCalled, 100); - } - - checkAppstoreServerCalled(); - }); - }); - }); -}); - diff --git a/src/sysinfo.js b/src/sysinfo.js index 0b65e908f..323b7193d 100644 --- a/src/sysinfo.js +++ b/src/sysinfo.js @@ -7,7 +7,6 @@ exports = module.exports = { }; var assert = require('assert'), - caas = require('./sysinfo/caas.js'), config = require('./config.js'), ec2 = require('./sysinfo/ec2.js'), generic = require('./sysinfo/generic.js'), @@ -40,7 +39,6 @@ function getApi(callback) { assert.strictEqual(typeof callback, 'function'); switch (config.provider()) { - case 'caas': return callback(null, caas); case 'ec2': return callback(null, ec2); case 'lightsail': return callback(null, ec2); case 'ami': return callback(null, ec2); diff --git a/src/sysinfo/caas.js b/src/sysinfo/caas.js deleted file mode 100644 index df1e53c47..000000000 --- a/src/sysinfo/caas.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -exports = module.exports = { - getPublicIp: getPublicIp -}; - -var assert = require('assert'), - superagent = require('superagent'), - safe = require('safetydance'), - SysInfoError = require('../sysinfo.js').SysInfoError; - -function getPublicIp(callback) { - assert.strictEqual(typeof callback, 'function'); - - if (process.env.BOX_ENV === 'test') return callback(null, '127.0.0.1'); - - superagent.get('http://169.254.169.254/metadata/v1.json').timeout(30 * 1000).end(function (error, result) { - if (error || result.statusCode !== 200) { - console.error('Error getting metadata', error); - return callback(new SysInfoError(SysInfoError.EXTERNAL_ERROR, 'Could not detect public IP from metadata')); - } - - // Note that we do not use a floating IP for 3 reasons: - // The PTR record is not set to floating IP, the outbound interface is not changeable to floating IP - // and there are reports that port 25 on floating IP is blocked. - var ip = safe.query(result.body, 'interfaces.public[0].ipv4.ip_address'); - if (!ip) return callback(new SysInfoError(SysInfoError.EXTERNAL_ERROR, 'Could not detect public IP from interface')); - - callback(null, ip); - }); -}