| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- const PortainerClient = require('portainer-api-client')
- const fs = require('fs')
- const figlet = require('figlet')
- const TYPES = {
- swarm: 1,
- compose: 2
- }
- const createClient = (config) => {
- config = Object.assign({
- url: null,
- username: null,
- password: null
- }, config)
- const log = config.log || console.log
- const warning = `# ${figlet.textSync('WARNING!', 'Colossal').split('\n').join('\n# ')}\n# This stack was deployed automatically. Any changes made here may be overwritten.\n#\n\n`
- const client = new PortainerClient(config.url, config.username, config.password);
- const call = async (method, path, data) => {
- if (config.verbose) log(method, path, data ? JSON.stringify(data, null, 4) : '')
- const result = await client.callApiWithKey(method, path, data)
- if (config.verbose) log(JSON.stringify(result, null, 4))
- return result
- }
- const getEndpointSwarm = async (endpointId) => await call('get', `/api/endpoints/${encodeURIComponent(endpointId)}/docker/swarm`)
- const getEndpoints = async () => await call('get', '/api/endpoints')
- const getSwarms = async () => await call('get', '/api/swarms')
- const getStacks = async () => await call('get', '/api/stacks')
- const deleteStack = async (opts) => {
- opts = Object.assign({
- name: null,
- id: null,
- endpointId: null
- }, opts)
- if (!opts.id) {
- if (!opts.name) {
- throw new Error('Either name or id required')
- }
- const stacks = await getStacks()
- const stack = stacks.find(x => x.Name === opts.name)
- if (!stack) throw new Error(`Stack ${opts.name} not found.`)
- opts.id = stack.Id
- }
- if (!opts.endpointId) {
- const endpoints = await getEndpoints()
- if (!endpoints || !endpoints.length) throw new Error('Could not find any endpoints')
- opts.endpointId = endpoints[0].Id
- }
- console.log(`Deleting stack ${opts.id}`)
- return call('delete', `/api/stacks/${encodeURIComponent(opts.id)}`)
- }
- const upsertStack = async (opts) => {
- opts = Object.assign({
- name: null,
- stackFile: null,
- stackFileContent: null,
- swarmId: null,
- endpointId: null,
- type: 'swarm',
- method: 'string',
- prune: true,
- warning: true
- }, opts)
- if (!opts.name) throw new Error('name required')
- if (!opts.stackFileContent) {
- if (!opts.stackFile) {
- throw new Error('stackFile or stackFileContent required')
- }
- opts.stackFileContent = fs.readFileSync(opts.stackFile, 'utf-8')
- }
- const type = TYPES[opts.type] || opts.type
- if (!opts.endpointId) {
- const endpoints = await getEndpoints()
- if (!endpoints || !endpoints.length) throw new Error('Could not find any endpoints')
- opts.endpointId = endpoints[0].Id
- }
- if (!opts.swarmId) {
- const swarm = await getEndpointSwarm(opts.endpointId)
- opts.swarmId = swarm.ID
- }
- const stacks = await getStacks()
- const stack = stacks.find(x => x.Name === opts.name)
- if (stack) {
- log(`Found existing stack ${opts.name}. Updating...`)
- return await call('PUT', `/api/stacks/${encodeURIComponent(stack.Id)}?method=${encodeURIComponent(opts.method)}&type=${encodeURIComponent(type)}&endpointId=${encodeURIComponent(opts.endpointId)}`, {
- Name: opts.name,
- StackFileContent: (opts.warning ? warning : '') + opts.stackFileContent,
- SwarmID: opts.swarmId,
- Prune: opts.prune
- })
- } else {
- log(`New stack ${opts.name}`)
- const stack = await call('POST', `/api/stacks?method=${encodeURIComponent(opts.method)}&type=${encodeURIComponent(type)}&endpointId=${encodeURIComponent(opts.endpointId)}`, {
- Name: opts.name,
- StackFileContent: (opts.warning ? warning : '') + opts.stackFileContent,
- SwarmID: opts.swarmId
- })
- await call('POST', '/api/resource_controls', {
- Type: 'stack',
- Public: true,
- ResourceID: opts.name,
- Users: [],
- Teams: [],
- SubResourceIDs: []
- })
- return stack
- }
- }
- return { getEndpoints, getSwarms, getStacks, upsertStack, deleteStack }
- }
- module.exports = { createClient }
|