diff --git a/ione_server.rb b/ione_server.rb index 1a20168d..674edf30 100644 --- a/ione_server.rb +++ b/ione_server.rb @@ -289,7 +289,7 @@ class IONe halt 200, {}, "" end begin - unless request.request_method == 'GET' then + unless ['GET', 'DELETE'].include? request.request_method then @request_body = request.body.read @request_hash = JSON.parse @request_body @request_hash['params'] = [] if @request_hash['params'].nil? diff --git a/models/AnsibleDriver.rb b/models/AnsibleDriver.rb index 5d6672fb..fee59229 100644 --- a/models/AnsibleDriver.rb +++ b/models/AnsibleDriver.rb @@ -34,15 +34,6 @@ def crop_zmq_error! # Crops Zmq backtrace and error code from message end end -class Hash - def duplicate_with_case! to_case = :up # Duplicates each key and value with key up- or down- cased - self.clone.each do |key, value| - self[key.send(to_case.to_s + 'case')] = value - end - nil - end -end - class AnsiblePlaybookModel attr_reader :method, :id @@ -166,30 +157,19 @@ def message end end -before do # This actions will be performed before any route - begin - @one_client = $cloud_auth.client(session[:user]) # Saving OpenNebula client for user - @one_user = OpenNebula::User.new_with_id(session[:user_id], @one_client) # Saving user object - rescue => e - @before_exception = e.message - end -end - get '/ansible' do # Returns full Ansible Playbooks pool in OpenNebula XML-POOL format begin pool = IONe.new($client, $db).ListAnsiblePlaybooks # Array of playbooks pool.delete_if {|pb| !ansible_check_permissions(pb, @one_user, 0) } # Deletes playbooks, which aren't under user access pool.map! do | pb | # Adds user and group name to every object - user, group = OpenNebula::User.new_with_id( pb['uid'], @one_client), - OpenNebula::Group.new_with_id( pb['gid'], @one_client) + user, group = OpenNebula::User.new_with_id( pb['uid'], @client), + OpenNebula::Group.new_with_id( pb['gid'], @client) user.info!; group.info! pb['vars'] = IONe.new($client, $db).GetAnsiblePlaybookVariables(pb['id']) pb.merge( 'uname' => user.name, 'gname' => group.name, 'vars' => pb['vars'].nil? ? {} : pb['vars'] ) end - pool.map{|playbook| playbook.duplicate_with_case! } # Duplicates every key with the same but upcase-d - # Returns in required format r(**{ :ANSIBLE_POOL => { :ANSIBLE => pool @@ -202,8 +182,7 @@ def message post '/ansible' do # Allocates new playbook begin - data = JSON.parse(@request_body) - r response: { ANSIBLE: { ID: AnsiblePlaybookModel.new(id:nil, data:data, user:@one_user).id }} + r response: { ANSIBLE: { ID: AnsiblePlaybookModel.new(id:nil, data:@request_hash, user:@one_user).id }} rescue JSON::ParserError # If JSON.parse fails r error: "Broken data received, unable to parse." rescue => e @@ -229,11 +208,11 @@ def message begin pb = AnsiblePlaybookModel.new(id:id, user:@one_user) # Getting playbook # Saving user and group to objects - user, group = OpenNebula::User.new_with_id( pb.body['uid'], @one_client), - OpenNebula::Group.new_with_id( pb.body['gid'], @one_client) + user, group = OpenNebula::User.new_with_id( pb.body['uid'], @client), + OpenNebula::Group.new_with_id( pb.body['gid'], @client) user.info!; group.info! # Retrieving information about this objects from ONe pb.body.merge!('uname' => user.name, 'gname' => group.name, 'vars' => pb.vars.nil? ? {} : pb.vars) # Adding user and group names to playbook body - pb.body.duplicate_with_case! # Duplicates every key with the same but upcase-d + r ANSIBLE: pb.body rescue => e r error: e.message, backtrace: e.backtrace @@ -251,8 +230,7 @@ def message post '/ansible/:id/action' do | id | # Performs action begin - data = JSON.parse(@request_body) - pb = AnsiblePlaybookModel.new(id:id, data:data, user:@one_user) + pb = AnsiblePlaybookModel.new(id:id, data:@request_hash, user:@one_user) r response: pb.call rescue JSON::ParserError # If JSON.parse fails @@ -263,11 +241,9 @@ def message end post '/ansible/:action' do | action | # Performs actions, which are defined as def self.method for AnsiblePlaybookModel model - data = JSON.parse(@request_body) - begin if action == 'check_syntax' then - r response: IONe.new($client, $db).CheckAnsiblePlaybookSyntax( data['body']) + r response: IONe.new($client, $db).CheckAnsiblePlaybookSyntax( @request_hash['body']) else r response: "Action is not defined" end @@ -351,25 +327,16 @@ def message end end - before do # This actions will be performed before any route - begin - @one_client = $cloud_auth.client(session[:user]) # Saving OpenNebula client for user - @one_user = OpenNebula::User.new_with_id(session[:user_id], @one_client) # Saving user object - rescue => e - @before_exception = e.message - end - end get '/ansible_process' do begin pool = IONe.new($client, $db).ListAnsiblePlaybookProcesses pool.delete_if {|apc| !@one_user.groups.include?(0) && apc['uid'] != @one_user.id } pool.map! do | apc | # Adds user name to every object - user = OpenNebula::User.new_with_id( apc['uid'], @one_client) + user = OpenNebula::User.new_with_id( apc['uid'], @client) user.info! apc.merge('id' => apc['proc_id'], 'uname' => user.name) end - pool.map{|playbook| playbook.duplicate_with_case! } # Duplicates every key with the same but upcase-d r(**{ :ANSIBLE_PROCESS_POOL => { @@ -383,8 +350,7 @@ def message post '/ansible_process' do begin - data = JSON.parse(@request_body) - r response: { ANSIBLE_PROCESS: { ID: AnsiblePlaybookProcessModel.new(id:nil, data:data, user:@one_user).id }} + r response: { ANSIBLE_PROCESS: { ID: AnsiblePlaybookProcessModel.new(id:nil, data:@request_hash, user:@one_user).id }} rescue JSON::ParserError # If JSON.parse fails r error: "Broken data received, unable to parse." rescue => e @@ -397,10 +363,9 @@ def message begin apc = AnsiblePlaybookProcessModel.new(id:id, user:@one_user) # Getting playbook # Saving user and group to objects - user = OpenNebula::User.new_with_id( apc.body['uid'], @one_client) + user = OpenNebula::User.new_with_id( apc.body['uid'], @client) user.info! apc.body.merge!('id' => apc.body['proc_id'], 'uname' => user.name) # Retrieving information about this objects from ONe - apc.body.duplicate_with_case! # Duplicates every key with the same but upcase-d r ANSIBLE_PROCESS: apc.body rescue => e r error: e.message, backtrace: e.backtrace @@ -422,8 +387,7 @@ def message post '/ansible_process/:id/action' do | id | # Performs action begin - data = JSON.parse(@request_body) - pb = AnsiblePlaybookProcessModel.new(id:id, data:data, user:@one_user) + pb = AnsiblePlaybookProcessModel.new(id:id, data:@request_hash, user:@one_user) r response: pb.call rescue JSON::ParserError # If JSON.parse fails diff --git a/ui/package-lock.json b/ui/package-lock.json index 271146b7..ad214f3e 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -2158,15 +2158,6 @@ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, "cacache": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", @@ -2193,31 +2184,6 @@ "unique-filename": "^1.1.1" } }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "find-cache-dir": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", @@ -2239,23 +2205,6 @@ "path-exists": "^4.0.0" } }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "loader-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", - "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -2320,15 +2269,6 @@ "minipass": "^3.1.1" } }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, "terser-webpack-plugin": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz", @@ -2345,17 +2285,6 @@ "terser": "^4.6.12", "webpack-sources": "^1.4.3" } - }, - "vue-loader-v16": { - "version": "npm:vue-loader@16.1.2", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.2.tgz", - "integrity": "sha512-8QTxh+Fd+HB6fiL52iEVLKqE9N1JSlMXLR92Ijm6g8PZrwIxckgpqjPDWRP5TWxdiPaHR+alUWsnu1ShQOwt+Q==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "hash-sum": "^2.0.0", - "loader-utils": "^2.0.0" - } } } }, @@ -2867,13 +2796,9 @@ "dev": true }, "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "arr-diff": { "version": "4.0.0", @@ -4320,6 +4245,11 @@ "q": "^1.1.2" } }, + "codemirror": { + "version": "5.59.2", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.59.2.tgz", + "integrity": "sha512-/D5PcsKyzthtSy2NNKCyJi3b+htRkoKv3idswR/tR6UAvMNKA7SrmyZy6fOONJxSRs1JlUWEDAbxqfdArbK8iA==" + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -4727,6 +4657,25 @@ "parse-json": "^4.0.0" }, "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -5913,6 +5862,15 @@ "v8-compile-cache": "^2.0.3" }, "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -5942,6 +5900,16 @@ "resolve-from": "^4.0.0" } }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -8983,13 +8951,11 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "^2.0.1" } }, "jsbn": { @@ -13017,6 +12983,27 @@ "stable": "^0.1.8", "unquote": "~1.1.1", "util.promisify": "~1.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + } } }, "symbol-tree": { @@ -13862,6 +13849,87 @@ } } }, + "vue-loader-v16": { + "version": "npm:vue-loader@16.1.2", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.2.tgz", + "integrity": "sha512-8QTxh+Fd+HB6fiL52iEVLKqE9N1JSlMXLR92Ijm6g8PZrwIxckgpqjPDWRP5TWxdiPaHR+alUWsnu1ShQOwt+Q==", + "dev": true, + "optional": true, + "requires": { + "chalk": "^4.1.0", + "hash-sum": "^2.0.0", + "loader-utils": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "optional": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "optional": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "optional": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "optional": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "optional": true + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "optional": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "optional": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "vue-ref": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/vue-ref/-/vue-ref-2.0.0.tgz", diff --git a/ui/package.json b/ui/package.json index cdf704f8..bd4e2c32 100644 --- a/ui/package.json +++ b/ui/package.json @@ -10,7 +10,9 @@ }, "dependencies": { "ant-design-vue": "^1.7.2", + "codemirror": "^5.59.2", "core-js": "^3.6.5", + "js-yaml": "^4.0.0", "vue": "^2.6.11", "vue-axios": "^3.2.0", "vue-router": "^3.2.0", diff --git a/ui/src/components/playbook/editor.vue b/ui/src/components/playbook/editor.vue new file mode 100644 index 00000000..2502ce94 --- /dev/null +++ b/ui/src/components/playbook/editor.vue @@ -0,0 +1,224 @@ + + + \ No newline at end of file diff --git a/ui/src/components/playbook/yaml-editor.vue b/ui/src/components/playbook/yaml-editor.vue new file mode 100644 index 00000000..9f8de4ec --- /dev/null +++ b/ui/src/components/playbook/yaml-editor.vue @@ -0,0 +1,78 @@ +