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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 77e70ad3672357e8772f829cdf43cb8005b82ec3
4
- data.tar.gz: 4f2b4a5249fbe6c31a6af63a6ffd9aeec60bbed0
2
+ SHA256:
3
+ metadata.gz: 794c51b66dd0d644686457e879f7afdac549631887c3992ff7fb3e0f605c75b6
4
+ data.tar.gz: 643df4d3a0afa76409a95bea74a9d1827ba52ccb34de79d1beef8100c9ecc21d
5
5
  SHA512:
6
- metadata.gz: 341100129b0941eaac64e24226fc100364209ab9821b7af26cdff2159e10064f188c7bb2add1d7829b3dc20835fe379c11f128f08ff447695a6d662a15b8c3e6
7
- data.tar.gz: f6502be9bc5df3826407317d315500fbc5d929082fb50ea0160508f1864baa329d5936fe777a982523aaae075cf2b132a162090be26b4739fb9030b1cf5d5a95
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
- :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: >-
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
- - name: Ticket Routing Details
43
- id: 11636
44
- value: >-
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
- :StatusId: 642
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][:Attributes]
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 'id' and 'value' fields.
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
@@ -38,7 +38,7 @@ task default: :test
38
38
  begin
39
39
  require 'rubocop/rake_task'
40
40
  RuboCop::RakeTask.new
41
- rescue StandardError => _
41
+ rescue StandardError => _e
42
42
  puts 'Rubocop not loaded.'
43
43
  end
44
44
 
@@ -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 => exception
10
- process_ajax_error exception, 'fetch teamdynamix tab information'
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.teamdynamix_asset_uid
14
+ return [[_('Asset'), 'None Associated or error from Team Dynamix']] unless @host.teamdynamix_asset
15
15
 
16
- get_teamdynamix_asset(@host.teamdynamix_asset_uid)
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
- nested_attrib_val = parent_attrib_val.select { |attrib| attrib['Name'] == child_attrib }
50
+
51
+ nested_attrib_val = parent_attrib_val.find { |attrib| attrib['Name'] == child_attrib }
56
52
  return '' if nested_attrib_val.blank?
57
- nested_attrib_val[0]['Value']
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
- included do
10
- before_create :create_teamdynamix_asset
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
- private
19
+ def teamdynamix_asset(search = false)
20
+ @teamdynamix_asset ||= td_api.get_asset(teamdynamix_asset_uid)
16
21
 
17
- def create_teamdynamix_asset
18
- # when the asset is already in teamdynamix
19
- assets = td_api.search_asset(SerialLike: name)
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
- if assets.empty?
22
- asset = td_api.create_asset(self)
23
- self.teamdynamix_asset_uid = asset['ID']
24
- elsif assets.length > 1
25
- raise 'Found more than 1 existing asset'
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(teamdynamix_asset_uid) if teamdynamix_asset_uid
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
- false
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(asset_id)
44
- uri = URI.parse("#{API_URL}/#{APP_ID}/assets/#{asset_id}")
45
- rest(:post, uri, retire_asset_payload(asset_id))
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: APP_ID,
117
- SerialNumber: host.name,
118
- Name: host.fqdn }
119
- create_attrs = evaluate_attributes(API_CONFIG[:create], host)
120
- default_attrs.merge(create_attrs)
121
- end
122
-
123
- def evaluate_attributes(create_attrs, host)
124
- create_attrs.symbolize_keys.each_with_object({}) do |(k, v), h|
125
- if k.eql?(:Attributes)
126
- h[:Attributes] = v.each_with_object([]) do |attribute, a|
127
- a << attribute.transform_keys(&:downcase)
128
- a.last['value'] = eval_attribute(a.last['value'], host)
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
- [:StatusID]
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
@@ -1,5 +1,5 @@
1
1
  Rails.application.routes.draw do
2
- constraints(:id => %r{[^\/]+}) do
2
+ constraints(:id => %r{[^/]+}) do
3
3
  resources :hosts do
