client.js 4.3 KB

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