foreman_teamdynamix 0.4.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|