rundeck 0.0.1.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.hound.yml +4 -0
- data/.rubocop.yml +7 -0
- data/.rubocop_todo.yml +35 -0
- data/.travis.yml +11 -0
- data/Gemfile +4 -0
- data/Guardfile +16 -0
- data/LICENSE.txt +10 -0
- data/README.md +49 -0
- data/Rakefile +8 -0
- data/lib/rundeck.rb +29 -0
- data/lib/rundeck/api.rb +17 -0
- data/lib/rundeck/client.rb +21 -0
- data/lib/rundeck/client/jobs.rb +119 -0
- data/lib/rundeck/client/keys.rb +177 -0
- data/lib/rundeck/configuration.rb +42 -0
- data/lib/rundeck/error.rb +45 -0
- data/lib/rundeck/objectified_hash.rb +24 -0
- data/lib/rundeck/request.rb +93 -0
- data/lib/rundeck/version.rb +3 -0
- data/rundeck.gemspec +33 -0
- data/spec/fixtures/empty.xml +0 -0
- data/spec/fixtures/job.xml +17 -0
- data/spec/fixtures/job_executions.xml +31 -0
- data/spec/fixtures/job_run.xml +16 -0
- data/spec/fixtures/jobs_import.xml +23 -0
- data/spec/fixtures/jobs_my_project.xml +14 -0
- data/spec/fixtures/jobs_xml.xml +32 -0
- data/spec/fixtures/jobs_yaml.xml +22 -0
- data/spec/fixtures/key_contents_public.xml +1 -0
- data/spec/fixtures/key_private.xml +8 -0
- data/spec/fixtures/key_public.xml +7 -0
- data/spec/fixtures/keys.xml +27 -0
- data/spec/rundeck/client/jobs_spec.rb +181 -0
- data/spec/rundeck/client/keys_spec.rb +216 -0
- data/spec/rundeck/client_spec.rb +36 -0
- data/spec/rundeck/objectified_hash_spec.rb +46 -0
- data/spec/rundeck/request_spec.rb +40 -0
- data/spec/rundeck_spec.rb +55 -0
- data/spec/spec_helper.rb +77 -0
- metadata +258 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3458d53ff90537da707c22e709751439806a0e3c
|
4
|
+
data.tar.gz: 3d4414a87b8d98dce1bceb9d66c46ad2d5583e66
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6fc35d21ed3a2138a6ac831b349ea5ecb23b16a15db24a254a1c7487d49adb333de9095b2a2235a0f23d66a1868406a01411e8f55d410418195e34ee7626eebb
|
7
|
+
data.tar.gz: 9629f50b5e04535b8e84b8095a4c5711186bf2af58ebb9a61dfa822f8b2752f09e854a81b86d509a9d0321167e75b3ebcdac2097d4906a8db5f15c6e004e8e66
|
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
.idea
|
19
|
+
.ruby-version
|
20
|
+
.ruby-gemset
|
21
|
+
.idea/
|
data/.hound.yml
ADDED
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# This configuration was generated by `rubocop --auto-gen-config`
|
2
|
+
# on 2014-09-01 15:55:09 -0500 using RuboCop version 0.25.0.
|
3
|
+
# The point is for the user to remove these configuration records
|
4
|
+
# one by one as the offenses are removed from the code base.
|
5
|
+
# Note that changes in the inspected code, or installation of new
|
6
|
+
# versions of RuboCop, may require this file to be generated again.
|
7
|
+
|
8
|
+
# Offense count: 1
|
9
|
+
Metrics/CyclomaticComplexity:
|
10
|
+
Max: 10
|
11
|
+
|
12
|
+
# Offense count: 1
|
13
|
+
# Configuration parameters: AllowURI.
|
14
|
+
Metrics/LineLength:
|
15
|
+
Max: 159
|
16
|
+
|
17
|
+
# Offense count: 1
|
18
|
+
# Configuration parameters: CountComments.
|
19
|
+
Metrics/MethodLength:
|
20
|
+
Max: 12
|
21
|
+
|
22
|
+
# Offense count: 2
|
23
|
+
Style/Documentation:
|
24
|
+
Severity: warning
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
# Offense count: 1
|
28
|
+
# Configuration parameters: MaxSlashes.
|
29
|
+
Style/RegexpLiteral:
|
30
|
+
Enabled: false
|
31
|
+
|
32
|
+
# Offense count: 1
|
33
|
+
# Cop supports --auto-correct.
|
34
|
+
Style/SpecialGlobalVars:
|
35
|
+
Enabled: false
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
group :red_green_refactor, halt_on_fail: true do
|
4
|
+
|
5
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
6
|
+
watch(/^spec\/.+_spec\.rb$/)
|
7
|
+
watch(/^lib\/(.+)\.rb$/) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
8
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
9
|
+
end
|
10
|
+
|
11
|
+
guard :rubocop do
|
12
|
+
watch(/.+\.rb$/)
|
13
|
+
watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
Copyright (c) 2014, Drew A. Blessing
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
5
|
+
|
6
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
7
|
+
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
9
|
+
|
10
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Rundeck Ruby Gem
|
2
|
+
|
3
|
+
## Work in progress. Not yet stable
|
4
|
+
|
5
|
+
**Note: Although the git repository is called 'rundeck-ruby', the gem is called 'Rundeck' on Rubygems.org. There is another gem called 'rundeck-ruby' on Rubygems.org and it is not affiliated with this project.**
|
6
|
+
|
7
|
+
[![Build Status](https://travis-ci.org/dblessing/rundeck-ruby.svg?branch=master)](https://travis-ci.org/dblessing/rundeck-ruby)
|
8
|
+
[![Dependency Status](https://gemnasium.com/dblessing/rundeck-ruby.svg)](https://gemnasium.com/dblessing/rundeck-ruby)
|
9
|
+
[![Code Climate](https://codeclimate.com/github/dblessing/rundeck-ruby/badges/gpa.svg)](https://codeclimate.com/github/dblessing/rundeck-ruby)
|
10
|
+
[![Test Coverage](https://codeclimate.com/github/dblessing/rundeck-ruby/badges/coverage.svg)](https://codeclimate.com/github/dblessing/rundeck-ruby)
|
11
|
+
|
12
|
+
A Ruby wrapper around the Rundeck API.
|
13
|
+
|
14
|
+
This library will strive to achieve reliable,
|
15
|
+
100% coverage of the Rundeck API. Please submit an issue if you find a bug and feel
|
16
|
+
free to submit a pull request to contribute fixes or new features.
|
17
|
+
|
18
|
+
The layout and the code in this library is inspired by https://github.com/NARKOZ/gitlab.
|
19
|
+
NARKOZ does a fantastic job of keeping code simple and achieving API feature parity.
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
Add this line to your application's Gemfile:
|
24
|
+
|
25
|
+
gem 'rundeck'
|
26
|
+
|
27
|
+
And then execute:
|
28
|
+
|
29
|
+
$ bundle
|
30
|
+
|
31
|
+
Or install it yourself as:
|
32
|
+
|
33
|
+
$ gem install rundeck
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
TODO: Write usage instructions here
|
38
|
+
|
39
|
+
## Contributing
|
40
|
+
|
41
|
+
1. Fork it
|
42
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
43
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
44
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
45
|
+
5. Create new Pull Request
|
46
|
+
|
47
|
+
## License
|
48
|
+
|
49
|
+
Released under the BSD 2-clause license. See LICENSE.txt for details.
|
data/Rakefile
ADDED
data/lib/rundeck.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rundeck/version'
|
2
|
+
require 'rundeck/configuration'
|
3
|
+
require 'rundeck/error'
|
4
|
+
require 'rundeck/objectified_hash'
|
5
|
+
require 'rundeck/request'
|
6
|
+
require 'rundeck/api'
|
7
|
+
require 'rundeck/client'
|
8
|
+
|
9
|
+
module Rundeck
|
10
|
+
extend Configuration
|
11
|
+
|
12
|
+
# Alias for Rundeck::Client.new
|
13
|
+
#
|
14
|
+
# @return [Rundeck::Client]
|
15
|
+
def self.client(options = {})
|
16
|
+
Rundeck::Client.new(options)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Delegate to Gitlab::Client
|
20
|
+
def self.method_missing(method, *args, &block)
|
21
|
+
return super unless client.respond_to?(method)
|
22
|
+
client.send(method, *args, &block)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Delegate to Gitlab::Client
|
26
|
+
def self.respond_to?(method)
|
27
|
+
client.respond_to?(method) || super
|
28
|
+
end
|
29
|
+
end
|
data/lib/rundeck/api.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Rundeck
|
2
|
+
# @private
|
3
|
+
class API < Request
|
4
|
+
# @private
|
5
|
+
attr_accessor(*Configuration::VALID_OPTIONS_KEYS)
|
6
|
+
|
7
|
+
# Creates a new API.
|
8
|
+
# @raise [Error:MissingCredentials]
|
9
|
+
def initialize(options = {})
|
10
|
+
options = Rundeck.options.merge(options)
|
11
|
+
Configuration::VALID_OPTIONS_KEYS.each do |key|
|
12
|
+
send("#{key}=", options[key])
|
13
|
+
end
|
14
|
+
set_request_defaults @endpoint, @api_token
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Rundeck
|
2
|
+
# Wrapper for the Rundeck REST API.
|
3
|
+
class Client < API
|
4
|
+
Dir[File.expand_path('../client/*.rb', __FILE__)].each { |f| require f }
|
5
|
+
|
6
|
+
include Jobs
|
7
|
+
include Keys
|
8
|
+
|
9
|
+
def objectify(result)
|
10
|
+
if result.is_a?(Hash)
|
11
|
+
ObjectifiedHash.new(result)
|
12
|
+
elsif result.is_a? Array
|
13
|
+
result.map! { |e| ObjectifiedHash.new(e) }
|
14
|
+
elsif result.nil?
|
15
|
+
nil
|
16
|
+
else
|
17
|
+
fail Error::Parsing, "Couldn't parse a response body"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Rundeck
|
2
|
+
class Client
|
3
|
+
# Defines methods related to projects.
|
4
|
+
module Jobs
|
5
|
+
# Gets a list of jobs for a specific project.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# Rundeck.jobs('project')
|
9
|
+
#
|
10
|
+
# @param [String] project Project name
|
11
|
+
# @param [Hash] options A set of options passed directly to HTTParty
|
12
|
+
# @return [Array<Rundeck::ObjectifiedHash>]
|
13
|
+
def jobs(project, options = {})
|
14
|
+
objectify get("/project/#{project}/jobs", options)['jobs']['job']
|
15
|
+
end
|
16
|
+
|
17
|
+
# Gets a single job by id
|
18
|
+
#
|
19
|
+
# @example Rundeck.job('c07518ef-b697-4792-9a59-5b4f08855b67')
|
20
|
+
#
|
21
|
+
# @param [String] id Job id
|
22
|
+
# @param [Hash] options A set of options passed directly to HTTParty
|
23
|
+
# @return [Rundeck::ObjectifiedHash]
|
24
|
+
def job(id, options = {})
|
25
|
+
objectify get("/job/#{id}", options)['joblist']['job']
|
26
|
+
end
|
27
|
+
|
28
|
+
# Delete a job
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
# Rundeck.delete_job('c07518ef-b697-4792-9a59-5b4f08855b67')
|
32
|
+
#
|
33
|
+
# @param [String] id Job id
|
34
|
+
# @param [Hash] options A set of options passed directly to HTTParty
|
35
|
+
# @return [Rundeck::ObjectifiedHash]
|
36
|
+
def delete_job(id, options = {})
|
37
|
+
delete("/job/#{id}", options)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Get executions for a specific job
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# Rundeck.job_executions('c07518ef-b697-4792-9a59-5b4f08855b67')
|
44
|
+
#
|
45
|
+
# @param [String] id Job id
|
46
|
+
# @param [Hash] options A set of options passed directly to HTTParty
|
47
|
+
# @return [Rundeck::ObjectifiedHash]
|
48
|
+
def job_executions(id, options = {})
|
49
|
+
r = get("/job/#{id}/executions", options)['result']['executions']['execution']
|
50
|
+
objectify r
|
51
|
+
end
|
52
|
+
|
53
|
+
# Run a job
|
54
|
+
#
|
55
|
+
# @example
|
56
|
+
# Rundeck.run_job('c07518ef-b697-4792-9a59-5b4f08855b67', 'DEBUG')
|
57
|
+
#
|
58
|
+
# @param [String] id Job id
|
59
|
+
# @param [Hash] options A set of options passed directly to HTTParty
|
60
|
+
# @return [Rundeck::ObjectifiedHash]
|
61
|
+
def run_job(id, options = {})
|
62
|
+
objectify post("/job/#{id}/executions", options)['result']['executions']['execution']
|
63
|
+
end
|
64
|
+
|
65
|
+
# Import a job or multiple jobs
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# job = "- id: c07518ef-b697-4792-9a59-5b4f08855b67
|
69
|
+
# project: Endeca
|
70
|
+
# ..."
|
71
|
+
# Rundeck.import_jobs(job)
|
72
|
+
#
|
73
|
+
# @example
|
74
|
+
# job = "<joblist>
|
75
|
+
# <job>
|
76
|
+
# <id>c07518ef-b697-4792-9a59-5b4f08855b67</id>
|
77
|
+
# ..."
|
78
|
+
# Rundeck.import_jobs(job, 'xml')
|
79
|
+
#
|
80
|
+
# @param [String] content The job definition(s) as yaml or xml
|
81
|
+
# @param [String] format The import format. 'yaml|xml', defaults to 'yaml'
|
82
|
+
# @param [Hash] options A set of options passed directly to HTTParty
|
83
|
+
# @return [Rundeck::ObjectifiedHash]
|
84
|
+
def import_jobs(content, format = 'yaml', options = {})
|
85
|
+
unless format =~ /yaml|xml/
|
86
|
+
fail Error::InvalidAttributes, 'format must be yaml or xml'
|
87
|
+
end
|
88
|
+
options[:headers] = {} if options[:headers].nil?
|
89
|
+
options[:headers].merge!(
|
90
|
+
'Content-Type' => 'application/x-www-form-urlencoded')
|
91
|
+
options[:body] = "xmlBatch=#{content}"
|
92
|
+
options[:query] = {} if options[:query].nil?
|
93
|
+
options[:query]['format'] = format
|
94
|
+
|
95
|
+
objectify post('/jobs/import', options)['result']
|
96
|
+
end
|
97
|
+
|
98
|
+
# Export jobs to yaml or xml format
|
99
|
+
#
|
100
|
+
# @example
|
101
|
+
# Rundeck.export_jobs('project')
|
102
|
+
#
|
103
|
+
# @param [String] project Project name
|
104
|
+
# @param [String] format The export format. 'yaml|xml', defaults to 'yaml'
|
105
|
+
# @param [Hash] options A set of options passed directly to HTTParty
|
106
|
+
# @return [String]
|
107
|
+
def export_jobs(project, format = 'yaml', options = {})
|
108
|
+
unless format =~ /yaml|xml/
|
109
|
+
fail Error::InvalidAttributes, 'format must be yaml or xml'
|
110
|
+
end
|
111
|
+
options[:query] = {} if options[:query].nil?
|
112
|
+
options[:query].merge!('project' => project, 'format' => format)
|
113
|
+
options[:format] = format
|
114
|
+
|
115
|
+
get('/jobs/export', options)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
module Rundeck
|
2
|
+
class Client
|
3
|
+
# Defines methods related to projects.
|
4
|
+
module Keys
|
5
|
+
STORAGE_KEYS_PATH = '/storage/keys'
|
6
|
+
|
7
|
+
# Gets a list of keys at a specific path.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# Rundeck.keys('path')
|
11
|
+
#
|
12
|
+
# @param [String] path A key storage path
|
13
|
+
# @param [Hash] options A set of options passed directly to HTTParty
|
14
|
+
# @return [Array<Rundeck::ObjectifiedHash>]
|
15
|
+
def keys(path = '', options = {})
|
16
|
+
r = get("#{STORAGE_KEYS_PATH}/#{path}", options)
|
17
|
+
|
18
|
+
# # In case a user provides a direct path to a key, error.
|
19
|
+
if r['resource']['contents']
|
20
|
+
objectify r['resource']['contents']['resource']
|
21
|
+
else
|
22
|
+
fail Error::InvalidAttributes,
|
23
|
+
'Please provide a key storage path that ' \
|
24
|
+
'isn\'t a direct path to a key'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Get a single key's metadata
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
# Rundeck.key_metadata('path/to/key1')
|
32
|
+
#
|
33
|
+
# @param [String] path A key storage path, including key name
|
34
|
+
# @param [Hash] options A set of options passed directly to HTTParty
|
35
|
+
# @return [Rundeck::ObjectifiedHash]
|
36
|
+
def key_metadata(path, options = {})
|
37
|
+
r = get("#{STORAGE_KEYS_PATH}/#{path}", options)
|
38
|
+
|
39
|
+
# In case a user provides a key path instead of a path to a single key.
|
40
|
+
if r['resource']['contents']
|
41
|
+
fail Error::InvalidAttributes,
|
42
|
+
'Please provide a key storage path that ' \
|
43
|
+
'is a direct path to a key'
|
44
|
+
else
|
45
|
+
objectify r['resource']['resource_meta']
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Get the contents of a key. Only allowed for public keys.
|
50
|
+
# Note: This method returns a raw string of the public key,
|
51
|
+
# not at ObjectifiedHash.
|
52
|
+
#
|
53
|
+
# @example
|
54
|
+
# Rundeck.key_contents('path/to/key1')
|
55
|
+
#
|
56
|
+
# @param [String] path A key storage path, including key name
|
57
|
+
# @param [Hash] options A set of options passed directly to HTTParty
|
58
|
+
# @return [Rundeck::ObjectifiedHash]
|
59
|
+
def key_contents(path, options = {})
|
60
|
+
# Check if key exists first. Otherwise we could return some
|
61
|
+
# weird strings. Also, raise error if user is trying to get a
|
62
|
+
# private key.
|
63
|
+
if key_metadata(path, options).rundeck_key_type == 'private'
|
64
|
+
fail Error::Unauthorized,
|
65
|
+
'You are not allowed to retrieve the contents of a private key'
|
66
|
+
end
|
67
|
+
|
68
|
+
options.merge!(format: :plain,
|
69
|
+
headers: { 'Accept' => 'application/pgp-keys' })
|
70
|
+
key = get("#{STORAGE_KEYS_PATH}/#{path}", options)
|
71
|
+
objectify 'public_key' => key
|
72
|
+
end
|
73
|
+
|
74
|
+
# Create a private key
|
75
|
+
#
|
76
|
+
# @example
|
77
|
+
# key = "-----BEGIN RSA PRIVATE KEY-----\nProc-Type:..."
|
78
|
+
# Rundeck.create_private_key('path', key)
|
79
|
+
#
|
80
|
+
# @param [String] path A key storage path
|
81
|
+
# @param [String] key The entire private key value
|
82
|
+
# @param [Hash] options A set of options passed directory to HTTParty
|
83
|
+
# @return [Rundeck::ObjectifiedHash]
|
84
|
+
def create_private_key(path, key, options = {})
|
85
|
+
create_or_update_key(path, key, 'private', 'post', options)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Update a private key
|
89
|
+
#
|
90
|
+
# @example
|
91
|
+
# key = "-----BEGIN RSA PRIVATE KEY-----\nProc-Type:..."
|
92
|
+
# Rundeck.update_private_key('path', key)
|
93
|
+
#
|
94
|
+
# @param [String] path A key storage path
|
95
|
+
# @param [String] key The entire private key value
|
96
|
+
# @param [Hash] options A set of options passed directory to HTTParty
|
97
|
+
# @return [Rundeck::ObjectifiedHash]
|
98
|
+
def update_private_key(path, key, options = {})
|
99
|
+
key_check(path, 'private', options)
|
100
|
+
create_or_update_key(path, key, 'public', 'put', options)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Create a public key
|
104
|
+
#
|
105
|
+
# @example
|
106
|
+
# key = "ssh-rsa AAAA.....3MOj user@example.com"
|
107
|
+
# Rundeck.create_public_key('path/to/key', key)
|
108
|
+
#
|
109
|
+
# @param [String] path A key storage path
|
110
|
+
# @param [String] key The entire private key value
|
111
|
+
# @param [Hash] options A set of options passed directory to HTTParty
|
112
|
+
# @return [Array<Rundeck::ObjectifiedHash>]
|
113
|
+
def create_public_key(path, key, options = {})
|
114
|
+
create_or_update_key(path, key, 'public', 'post', options)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Update a public key
|
118
|
+
#
|
119
|
+
# @example
|
120
|
+
# key = "ssh-rsa AAAA.....3MOj user@example.com"
|
121
|
+
# Rundeck.update_public_key('path/to/key', key)
|
122
|
+
#
|
123
|
+
# @param [String] path A key storage path
|
124
|
+
# @param [String] key The entire private key value
|
125
|
+
# @param [Hash] options A set of options passed directory to HTTParty
|
126
|
+
# @return [Array<Rundeck::ObjectifiedHash>]
|
127
|
+
def update_public_key(path, key, options = {})
|
128
|
+
key_check(path, 'public', options)
|
129
|
+
create_or_update_key(path, key, 'public', 'put', options)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Delete a key
|
133
|
+
#
|
134
|
+
# @example
|
135
|
+
# Rundeck.delete_key('path/to/key')
|
136
|
+
#
|
137
|
+
# @param [String] path A key storage path
|
138
|
+
# @param [Hash] options A set of options passed directly to HTTParty
|
139
|
+
# @return [nil]
|
140
|
+
def delete_key(path, options = {})
|
141
|
+
delete("#{STORAGE_KEYS_PATH}/#{path}", options)
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def key_check(path, type, options)
|
147
|
+
# Check existence and type
|
148
|
+
if key_metadata(path, options).rundeck_key_type != type
|
149
|
+
fail Error::NotFound,
|
150
|
+
"A #{type} key was not found at the specified path."
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def create_or_update_key(path, key, type, method, options)
|
155
|
+
key_type_headers(type, options)
|
156
|
+
options.merge!(body: key)
|
157
|
+
|
158
|
+
if method == 'post'
|
159
|
+
objectify post("#{STORAGE_KEYS_PATH}/#{path}", options)['resource']['resource_meta']
|
160
|
+
elsif method == 'put'
|
161
|
+
objectify put("#{STORAGE_KEYS_PATH}/#{path}", options)['resource']['resource_meta']
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def key_type_headers(type, options)
|
166
|
+
if type == 'private'
|
167
|
+
options.merge!(headers: { 'Content-Type' => 'application/octet-stream' })
|
168
|
+
elsif type == 'public'
|
169
|
+
options.merge!(headers: { 'Content-Type' => 'application/pgp-key' })
|
170
|
+
else
|
171
|
+
fail Error::InvalidAttributes,
|
172
|
+
'Invalid key type specified. Must be public or private.'
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|