lmc 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b3a6cc095210c99890c8ebb6b1c24f18fdee5ace
4
+ data.tar.gz: c32528dfb1a87d9238db2c96f23297dbdd75660f
5
+ SHA512:
6
+ metadata.gz: 32ff5ff2362f3534b20e8dab058cc0faccf9f754fa7858b89e5693f26be5c7d2adab48af988660df597242323bcb58f39f46440ba75efd938d8517f7dbaf468c
7
+ data.tar.gz: b9c2259efdb008fca13912c5066a966d66b65f25a92843413d2447bc0ee20011365869f1514f0f1c265b73f0ea64fd2176892b475bdf481e6e9115c13b9f958a
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /doc/
5
+ /pkg/
6
+ /spec/reports/
7
+ /tmp/
8
+ .idea/workspace.xml
9
+ .idea/tasks.xml
10
+ .idea/.rakeTasks
11
+ Gemfile.lock
12
+ test_credentials.yaml
13
+ lmc-*.gem
@@ -0,0 +1,13 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0">
3
+ <option name="myName" value="Project Default" />
4
+ <inspection_tool class="RubyInstanceMethodNamingConvention" enabled="true" level="WARNING" enabled_by_default="true">
5
+ <scope name="Tests" level="WARNING" enabled="false" />
6
+ </inspection_tool>
7
+ <inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
8
+ <option name="processCode" value="true" />
9
+ <option name="processLiterals" value="true" />
10
+ <option name="processComments" value="true" />
11
+ </inspection_tool>
12
+ </profile>
13
+ </component>
data/.idea/lmc.iml ADDED
@@ -0,0 +1,31 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="RUBY_MODULE" version="4">
3
+ <component name="ModuleRunConfigurationManager">
4
+ <shared />
5
+ </component>
6
+ <component name="NewModuleRootManager">
7
+ <content url="file://$MODULE_DIR$" />
8
+ <orderEntry type="jdk" jdkName="rbenv: 2.4.1" jdkType="RUBY_SDK" />
9
+ <orderEntry type="sourceFolder" forTests="false" />
10
+ <orderEntry type="library" scope="PROVIDED" name="ansi (v1.5.0, rbenv: 2.4.1) [gem]" level="application" />
11
+ <orderEntry type="library" scope="PROVIDED" name="builder (v3.2.3, rbenv: 2.4.1) [gem]" level="application" />
12
+ <orderEntry type="library" scope="PROVIDED" name="bundler (v1.16.1, rbenv: 2.4.1) [gem]" level="application" />
13
+ <orderEntry type="library" scope="PROVIDED" name="docile (v1.1.5, rbenv: 2.4.1) [gem]" level="application" />
14
+ <orderEntry type="library" scope="PROVIDED" name="domain_name (v0.5.20170404, rbenv: 2.4.1) [gem]" level="application" />
15
+ <orderEntry type="library" scope="PROVIDED" name="http-cookie (v1.0.3, rbenv: 2.4.1) [gem]" level="application" />
16
+ <orderEntry type="library" scope="PROVIDED" name="json (v2.1.0, rbenv: 2.4.1) [gem]" level="application" />
17
+ <orderEntry type="library" scope="PROVIDED" name="mime-types (v3.1, rbenv: 2.4.1) [gem]" level="application" />
18
+ <orderEntry type="library" scope="PROVIDED" name="mime-types-data (v3.2016.0521, rbenv: 2.4.1) [gem]" level="application" />
19
+ <orderEntry type="library" scope="PROVIDED" name="minitest (v5.11.3, rbenv: 2.4.1) [gem]" level="application" />
20
+ <orderEntry type="library" scope="PROVIDED" name="minitest-reporters (v1.1.19, rbenv: 2.4.1) [gem]" level="application" />
21
+ <orderEntry type="library" scope="PROVIDED" name="netrc (v0.11.0, rbenv: 2.4.1) [gem]" level="application" />
22
+ <orderEntry type="library" scope="PROVIDED" name="rake (v10.5.0, rbenv: 2.4.1) [gem]" level="application" />
23
+ <orderEntry type="library" scope="PROVIDED" name="recursive-open-struct (v1.1.0, rbenv: 2.4.1) [gem]" level="application" />
24
+ <orderEntry type="library" scope="PROVIDED" name="rest-client (v2.0.2, rbenv: 2.4.1) [gem]" level="application" />
25
+ <orderEntry type="library" scope="PROVIDED" name="ruby-progressbar (v1.9.0, rbenv: 2.4.1) [gem]" level="application" />
26
+ <orderEntry type="library" scope="PROVIDED" name="simplecov (v0.15.1, rbenv: 2.4.1) [gem]" level="application" />
27
+ <orderEntry type="library" scope="PROVIDED" name="simplecov-html (v0.10.2, rbenv: 2.4.1) [gem]" level="application" />
28
+ <orderEntry type="library" scope="PROVIDED" name="unf (v0.1.4, rbenv: 2.4.1) [gem]" level="application" />
29
+ <orderEntry type="library" scope="PROVIDED" name="unf_ext (v0.0.7.5, rbenv: 2.4.1) [gem]" level="application" />
30
+ </component>
31
+ </module>
data/.idea/misc.xml ADDED
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectRootManager" version="2" project-jdk-name="rbenv: 1.9.3-p551" project-jdk-type="RUBY_SDK" />
4
+ </project>
data/.idea/modules.xml ADDED
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/lmc.iml" filepath="$PROJECT_DIR$/.idea/lmc.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
data/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
+ </component>
6
+ </project>
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.4.1
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.1
5
+ before_install: gem install bundler -v 1.16.1
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in lmc.gemspec
6
+ gemspec
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # Lmc
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/lmc`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'lmc'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install lmc
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ### Tests against real LMC instances
34
+
35
+ #### credentials file
36
+ email: testuser@foocorp.example
37
+ password: Foobar1+
38
+ lmc_url: https://my.lmc.example
39
+ ## Contributing
40
+
41
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/lmc.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "lmc"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,3 @@
1
+ assets
2
+ index.html
3
+ .resultset.json*
@@ -0,0 +1,5 @@
1
+ {
2
+ "result": {
3
+ "covered_percent": 83.38
4
+ }
5
+ }
data/lib/lmc.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'json'
2
+ require 'restclient'
3
+
4
+ Dir.glob(File.expand_path("../lmc/*.rb", __FILE__)).each do |file|
5
+ require file
6
+ end
7
+
8
+ Dir.glob(File.expand_path("../lmc/exceptions/*.rb", __FILE__)).each do |file|
9
+ require file
10
+ end
11
+
12
+ module LMC
13
+ def self.useful
14
+ return true
15
+ end
16
+ end
@@ -0,0 +1,175 @@
1
+ require_relative 'account_manager.rb'
2
+ require_relative 'entity'
3
+ module LMC
4
+ class Account < Entity
5
+ ROOT_ACCOUNT_UUID = '9ec458c2-d05f-3004-96f0-ebe73fa20de8'
6
+ attr_accessor :name
7
+ attr_reader :id, :state, :type
8
+
9
+ def self.get(id)
10
+ cloud = Cloud.instance
11
+ result = cloud.get ["cloud-service-auth", "accounts", id.to_s]
12
+ return Account.new(result.body)
13
+ end
14
+
15
+ def self.get_by_uuid uuid
16
+ raise "Missing argument" if uuid.nil?
17
+ return self.get uuid
18
+ end
19
+
20
+ def self.get_by_name(name, type = nil)
21
+ raise "Missing argument" if name.nil?
22
+ accounts = Cloud.instance.get_accounts_objects.select do |a|
23
+ (name.nil? || a.name == name) && (type.nil? || a.type == type)
24
+ end
25
+ if accounts.length == 1
26
+ return accounts[0]
27
+ elsif accounts.length == 0
28
+ raise 'Did not find account'
29
+ else
30
+ raise 'Account name not unique'
31
+ end
32
+ end
33
+
34
+
35
+ def initialize(data)
36
+ @cloud = LMC::Cloud.instance
37
+ apply_data(data)
38
+ end
39
+
40
+ #returns itself, allows chaining
41
+ def save
42
+ response = if @id.nil?
43
+ @cloud.auth_for_accounts [@parent]
44
+ @cloud.post ["cloud-service-auth", "accounts"], self
45
+ else
46
+ @cloud.post path, self
47
+ end
48
+ apply_data(response.body)
49
+ return self
50
+ end
51
+
52
+ def delete
53
+ if @id != nil
54
+ @cloud.auth_for_accounts [@id]
55
+ deleted = @cloud.delete ["cloud-service-auth", "accounts", @id]
56
+ if deleted.code == 200
57
+ @id = nil
58
+ return true
59
+ else
60
+ raise "unable to delete account: #{deleted.body.message}"
61
+ end
62
+ end
63
+ end
64
+
65
+ def exists?
66
+ # noch ungelöst: woran mache ich fest, ob das objekt in der DB schon da ist.
67
+ # Bleibt wohl nix außer manuell auf @id != nil zu checken.
68
+ @id != nil
69
+ end
70
+
71
+ def members
72
+ ids = Cloud.instance.get ["cloud-service-auth", "accounts", @id, 'members'], {"select" => "id"}
73
+ puts ids.inspect if Cloud.debug
74
+ principals = ids.map do |principal_id|
75
+ response = Cloud.instance.get ["cloud-service-auth", "accounts", @id, 'members', principal_id]
76
+ if response.code == 200
77
+ principal = response.body
78
+ else
79
+ raise "ERROR: #{response.code} #{response.body.message}"
80
+ end
81
+ puts principal.inspect if Cloud.debug
82
+ principal
83
+ end
84
+ return principals
85
+ end
86
+
87
+ def find_member_by_name name
88
+ members.find {|m| m.name == name}
89
+ end
90
+
91
+ #def update_member(principal_id, data)
92
+ # response = @cloud.post ["cloud-service-auth", "accounts", id, 'members', principal_id], data
93
+ # return response
94
+ #end
95
+
96
+ def remove_membership(member_id)
97
+ response = @cloud.delete ["cloud-service-auth", "accounts", id, "members", member_id]
98
+ end
99
+
100
+ def remove_membership_self
101
+ response = @cloud.delete ["cloud-service-auth", "accounts", id, "members", "self"]
102
+ end
103
+
104
+ def authorities
105
+ response = @cloud.get ['cloud-service-auth', 'accounts', id, 'authorities']
106
+ if response.code == 200
107
+ return response.body
108
+ else
109
+ raise 'Unable to get authorities'
110
+ end
111
+ end
112
+
113
+ def children
114
+ @cloud.auth_for_account self
115
+ response = @cloud.get ['cloud-service-auth', 'accounts', id, 'children']
116
+ response.map {|child| Account.new child}
117
+ end
118
+
119
+ def logs
120
+ # https://lmctest/cloud-service-logging/accounts/6392b234-b11c-498a-a077-a5f5b23c54a0/logs?lang=DE
121
+ cloud = Cloud.instance
122
+ cloud.auth_for_accounts [id]
123
+ cloud.get(["cloud-service-logging", "accounts", id, "logs?lang=DE"]).body
124
+ end
125
+
126
+ def sites
127
+ # private clouds can not have sites
128
+ return [] if @type == "PRIVATE_CLOUD"
129
+ @cloud.auth_for_accounts([id])
130
+ response = @cloud.get ["cloud-service-devices", "accounts", id, "sites"]
131
+ if response.code == 200
132
+ return response.body.map {|data|
133
+ Site.new(data, self)
134
+ }
135
+ elsif response.code == 404
136
+ return []
137
+ end
138
+ end
139
+
140
+ def config_updatestates
141
+ @cloud.auth_for_accounts([id])
142
+ response = @cloud.get ["cloud-service-config", "configdevice", "accounts", id, "updatestates"]
143
+ return LMC::Configstates.new response.body
144
+ end
145
+
146
+ def to_json(*a)
147
+ {
148
+ "name" => @name,
149
+ "state" => @state,
150
+ "type" => @type,
151
+ "parent" => @parent
152
+ }.to_json(*a)
153
+ end
154
+
155
+ def to_s
156
+ "#{name}"
157
+ end
158
+
159
+ private
160
+
161
+ ## should be put into entity or such
162
+ def path
163
+ ["cloud-service-auth", "accounts", @id].join("/")
164
+ end
165
+
166
+ def apply_data(data)
167
+ @id = data["id"]
168
+ @parent = data["parent"]
169
+ @name = data["name"]
170
+ @state = data["state"]
171
+ @type = data["type"]
172
+ end
173
+
174
+ end
175
+ end
data/lib/lmc/Cloud.rb ADDED
@@ -0,0 +1,230 @@
1
+ require 'base64'
2
+ require 'json'
3
+ require 'restclient'
4
+
5
+ module LMC
6
+ class Cloud
7
+ #include ActionView::Helpers::DateHelper
8
+
9
+ class << self
10
+ attr_writer :cloud_host, :user, :password
11
+ attr_accessor :verbose, :debug, :verify_tls, :use_tls
12
+ Cloud.use_tls = true
13
+ Cloud.verify_tls = true
14
+ end
15
+
16
+ # def self.cloud_host=(cloud_host)
17
+ # @@cloud_host = cloud_host
18
+ # end
19
+
20
+ def self.instance(opts = {authorize: true})
21
+ @@inst ||= self.new(@cloud_host, @user, @password, opts[:authorize])
22
+ end
23
+
24
+
25
+ attr_reader :auth_ok, :cloud_host
26
+
27
+ def initialize(cloud_host, user, pass, auth=true)
28
+ @auth_ok = false
29
+ @cloud_host = cloud_host
30
+ @user = user
31
+ @password = pass
32
+ @verify_tls = Cloud.verify_tls
33
+ authorize if auth
34
+ end
35
+
36
+ # hide password from dumps
37
+ def inspect
38
+ "#<Cloud:#{object_id}, #{build_url}>"
39
+ end
40
+
41
+ def get_backstage_serviceinfos
42
+ get "cloud-service-backstage/serviceinfos"
43
+ end
44
+
45
+ def get_accounts
46
+ get "cloud-service-auth/accounts"
47
+ end
48
+
49
+ def get_accounts_objects
50
+ result = get ["cloud-service-auth", "accounts"]
51
+ if result.code == 200
52
+ accounts = result.map do |aj|
53
+ Account.new(aj)
54
+ end
55
+ else
56
+ raise "Unable to fetch accounts: #{result.body.message}"
57
+ end
58
+
59
+ return accounts
60
+ end
61
+
62
+ # functionality should be moved to Account class
63
+ #def get_account(name, type = nil)
64
+ # accounts = get_accounts_objects.select do |a|
65
+ # (name.nil? || a.name == name) && (type.nil? || a.type == type)
66
+ # end
67
+ # if accounts.length == 1
68
+ # return accounts[0]
69
+ # else
70
+ # raise "Did not specify exactly one account"
71
+ # end
72
+ #end
73
+
74
+ def invite_user_to_account(email, account_id, type, authorities = [])
75
+ body = {name: email, state: "ACTIVE", type: type}
76
+ body["authorities"] = authorities
77
+ post ["cloud-service-auth", "accounts", account_id, 'members'], body
78
+ end
79
+
80
+ def get(path, params = nil)
81
+ RestClient.log = ("stdout") if Cloud.debug
82
+ begin
83
+ prepared_headers = headers
84
+ prepared_headers[:params] = params
85
+ args = {
86
+ :method => :get,
87
+ :url => build_url(path),
88
+ :headers => prepared_headers,
89
+ }
90
+ args.merge!(rest_options)
91
+ resp = RestClient::Request.execute args
92
+ return LMCResponse.new(resp)
93
+ rescue RestClient::ExceptionWithResponse => e
94
+ puts "EXCEPTION: " + e.to_s if Cloud.debug
95
+ puts "EX.response: " + e.response.to_s if Cloud.debug
96
+ puts JSON.parse(e.response)["message"] if Cloud.debug
97
+ raise e
98
+ #return LMCResponse.new(e.response)
99
+ end
100
+ end
101
+
102
+ def put(path, body_object)
103
+ RestClient.log = ("stdout") if Cloud.debug
104
+ begin
105
+ args = {
106
+ :method => :put,
107
+ :url => build_url(path),
108
+ :payload => body_object.to_json,
109
+ :headers => headers
110
+
111
+ }
112
+ args.merge!(rest_options)
113
+ resp = RestClient::Request.execute args
114
+ return LMCResponse.new(resp)
115
+ rescue RestClient::ExceptionWithResponse => e
116
+ puts "EXCEPTION: " + e.to_s if Cloud.debug
117
+ puts "EX.response: " + e.response.to_s if Cloud.debug
118
+ puts JSON.parse(e.response)["message"] if Cloud.debug
119
+ return LMCResponse.new(e.response)
120
+ end
121
+ end
122
+
123
+ def post(path, body_object)
124
+ RestClient.log = ("stdout") if Cloud.debug
125
+ begin
126
+ args = {
127
+ :method => :post,
128
+ :url => build_url(path),
129
+ :payload => body_object.to_json,
130
+ :headers => headers
131
+
132
+ }
133
+ args.merge!(rest_options)
134
+ resp = RestClient::Request.execute args
135
+ return LMCResponse.new(resp)
136
+ rescue RestClient::ExceptionWithResponse => e
137
+ puts "EXCEPTION: " + e.to_s if Cloud.debug
138
+ puts "EX.response: " + e.response.to_s if Cloud.debug
139
+ puts JSON.parse(e.response)["message"] if Cloud.debug
140
+ raise e
141
+ end
142
+ end
143
+
144
+ def delete(path, body_object = nil)
145
+ RestClient.log = ("stdout") if Cloud.debug
146
+ begin
147
+ args = {
148
+ :method => :delete,
149
+ :url => build_url(path),
150
+ :payload => body_object.to_json,
151
+ :headers => headers
152
+ }
153
+ args.merge!(rest_options)
154
+ resp = RestClient::Request.execute args
155
+ return LMCResponse.new(resp)
156
+ rescue RestClient::ExceptionWithResponse => e
157
+ puts "EXCEPTION: " + e.to_s if Cloud.debug
158
+ puts "EX.response: " + e.response.to_s if Cloud.debug
159
+ puts JSON.parse(e.response)["message"] if Cloud.debug
160
+ return LMCResponse.new(e.response)
161
+ end
162
+ end
163
+
164
+ ##
165
+ # public accessors
166
+ ##
167
+ def session_token
168
+ @auth_token["value"]
169
+ end
170
+
171
+ def build_url(*path_components)
172
+ protocol = "https"
173
+ if !Cloud.use_tls
174
+ protocol = "http"
175
+ end
176
+ ["#{protocol}://#{@cloud_host}", path_components].flatten.compact.join("/")
177
+ end
178
+
179
+ def auth_for_accounts(account_ids)
180
+ puts "Authorizing for accounts: " + account_ids.to_s if Cloud.debug
181
+ authorize(account_ids)
182
+ end
183
+
184
+ def auth_for_account(account)
185
+ auth_for_accounts([account.id])
186
+ end
187
+
188
+ def accept_tos(tos)
189
+ authorize([], tos)
190
+ end
191
+
192
+
193
+ private
194
+ def authorize(account_ids = [], tos = [])
195
+ begin
196
+ reply = post(["cloud-service-auth", "auth"], {name: @user, password: @password, accountIds: account_ids, termsOfUse: tos})
197
+ puts "authorize reply " + reply.inspect if Cloud.debug
198
+ @auth_token = reply
199
+ @auth_ok = true
200
+ rescue ::RestClient::ExceptionWithResponse => e
201
+ response = JSON.parse(e.response.body)
202
+ if response['code'] == 100
203
+ raise LMC::OutdatedTermsOfUseException.new(response)
204
+ end
205
+ end
206
+ end
207
+
208
+ def auth_bearer
209
+ "Bearer " + session_token
210
+ end
211
+
212
+ def headers
213
+ headers = {}
214
+ headers[:content_type] = 'application/json'
215
+ if @auth_ok
216
+ headers[:Authorization] = auth_bearer
217
+ end
218
+ return headers
219
+ end
220
+
221
+ def rest_options
222
+ options = {}
223
+ if !@verify_tls
224
+ options[:verify_ssl] = false
225
+ end
226
+ return options
227
+ end
228
+ end
229
+
230
+ end
@@ -0,0 +1,14 @@
1
+ module LMC
2
+ class Configstates
3
+ attr_reader :actual, :outdated
4
+
5
+ def initialize(data)
6
+ @actual = data["ACTUAL"]
7
+ @outdated = data["OUTDATED"]
8
+ @actual ||= 0
9
+ @outdated ||= 0
10
+ end
11
+
12
+ end
13
+
14
+ end
data/lib/lmc/Device.rb ADDED
@@ -0,0 +1,72 @@
1
+ module LMC
2
+ class Device
3
+ attr_reader :id, :name, :model, :serial, :heartbeatstate
4
+
5
+ def initialize(data)
6
+ @cloud = Cloud.instance
7
+ @id = data["id"]
8
+ @comment = data["comment"]
9
+ @name = data["status"]["name"]
10
+ @serial = data["status"]["serial"]
11
+ @model = data["status"]["model"]
12
+ @heartbeatstate = data["status"]["heartbeatState"]
13
+ @status = data["status"]
14
+ @account = data["account"]
15
+ end
16
+
17
+ def get_config_for_account(account)
18
+ response = @cloud.get ["cloud-service-config", "configbuilder", "accounts", account.id, "devices", @id, "ui"]
19
+ JSON.parse(JSON.generate(response.body.to_h)) #terrible hack to get it to work for now. needs way to get more raw body_object from Response
20
+ end
21
+
22
+ def set_config_for_account(config, account)
23
+ @cloud.put ["cloud-service-config", "configbuilder", "accounts", account.id, "devices", @id, "ui"], config
24
+ end
25
+
26
+ def get_monitor_widgets(widget_item_ids)
27
+ @cloud.get ["cloud-service-monitoring", @account.id, "devices", @id, "monitordata"], {:widgetItemIds => widget_item_ids.join(",")}
28
+ end
29
+
30
+ def self.get_for_account(account)
31
+ cloud = Cloud.instance
32
+ cloud.auth_for_accounts [account.id]
33
+ list = cloud.get ["cloud-service-devices", "accounts", account.id, "devices"]
34
+ if list.code != 200
35
+ puts "Error getting devices: #{list.body.message}"
36
+ exit 1
37
+ end
38
+ devices = list.map do |data|
39
+ data["account"] = account
40
+ LMC::Device.new(data)
41
+ end
42
+ end
43
+
44
+ def self.get_for_account_id(account_id)
45
+ self.get_for_account Account.get(account_id)
46
+ end
47
+
48
+ def config_state
49
+ @config_state ||= get_config_state
50
+ end
51
+
52
+ def logs
53
+ # https://lmctest/#/project/6392b234-b11c-498a-a077-a5f5b23c54a0/devices/compact/eaafa152-62cf-48a1-be65-b222886daa6d/logging
54
+ #cloud = Cloud.instance
55
+ ##cloud.auth_for_accounts [id]
56
+ #cloud.get ["cloud-service-logging", "accounts", id, "logs?lang=DE"]
57
+ raise "device logs not supported"
58
+ end
59
+
60
+ private
61
+ def get_config_state
62
+ reply = @cloud.get ["cloud-service-config", "configdevice", "accounts", @account.id, "state"], {"deviceIds" => @id}
63
+ if reply.code == 200
64
+ # binding.pry
65
+ DeviceConfigState.new reply.body[@id]
66
+ end
67
+ end
68
+
69
+
70
+ end
71
+
72
+ end
@@ -0,0 +1,53 @@
1
+ require 'ostruct'
2
+ module LMC
3
+ class LMCResponse
4
+
5
+ attr_reader :body, :code, :headers
6
+
7
+ def initialize(response)
8
+ @body_object = {}
9
+ if response.bytesize > 0
10
+ @body_object = JSON.parse response.body
11
+ end
12
+ if @body_object.class == Array
13
+ @body = @body_object.map {|elem|
14
+ if elem.is_a? Hash then
15
+ OpenStruct.new(elem)
16
+ else
17
+ elem
18
+ end}
19
+ elsif @body_object.class == Hash
20
+ @body = OpenStruct.new(@body_object)
21
+ elsif @body_object.class == TrueClass || @body_object.class == FalseClass
22
+ @body = @body_object
23
+ else
24
+ raise "Unknown json parse result"
25
+ end
26
+ @code = response.code
27
+ @headers = response.headers
28
+ end
29
+
30
+ # body_object and these methods allow to use LMCResponse objects in place
31
+ # of the old response which was just the body parsed to a hash or array
32
+ def [](key)
33
+ @body_object[key]
34
+ end
35
+
36
+ def map(&block)
37
+ @body_object.map &block
38
+ end
39
+
40
+ def each(&block)
41
+ @body_object.each &block
42
+ end
43
+
44
+ def to_s
45
+ "Response: Code: #{@code}, Body: #{@body_object.to_s}"
46
+ end
47
+
48
+ def empty?
49
+ @body_object.empty?
50
+ end
51
+ end
52
+
53
+ end
data/lib/lmc/Site.rb ADDED
@@ -0,0 +1,37 @@
1
+ module LMC
2
+ class Site
3
+ attr_accessor :name
4
+ attr_reader :id, :account
5
+
6
+ def initialize(data, account)
7
+ @cloud = Cloud.instance
8
+ @id = data["id"]
9
+ @name = data["name"]
10
+ @subnet_group_id = data["subnetGroupId"]
11
+ @account = account
12
+
13
+ if @account
14
+ @cloud.auth_for_account @account
15
+ end
16
+ end
17
+
18
+ def to_s
19
+ "#{@name}"
20
+ end
21
+
22
+ def account=(account)
23
+ if @account == nil
24
+ @account = account
25
+ return true
26
+ else
27
+ raise "Cannot replace account for site"
28
+ end
29
+ end
30
+
31
+ def configstates
32
+ response = @cloud.get ["cloud-service-config", "configsubnetgroup", "accounts", @account.id, "subnetgroups", @subnet_group_id, "updatestates"]
33
+ states = LMC::Configstates.new response.body
34
+ end
35
+ end
36
+
37
+ end
data/lib/lmc/User.rb ADDED
@@ -0,0 +1,40 @@
1
+ module LMC
2
+ class User
3
+ #todo: look into hiding password
4
+ attr_reader :email
5
+
6
+ def initialize(data)
7
+ @email = data["email"]
8
+ @password = data["password"]
9
+ end
10
+
11
+ # current registration process unclear and likely to have changed
12
+ # since this code was written.
13
+ #def register()
14
+ # # cloud instance by default authenticates.
15
+ # # for registration specifically, no authentication is required
16
+ # # should be possible without email and password for "admin" user
17
+ # cloud = Cloud.instance
18
+ # cloud.post ["cloud-service-auth", "users"], {"password" => @password, "email" => @email}
19
+ #end
20
+
21
+ def update(old_pw)
22
+ cloud = Cloud.instance
23
+ begin
24
+ cloud.post ["cloud-service-auth", "users", "self", "password"], {"password" => @password, 'verification' => old_pw}
25
+ rescue RestClient::BadRequest => e
26
+ response_body = JSON.parse(e.response)
27
+ raise "#{e.message} - #{response_body['message']}"
28
+ end
29
+ end
30
+
31
+ def request_pw_reset
32
+ #https://beta.cloud.lancom.de/cloud-service-auth/actions
33
+ cloud = Cloud.instance
34
+ post_data = {"type" => "PASSWORD_RESET", "name" => @email}
35
+ cloud.post ["cloud-service-auth", "actions"], post_data
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,83 @@
1
+ module LMC
2
+ class AccountManager
3
+ @options
4
+ @global_options
5
+ @errors
6
+ attr_reader :errors
7
+
8
+ def initialize(options, global_options)
9
+ @options = options
10
+ @global_options = global_options
11
+ @errors = []
12
+ end
13
+
14
+ # returns nil if invite did not work
15
+ def invite(lmcen, distro, line, type, authority_name)
16
+ lmcen.auth_for_accounts([distro["id"]])
17
+ line = line.strip.downcase
18
+ begin
19
+ account = Account.get(distro["id"])
20
+ account_authorities = account.authorities
21
+ #puts account_authorities.inspect if @global_options[:debug]
22
+ if @global_options[:debug]
23
+ account_authorities.each do |a|
24
+ puts a["name"]
25
+ puts a.inspect
26
+ end
27
+ end
28
+ authority = account_authorities.find {|auth| auth["name"] == authority_name}
29
+ #puts "account authorities: #{account_authorities}" if @global_options[:debug]
30
+ puts authority if @global_options[:debug]
31
+ if !@options[:dry]
32
+ # TODO wenn der default authority nicht gibt geht das ding kaputt
33
+ invited = lmcen.invite_user_to_account(line, distro["id"], type, [authority["id"]])
34
+ puts "Invite response:" + invited.inspect if @global_options[:debug]
35
+ puts "Invited " + invited["name"].to_s + " to account #{distro["name"]}(#{invited.code})." if @global_options[:v]
36
+ if invited.code != 200
37
+ @errors << {:line => line, :result => invited.body}
38
+ return nil
39
+ end
40
+ else
41
+ invited = {"name" => line}
42
+ end
43
+
44
+ invite_url = lmcen.build_url("#", "register", Base64.encode64(invited["name"]))
45
+ if @options["show-csv"]
46
+ puts "\n" + invited["name"] + ", " + invite_url
47
+ end
48
+ if @options["send-mail"] && invited
49
+ mailbody = <<END
50
+ Hallo,
51
+ auf #{lmcen.cloud_host} wurde eine Einladung zu dem Account #{distro["name"]} für den Nutzer #{invited["name"]} erstellt.
52
+
53
+ Falls der Account noch nicht existiert, kann dieser Link zur Registrierung genutzt werden:
54
+ END
55
+ mail = Mail.new do
56
+ from "Philipp Erbelding <philipp.erbelding@lancom.de>"
57
+ to invited["name"]
58
+ subject "Einladung auf " + lmcen.cloud_host
59
+ body mailbody + invite_url
60
+ end
61
+
62
+ puts invite_url
63
+ if !@options[:dry]
64
+ puts "sending mail to " + invited["name"]
65
+ mail.delivery_method :smtp, address: "lcs-mail"
66
+ mail.deliver
67
+ else
68
+ puts "[DRY RUN] would send mail to " + invited["name"]
69
+ end
70
+ puts mail.to_s if @global_options[:v]
71
+ end
72
+
73
+ rescue RestClient::ExceptionWithResponse => e
74
+ puts e.to_s
75
+ puts invited.inspect
76
+ resp = JSON.parse(e.response)
77
+ puts resp.inspect
78
+ puts resp["message"]
79
+ end
80
+ return true
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,6 @@
1
+ require 'ostruct'
2
+ module LMC
3
+ class DeviceConfigState < OpenStruct
4
+
5
+ end
6
+ end
data/lib/lmc/entity.rb ADDED
@@ -0,0 +1,17 @@
1
+ module LMC
2
+ class Entity
3
+ def self.get_by_uuid_or_name term
4
+ raise "Missing argument" if term.nil?
5
+ begin
6
+ return self.get_by_uuid term
7
+ rescue RestClient::BadRequest, URI::InvalidURIError
8
+ return self.get_by_name term
9
+ end
10
+ end
11
+
12
+ def [] key
13
+ self.send(key)
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module LMC
2
+ class OutdatedTermsOfUseException < Exception
3
+ def initialize(response = {})
4
+ @response = response
5
+ end
6
+
7
+ def response
8
+ r = "Terms of use must be accepted before using this LMC instance:\n"
9
+ missing.each do |tos|
10
+ r += "Name: #{tos['name']}, Date #{tos['acceptance']}\n"
11
+
12
+ end
13
+ return r
14
+ end
15
+ def missing
16
+ @response['details']['missing']
17
+ end
18
+ end
19
+
20
+
21
+ end
@@ -0,0 +1,15 @@
1
+ module LMC
2
+ class Membership
3
+ attr_accessor :name, :type, :state, :authorities
4
+
5
+ def to_json(*a)
6
+ {
7
+ "name" => @name,
8
+ "type" => @type,
9
+ "state" => @state,
10
+ "authorities" => @authorities
11
+ }.to_json(*a)
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,34 @@
1
+ module LMC
2
+ class Principal
3
+ def initialize(data)
4
+ apply_data(data)
5
+ end
6
+
7
+ #returns itself, allows chaining
8
+ def save
9
+ response = if @id.nil?
10
+ Cloud.instance.post ["cloud-service-auth", "principals"], self
11
+ else
12
+ raise "editing principals not supported"
13
+ #@cloud.put ["cloud-service-auth", "principals", @id], self
14
+ end
15
+ apply_data(response.body)
16
+ return self
17
+ end
18
+ def to_json(*a)
19
+ {
20
+ "name" => @name,
21
+ "type" => @type,
22
+ "password" => @password
23
+ }.to_json(*a)
24
+ end
25
+
26
+ private
27
+ def apply_data(data)
28
+ @id = data['id']
29
+ @name = data['name']
30
+ @password = data['password']
31
+ @type = data['type']
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module LMC
2
+ VERSION = "0.4.0"
3
+ end
data/lmc.gemspec ADDED
@@ -0,0 +1,42 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "lmc/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "lmc"
8
+ spec.version = LMC::VERSION
9
+ spec.authors = ["erpel"]
10
+ spec.email = ["philipp@copythat.de"]
11
+
12
+ spec.summary = %q{Library for interacting with LMC cloud instances}
13
+ # spec.homepage = "https://copythat.de"
14
+ spec.license = 'BSD-3-Clause'
15
+
16
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ if spec.respond_to?(:metadata)
19
+ #spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
20
+ else
21
+ raise "RubyGems 2.0 or newer is required to protect against " \
22
+ "public gem pushes."
23
+ end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{^(test|spec|features)/})
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_development_dependency 'bundler', '~> 1.16'
33
+ spec.add_development_dependency 'minitest', '~> 5.0'
34
+ spec.add_development_dependency 'minitest-reporters', '~> 1.1'
35
+ spec.add_development_dependency 'rake', '~> 10.0'
36
+ spec.add_development_dependency 'recursive-open-struct', '~> 1.1'
37
+ spec.add_development_dependency 'simplecov', '~> 0.15'
38
+ spec.add_development_dependency 'pry-nav', '~> 0.2.4'
39
+
40
+ spec.add_runtime_dependency 'json', '~> 2.0'
41
+ spec.add_runtime_dependency 'rest-client', '~> 2.0'
42
+ end
metadata ADDED
@@ -0,0 +1,201 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lmc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - erpel
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-07-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest-reporters
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.1'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: recursive-open-struct
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.15'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.15'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry-nav
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.2.4
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.2.4
111
+ - !ruby/object:Gem::Dependency
112
+ name: json
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '2.0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '2.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rest-client
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '2.0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '2.0'
139
+ description:
140
+ email:
141
+ - philipp@copythat.de
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".gitignore"
147
+ - ".idea/inspectionProfiles/Project_Default.xml"
148
+ - ".idea/lmc.iml"
149
+ - ".idea/misc.xml"
150
+ - ".idea/modules.xml"
151
+ - ".idea/vcs.xml"
152
+ - ".ruby-version"
153
+ - ".travis.yml"
154
+ - Gemfile
155
+ - README.md
156
+ - Rakefile
157
+ - bin/console
158
+ - bin/setup
159
+ - coverage/.gitignore
160
+ - coverage/.last_run.json
161
+ - lib/lmc.rb
162
+ - lib/lmc/Account.rb
163
+ - lib/lmc/Cloud.rb
164
+ - lib/lmc/Configstates.rb
165
+ - lib/lmc/Device.rb
166
+ - lib/lmc/Response.rb
167
+ - lib/lmc/Site.rb
168
+ - lib/lmc/User.rb
169
+ - lib/lmc/account_manager.rb
170
+ - lib/lmc/device_config_state.rb
171
+ - lib/lmc/entity.rb
172
+ - lib/lmc/exceptions/lmc_outdated_terms_of_use_exception.rb
173
+ - lib/lmc/membership.rb
174
+ - lib/lmc/principal.rb
175
+ - lib/lmc/version.rb
176
+ - lmc.gemspec
177
+ homepage:
178
+ licenses:
179
+ - BSD-3-Clause
180
+ metadata: {}
181
+ post_install_message:
182
+ rdoc_options: []
183
+ require_paths:
184
+ - lib
185
+ required_ruby_version: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ required_rubygems_version: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ requirements: []
196
+ rubyforge_project:
197
+ rubygems_version: 2.6.11
198
+ signing_key:
199
+ specification_version: 4
200
+ summary: Library for interacting with LMC cloud instances
201
+ test_files: []