4
4
  member do
5
5
  get 'teamdynamix'
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 '>= 1.7'
19
+ requires_foreman '>= 2.3'
20
20
 
21
21
  # Add permissions
22
22
  security_block :foreman_teamdynamix do
23
- ps = permission :view_hosts,
24
- { :hosts => [:teamdynamix] },
25
- :resource_type => 'Host'
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
- begin
36
- HostsHelper.send(:include, ForemanTeamdynamix::HostsHelperExtensions)
37
- ::HostsController.send(:include, ForemanTeamdynamix::HostsControllerExtensions)
38
- ::Host::Managed.send(:include, ForemanTeamdynamix::HostExtensions)
39
- rescue StandardError => e
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|
@@ -1,3 +1,3 @@
1
1
  module ForemanTeamdynamix
2
- VERSION = '0.4.0'.freeze
2
+ VERSION = '2.0.0'.freeze
3
3
  end
@@ -11,7 +11,7 @@ namespace :test do
11
11
  end
12
12
 
13
13
  namespace :foreman_teamdynamix do
14
- task :rubocop do
14
+ task rubocop: :environment do
15
15
  begin
16
16
  require 'rubocop/rake_task'
17
17
  RuboCop::RakeTask.new(:rubocop_foreman_teamdynamix) do |task|
@@ -1,4 +1,4 @@
1
- desc <<-DESC.strip_heredoc.squish
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
- creates = 0
16
- updates_from_serial_matching = 0
17
- update_from_asset_id = 0
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
- Host.all.each do |h|
23
- # if asset exists, update it
24
- if td_api.asset_exist?(h.teamdynamix_asset_uid)
25
- td_api.update_asset(h)
26
- update_from_asset_id += 1
27
- else
28
- assets = td_api.search_asset(SerialLike: h.name)
29
- if assets.empty?
30
- asset = td_api.create_asset(h)
31
- h.teamdynamix_asset_uid = asset['ID']
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: #{creates}" unless creates.eql?(0)
45
- unless updates_from_serial_matching.eql?(0)
46
- puts "Assets updated from serial search: #{updates_from_serial_matching}"
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
File without changes
File without changes
File without changes
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, 200
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, "<div id=\"teamdynamix\" class=\"tab-pane\" data-ajax-url=\"/hosts/#{host.name}/teamdynamix\" data-on-complete=\"onContentLoad\">"
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) { { 'Asset ID' => 'ID', 'Owner' => 'OwningCustomerName', 'Parent Asset' => 'ParentID' } }
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 teamdynamix_title, 'Team Dynamix'
61
+ assert_equal('Team Dynamix', teamdynamix_title)
60
62
  SETTINGS[:teamdynamix][:title] = title_orig
61
63
  end
62
64
  end
File without changes
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) { 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1bmlxdWVfbmFtZSI6InR5YWdpbkBtaWFtaW9oLmVkdSIsImlzcyI6IlREIiwiYXVkIjoiaHR0cHM6Ly93d3cudGVhbWR5bmFtaXguY29tLyIsImV4cCI6MTUxNzA2OTU1OSwibmJmIjoxNTE2OTgzMTU5fQ.PkvKbYQCV-hY7_ni4-Zg3qJARBagSzz99fclBYyxxas' }
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 + '/' + app_id + '/assets/' + sample_asset_id }
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 + '/' + app_id + '/assets' }
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 + '/auth')
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' => 'Bearer ' + dummy_token,
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 + '/' + app_id + '/assets/' + sample_asset_id }
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' => 'Bearer ' + dummy_token,
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' => 'Bearer ' + dummy_token,
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' => 'Bearer ' + dummy_token,
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 + '/auth')
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' => 'Bearer ' + dummy_token })
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
@@ -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.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: 2018-04-19 00:00:00.000000000 Z
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: '0'
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.11
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