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
@@ -0,0 +1,42 @@
|
|
1
|
+
module Rundeck
|
2
|
+
# Defines constants and methods related to configuration.
|
3
|
+
module Configuration
|
4
|
+
# An array of valid keys in the options hash when configuring a Rundeck::API.
|
5
|
+
VALID_OPTIONS_KEYS = [:endpoint, :api_token, :user_agent].freeze
|
6
|
+
|
7
|
+
# The user agent that will be sent to the API endpoint if none is set.
|
8
|
+
DEFAULT_USER_AGENT = "Rundeck Ruby Gem #{Rundeck::VERSION}".freeze
|
9
|
+
|
10
|
+
# @private
|
11
|
+
attr_accessor(*VALID_OPTIONS_KEYS)
|
12
|
+
|
13
|
+
# Sets all configuration options to their default values
|
14
|
+
# when this module is extended.
|
15
|
+
def self.extended(base)
|
16
|
+
base.reset
|
17
|
+
end
|
18
|
+
|
19
|
+
# Convenience method to allow configuration options to be set in a block.
|
20
|
+
def configure
|
21
|
+
yield self
|
22
|
+
end
|
23
|
+
|
24
|
+
# Creates a hash of options and their values.
|
25
|
+
def options
|
26
|
+
VALID_OPTIONS_KEYS.reduce({}) do |option, key|
|
27
|
+
option.merge!(key => send(key))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def endpoint=(endpoint)
|
32
|
+
@endpoint = "#{endpoint}/api/12"
|
33
|
+
end
|
34
|
+
|
35
|
+
# Resets all configuration options to the defaults.
|
36
|
+
def reset
|
37
|
+
self.endpoint = ENV['RUNDECK_API_ENDPOINT']
|
38
|
+
self.api_token = ENV['RUNDECK_API_TOKEN']
|
39
|
+
self.user_agent = DEFAULT_USER_AGENT
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Rundeck
|
2
|
+
module Error
|
3
|
+
# Custom error class for rescuing from all Rundeck errors.
|
4
|
+
class Error < StandardError; end
|
5
|
+
|
6
|
+
# Raise when attributes are missing.
|
7
|
+
class MissingAttributes < Error; end
|
8
|
+
|
9
|
+
# Raise when attributes are invalid.
|
10
|
+
class InvalidAttributes < Error; end
|
11
|
+
|
12
|
+
# Raised when API endpoint credentials not configured.
|
13
|
+
class MissingCredentials < Error; end
|
14
|
+
|
15
|
+
# Raised when impossible to parse response body.
|
16
|
+
class Parsing < Error; end
|
17
|
+
|
18
|
+
# Raised when API endpoint returns the HTTP status code 400.
|
19
|
+
class BadRequest < Error; end
|
20
|
+
|
21
|
+
# Raised when API endpoint returns the HTTP status code 401.
|
22
|
+
class Unauthorized < Error; end
|
23
|
+
|
24
|
+
# Raised when API endpoint returns the HTTP status code 403.
|
25
|
+
class Forbidden < Error; end
|
26
|
+
|
27
|
+
# Raised when API endpoint returns the HTTP status code 404.
|
28
|
+
class NotFound < Error; end
|
29
|
+
|
30
|
+
# Raised when API endpoint returns the HTTP status code 405.
|
31
|
+
class MethodNotAllowed < Error; end
|
32
|
+
|
33
|
+
# Raised when API endpoint returns the HTTP status code 409.
|
34
|
+
class Conflict < Error; end
|
35
|
+
|
36
|
+
# Raised when API endpoint returns the HTTP status code 500.
|
37
|
+
class InternalServerError < Error; end
|
38
|
+
|
39
|
+
# Raised when API endpoint returns the HTTP status code 502.
|
40
|
+
class BadGateway < Error; end
|
41
|
+
|
42
|
+
# Raised when API endpoint returns the HTTP status code 503.
|
43
|
+
class ServiceUnavailable < Error; end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Rundeck
|
2
|
+
# Converts hashes to the objects.
|
3
|
+
class ObjectifiedHash
|
4
|
+
# Creates a new ObjectifiedHash object.
|
5
|
+
def initialize(hash)
|
6
|
+
@hash = hash
|
7
|
+
@data = hash.each_with_object({}) do |(key, value), data|
|
8
|
+
value = ObjectifiedHash.new(value) if value.is_a? Hash
|
9
|
+
data[key.to_s.downcase] = value
|
10
|
+
data
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_hash
|
15
|
+
@hash
|
16
|
+
end
|
17
|
+
alias_method :to_h, :to_hash
|
18
|
+
|
19
|
+
# Delegate to ObjectifiedHash.
|
20
|
+
def method_missing(key)
|
21
|
+
@data.key?(key.to_s) ? @data[key.to_s] : nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'libxml'
|
3
|
+
|
4
|
+
module Rundeck
|
5
|
+
# @private
|
6
|
+
class Request
|
7
|
+
include HTTParty
|
8
|
+
|
9
|
+
format :xml
|
10
|
+
attr_accessor :api_token
|
11
|
+
|
12
|
+
def get(path, options = {})
|
13
|
+
request_settings(options)
|
14
|
+
validate self.class.get(path, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def post(path, options = {})
|
18
|
+
request_settings(options, path)
|
19
|
+
validate self.class.post(path, options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def put(path, options = {})
|
23
|
+
request_settings(options)
|
24
|
+
validate self.class.put(path, options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete(path, options = {})
|
28
|
+
request_settings(options)
|
29
|
+
validate self.class.delete(path, options)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Checks the response code for common errors.
|
33
|
+
# Returns parsed response for successful requests.
|
34
|
+
def validate(response)
|
35
|
+
case response.code
|
36
|
+
when 400 then fail Error::BadRequest, error_message(response)
|
37
|
+
when 401 then fail Error::Unauthorized, error_message(response)
|
38
|
+
when 403 then fail Error::Forbidden, error_message(response)
|
39
|
+
when 404 then fail Error::NotFound, error_message(response)
|
40
|
+
when 405 then fail Error::MethodNotAllowed, error_message(response)
|
41
|
+
when 409 then fail Error::Conflict, error_message(response)
|
42
|
+
when 500 then fail Error::InternalServerError, error_message(response)
|
43
|
+
when 502 then fail Error::BadGateway, error_message(response)
|
44
|
+
when 503 then fail Error::ServiceUnavailable, error_message(response)
|
45
|
+
end
|
46
|
+
|
47
|
+
response.parsed_response
|
48
|
+
end
|
49
|
+
|
50
|
+
# Sets a base_uri and default_params for requests.
|
51
|
+
# @raise [Error::MissingCredentials] if endpoint not set.
|
52
|
+
def set_request_defaults(endpoint, api_token)
|
53
|
+
unless endpoint
|
54
|
+
fail Error::MissingCredentials, 'Please set an endpoint to API'
|
55
|
+
end
|
56
|
+
@api_token = api_token
|
57
|
+
|
58
|
+
self.class.base_uri endpoint
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def request_settings(options, path = nil)
|
64
|
+
api_token_header(options, path)
|
65
|
+
accept_header(options)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Sets a PRIVATE-TOKEN header for requests.
|
69
|
+
# @raise [Error::MissingCredentials] if api_token not set.
|
70
|
+
def api_token_header(options, path = nil)
|
71
|
+
return nil if path == '/j_security_check'
|
72
|
+
unless @api_token
|
73
|
+
fail Error::MissingCredentials, 'Please set a api_token for user'
|
74
|
+
end
|
75
|
+
options[:headers] = {} if options[:headers].nil?
|
76
|
+
options[:headers].merge!('X-Rundeck-Auth-Token' => @api_token)
|
77
|
+
end
|
78
|
+
|
79
|
+
def accept_header(options)
|
80
|
+
return nil if options[:headers].nil?
|
81
|
+
|
82
|
+
unless options[:headers].include?('Accept')
|
83
|
+
options[:headers].merge!('Accept' => 'application/xml')
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def error_message(response)
|
88
|
+
"Server responded with code #{response.code}, " \
|
89
|
+
"message: #{response.parsed_response['result']['error'][1]['message']}. " \
|
90
|
+
"Request URI: #{response.request.base_uri}#{response.request.path}"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/rundeck.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rundeck/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'rundeck'
|
8
|
+
spec.version = Rundeck::VERSION
|
9
|
+
spec.authors = ['Drew A. Blessing']
|
10
|
+
spec.email = ['drew.blessing@mac.com']
|
11
|
+
spec.description = 'Ruby client for Rundeck API'
|
12
|
+
spec.summary = 'A ruby wrapper for the Rundeck API'
|
13
|
+
spec.homepage = 'https://github.com/dblessing/rundeck'
|
14
|
+
spec.license = 'BSD-2-Clause'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_runtime_dependency 'httparty'
|
22
|
+
spec.add_runtime_dependency 'libxml-ruby'
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_development_dependency 'rspec', '~> 3.1.0'
|
27
|
+
spec.add_development_dependency 'rspec-core', '~> 3.1.2'
|
28
|
+
spec.add_development_dependency 'rspec-its', '~> 1.0.0'
|
29
|
+
spec.add_development_dependency 'webmock'
|
30
|
+
spec.add_development_dependency 'codeclimate-test-reporter'
|
31
|
+
spec.add_development_dependency 'guard-rspec', '~> 4.3.0'
|
32
|
+
spec.add_development_dependency 'guard-rubocop'
|
33
|
+
end
|
File without changes
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<joblist>
|
2
|
+
<job>
|
3
|
+
<id>c07518ef-b697-4792-9a59-5b4f08855b67</id>
|
4
|
+
<loglevel>INFO</loglevel>
|
5
|
+
<sequence keepgoing='false' strategy='node-first'>
|
6
|
+
<command>
|
7
|
+
<exec>echo 'Hello world!'</exec>
|
8
|
+
</command>
|
9
|
+
</sequence>
|
10
|
+
<description>Well, Hello World</description>
|
11
|
+
<name>Hello World</name>
|
12
|
+
<context>
|
13
|
+
<project>My_Project</project>
|
14
|
+
</context>
|
15
|
+
<uuid>c07518ef-b697-4792-9a59-5b4f08855b67</uuid>
|
16
|
+
</job>
|
17
|
+
</joblist>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<result success='true' apiversion='12'>
|
2
|
+
<executions count='2'>
|
3
|
+
<execution id='2' href='http://localhost:4440/execution/follow/2' status='aborted' project='My_Project'>
|
4
|
+
<user>admin</user>
|
5
|
+
<date-started unixtime='1409608790308'>2014-09-01T21:59:50Z</date-started>
|
6
|
+
<date-ended unixtime='1409608832192'>2014-09-01T22:00:32Z</date-ended>
|
7
|
+
<abortedby>admin</abortedby>
|
8
|
+
<job id='c07518ef-b697-4792-9a59-5b4f08855b67'>
|
9
|
+
<name>Job 1</name>
|
10
|
+
<group></group>
|
11
|
+
<project>My_Project</project>
|
12
|
+
<description>test</description>
|
13
|
+
</job>
|
14
|
+
<description>echo 'Hello world'</description>
|
15
|
+
<argstring />
|
16
|
+
</execution>
|
17
|
+
<execution id='1' href='http://dc-mb-am-009.bucklehq.com:4440/execution/follow/1' status='success' project='My_Project'>
|
18
|
+
<user>admin</user>
|
19
|
+
<date-started unixtime='1409608610264'>2014-09-01T21:56:50Z</date-started>
|
20
|
+
<date-ended unixtime='1409608781159'>2014-09-01T21:59:41Z</date-ended>
|
21
|
+
<job id='c07518ef-b697-4792-9a59-5b4f08855b67'>
|
22
|
+
<name>Job 1</name>
|
23
|
+
<group></group>
|
24
|
+
<project>My_Project</project>
|
25
|
+
<description>Awesome job 1</description>
|
26
|
+
</job>
|
27
|
+
<description>echo 'Hello world'</description>
|
28
|
+
<argstring />
|
29
|
+
</execution>
|
30
|
+
</executions>
|
31
|
+
</result>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<result success='true' apiversion='12'>
|
2
|
+
<executions count='1'>
|
3
|
+
<execution id='4' href='http://localhost:4440/execution/follow/4' status='running' project='My_Project'>
|
4
|
+
<user>admin</user>
|
5
|
+
<date-started unixtime='1411238010218'>2014-09-20T18:33:30Z</date-started>
|
6
|
+
<job id='2fe8bfbb-d12e-49b5-859b-7472cf1ed3a0' averageDuration='1003'>
|
7
|
+
<name>My_Job</name>
|
8
|
+
<group></group>
|
9
|
+
<project>My_Project</project>
|
10
|
+
<description>This is an awesome job</description>
|
11
|
+
</job>
|
12
|
+
<description>echo "foo"</description>
|
13
|
+
<argstring />
|
14
|
+
</execution>
|
15
|
+
</executions>
|
16
|
+
</result>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<result>
|
2
|
+
<succeeded count="1">
|
3
|
+
<job>
|
4
|
+
<id>c07518ef-b697-4792-9a59-5b4f08855b67</id>
|
5
|
+
<loglevel>INFO</loglevel>
|
6
|
+
<sequence keepgoing='false' strategy='node-first'>
|
7
|
+
<command>
|
8
|
+
<exec>echo 'Hello world!'</exec>
|
9
|
+
</command>
|
10
|
+
</sequence>
|
11
|
+
<description>Well, Hello World</description>
|
12
|
+
<name>Hello World</name>
|
13
|
+
<context>
|
14
|
+
<project>My_Project</project>
|
15
|
+
</context>
|
16
|
+
<uuid>c07518ef-b697-4792-9a59-5b4f08855b67</uuid>
|
17
|
+
</job>
|
18
|
+
</succeeded>
|
19
|
+
<failed count="0">
|
20
|
+
</failed>
|
21
|
+
<skipped count="0">
|
22
|
+
</skipped>
|
23
|
+
</result>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<jobs count='2'>
|
2
|
+
<job id='c07518ef-b697-4792-9a59-5b4f08855b67'>
|
3
|
+
<name>Job 1</name>
|
4
|
+
<group />
|
5
|
+
<project>My_Project</project>
|
6
|
+
<description>My first super awesome project</description>
|
7
|
+
</job>
|
8
|
+
<job id='9c922902-faa6-49cf-aa8d-4de3f5e1d3e1'>
|
9
|
+
<name>Job 2</name>
|
10
|
+
<group>My_Group</group>
|
11
|
+
<project>My_Project</project>
|
12
|
+
<description>My second project</description>
|
13
|
+
</job>
|
14
|
+
</jobs>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<joblist>
|
2
|
+
<job>
|
3
|
+
<id>c07518ef-b697-4792-9a59-5b4f08855b67</id>
|
4
|
+
<loglevel>INFO</loglevel>
|
5
|
+
<sequence keepgoing='false' strategy='node-first'>
|
6
|
+
<command>
|
7
|
+
<exec>echo 'hello world'</exec>
|
8
|
+
</command>
|
9
|
+
</sequence>
|
10
|
+
<description>Hello World</description>
|
11
|
+
<name>hello</name>
|
12
|
+
<context>
|
13
|
+
<project>my_project</project>
|
14
|
+
</context>
|
15
|
+
<uuid>c07518ef-b697-4792-9a59-5b4f08855b67</uuid>
|
16
|
+
</job>
|
17
|
+
<job>
|
18
|
+
<id>9c922902-faa6-49cf-aa8d-4de3f5e1d3e1</id>
|
19
|
+
<loglevel>INFO</loglevel>
|
20
|
+
<sequence keepgoing='false' strategy='node-first'>
|
21
|
+
<command>
|
22
|
+
<exec>echo 'foo'</exec>
|
23
|
+
</command>
|
24
|
+
</sequence>
|
25
|
+
<description>Foo Bar</description>
|
26
|
+
<name>foo</name>
|
27
|
+
<context>
|
28
|
+
<project>my_project</project>
|
29
|
+
</context>
|
30
|
+
<uuid>9c922902-faa6-49cf-aa8d-4de3f5e1d3e1</uuid>
|
31
|
+
</job>
|
32
|
+
</joblist>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
- id: c07518ef-b697-4792-9a59-5b4f08855b67
|
2
|
+
project: Endeca
|
3
|
+
loglevel: INFO
|
4
|
+
sequence:
|
5
|
+
keepgoing: false
|
6
|
+
strategy: node-first
|
7
|
+
commands:
|
8
|
+
- exec: echo 'boom'
|
9
|
+
description: test
|
10
|
+
name: test
|
11
|
+
uuid: c07518ef-b697-4792-9a59-5b4f08855b67
|
12
|
+
- id: 9c922902-faa6-49cf-aa8d-4de3f5e1d3e1
|
13
|
+
project: Endeca
|
14
|
+
loglevel: INFO
|
15
|
+
sequence:
|
16
|
+
keepgoing: false
|
17
|
+
strategy: node-first
|
18
|
+
commands:
|
19
|
+
- exec: echo 'boom'
|
20
|
+
description: test
|
21
|
+
name: test
|
22
|
+
uuid: 9c922902-faa6-49cf-aa8d-4de3f5e1d3e1
|
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDaNirADvOztppFoWeH+fc+5u8zQwRNeiamCXbrcWEK+/fB+Jqf/k1CLlikvp0dt1TKFmQXYJc58ZHv2RRxfe1lMdnv04VDVTE6DoB1jShnv0VL/KN0J+bNm4WLCyJ1NEdhnlZN5nt9U0RkYSG8hcuvREJ5R/5miCCRMSeH4hDmT22v7mV+qZQArRprs1EOE3o25lItefa/c5h85uJMYgnMIMQjT4hhr1JhWg2NdpN08fwS0Bif3JKk3C1YOa3RgW+Wrd0hFQ5iPSBTgmAxWjdgMp1xT4Nw8V8kujiH1jBLfJTXwDgm7csS/Z0H+gORpz6qnkbWKcWVzX3izFLZlxUH user@example.com
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<resource path='keys/path/to/my_key' type='file' url='http://localhost:4440/api/12/storage/keys/path/to/my_key' name='path/to/my_key'>
|
2
|
+
<resource-meta>
|
3
|
+
<Rundeck-content-type>application/octet-stream</Rundeck-content-type>
|
4
|
+
<Rundeck-content-size>1765</Rundeck-content-size>
|
5
|
+
<Rundeck-content-mask>content</Rundeck-content-mask>
|
6
|
+
<Rundeck-key-type>private</Rundeck-key-type>
|
7
|
+
</resource-meta>
|
8
|
+
</resource>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<resource path='keys/key1' type='file' url='http://localhost:4440/api/12/storage/keys/key1' name='key1'>
|
2
|
+
<resource-meta>
|
3
|
+
<Rundeck-content-type>application/pgp-keys</Rundeck-content-type>
|
4
|
+
<Rundeck-content-size>406</Rundeck-content-size>
|
5
|
+
<Rundeck-key-type>public</Rundeck-key-type>
|
6
|
+
</resource-meta>
|
7
|
+
</resource>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<resource path='keys' type='directory' url='http://localhost:4440/api/12/storage/keys'>
|
2
|
+
<contents count='4'>
|
3
|
+
<resource path='keys/key1' type='file' url='http://localhost:4440/api/12/storage/keys/key1' name='key1'>
|
4
|
+
<resource-meta>
|
5
|
+
<Rundeck-content-type>application/pgp-keys</Rundeck-content-type>
|
6
|
+
<Rundeck-content-size>406</Rundeck-content-size>
|
7
|
+
<Rundeck-key-type>public</Rundeck-key-type>
|
8
|
+
</resource-meta>
|
9
|
+
</resource>
|
10
|
+
<resource path='keys/key2' type='file' url='http://localhost:4440/api/12/storage/keys/key2' name='key2'>
|
11
|
+
<resource-meta>
|
12
|
+
<Rundeck-content-type>application/octet-stream</Rundeck-content-type>
|
13
|
+
<Rundeck-content-size>1765</Rundeck-content-size>
|
14
|
+
<Rundeck-content-mask>content</Rundeck-content-mask>
|
15
|
+
<Rundeck-key-type>private</Rundeck-key-type>
|
16
|
+
</resource-meta>
|
17
|
+
</resource>
|
18
|
+
<resource path='keys/key3' type='file' url='http://localhost:4440/api/12/storage/keys/key3' name='key3'>
|
19
|
+
<resource-meta>
|
20
|
+
<Rundeck-content-type>application/octet-stream</Rundeck-content-type>
|
21
|
+
<Rundeck-content-size>1765</Rundeck-content-size>
|
22
|
+
<Rundeck-content-mask>content</Rundeck-content-mask>
|
23
|
+
<Rundeck-key-type>private</Rundeck-key-type>
|
24
|
+
</resource-meta>
|
25
|
+
</resource>
|
26
|
+
</contents>
|
27
|
+
</resource>
|