foreman_teamdynamix 0.4.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/LICENSE +0 -0
- data/README.md +17 -16
- data/Rakefile +1 -1
- data/app/controllers/concerns/foreman_teamdynamix/hosts_controller_extensions.rb +2 -2
- data/app/helpers/concerns/foreman_teamdynamix/hosts_helper_extensions.rb +8 -11
- data/app/models/concerns/foreman_teamdynamix/host_extensions.rb +38 -17
- data/app/overrides/teamdynamix_add_tab.rb +0 -0
- data/app/overrides/teamdynamix_add_tab_link.rb +0 -0
- data/app/services/teamdynamix_api.rb +42 -34
- data/app/views/foreman_teamdynamix/hosts/_teamdynamix.html.erb +0 -0
- data/config/routes.rb +1 -1
- data/db/migrate/20171228033228_add_teamdynamix_asset_uid_to_hosts.rb +0 -0
- data/lib/foreman_teamdynamix.rb +0 -0
- data/lib/foreman_teamdynamix/engine.rb +9 -14
- data/lib/foreman_teamdynamix/version.rb +1 -1
- data/lib/tasks/foreman_teamdynamix_tasks.rake +1 -1
- data/lib/tasks/teamdynamix.rake +24 -29
- data/locale/Makefile +0 -0
- data/locale/en/foreman_teamdynamix.po +0 -0
- data/locale/foreman_teamdynamix.pot +0 -0
- data/locale/gemspec.rb +0 -0
- data/test/fake_teamdynamix_api.rb +0 -0
- data/test/functional/concerns/hosts_controller_extensions_test.rb +5 -4
- data/test/helpers/concerns/foreman_teamdynamix/hosts_helper_extensions_test.rb +4 -2
- data/test/models/host_extensions_test.rb +0 -0
- data/test/sample_asset.json +0 -0
- data/test/services/teamdynamix_api_test.rb +13 -11
- data/test/test_plugin_helper.rb +1 -1
- data/test/unit/foreman_teamdynamix_test.rb +0 -0
- metadata +22 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 794c51b66dd0d644686457e879f7afdac549631887c3992ff7fb3e0f605c75b6
|
4
|
+
data.tar.gz: 643df4d3a0afa76409a95bea74a9d1827ba52ccb34de79d1beef8100c9ecc21d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43388c4a90d67990cafa869640227c28dcc11d16ec9a404aca967c4e06ef44ee1637c9d95fb381cc398eca99f40a1e713799c11b0432510061da40286b6f14a6
|
7
|
+
data.tar.gz: a197a8ec8140d1d076b5173529d1bde01c8c3145708f701bf7ba3088fcb0f2d142b4c95eee03269ccbe4925a4ae0e10716f849b08bd1b442879f376e8f4c1ae1
|
data/LICENSE
CHANGED
File without changes
|
data/README.md
CHANGED
@@ -28,23 +28,23 @@ Example Configuration
|
|
28
28
|
:username: 'xxxxxx'
|
29
29
|
:password: 'xxxxxx'
|
30
30
|
:create:
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
-
|
36
|
-
|
37
|
-
|
38
|
-
-
|
39
|
-
|
40
|
-
|
31
|
+
StatusID: 641
|
32
|
+
AcquisitionDate: host.created_at
|
33
|
+
OwningCustomerName: "'foreman_teamdynamix_plugin_test'"
|
34
|
+
Attributes:
|
35
|
+
- Name: mu.ci.Lifecycle Status
|
36
|
+
ID: 11634
|
37
|
+
Value: 26190
|
38
|
+
- Name: mu.ci.Description
|
39
|
+
ID: 11632
|
40
|
+
Value: >-
|
41
41
|
"created by ForemanTeamdynamix plugin, owner is #{host.owner_id}"
|
42
|
-
-
|
43
|
-
|
44
|
-
|
42
|
+
- Name: Ticket Routing Details
|
43
|
+
ID: 11636
|
44
|
+
Value: >-
|
45
45
|
"Asset for host running on OS #{host.operatingsystem_id}"
|
46
46
|
:delete:
|
47
|
-
|
47
|
+
StatusId: 642
|
48
48
|
:fields:
|
49
49
|
:url: https://miamioh.teamdynamix.com/SBTDNext/Apps
|
50
50
|
Asset ID: ID
|
@@ -58,9 +58,10 @@ Example Configuration
|
|
58
58
|
* All attributes are passed to the TeamDynamix API as is, while creating or deleting a TeamDynamix Asset.
|
59
59
|
* An asset gets created or deleted with the Foreman Host create or delete life cycle event.
|
60
60
|
|
61
|
-
[:api][:create][
|
61
|
+
[:api][:create][Attributes]
|
62
62
|
* To configure any [Custom Attributes](https://api.teamdynamix.com/TDWebApi/Home/type/TeamDynamix.Api.CustomAttributes.CustomAttribute) for the asset.
|
63
|
-
* It must contain expected value for '
|
63
|
+
* It must contain expected value for 'Name', 'ID' and 'Value' fields.
|
64
|
+
* Notice the case of 'Name', 'ID' and 'Value', this must match for correct merging.
|
64
65
|
* rest of the fields are optional, check the Custom Attribute's definition for what other fields are updatable.
|
65
66
|
* Code evaluation is supported for custom attribute's value.
|
66
67
|
|
data/Rakefile
CHANGED
@@ -6,8 +6,8 @@ module ForemanTeamdynamix
|
|
6
6
|
def teamdynamix
|
7
7
|
find_resource
|
8
8
|
render partial: 'foreman_teamdynamix/hosts/teamdynamix', :locals => { :host => @host }
|
9
|
-
rescue ActionView::Template::Error =>
|
10
|
-
process_ajax_error
|
9
|
+
rescue ActionView::Template::Error => e
|
10
|
+
process_ajax_error e, 'fetch teamdynamix tab information'
|
11
11
|
end
|
12
12
|
|
13
13
|
private
|
@@ -11,9 +11,9 @@ module ForemanTeamdynamix
|
|
11
11
|
|
12
12
|
def teamdynamix_fields
|
13
13
|
td_pane_fields = SETTINGS[:teamdynamix][:fields] || DEFAULT_TD_PANE_FIELDS
|
14
|
-
return [[_('Asset'), 'None Associated']] unless @host.
|
14
|
+
return [[_('Asset'), 'None Associated or error from Team Dynamix']] unless @host.teamdynamix_asset
|
15
15
|
|
16
|
-
|
16
|
+
@asset = @host.teamdynamix_asset
|
17
17
|
|
18
18
|
# display a link to the asset if url set
|
19
19
|
fields = asset_uri(td_pane_fields)
|
@@ -32,29 +32,26 @@ module ForemanTeamdynamix
|
|
32
32
|
def asset_uri(td_pane_fields)
|
33
33
|
if td_pane_fields[:url]
|
34
34
|
uri = "#{td_pane_fields[:url]}/#{@asset['AppID']}/Assets/AssetDet?AssetID=#{@asset['ID']}"
|
35
|
-
[[_('URI'), link_to(@asset['SerialNumber'], uri, target: '_blank')]]
|
35
|
+
[[_('URI'), link_to(@asset['SerialNumber'], uri, target: '_blank', rel: 'noopener')]]
|
36
36
|
else
|
37
37
|
[]
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
def get_teamdynamix_asset(asset_id)
|
42
|
-
@asset = @host.td_api.get_asset(asset_id)
|
43
|
-
rescue StandardError => e
|
44
|
-
raise "Error getting asset Data from Team Dynamix: #{e.message}"
|
45
|
-
end
|
46
|
-
|
47
41
|
def get_nested_attrib_val(nested_attrib)
|
48
42
|
nested_attrib_tokens = nested_attrib.split('.')
|
49
43
|
parent_attrib = nested_attrib_tokens.first
|
50
44
|
child_attrib = nested_attrib_tokens[1..nested_attrib_tokens.length].join('.')
|
51
45
|
return '' if parent_attrib.blank? || child_attrib.blank?
|
46
|
+
|
52
47
|
child_attrib.delete!("'")
|
53
48
|
parent_attrib_val = @asset[parent_attrib]
|
54
49
|
return '' if parent_attrib_val.blank?
|
55
|
-
|
50
|
+
|
51
|
+
nested_attrib_val = parent_attrib_val.find { |attrib| attrib['Name'] == child_attrib }
|
56
52
|
return '' if nested_attrib_val.blank?
|
57
|
-
|
53
|
+
|
54
|
+
nested_attrib_val['Value']
|
58
55
|
end
|
59
56
|
end
|
60
57
|
end
|
@@ -2,38 +2,59 @@ module ForemanTeamdynamix
|
|
2
2
|
module HostExtensions
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
|
+
included do
|
6
|
+
before_create :create_or_update_teamdynamix_asset
|
7
|
+
before_destroy :retire_teamdynamix_asset
|
8
|
+
validates :teamdynamix_asset_uid, uniqueness: { :allow_blank => true }
|
9
|
+
end
|
10
|
+
|
5
11
|
def td_api
|
6
12
|
@td_api ||= TeamdynamixApi.instance
|
7
13
|
end
|
8
14
|
|
9
|
-
|
10
|
-
|
11
|
-
before_destroy :retire_teamdynamix_asset
|
12
|
-
validates :teamdynamix_asset_uid, uniqueness: { :allow_blank => true }
|
15
|
+
def teamdynamix_asset_status
|
16
|
+
@teamdynamix_asset_status
|
13
17
|
end
|
14
18
|
|
15
|
-
|
19
|
+
def teamdynamix_asset(search = false)
|
20
|
+
@teamdynamix_asset ||= td_api.get_asset(teamdynamix_asset_uid)
|
16
21
|
|
17
|
-
|
18
|
-
|
19
|
-
|
22
|
+
if search && !@teamdynamix_asset
|
23
|
+
assets = td_api.search_asset(SerialLike: name)
|
24
|
+
if assets.length == 1
|
25
|
+
@teamdynamix_asset = td_api.get_asset(assets.first['ID'])
|
26
|
+
self.teamdynamix_asset_uid = teamdynamix_asset['ID']
|
27
|
+
@teamdynamix_asset_status = :updated_search
|
28
|
+
elsif assets.length > 1
|
29
|
+
errors.add(:base, _("Search for asset in TeamDynamix failed: Found #{assets.length} matching assets"))
|
30
|
+
end
|
31
|
+
end
|
20
32
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
else
|
27
|
-
self.teamdynamix_asset_uid = assets.first['ID']
|
33
|
+
@teamdynamix_asset
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_or_update_teamdynamix_asset(save = false)
|
37
|
+
if teamdynamix_asset(true)
|
28
38
|
td_api.update_asset(self)
|
39
|
+
@teamdynamix_asset_status ||= :updated_id
|
40
|
+
self.save if save
|
41
|
+
elsif errors.empty?
|
42
|
+
@teamdynamix_asset = td_api.create_asset(self)
|
43
|
+
self.teamdynamix_asset_uid = teamdynamix_asset['ID']
|
44
|
+
@teamdynamix_asset_status = :created
|
45
|
+
self.save if save
|
46
|
+
else
|
47
|
+
false
|
29
48
|
end
|
30
49
|
rescue StandardError => e
|
31
|
-
errors.add(:base, _("Could not create the asset for the host in TeamDynamix: #{e.message}"))
|
50
|
+
errors.add(:base, _("Could not create or update the asset for the host in TeamDynamix: #{e.message}"))
|
32
51
|
false
|
33
52
|
end
|
34
53
|
|
54
|
+
private
|
55
|
+
|
35
56
|
def retire_teamdynamix_asset
|
36
|
-
td_api.retire_asset(
|
57
|
+
td_api.retire_asset(self) if teamdynamix_asset
|
37
58
|
rescue StandardError => e
|
38
59
|
errors.add(:base, _("Could not retire the asset for the host in TeamDynamix: #{e.message}"))
|
39
60
|
false
|
File without changes
|
File without changes
|
@@ -5,12 +5,15 @@ class TeamdynamixApi
|
|
5
5
|
if SETTINGS[:teamdynamix].blank?
|
6
6
|
raise('Missing configurations for the plugin see https://github.com/MiamiOH/foreman_teamdynamix')
|
7
7
|
end
|
8
|
+
|
8
9
|
API_CONFIG = SETTINGS[:teamdynamix][:api]
|
9
10
|
|
10
11
|
raise('Missing Team Dynamix Api ID in plugin settings') if API_CONFIG[:appId].blank?
|
12
|
+
|
11
13
|
APP_ID = API_CONFIG[:appId]
|
12
14
|
|
13
15
|
raise('Missing Team Dynamix API URL in plugin settings') if API_CONFIG[:url].blank?
|
16
|
+
|
14
17
|
API_URL = API_CONFIG[:url]
|
15
18
|
|
16
19
|
def initialize
|
@@ -20,14 +23,12 @@ class TeamdynamixApi
|
|
20
23
|
|
21
24
|
# returns TeamDynamix.Api.Assets.Asset
|
22
25
|
def get_asset(asset_id)
|
26
|
+
return nil unless asset_id
|
27
|
+
|
23
28
|
uri = URI.parse("#{API_URL}/#{APP_ID}/assets/#{asset_id}")
|
24
29
|
rest(:get, uri)
|
25
|
-
end
|
26
|
-
|
27
|
-
def asset_exist?(asset_id)
|
28
|
-
get_asset(asset_id).present?
|
29
30
|
rescue RuntimeError
|
30
|
-
|
31
|
+
nil
|
31
32
|
end
|
32
33
|
|
33
34
|
def create_asset(host)
|
@@ -40,9 +41,9 @@ class TeamdynamixApi
|
|
40
41
|
rest(:post, uri, update_asset_payload(host))
|
41
42
|
end
|
42
43
|
|
43
|
-
def retire_asset(
|
44
|
-
uri = URI.parse("#{API_URL}/#{APP_ID}/assets/#{
|
45
|
-
rest(:post, uri, retire_asset_payload(
|
44
|
+
def retire_asset(host)
|
45
|
+
uri = URI.parse("#{API_URL}/#{APP_ID}/assets/#{host.teamdynamix_asset_uid}")
|
46
|
+
rest(:post, uri, retire_asset_payload(host))
|
46
47
|
end
|
47
48
|
|
48
49
|
# Gets a list of assets matching the specified criteria. (IEnumerable(Of TeamDynamix.Api.Assets.Asset))
|
@@ -106,26 +107,38 @@ class TeamdynamixApi
|
|
106
107
|
end
|
107
108
|
end
|
108
109
|
|
109
|
-
def retire_asset_payload(asset_id)
|
110
|
-
asset = get_asset(asset_id)
|
111
|
-
asset.merge(API_CONFIG[:delete].stringify_keys)
|
112
|
-
end
|
113
|
-
|
114
110
|
def create_asset_payload(host)
|
115
111
|
ensure_configured_create_params
|
116
|
-
default_attrs = { AppID
|
117
|
-
SerialNumber
|
118
|
-
Name
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
112
|
+
default_attrs = { 'AppID' => APP_ID,
|
113
|
+
'SerialNumber' => host.name,
|
114
|
+
'Name' => host.fqdn }
|
115
|
+
evaluate_attributes(API_CONFIG[:create], host, default_attrs)
|
116
|
+
end
|
117
|
+
|
118
|
+
def update_asset_payload(host)
|
119
|
+
default_attrs = { 'AppID' => APP_ID,
|
120
|
+
'SerialNumber' => host.name,
|
121
|
+
'Name' => host.fqdn }
|
122
|
+
evaluate_attributes(API_CONFIG[:create], host, host.teamdynamix_asset.merge(default_attrs))
|
123
|
+
end
|
124
|
+
|
125
|
+
def retire_asset_payload(host)
|
126
|
+
evaluate_attributes(API_CONFIG[:delete], host, host.teamdynamix_asset)
|
127
|
+
end
|
128
|
+
|
129
|
+
def evaluate_attributes(attrs, host, asset = {})
|
130
|
+
attrs.stringify_keys.each_with_object(asset) do |(k, v), h|
|
131
|
+
if k.eql?('Attributes')
|
132
|
+
h['Attributes'] ||= []
|
133
|
+
v.each do |attrib|
|
134
|
+
attrib_c = attrib.stringify_keys
|
135
|
+
match = h['Attributes'].find { |attrib_a| attrib_a['Name'] == attrib_c['Name'] }
|
136
|
+
if match
|
137
|
+
match['Value'] = eval_attribute(attrib_c['Value'], host)
|
138
|
+
else
|
139
|
+
attrib_c['Value'] = eval_attribute(attrib_c['Value'], host)
|
140
|
+
h['Attributes'] << attrib_c
|
141
|
+
end
|
129
142
|
end
|
130
143
|
else
|
131
144
|
h[k] = eval_attribute(v, host)
|
@@ -140,21 +153,16 @@ class TeamdynamixApi
|
|
140
153
|
end
|
141
154
|
|
142
155
|
def must_configure_create_params
|
143
|
-
[
|
156
|
+
['StatusID']
|
144
157
|
end
|
145
158
|
|
146
159
|
def valid_auth_token?(token)
|
147
|
-
token.match(/^[a-zA-Z0-9
|
148
|
-
end
|
149
|
-
|
150
|
-
def update_asset_payload(host)
|
151
|
-
payload = { ID: host.teamdynamix_asset_uid }
|
152
|
-
payload.merge(create_asset_payload(host))
|
160
|
+
token.match(/^[a-zA-Z0-9.\-_]*$/)
|
153
161
|
end
|
154
162
|
|
155
163
|
def ensure_configured_create_params
|
156
164
|
must_configure_create_params.each do |must_configure_param|
|
157
|
-
unless API_CONFIG[:create].include?(must_configure_param)
|
165
|
+
unless API_CONFIG[:create].include?(must_configure_param) || API_CONFIG[:create].include?(must_configure_param.to_sym)
|
158
166
|
raise("#{must_configure_param} is required. Set it as a configuration item.")
|
159
167
|
end
|
160
168
|
end
|
File without changes
|
data/config/routes.rb
CHANGED
File without changes
|
data/lib/foreman_teamdynamix.rb
CHANGED
File without changes
|
@@ -16,29 +16,24 @@ module ForemanTeamdynamix
|
|
16
16
|
|
17
17
|
initializer 'foreman_teamdynamix.register_plugin', :before => :finisher_hook do |_app|
|
18
18
|
Foreman::Plugin.register :foreman_teamdynamix do
|
19
|
-
requires_foreman '>=
|
19
|
+
requires_foreman '>= 2.3'
|
20
20
|
|
21
21
|
# Add permissions
|
22
22
|
security_block :foreman_teamdynamix do
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
pn = ps.pop
|
27
|
-
po = ps.detect { |p| p.name == :view_hosts }
|
28
|
-
po.actions << pn.actions.first
|
23
|
+
permission :view_teamdynamix,
|
24
|
+
{ :hosts => [:teamdynamix] },
|
25
|
+
:resource_type => 'Host'
|
29
26
|
end
|
30
27
|
end
|
31
28
|
end
|
32
29
|
|
33
30
|
# Include concerns in this config.to_prepare block
|
34
31
|
config.to_prepare do
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
Rails.logger.warn "ForemanTeamdynamix: skipping engine hook (#{e})"
|
41
|
-
end
|
32
|
+
HostsHelper.include ForemanTeamdynamix::HostsHelperExtensions
|
33
|
+
::HostsController.include ForemanTeamdynamix::HostsControllerExtensions
|
34
|
+
::Host::Managed.include ForemanTeamdynamix::HostExtensions
|
35
|
+
rescue StandardError => e
|
36
|
+
Rails.logger.warn "ForemanTeamdynamix: skipping engine hook (#{e})"
|
42
37
|
end
|
43
38
|
|
44
39
|
initializer 'foreman_teamdynamix.register_gettext', after: :load_config_initializers do |_app|
|
data/lib/tasks/teamdynamix.rake
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
desc
|
1
|
+
desc <<~DESC.squish
|
2
2
|
Scans existing hosts and creates or updates the asset in TeamDynamix.
|
3
3
|
* If found, update the fields in the TeamDynamix asset.
|
4
4
|
* If not found, create a TeamDynamix asset with desired fields.
|
@@ -6,46 +6,41 @@ desc <<-DESC.strip_heredoc.squish
|
|
6
6
|
It could be run for all the hosts as:
|
7
7
|
* rake teamydynamix:sync:hosts
|
8
8
|
|
9
|
+
Available options:
|
10
|
+
* where => where string for limiting host query
|
11
|
+
* limit => limit for limiting host query
|
12
|
+
|
9
13
|
DESC
|
10
14
|
namespace :teamdynamix do
|
11
15
|
namespace :sync do
|
12
16
|
task :hosts => :environment do
|
13
|
-
td_api = TeamdynamixApi.instance
|
14
17
|
errors = []
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
created = 0
|
19
|
+
updated_search = 0
|
20
|
+
updated_id = 0
|
18
21
|
|
19
22
|
console_user = User.find_by(login: 'foreman_console_admin')
|
20
23
|
User.current = console_user
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
errors.push("Could not save host: #{h.name} (#{h.id})") unless h.save
|
33
|
-
creates += 1
|
34
|
-
elsif assets.length > 1
|
35
|
-
errors.push("Could not sync: Found more than 1 asset for #{h.name} (#{h.id})")
|
36
|
-
else
|
37
|
-
h.teamdynamix_asset_uid = assets.first['ID']
|
38
|
-
td_api.update_asset(h)
|
39
|
-
errors.push("Could not save host: #{h.name} (#{h.id})") unless h.save
|
40
|
-
updates_from_serial_matching += 1
|
25
|
+
hosts = Host
|
26
|
+
hosts = hosts.where(ENV['where']) if ENV['where']
|
27
|
+
hosts = hosts.limit(ENV['limit']) if ENV['limit']
|
28
|
+
|
29
|
+
hosts.all.each do |h|
|
30
|
+
if h.create_or_update_teamdynamix_asset(true)
|
31
|
+
case h.teamdynamix_asset_status
|
32
|
+
when :created then created += 1
|
33
|
+
when :updated_search then updated_search += 1
|
34
|
+
when :updated_id then updated_id += 1
|
41
35
|
end
|
36
|
+
else
|
37
|
+
errors.push("Could not save host: #{h.name} (#{h.id}):\n #{h.errors.full_messages.join("\n ")}")
|
42
38
|
end
|
39
|
+
sleep(1.5) # TD only allows 60 api calls per minute
|
43
40
|
end
|
44
|
-
puts "Assets created: #{
|
45
|
-
unless
|
46
|
-
|
47
|
-
end
|
48
|
-
puts "Assets updated from ID: #{update_from_asset_id}" unless update_from_asset_id.eql?(0)
|
41
|
+
puts "Assets created: #{created}" unless created.eql?(0)
|
42
|
+
puts "Assets updated from serial search: #{updated_search}" unless updated_search.eql?(0)
|
43
|
+
puts "Assets updated from ID: #{updated_id}" unless updated_id.eql?(0)
|
49
44
|
puts "Errors:\n#{errors.join("\n")}" unless errors.empty?
|
50
45
|
end
|
51
46
|
end
|
data/locale/Makefile
CHANGED
File without changes
|
File without changes
|
File without changes
|
data/locale/gemspec.rb
CHANGED
File without changes
|
File without changes
|
@@ -7,7 +7,7 @@ class HostsControllerTest < ActionController::TestCase
|
|
7
7
|
before do
|
8
8
|
Host::Managed.any_instance.stubs(:td_api).returns(td_api)
|
9
9
|
end
|
10
|
-
# rubocop:disable Style/StringLiterals, HttpPositionalArguments
|
10
|
+
# rubocop:disable Style/StringLiterals, Rails/HttpPositionalArguments
|
11
11
|
describe 'Given host exist as an asset in TeamDynamix' do
|
12
12
|
describe 'when TeamDynamix asset attributes are configured' do
|
13
13
|
describe 'GET hosts/show' do
|
@@ -15,9 +15,10 @@ class HostsControllerTest < ActionController::TestCase
|
|
15
15
|
get :show, { :id => host.name }, set_session_user
|
16
16
|
assert_includes response.headers['Content-Type'], 'text/html'
|
17
17
|
assert_includes response.body, "<ul id=\"myTab\""
|
18
|
-
assert_equal response.status
|
18
|
+
assert_equal(200, response.status)
|
19
19
|
assert_includes response.body, "<li><a href=\"#teamdynamix\" data-toggle=\"tab\">#{td_tab_title}</a></li>"
|
20
|
-
assert_includes response.body,
|
20
|
+
assert_includes response.body,
|
21
|
+
"<div id=\"teamdynamix\" class=\"tab-pane\" data-ajax-url=\"/hosts/#{host.name}/teamdynamix\" data-on-complete=\"onContentLoad\">"
|
21
22
|
end
|
22
23
|
test 'TeamDynamix tab contains configured asset attributes' do
|
23
24
|
skip
|
@@ -27,5 +28,5 @@ class HostsControllerTest < ActionController::TestCase
|
|
27
28
|
end
|
28
29
|
end
|
29
30
|
end
|
30
|
-
# rubocop:enable Style/StringLiterals, HttpPositionalArguments
|
31
|
+
# rubocop:enable Style/StringLiterals, Rails/HttpPositionalArguments
|
31
32
|
end
|
@@ -13,7 +13,9 @@ class HostsHelperExtensionsTest < ActiveSupport::TestCase
|
|
13
13
|
describe '#teamdynamix_fields' do
|
14
14
|
let(:sample_asset) { td_api.get_asset }
|
15
15
|
let(:default_fields) { [sample_asset_uri] }
|
16
|
-
let(:direct_attribs_config)
|
16
|
+
let(:direct_attribs_config) do
|
17
|
+
{ 'Asset ID' => 'ID', 'Owner' => 'OwningCustomerName', 'Parent Asset' => 'ParentID' }
|
18
|
+
end
|
17
19
|
let(:direct_attribs_fields) { get_direct_asset_attribs_val(direct_attribs_config) }
|
18
20
|
let(:expected_fields) { default_fields + direct_attribs_fields }
|
19
21
|
before do
|
@@ -56,7 +58,7 @@ class HostsHelperExtensionsTest < ActiveSupport::TestCase
|
|
56
58
|
|
57
59
|
test 'settings title is not present: return default title' do
|
58
60
|
SETTINGS[:teamdynamix][:title] = nil
|
59
|
-
assert_equal
|
61
|
+
assert_equal('Team Dynamix', teamdynamix_title)
|
60
62
|
SETTINGS[:teamdynamix][:title] = title_orig
|
61
63
|
end
|
62
64
|
end
|
File without changes
|
data/test/sample_asset.json
CHANGED
File without changes
|
@@ -8,17 +8,19 @@ class TeamdynamixApiTest < ActiveSupport::TestCase
|
|
8
8
|
let(:api_url) { api_config[:url] }
|
9
9
|
let(:host) { FactoryBot.build(:host, :managed) }
|
10
10
|
let(:auth_payload) { { username: api_config[:username], password: api_config[:password] }.to_json }
|
11
|
-
let(:dummy_token)
|
11
|
+
let(:dummy_token) do
|
12
|
+
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1bmlxdWVfbmFtZSI6InR5YWdpbkBtaWFtaW9oLmVkdSIsImlzcyI6IlREIiwiYXVkIjoiaHR0cHM6Ly93d3cudGVhbWR5bmFtaXguY29tLyIsImV4cCI6MTUxNzA2OTU1OSwibmJmIjoxNTE2OTgzMTU5fQ.PkvKbYQCV-hY7_ni4-Zg3qJARBagSzz99fclBYyxxas'
|
13
|
+
end
|
12
14
|
let(:sample_asset) { FakeTeamdynamixApi.new.get_asset }
|
13
15
|
let(:sample_asset_id) { sample_asset['ID'].to_s }
|
14
16
|
let(:host_name) { 'delete.foreman_teamdynamix.com' }
|
15
|
-
let(:get_asset_path) { api_url
|
17
|
+
let(:get_asset_path) { "#{api_url}/#{app_id}/assets/#{sample_asset_id}" }
|
16
18
|
let(:create_status_id) { 641 }
|
17
19
|
let(:custom_attributes) do
|
18
20
|
[{ 'name' => 'mu.ci.Lifecycle Status', 'id' => 11_634, 'value' => '26193' },
|
19
21
|
{ 'name' => 'mu.ci.Description', 'id' => 11_632, 'value' => 'Foreman host created by ForemanTeamdynamix plugin' }]
|
20
22
|
end
|
21
|
-
let(:create_path) { api_url
|
23
|
+
let(:create_path) { "#{api_url}/#{app_id}/assets" }
|
22
24
|
let(:create_payload) do
|
23
25
|
{ AppID: app_id,
|
24
26
|
SerialNumber: host_name,
|
@@ -27,7 +29,7 @@ class TeamdynamixApiTest < ActiveSupport::TestCase
|
|
27
29
|
Attributes: custom_attributes }
|
28
30
|
end
|
29
31
|
before do
|
30
|
-
stub_request(:post, api_url
|
32
|
+
stub_request(:post, "#{api_url}/auth")
|
31
33
|
.with(body: auth_payload,
|
32
34
|
headers: { 'Content-Type' => 'application/json' })
|
33
35
|
.to_return(status: 200, body: dummy_token)
|
@@ -45,7 +47,7 @@ class TeamdynamixApiTest < ActiveSupport::TestCase
|
|
45
47
|
context 'Valid Request' do
|
46
48
|
before do
|
47
49
|
stub_request(:post, update_path)
|
48
|
-
.with(headers: { 'Authorization' =>
|
50
|
+
.with(headers: { 'Authorization' => "Bearer #{dummy_token}",
|
49
51
|
'Content-Type' => 'application/json' },
|
50
52
|
body: update_payload)
|
51
53
|
.to_return(status: 200, body: sample_asset.to_json)
|
@@ -67,10 +69,10 @@ class TeamdynamixApiTest < ActiveSupport::TestCase
|
|
67
69
|
end
|
68
70
|
describe 'valid request' do
|
69
71
|
let(:retired_asset) { sample_asset.merge('StatusID' => retire_status_id) }
|
70
|
-
let(:retire_path) { api_url
|
72
|
+
let(:retire_path) { "#{api_url}/#{app_id}/assets/#{sample_asset_id}" }
|
71
73
|
before do
|
72
74
|
stub_request(:post, retire_path)
|
73
|
-
.with(headers: { 'Authorization' =>
|
75
|
+
.with(headers: { 'Authorization' => "Bearer #{dummy_token}",
|
74
76
|
'Content-Type' => 'application/json' })
|
75
77
|
.to_return(status: 200, body: retired_asset.to_json)
|
76
78
|
end
|
@@ -91,7 +93,7 @@ class TeamdynamixApiTest < ActiveSupport::TestCase
|
|
91
93
|
context 'Valid Request' do
|
92
94
|
before do
|
93
95
|
stub_request(:post, create_path)
|
94
|
-
.with(headers: { 'Authorization' =>
|
96
|
+
.with(headers: { 'Authorization' => "Bearer #{dummy_token}",
|
95
97
|
'Content-Type' => 'application/json' },
|
96
98
|
body: create_payload)
|
97
99
|
.to_return(status: 200, body: sample_asset.to_json)
|
@@ -112,7 +114,7 @@ class TeamdynamixApiTest < ActiveSupport::TestCase
|
|
112
114
|
# rubocop:enable Style/StringLiterals
|
113
115
|
before do
|
114
116
|
stub_request(:post, create_path)
|
115
|
-
.with(headers: { 'Authorization' =>
|
117
|
+
.with(headers: { 'Authorization' => "Bearer #{dummy_token}",
|
116
118
|
'Content-Type' => 'application/json' },
|
117
119
|
body: create_payload)
|
118
120
|
.to_return(status: 400, body: error_body)
|
@@ -138,7 +140,7 @@ class TeamdynamixApiTest < ActiveSupport::TestCase
|
|
138
140
|
let(:error) { { status: "403", msg: "", body: error_body }.to_json }
|
139
141
|
# rubocop:enable Style/StringLiterals
|
140
142
|
before do
|
141
|
-
stub_request(:post, api_url
|
143
|
+
stub_request(:post, "#{api_url}/auth")
|
142
144
|
.with(body: auth_payload)
|
143
145
|
.to_return(status: 403, body: error_body)
|
144
146
|
end
|
@@ -154,7 +156,7 @@ class TeamdynamixApiTest < ActiveSupport::TestCase
|
|
154
156
|
context 'Valid Request' do
|
155
157
|
before do
|
156
158
|
stub_request(:get, get_asset_path)
|
157
|
-
.with(headers: { 'Authorization' =>
|
159
|
+
.with(headers: { 'Authorization' => "Bearer #{dummy_token}" })
|
158
160
|
.to_return(status: 200, body: sample_asset.to_json)
|
159
161
|
end
|
160
162
|
it 'returns asset json' do
|
data/test/test_plugin_helper.rb
CHANGED
@@ -28,7 +28,7 @@ end
|
|
28
28
|
def sample_asset_uri
|
29
29
|
api_url = SETTINGS[:teamdynamix][:api][:url]
|
30
30
|
asset_uri = api_url.split('api').first + sample_asset['Uri']
|
31
|
-
[_('URI'), link_to(sample_asset['Uri'], asset_uri, target: '_blank')]
|
31
|
+
[_('URI'), link_to(sample_asset['Uri'], asset_uri, target: '_blank', rel: 'noopener')]
|
32
32
|
end
|
33
33
|
|
34
34
|
require 'webmock/minitest'
|
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_teamdynamix
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nipendar Tyagi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: deface
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop-rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: webmock
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -101,7 +115,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
101
115
|
requirements:
|
102
116
|
- - ">="
|
103
117
|
- !ruby/object:Gem::Version
|
104
|
-
version:
|
118
|
+
version: 2.5.0
|
105
119
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
120
|
requirements:
|
107
121
|
- - ">="
|
@@ -109,16 +123,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
123
|
version: '0'
|
110
124
|
requirements: []
|
111
125
|
rubyforge_project:
|
112
|
-
rubygems_version: 2.6
|
126
|
+
rubygems_version: 2.7.6
|
113
127
|
signing_key:
|
114
128
|
specification_version: 4
|
115
129
|
summary: Creates TeamDynamix Asset when a host is created in Foreman
|
116
130
|
test_files:
|
117
|
-
- test/models/host_extensions_test.rb
|
118
131
|
- test/fake_teamdynamix_api.rb
|
119
|
-
- test/test_plugin_helper.rb
|
120
|
-
- test/sample_asset.json
|
121
132
|
- test/functional/concerns/hosts_controller_extensions_test.rb
|
133
|
+
- test/helpers/concerns/foreman_teamdynamix/hosts_helper_extensions_test.rb
|
134
|
+
- test/models/host_extensions_test.rb
|
135
|
+
- test/sample_asset.json
|
122
136
|
- test/services/teamdynamix_api_test.rb
|
137
|
+
- test/test_plugin_helper.rb
|
123
138
|
- test/unit/foreman_teamdynamix_test.rb
|
124
|
-
- test/helpers/concerns/foreman_teamdynamix/hosts_helper_extensions_test.rb
|