import { hash } from 'rsvp'; import { get, set, computed, observer } from '@ember/object'; import { alias } from '@ember/object/computed'; import Component from '@ember/component'; import NodeDriver, {registerDisplayLocation, registerDisplaySize } from 'shared/mixins/node-driver'; import fetch from 'ember-api-store/utils/fetch'; import { addQueryParam, addQueryParams } from 'shared/utils/util'; import layout from './template'; import { inject as service } from '@ember/service'; registerDisplayLocation(DRIVER, 'config.region'); registerDisplaySize(DRIVER, 'config.size'); const DRIVER = 'digitalocean'; const DIGITALOCEAN_API = 'api.digitalocean.com/v2'; const VALID_IMAGES = [ 'rancheros', // 'centos-6-x64', 'centos-7-x64', 'coreos-alpha', 'coreos-beta', 'coreos-stable', // 'debian-7-x64', 'debian-8-x64', 'fedora-23-x64', 'fedora-24-x64', // 'freebsd-10-1-x64', // 'freebsd-10-2-x64', 'ubuntu-14-04-x64', 'ubuntu-16-04-x64', 'ubuntu-18-04-x64', // 'ubuntu-16-10-x64' ]; export default Component.extend(NodeDriver, { app: service(), layout, driverName: 'digitalocean', regionChoices: null, model: null, config: alias('model.digitaloceanConfig'), step: 1, sizeChoices: null, imageChoices: null, filteredSizeChoices: computed('config.region', function(){ let region = get(this,'regionChoices').findBy('slug', get(this,'config.region')); let sizes = get(this,'sizeChoices'); let out = sizes.filter((size) => { return region.sizes.indexOf(size.slug) >= 0; }); return out; }), actions: { getData(cb) { let promises = { regions: this.apiRequest('regions'), images: this.apiRequest('images', {params: {type: 'distribution'}}), sizes: this.apiRequest('sizes') }; hash(promises).then((hash) => { let filteredRegions = hash.regions.regions.filter(function(region) { return region.available && (region.features.indexOf('metadata') >= 0); }).sortBy('name'); let filteredSizes = hash.sizes.sizes.map((size) => { size.memoryGb = size.memory/1024; size.highMem = size.slug.indexOf('m-') >= 0; return size; }).filter((size) => { return size.available; }).sortBy('highMem','memory'); let filteredImages = hash.images.images.filter(function(image) { // 64-bit only return !((image.name||'').match(/x32$/)); }).map(function(image) { image.disabled = VALID_IMAGES.indexOf(image.slug) === -1; return image; }); filteredImages = filteredImages.sortBy('distribution','name'); this.setProperties({ regionChoices: filteredRegions, sizeChoices: filteredSizes, imageChoices: filteredImages }); this.setProperties({ step: 2, errors: null, }); this.sendAction('hidePicker'); }, (err) => { let errors = get(this,'errors') || []; errors.push(`${err.statusText}: ${err.body.message}`); this.setProperties({ errors: errors, }); cb(); }); }, }, bootstrap() { let config = get(this,'globalStore').createRecord({ type: 'digitaloceanConfig', size: '1gb', region: 'nyc3', image: 'ubuntu-16-04-x64', sshUser: 'root' }); const model = get(this, 'model'); set(model, 'digitaloceanConfig', config); }, imageChanged: observer('config.image', function() { const image = get(this, 'config.image'); const user = get(this, 'config.sshUser'); if ( image === 'rancheros' && user === 'root' ) { set(this, 'config.sshUser', 'rancher'); } else if ( image !== 'rancheros' && user === 'rancher' ) { set(this, 'config.sshUser', 'root'); } }), apiRequest(command, opt, out) { opt = opt || {}; let url = get(this,'app.proxyEndpoint')+'/'; if ( opt.url ) { url += opt.url.replace(/^http[s]?\/\//,''); } else { url += `${DIGITALOCEAN_API}/${command}`; url = addQueryParam(url,'per_page', opt.per_page || 100); url = addQueryParams(url,opt.params||{}); } return fetch(url, { headers: { 'Accept': 'application/json', 'X-Api-Auth-Header': 'Bearer ' + get(this,'config.accessToken'), }, }).then((res) => { let body = res.body; if ( out ) { out[command].pushObjects(body[command]); } else { out = body; } // De-paging if ( body && body.links && body.links.pages && body.links.pages.next ) { opt.url = body.links.pages.next; return this.apiRequest(command, opt, out).then(() => { return out; }); } else { return out; } }); } });