client.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. const Api = require('./api')
  2. const fs = require('fs')
  3. const figlet = require('figlet')
  4. const TYPES = {
  5. swarm: 1,
  6. compose: 2
  7. }
  8. const createClient = async (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 api = new Api(config)
  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 api.endpoints.list()
  25. const getStacks = async () => await api.stacks.list()
  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. 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. log(`New stack ${opts.name}`)
  90. const stack = 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. await call('POST', '/api/resource_controls', {
  96. Type: 'stack',
  97. Public: true,
  98. ResourceID: opts.name,
  99. Users: [],
  100. Teams: [],
  101. SubResourceIDs: []
  102. })
  103. return stack
  104. }
  105. }
  106. return { getEndpoints, getStacks, upsertStack, deleteStack }
  107. }
  108. module.exports = { createClient }