client.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. const PortainerClient = require('portainer-api-client')
  2. const fs = require('fs')
  3. const figlet = require('figlet')
  4. const TYPES = {
  5. swarm: 1,
  6. compose: 2
  7. }
  8. const createClient = (config) => {
  9. config = Object.assign({
  10. url: null,
  11. username: null,
  12. password: null
  13. }, config)
  14. const log = config.log || console.log
  15. 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`
  16. const client = new PortainerClient(config.url, config.username, config.password);
  17. const call = async (method, path, data) => {
  18. if (config.verbose) log(method, path, data ? JSON.stringify(data, null, 4) : '')
  19. const result = await client.callApiWithKey(method, path, data)
  20. if (config.verbose) log(JSON.stringify(result, null, 4))
  21. return result
  22. }
  23. const getEndpointSwarm = async (endpointId) => await call('get', `/api/endpoints/${encodeURIComponent(endpointId)}/docker/swarm`)
  24. const getEndpoints = async () => await call('get', '/api/endpoints')
  25. const getSwarms = async () => await call('get', '/api/swarms')
  26. const getStacks = async () => await call('get', '/api/stacks')
  27. const deleteStack = async (opts) => {
  28. opts = Object.assign({
  29. name: null,
  30. id: null,
  31. endpointId: null
  32. }, opts)
  33. if (!opts.id) {
  34. if (!opts.name) {
  35. throw new Error('Either name or id required')
  36. }
  37. const stacks = await getStacks()
  38. const stack = stacks.find(x => x.Name === opts.name)
  39. if (!stack) throw new Error(`Stack ${opts.name} not found.`)
  40. opts.id = stack.Id
  41. }
  42. if (!opts.endpointId) {
  43. const endpoints = await getEndpoints()
  44. if (!endpoints || !endpoints.length) throw new Error('Could not find any endpoints')
  45. opts.endpointId = endpoints[0].Id
  46. }
  47. console.log(`Deleting stack ${opts.id}`)
  48. return call('delete', `/api/stacks/${encodeURIComponent(opts.id)}`)
  49. }
  50. const upsertStack = async (opts) => {
  51. opts = Object.assign({
  52. name: null,
  53. stackFile: null,
  54. stackFileContent: null,
  55. swarmId: null,
  56. endpointId: null,
  57. type: 'swarm',
  58. method: 'string',
  59. prune: true,
  60. warning: true
  61. }, opts)
  62. if (!opts.name) throw new Error('name required')
  63. if (!opts.stackFileContent) {
  64. if (!opts.stackFile) {
  65. throw new Error('stackFile or stackFileContent required')
  66. }
  67. opts.stackFileContent = fs.readFileSync(opts.stackFile, 'utf-8')
  68. }
  69. const type = TYPES[opts.type] || opts.type
  70. if (!opts.endpointId) {
  71. const endpoints = await getEndpoints()
  72. if (!endpoints || !endpoints.length) throw new Error('Could not find any endpoints')
  73. opts.endpointId = endpoints[0].Id
  74. }
  75. if (!opts.swarmId) {
  76. const swarm = await getEndpointSwarm(opts.endpointId)
  77. opts.swarmId = swarm.ID
  78. }
  79. const stacks = await getStacks()
  80. const stack = stacks.find(x => x.Name === opts.name)
  81. if (stack) {
  82. log(`Found existing stack ${opts.name}. Updating...`)
  83. return await call('PUT', `/api/stacks/${encodeURIComponent(stack.Id)}?method=${encodeURIComponent(opts.method)}&type=${encodeURIComponent(type)}&endpointId=${encodeURIComponent(opts.endpointId)}`, {
  84. Name: opts.name,
  85. StackFileContent: (opts.warning ? warning : '') + opts.stackFileContent,
  86. SwarmID: opts.swarmId,
  87. Prune: opts.prune
  88. })
  89. } else {
  90. log(`New stack ${opts.name}`)
  91. return await call('POST', `/api/stacks?method=${encodeURIComponent(opts.method)}&type=${encodeURIComponent(type)}&endpointId=${encodeURIComponent(opts.endpointId)}`, {
  92. Name: opts.name,
  93. StackFileContent: (opts.warning ? warning : '') + opts.stackFileContent,
  94. SwarmID: opts.swarmId
  95. })
  96. }
  97. }
  98. return { getEndpoints, getSwarms, getStacks, upsertStack, deleteStack }
  99. }
  100. module.exports = { createClient }