dashboard/shell/store/digitalocean.js

199 lines
4.7 KiB
JavaScript

import { sortBy } from '@shell/utils/sort';
import { addParam, addParams } from '@shell/utils/url';
const ENDPOINT = 'api.digitalocean.com/v2';
const PLAN_SORTS = {
s: 1,
g: 2,
gd: 2,
c: 3,
m: 4,
so: 5,
standard: 98,
other: 99,
};
const VALID_IMAGES = [
/^centos-\d+-x64$/,
/^debian-\d+-x64$/,
/^fedora-\d+-x64$/,
/^ubuntu-\d+-\d+-x64$/,
];
export const state = () => {
return { cache: {} };
};
export const mutations = {
setCache(state, { credentialId, key, value }) {
let cache = state.cache[credentialId];
if ( !cache ) {
cache = {};
state.cache[credentialId] = cache;
}
cache[key] = value;
},
};
export const getters = {
fromCache: (state) => ({ credentialId, key }) => {
return state.cache[credentialId]?.[key];
},
};
export const actions = {
async regionOptions({ state, commit, dispatch }, { credentialId }) {
const regions = await dispatch('cachedCommand', { credentialId, command: 'regions' });
const out = regions.regions.filter((region) => {
return region.available && region.features.includes('metadata');
}).map((region) => {
return {
label: region.name,
value: region.slug,
};
});
return sortBy(out, 'label');
},
async instanceOptions({ dispatch, rootGetters }, { credentialId, region }) {
const regions = await dispatch('cachedCommand', { credentialId, command: 'regions' });
const sizes = await dispatch('cachedCommand', { credentialId, command: 'sizes' });
const regionInfo = regions.regions.find((x) => x.slug === region);
const available = sizes.sizes.filter((size) => regionInfo.sizes.includes(size.slug)).map((size) => {
const match = size.slug.match(/^(so|gd|g|c|m|s).*-/);
const plan = match ? match[1] : (size.slug.includes('-') ? 'standard' : 'other');
const out = {
plan,
planSort: PLAN_SORTS[plan],
memoryGb: size.memory / 1024,
disk: size.disk,
vcpus: size.vcpus,
value: size.slug
};
out.label = rootGetters['i18n/t']('cluster.machineConfig.digitalocean.sizeLabel', out);
return out;
}).filter((size) => size.plan !== 'other');
return sortBy(available, ['planSort', 'memoryGb', 'vcpus', 'disk']);
},
async imageOptions({ dispatch }, { credentialId, region }) {
const images = await dispatch('cachedCommand', { credentialId, command: 'images' });
const out = images.images.filter((x) => {
if ( !x.slug || x.slug.match(/x32/) ) {
return false;
}
let valid = false;
for ( const re of VALID_IMAGES ) {
if ( x.slug.match(re) ) {
valid = true;
break;
}
}
if ( !valid ) {
return false;
}
if ( !x.regions.includes(region) ) {
return false;
}
if ( x.status !== 'available' ) {
return false;
}
return true;
}).map((x) => {
let label = `${ x.distribution || '' } ${ x.name || x.description || '' }`;
label = label.replace(/ image/, '').replace(' x86', '').replace(' x64', '').trim();
if ( !label ) {
label = x.slug;
}
return {
label,
value: x.slug
};
});
return sortBy(out, ['label', 'value']);
},
async cachedCommand({
state, getters, commit, dispatch
}, { credentialId, command }) {
let out = getters['fromCache']({ credentialId, key: command });
if ( !out ) {
out = await dispatch('request', { credentialId, command });
commit('setCache', {
credentialId, key: command, value: out
});
}
return out;
},
async request({ dispatch }, {
token, credentialId, command, opt, out
}) {
opt = opt || {};
let url = '/meta/proxy/';
if ( opt.url ) {
url += opt.url.replace(/^https?:\/\//, '');
} else {
url += `${ ENDPOINT }/${ command }`;
url = addParam(url, 'per_page', opt.per_page || 1000);
url = addParams(url, opt.params || {});
}
const headers = { Accept: 'application/json' };
if ( credentialId ) {
headers['x-api-cattleauth-header'] = `Bearer credID=${ credentialId } passwordField=accessToken`;
} else if ( token ) {
headers['x-api-auth-header'] = `Bearer ${ token }`;
}
const res = await dispatch('management/request', {
url,
headers,
redirectUnauthorized: false,
}, { root: true });
if ( out ) {
out[command] = out[command].concat(res[command]);
} else {
out = res;
}
// De-pagination
if ( res?.links?.pages?.next ) {
opt.url = res.links.pages.next;
return dispatch('request', {
token, credentialId, command, opt, out
});
}
return out;
},
};