icontrol_rest 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +15 -0
- data/README.md +60 -0
- data/Rakefile +9 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/icontrol_rest/client.rb +136 -0
- data/lib/icontrol_rest/logger.rb +33 -0
- data/lib/icontrol_rest/version.rb +5 -0
- data/lib/icontrol_rest.rb +14 -0
- metadata +82 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 04f7ecf74aee27e247b202b91bfa851831a4887f
|
4
|
+
data.tar.gz: 39f67265927ec920c8e48d56466a4bfc3432d264
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 644b8cbc0279c05ca28b54cd61bc964697391dc1027bad2f7e69ba45f87791310c6c085373c9c99bf4b83ba754fa3200ae973b650376bd238b8fd96ce1b1015b
|
7
|
+
data.tar.gz: '019a150a73271c5515f2efa574fc6aa8e548c03818586bdd88acfacea1dc1e16728ec29fc51a3be2e980124b6e2fd45cc399023a5b9aa653a5be5f6ed79daa99'
|
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in icontrol.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
group :development do
|
7
|
+
gem 'bundler', '~> 1.11'
|
8
|
+
gem 'pry'
|
9
|
+
end
|
10
|
+
|
11
|
+
# build-time dependencies
|
12
|
+
gem 'rake', '~> 10.0'
|
13
|
+
gem 'rspec', '~> 3.4'
|
14
|
+
gem 'rubocop', '~> 0.47'
|
15
|
+
gem 'simplecov', '~> 0.13'
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Icontrol
|
2
|
+
|
3
|
+
Gem used to wrap iControl API REST calls to an F5. The intent of this client is to match the iControl API methods and pass the response without modification. It does not contain business logic to scrub a response or prevent certain methods. This logic is to be in your orchestration layer, not in the client.
|
4
|
+
|
5
|
+
This has been tested against 11.5.4, but should be compatible with future versions. If this gem isn't compatible with a newer version of BIG-IP, or doesn't have the functionality required to access a certain method, feel free to follow the [guidelines for contributing](.github/CONTRIBUTING.md) and provide an enhancement. When doing so, please follow semantic versioning when considering changes.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'icontrol_rest'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
```
|
18
|
+
$ bundle install
|
19
|
+
```
|
20
|
+
|
21
|
+
Or install it yourself:
|
22
|
+
|
23
|
+
```
|
24
|
+
$ gem install icontrol_rest
|
25
|
+
```
|
26
|
+
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
require 'icontrol_rest'
|
32
|
+
|
33
|
+
api = IcontrolRest::Client.new(host: '1.2.3.4', user: 'user', pass: 'pass', verify_cert: false)
|
34
|
+
# => <IcontrolRest::Client:0x007fb953ab7750 @options={ ... }>
|
35
|
+
|
36
|
+
api.get_sys_dns
|
37
|
+
# => {"kind"=>"tm:sys:dns:dnsstate",
|
38
|
+
"selfLink"=>"https://localhost/mgmt/tm/sys/dns?ver=11.5.4",
|
39
|
+
"description"=>"configured-by-dhcp",
|
40
|
+
"nameServers"=>["1.2.3.72", "1.2.3.73"],
|
41
|
+
"search"=>["domain.com"]}
|
42
|
+
|
43
|
+
# Or you can manually do it:
|
44
|
+
api.get('/mgmt/tm/sys/dns')
|
45
|
+
# => {"kind"=>"tm:sys:dns:dnsstate",
|
46
|
+
"selfLink"=>"https://localhost/mgmt/tm/sys/dns?ver=11.5.4",
|
47
|
+
"description"=>"configured-by-dhcp",
|
48
|
+
"nameServers"=>["1.2.3.72", "1.2.3.73"],
|
49
|
+
"search"=>["domain.com"]}
|
50
|
+
```
|
51
|
+
|
52
|
+
|
53
|
+
## Development
|
54
|
+
|
55
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
56
|
+
|
57
|
+
|
58
|
+
## Contributing
|
59
|
+
|
60
|
+
Please review the [guidelines for contributing](.github/CONTRIBUTING.md) to this repository.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'icontrol_rest'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require 'pry'
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'pry'
|
15
|
+
Pry.start
|
data/bin/setup
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module IcontrolRest
|
4
|
+
# A iControl REST Client for retrieving data from F5s.
|
5
|
+
class Client
|
6
|
+
include HTTParty
|
7
|
+
format :json
|
8
|
+
|
9
|
+
# A client used to interact with a devices iControl API. Turns method calls into REST commands.
|
10
|
+
#
|
11
|
+
# host - The ip or hostname of the host we're trying to reach as a string
|
12
|
+
# user - The username of the account we're connecting with as a string.
|
13
|
+
# pass - the pass of the account we're connecting with.
|
14
|
+
# verify_cert - Boolean of whether we want to check certificates.
|
15
|
+
# timeout - Integer of seconds we want the timeout to be set to.
|
16
|
+
# sleep - Number of seconds to sleep after an icontrol call.
|
17
|
+
#
|
18
|
+
# Examples
|
19
|
+
#
|
20
|
+
# api = IcontrolRest::Client.new(host: '1.2.3.4', user: 'user', pass: 'pass', verify_cert: false)
|
21
|
+
# # => #<IcontrolRest::Client:0x007fb953ab7750 @options={ ... }>
|
22
|
+
#
|
23
|
+
# api.get_sys_dns
|
24
|
+
# # => {"kind"=>"tm:sys:dns:dnsstate",
|
25
|
+
# "selfLink"=>"https://localhost/mgmt/tm/sys/dns?ver=11.5.4",
|
26
|
+
# "description"=>"configured-by-dhcp",
|
27
|
+
# "nameServers"=>["1.2.3.72", "1.2.3.73"],
|
28
|
+
# "search"=>["domain.com"]}
|
29
|
+
#
|
30
|
+
# rubocop:disable Metrics/ParameterLists
|
31
|
+
def initialize(host:, pass:, user:, timeout: 100, verify_cert: true, sleep: 0, tries: 1)
|
32
|
+
self.class.base_uri "https://#{host}"
|
33
|
+
@sleep = sleep.to_i
|
34
|
+
@tries = tries.to_i
|
35
|
+
@options = { basic_auth: { username: user, password: pass }, headers: { 'Content-Type' => 'application/json' },
|
36
|
+
verify: verify_cert, timeout: timeout }
|
37
|
+
@retry_handler = proc do |exception, try, _elapsed_time, _next_interval|
|
38
|
+
logger.error { "#{exception.class}: #{exception.message} - try #{try}" }
|
39
|
+
if exception.class == JSON::ParserError
|
40
|
+
logger.info { "F5 configuration utility not ready to proceed, sleeping '30' seconds." }
|
41
|
+
sleep 30
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
# rubocop:enable Metrics/ParameterList
|
46
|
+
|
47
|
+
# Public: Returns a set logger. If none exists, a NullLogger is returned for stability.
|
48
|
+
def logger
|
49
|
+
@logger ||= IcontrolRest::Logging::NullLogger.new
|
50
|
+
end
|
51
|
+
|
52
|
+
# Public - Delete/Get request method.
|
53
|
+
#
|
54
|
+
# route - URI to send to server as a string.
|
55
|
+
#
|
56
|
+
# Returns - response from the server as a hash.
|
57
|
+
#
|
58
|
+
# Examples
|
59
|
+
#
|
60
|
+
# api.get('/mgmt/tm/sys/dns')
|
61
|
+
# # => {"kind"=>"tm:sys:dns:dnsstate",
|
62
|
+
# "selfLink"=>"https://localhost/mgmt/tm/sys/dns?ver=11.5.4",
|
63
|
+
# "description"=>"configured-by-dhcp",
|
64
|
+
# "nameServers"=>["1.2.3.72", "1.2.3.73"],
|
65
|
+
# "search"=>["domain.com"]}
|
66
|
+
#
|
67
|
+
%w[delete get].each do |action|
|
68
|
+
define_method(action.to_s) do |route, _arg = nil|
|
69
|
+
send_request { self.class.send(action, route, @options) }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Public - Post/Put request methods.
|
74
|
+
#
|
75
|
+
# route - URI to send to server as a string.
|
76
|
+
# data - Hash of parameters to pass with request.
|
77
|
+
#
|
78
|
+
# Returns - response from the server as a hash.
|
79
|
+
%w[post put].each do |action|
|
80
|
+
define_method(action.to_s) do |route, data|
|
81
|
+
body = {}
|
82
|
+
body[:body] = data.to_json
|
83
|
+
send_request { self.class.send(action, route, body.merge(@options)) }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
# Private - Handles response and raises error if the response isn't a 200.
|
90
|
+
#
|
91
|
+
# block - Takes block to yield.
|
92
|
+
#
|
93
|
+
# Returns - response from the server as a hash.
|
94
|
+
#
|
95
|
+
# Raises - RuntimeError when the server returns a response that isn't a 200
|
96
|
+
def send_request
|
97
|
+
Retriable.retriable on_retry: @retry_handler, tries: @tries do
|
98
|
+
response = yield
|
99
|
+
sleep(@sleep) if @sleep.positive?
|
100
|
+
return response if response.code == 200
|
101
|
+
raise "#{response['code']}: #{response['message']}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Private - Converts a missing method into a REST request.
|
106
|
+
#
|
107
|
+
# method_name - Symbol of unknown method called.
|
108
|
+
# *args - An array of arguments passed with the method call.
|
109
|
+
#
|
110
|
+
# Returns - Response from the method called.
|
111
|
+
def method_missing(method_name, *args)
|
112
|
+
super unless respond_to_missing?(method_name)
|
113
|
+
route_chain = method_name.to_s.split('_')
|
114
|
+
send(route_chain[0].downcase, route(route_chain), args.first)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Private - Adds methods prefixed with delete/get/post/put to object.
|
118
|
+
#
|
119
|
+
# method_name - Symbol of unknown method called.
|
120
|
+
#
|
121
|
+
# Returns - true if the object responds to it, or if delete/get..etc.
|
122
|
+
def respond_to_missing?(method_name, include_private = false)
|
123
|
+
method_name.to_s.start_with?('delete', 'get', 'post', 'put') || super
|
124
|
+
end
|
125
|
+
|
126
|
+
# Private - Converts the route chain into a uri.
|
127
|
+
#
|
128
|
+
# route_chain - An array of route chain.
|
129
|
+
#
|
130
|
+
# Returns - A URI as a string.
|
131
|
+
def route(route_chain)
|
132
|
+
raise 'Empty route chain.' if route_chain.length <= 1
|
133
|
+
"/mgmt/tm/#{route_chain[1..route_chain.length].join('/')}"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module IcontrolRest
|
4
|
+
# Module to handle all logging across our gem
|
5
|
+
module Logging
|
6
|
+
class << self
|
7
|
+
attr_writer :logger
|
8
|
+
end
|
9
|
+
|
10
|
+
# Default logger to be used if logging configuration is not supplied by the user.
|
11
|
+
class NullLogger < Logger
|
12
|
+
def initialize(*)
|
13
|
+
# Intentionally do nothing
|
14
|
+
end
|
15
|
+
|
16
|
+
def add(*)
|
17
|
+
# Intentionally do nothing
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.logger
|
22
|
+
@logger ||= NullLogger.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.use_logger(logger)
|
26
|
+
@logger = logger
|
27
|
+
end
|
28
|
+
|
29
|
+
def logger
|
30
|
+
Logging.logger
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'httparty'
|
4
|
+
require 'logger'
|
5
|
+
require 'retriable'
|
6
|
+
require 'uri'
|
7
|
+
|
8
|
+
require 'icontrol_rest/logger'
|
9
|
+
require 'icontrol_rest/client'
|
10
|
+
require 'icontrol_rest/version'
|
11
|
+
|
12
|
+
# Module to hold iControl logic.
|
13
|
+
module IcontrolRest
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: icontrol_rest
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jerrod Carpenter
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-10-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httparty
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.13'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.13'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: retriable
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
description: Allows user to interact with iControl REST interface.
|
42
|
+
email:
|
43
|
+
- jscarpenter25@gmail.com
|
44
|
+
executables:
|
45
|
+
- console
|
46
|
+
- setup
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- Gemfile
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- bin/console
|
54
|
+
- bin/setup
|
55
|
+
- lib/icontrol_rest.rb
|
56
|
+
- lib/icontrol_rest/client.rb
|
57
|
+
- lib/icontrol_rest/logger.rb
|
58
|
+
- lib/icontrol_rest/version.rb
|
59
|
+
homepage: https://github.com/cerner/icontrol_rest.git
|
60
|
+
licenses: []
|
61
|
+
metadata: {}
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project:
|
78
|
+
rubygems_version: 2.6.11
|
79
|
+
signing_key:
|
80
|
+
specification_version: 4
|
81
|
+
summary: Allows user to interact with iControl REST interface.
|
82
|
+
test_files: []
|