Project

General

Profile

Revision 611959a3

Added by Thomas McKay over 5 years ago

fixes #16281 - add --itemized-subscriptions to activation-keys

View differences:

lib/hammer_cli_csv.rb
6 6
  require 'hammer_cli_foreman_tasks'
7 7

  
8 8
  require 'hammer_cli_csv/base'
9
  require 'hammer_cli_csv/utils/subscriptions'
9 10

  
10 11
  require 'hammer_cli_csv/csv'
11 12
  require 'hammer_cli_csv/activation_keys'
lib/hammer_cli_csv/activation_keys.rb
1 1
module HammerCLICsv
2 2
  class CsvCommand
3 3
    class ActivationKeysCommand < BaseCommand
4
      include ::HammerCLICsv::Utils::Subscriptions
5

  
4 6
      command_name 'activation-keys'
5 7
      desc         _('import or export activation keys')
6 8

  
9
      def self.supported?
10
        true
11
      end
12

  
13
      option %w(--itemized-subscriptions), :flag, _('Export one subscription per row, only process update subscriptions on import')
14

  
7 15
      ORGANIZATION = 'Organization'
8 16
      DESCRIPTION = 'Description'
9 17
      LIMIT = 'Limit'
......
13 21
      SERVICELEVEL = "Service Level"
14 22
      RELEASEVER = "Release Version"
15 23
      AUTOATTACH = "Auto-Attach"
16
      SUBSCRIPTIONS = 'Subscriptions'
17 24

  
18 25
      def export(csv)
19
        csv << [NAME, ORGANIZATION, DESCRIPTION, LIMIT, ENVIRONMENT, CONTENTVIEW,
20
                HOSTCOLLECTIONS, AUTOATTACH, SERVICELEVEL, RELEASEVER, SUBSCRIPTIONS]
26
        if option_itemized_subscriptions?
27
          export_itemized_subscriptions csv
28
        else
29
          export_all csv
30
        end
31
      end
32

  
33
      def export_itemized_subscriptions(csv)
34
        csv << shared_headers + [Utils::Subscriptions::SUBS_NAME, Utils::Subscriptions::SUBS_TYPE,
35
                                 Utils::Subscriptions::SUBS_QUANTITY, Utils::Subscriptions::SUBS_SKU,
36
                                 Utils::Subscriptions::SUBS_CONTRACT, Utils::Subscriptions::SUBS_ACCOUNT,
37
                                 Utils::Subscriptions::SUBS_START, Utils::Subscriptions::SUBS_END]
38
        iterate_activationkeys(csv) do |activationkey|
39
          columns = shared_columns(activationkey)
40
          @api.resource(:subscriptions).call(:index, {
41
              'organization_id' => activationkey['organization']['id'],
42
              'activation_key_id' => activationkey['id']
43
          })['results'].collect do |subscription|
44
            subscription_type = subscription['product_id'].to_i == 0 ? 'Red Hat' : 'Custom'
45
            subscription_type += ' Guest' if subscription['type'] == 'STACK_DERIVED'
46
            subscription_type += ' Temporary' if subscription['type'] == 'UNMAPPED_GUEST'
47
            amount = (subscription['quantity_attached'].nil? || subscription['quantity_attached'] < 1) ? 'Automatic' : subscription['quantity_attached']
48
            csv << columns +
49
              [subscription['product_name'], subscription_type, amount,
50
               subscription['product_id'], subscription['contract_number'], subscription['account_number'],
51
               DateTime.parse(subscription['start_date']),
52
               DateTime.parse(subscription['end_date'])]
53
          end
54
        end
55
      end
56

  
57
      def export_all(csv)
58
        csv << shared_headers + [SUBSCRIPTIONS]
59
        iterate_activationkeys(csv) do |activationkey|
60
          subscriptions = CSV.generate do |column|
61
            column << @api.resource(:subscriptions).call(:index, {
62
                          'organization_id' => activationkey['organization']['id'],
63
                          'activation_key_id' => activationkey['id']
64
                      })['results'].collect do |subscription|
65
              amount = (subscription['quantity_attached'].nil? || subscription['quantity_attached'] < 1) ? 'Automatic' : subscription['quantity_attached']
66
              "#{amount}"\
67
              "|#{subscription['product_id']}"\
68
              "|#{subscription['product_name']}"\
69
              "|#{subscription['contract_number']}|#{subscription['account_number']}"
70
            end
71
          end
72
          subscriptions.delete!("\n")
73
          csv << shared_columns(activationkey) + [subscriptions]
74
        end
75
      end
76

  
77
      def iterate_activationkeys(csv)
21 78
        @api.resource(:organizations).call(:index, {
22 79
            :per_page => 999999
23 80
        })['results'].each do |organization|
......
27 84
              'per_page' => 999999,
28 85
              'organization_id' => organization['id']
29 86
          })['results'].each do |activationkey|
30
            name = namify(activationkey['name'])
31
            count = 1
32
            description = activationkey['description']
33
            limit = activationkey['unlimited_content_hosts'] ? 'Unlimited' : activationkey['max_content_hosts']
34
            environment = activationkey['environment']['label']
35
            contentview = activationkey['content_view']['name']
36
            hostcollections = export_column(activationkey, 'host_collections', 'name')
37
            autoattach = activationkey['auto_attach'] ? 'Yes' : 'No'
38
            servicelevel = activationkey['service_level']
39
            releasever = activationkey['release_version']
40
            subscriptions = CSV.generate do |column|
41
              column << @api.resource(:subscriptions).call(:index, {
42
                            'organization_id' => organization['id'],
43
                            'activation_key_id' => activationkey['id']
44
                        })['results'].collect do |subscription|
45
                amount = subscription['amount'] == 0 ? 'Automatic' : subscription['amount']
46
                sku = subscription['product_id'].match(/\A[0-9]/) ? 'Custom' : subscription['product_id']
47
                "#{amount}|#{sku}|#{subscription['product_name']}"
48
              end
49
            end
50
            subscriptions.delete!("\n")
51
            csv << [name, count, organization['name'], description, limit, environment, contentview,
52
                    hostcollections, servicelevel, releasever, autoattach, subscriptions]
87
            yield activationkey
53 88
          end
54 89
        end
55 90
      end
......
58 93
        @existing = {}
59 94

  
60 95
        thread_import do |line|
61
          create_activationkeys_from_csv(line)
96
          create_from_csv(line)
62 97
        end
63 98
      end
64 99

  
65
      def create_activationkeys_from_csv(line)
100
      def create_from_csv(line)
66 101
        return if option_organization && line[ORGANIZATION] != option_organization
67 102

  
68
        if !@existing[line[ORGANIZATION]]
69
          @existing[line[ORGANIZATION]] = {}
70
          @api.resource(:activation_keys).call(:index, {
71
              'per_page' => 999999,
72
              'organization_id' => foreman_organization(:name => line[ORGANIZATION])
73
          })['results'].each do |activationkey|
74
            @existing[line[ORGANIZATION]][activationkey['name']] = activationkey['id'] if activationkey
75
          end
76
        end
103
        update_existing(line)
77 104

  
78 105
        count(line[COUNT]).times do |number|
79 106
          name = namify(line[NAME], number)
80 107

  
81
          params = {
82
                     'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
83
                     'name' => name,
84
                     'environment_id' => lifecycle_environment(line[ORGANIZATION],
85
                                                               :name => line[ENVIRONMENT]),
86
                     'content_view_id' => katello_contentview(line[ORGANIZATION],
87
                                                              :name => line[CONTENTVIEW]),
88
                     'description' => line[DESCRIPTION],
89
                     'unlimited_content_hosts' => (line[LIMIT] == 'Unlimited') ? true : false,
90
                     'max_content_hosts' => (line[LIMIT] == 'Unlimited') ? nil : line[LIMIT].to_i
91
                   }
92
          params['auto_attach'] = (line[AUTOATTACH] == 'Yes' ? true : false) if params['auto_attach']
93
          params['service_level'] = line[SERVICELEVEL].nil? || line[SERVICELEVEL].empty? ? nil : line[SERVICELEVEL]
94
          params['release_version'] = line[RELEASEVER].nil? || line[RELEASEVER].empty? ? nil : line[RELEASEVER]
95
          if !@existing[line[ORGANIZATION]].include? name
96
            print _("Creating activation key '%{name}'...") % {:name => name} if option_verbose?
97
            activationkey = @api.resource(:activation_keys).call(:create, params)
98
            @existing[line[ORGANIZATION]][activationkey['name']] = activationkey['id']
108
          if option_itemized_subscriptions?
109
            update_itemized_subscriptions(name, line)
99 110
          else
100
            print _("Updating activation key '%{name}'...") % {:name => name} if option_verbose?
101
            params['id'] = @existing[line[ORGANIZATION]][name]
102
            activationkey = @api.resource(:activation_keys).call(:update, params)
111
            update_or_create(name, line)
103 112
          end
113
        end
114
      end
115

  
116
      def update_itemized_subscriptions(name, line)
117
        raise _("Activation key '%{name}' must already exist with --itemized_subscriptions") % {:name => name} unless @existing[line[ORGANIZATION]].include? name
104 118

  
105
          update_subscriptions(activationkey, line)
106
          update_groups(activationkey, line)
119
        print(_("Updating subscriptions for activation key '%{name}'...") % {:name => name}) if option_verbose?
120
        activationkey = @api.resource(:activation_keys).call(:show, {:id => @existing[line[ORGANIZATION]][name]})
121
        update_subscriptions(activationkey, line, false)
122
        puts _('done') if option_verbose?
123
      end
107 124

  
108
          puts _('done') if option_verbose?
125
      def update_or_create(name, line)
126
        params = {
127
                   'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
128
                   'name' => name,
129
                   'environment_id' => lifecycle_environment(line[ORGANIZATION],
130
                                                             :name => line[ENVIRONMENT]),
131
                   'content_view_id' => katello_contentview(line[ORGANIZATION],
132
                                                            :name => line[CONTENTVIEW]),
133
                   'description' => line[DESCRIPTION],
134
                   'unlimited_content_hosts' => (line[LIMIT] == 'Unlimited') ? true : false,
135
                   'max_content_hosts' => (line[LIMIT] == 'Unlimited') ? nil : line[LIMIT].to_i
136
                 }
137
        params['auto_attach'] = (line[AUTOATTACH] == 'Yes' ? true : false) if params['auto_attach']
138
        params['service_level'] = line[SERVICELEVEL].nil? || line[SERVICELEVEL].empty? ? nil : line[SERVICELEVEL]
139
        params['release_version'] = line[RELEASEVER].nil? || line[RELEASEVER].empty? ? nil : line[RELEASEVER]
140
        if !@existing[line[ORGANIZATION]].include? name
141
          print _("Creating activation key '%{name}'...") % {:name => name} if option_verbose?
142
          activationkey = @api.resource(:activation_keys).call(:create, params)
143
          @existing[line[ORGANIZATION]][activationkey['name']] = activationkey['id']
144
        else
145
          print _("Updating activation key '%{name}'...") % {:name => name} if option_verbose?
146
          params['id'] = @existing[line[ORGANIZATION]][name]
147
          activationkey = @api.resource(:activation_keys).call(:update, params)
109 148
        end
149

  
150
        update_subscriptions(activationkey, line, true)
151
        update_groups(activationkey, line)
152

  
153
        puts _('done') if option_verbose?
110 154
      end
111 155

  
112 156
      def update_groups(activationkey, line)
......
121 165
        end
122 166
      end
123 167

  
124
      def update_subscriptions(activationkey, line)
125
        if line[SUBSCRIPTIONS] && line[SUBSCRIPTIONS] != ''
126
          subscriptions = CSV.parse_line(line[SUBSCRIPTIONS], {:skip_blanks => true}).collect do |subscription_details|
127
            (amount, sku, name) = subscription_details.split('|')
128
            {
129
              :id => katello_subscription(line[ORGANIZATION], :name => name),
130
              :quantity => (amount.nil? || amount == 'Automatic') ? 0 : amount
131
            }
168
      def update_subscriptions(activationkey, line, remove_existing)
169
        existing_subscriptions = @api.resource(:subscriptions).call(:index, {
170
            'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
171
            'per_page' => 999999,
172
            'activation_key_id' => activationkey['id']
173
        })['results']
174
        if remove_existing && existing_subscriptions.length > 0
175
          existing_subscriptions.map! do |existing_subscription|
176
            {:id => existing_subscription['id'], :quantity => existing_subscription['quantity_consumed']}
132 177
          end
178
          @api.resource(:activation_keys).call(:remove_subscriptions, {
179
            'id' => activationkey['id'],
180
            'subscriptions' => existing_subscriptions
181
          })
182
          existing_subscriptions = []
183
        end
133 184

  
134
          existing_subscriptions = @api.resource(:subscriptions).call(:index, {
135
              'organization_id' => foreman_organization(:name => line[ORGANIZATION]),
136
              'per_page' => 999999,
137
              'activation_key_id' => activationkey['id']
138
          })['results']
139
          if existing_subscriptions.length > 0
140
            @api.resource(:activation_keys).call(:remove_subscriptions, {
141
              'id' => activationkey['id'],
142
              'subscriptions' => existing_subscriptions
143
            })
185
        if line[Utils::Subscriptions::SUBS_NAME].nil? && line[Utils::Subscriptions::SUBS_SKU].nil?
186
          all_in_one_subscription(activationkey, existing_subscriptions, line)
187
        else
188
          single_subscription(activationkey, existing_subscriptions, line)
189
        end
190
      end
191

  
192
      def single_subscription(activationkey, existing_subscriptions, line)
193
        already_attached = false
194
        if line[Utils::Subscriptions::SUBS_SKU]
195
          already_attached = existing_subscriptions.detect do |subscription|
196
            line[Utils::Subscriptions::SUBS_SKU] == subscription['product_id']
144 197
          end
198
        elsif line[Utils::Subscriptions::SUBS_NAME]
199
          already_attached = existing_subscriptions.detect do |subscription|
200
            line[Utils::Subscriptions::SUBS_NAME] == subscription['name']
201
          end
202
        end
203
        if already_attached
204
          print _(" '%{name}' already attached...") % {:name => already_attached['name']}
205
          return
206
        end
145 207

  
146
          @api.resource(:activation_keys).call(:add_subscriptions, {
147
              'id' => activationkey['id'],
148
              'subscriptions' => subscriptions
149
          })
208
        available_subscriptions = @api.resource(:subscriptions).call(:index, {
209
                                                                       'organization_id' => activationkey['organization']['id'],
210
                                                                       'activation_key_id' => activationkey['id'],
211
                                                                       'available_for' => 'activation_key'
212
                                                                     })['results']
213

  
214
        matches = matches_by_sku_and_name([], line, available_subscriptions)
215
        matches = matches_by_type(matches, line)
216
        matches = matches_by_account(matches, line)
217
        matches = matches_by_contract(matches, line)
218
        matches = matches_by_quantity(matches, line)
219

  
220
        raise _("No matching subscriptions") if matches.empty?
221

  
222
        match = matches[0]
223
        print _(" attaching '%{name}'...") % {:name => match['name']} if option_verbose?
224

  
225
        @api.resource(:activation_keys).call(:add_subscriptions, {
226
            'id' => activationkey['id'],
227
            'subscriptions' => [match]
228
        })
229
      end
230

  
231
      def all_in_one_subscription(activationkey, existing_subscriptions, line)
232
        return if line[SUBSCRIPTIONS].nil? || line[SUBSCRIPTIONS].empty?
233

  
234
        subscriptions = CSV.parse_line(line[SUBSCRIPTIONS], {:skip_blanks => true}).collect do |details|
235
          (amount, sku, name, contract, account) = split_subscription_details(details)
236
          {
237
            :id => get_subscription(line[ORGANIZATION], :name => name),
238
            :quantity => (amount.nil? || amount == 'Automatic') ? 0 : amount.to_i
239
          }
150 240
        end
241

  
242
        @api.resource(:activation_keys).call(:add_subscriptions, {
243
                                               'id' => activationkey['id'],
244
                                               'subscriptions' => subscriptions
245
                                             })
151 246
      end
152 247

  
153 248
      def usage_limit(limit)
154 249
        Integer(limit) rescue -1
155 250
      end
251

  
252
      def shared_headers
253
        [NAME, ORGANIZATION, DESCRIPTION, LIMIT, ENVIRONMENT, CONTENTVIEW,
254
         HOSTCOLLECTIONS, AUTOATTACH, SERVICELEVEL, RELEASEVER]
255
      end
256

  
257
      def shared_columns(activationkey)
258
        name = namify(activationkey['name'])
259
        organization = activationkey['organization']['name']
260
        description = activationkey['description']
261
        limit = activationkey['unlimited_content_hosts'] ? 'Unlimited' : activationkey['max_content_hosts']
262
        environment = activationkey['environment'].nil? ? nil : activationkey['environment']['label']
263
        contentview = activationkey['content_view'].nil? ? nil : activationkey['content_view']['name']
264
        hostcollections = export_column(activationkey, 'host_collections', 'name')
265
        autoattach = activationkey['auto_attach'] ? 'Yes' : 'No'
266
        servicelevel = activationkey['service_level']
267
        releasever = activationkey['release_version']
268
        [name, organization, description, limit, environment, contentview, hostcollections,
269
         autoattach, servicelevel, releasever]
270
      end
271

  
272
      def update_existing(line)
273
        if !@existing[line[ORGANIZATION]]
274
          @existing[line[ORGANIZATION]] = {}
275
          @api.resource(:activation_keys).call(:index, {
276
              'per_page' => 999999,
277
              'organization_id' => foreman_organization(:name => line[ORGANIZATION])
278
          })['results'].each do |activationkey|
279
            @existing[line[ORGANIZATION]][activationkey['name']] = activationkey['id'] if activationkey
280
          end
281
        end
282
      end
156 283
    end
157 284
  end
158 285
end
lib/hammer_cli_csv/base.rb
799 799
      result
800 800
    end
801 801

  
802
    def katello_subscription(organization, options = {})
803
      @subscriptions ||= {}
804
      @subscriptions[organization] ||= {}
805

  
806
      if options[:name]
807
        return nil if options[:name].nil? || options[:name].empty?
808
        options[:id] = @subscriptions[organization][options[:name]]
809
        if !options[:id]
810
          results = @api.resource(:subscriptions).call(:index, {
811
              :per_page => 999999,
812
              'organization_id' => foreman_organization(:name => organization),
813
              'search' => "name = \"#{options[:name]}\""
814
          })
815
          raise "No subscriptions match '#{options[:name]}'" if results['subtotal'] == 0
816
          raise "Too many subscriptions match '#{options[:name]}'" if results['subtotal'] > 1
817
          subscription = results['results'][0]
818
          @subscriptions[organization][options[:name]] = subscription['id']
819
          options[:id] = @subscriptions[organization][options[:name]]
820
          raise "Subscription '#{options[:name]}' not found" if !options[:id]
821
        end
822
        result = options[:id]
823
      else
824
        return nil if options[:id].nil?
825
        options[:name] = @subscriptions.key(options[:id])
826
        if !options[:name]
827
          subscription = @api.resource(:subscriptions).call(:show, {'id' => options[:id]})
828
          raise "Subscription '#{options[:name]}' not found" if !subscription || subscription.empty?
829
          options[:name] = subscription['name']
830
          @subscriptions[options[:name]] = options[:id]
831
        end
832
        result = options[:name]
833
      end
834

  
835
      result
836
    end
837

  
838 802
    def katello_hostcollection(organization, options = {})
839 803
      @hostcollections ||= {}
840 804
      @hostcollections[organization] ||= {}
lib/hammer_cli_csv/content_hosts.rb
1
#require 'hammer_cli_csv/utils/subscription_utils'
2

  
1 3
module HammerCLICsv
2 4
  class CsvCommand
3 5
    class ContentHostsCommand < BaseCommand
4 6
      include ::HammerCLIForemanTasks::Helper
7
      include ::HammerCLICsv::Utils::Subscriptions
5 8

  
6 9
      command_name 'content-hosts'
7 10
      desc         'import or export content hosts'
......
10 13
        true
11 14
      end
12 15

  
13
      option %w(--subscriptions-only), :flag, 'Export only detailed subscription information'
16
      option %w(--itemized-subscriptions), :flag, _('Export one subscription per row, only process update subscriptions on import')
14 17

  
15 18
      ORGANIZATION = 'Organization'
16 19
      ENVIRONMENT = 'Environment'
......
25 28
      CORES = 'Cores'
26 29
      SLA = 'SLA'
27 30
      PRODUCTS = 'Products'
28
      SUBSCRIPTIONS = 'Subscriptions'
29
      SUBS_NAME = 'Subscription Name'
30
      SUBS_TYPE = 'Subscription Type'
31
      SUBS_QUANTITY = 'Subscription Quantity'
32
      SUBS_SKU = 'Subscription SKU'
33
      SUBS_CONTRACT = 'Subscription Contract'
34
      SUBS_ACCOUNT = 'Subscription Account'
35
      SUBS_START = 'Subscription Start'
36
      SUBS_END = 'Subscription End'
37 31

  
38 32
      def export(csv)
39
        if option_subscriptions_only?
40
          export_subscriptions csv
33
        if option_itemized_subscriptions?
34
          export_itemized_subscriptions csv
41 35
        else
42 36
          export_all csv
43 37
        end
44 38
      end
45 39

  
46
      def export_subscriptions(csv)
47
        csv << shared_headers + [SUBS_NAME, SUBS_TYPE, SUBS_QUANTITY, SUBS_SKU,
48
                                 SUBS_CONTRACT, SUBS_ACCOUNT, SUBS_START, SUBS_END]
40
      def export_itemized_subscriptions(csv)
41
        csv << shared_headers + [Utils::Subscriptions::SUBS_NAME, Utils::Subscriptions::SUBS_TYPE,
42
                                 Utils::Subscriptions::SUBS_QUANTITY, Utils::Subscriptions::SUBS_SKU,
43
                                 Utils::Subscriptions::SUBS_CONTRACT, Utils::Subscriptions::SUBS_ACCOUNT,
44
                                 Utils::Subscriptions::SUBS_START, Utils::Subscriptions::SUBS_END]
49 45
        iterate_hosts(csv) do |host|
50 46
          export_line = shared_columns(host)
51 47
          if host['subscription_facet_attributes']
......
74 70
      end
75 71

  
76 72
      def export_all(csv)
77
        csv << shared_headers + [SUBSCRIPTIONS]
73
        csv << shared_headers + [Utils::Subscriptions::SUBSCRIPTIONS]
78 74
        iterate_hosts(csv) do |host|
79 75
          if host['subscription_facet_attributes']
80 76
            subscriptions = CSV.generate do |column|
......
146 142
        count(line[COUNT]).times do |number|
147 143
          name = namify(line[NAME], number)
148 144

  
149
          if option_subscriptions_only?
150
            update_subscriptions_only(name, line)
145
          if option_itemized_subscriptions?
146
            update_itemized_subscriptions(name, line)
151 147
          else
152 148
            update_or_create(name, line)
153 149
          end
......
156 152

  
157 153
      private
158 154

  
159
      def update_subscriptions_only(name, line)
160
        raise _("Content host '%{name}' must already exist with --subscriptions-only") % {:name => name} unless @existing.include? name
155
      def update_itemized_subscriptions(name, line)
156
        raise _("Content host '%{name}' must already exist with --itemized-subscriptions") % {:name => name} unless @existing.include? name
161 157

  
162 158
        print(_("Updating subscriptions for content host '%{name}'...") % {:name => name}) if option_verbose?
163 159
        host = @api.resource(:hosts).call(:show, {:id => @existing[name]})
......
273 269
          existing_subscriptions = []
274 270
        end
275 271

  
276
        if line[SUBS_NAME].nil? && line[SUBS_SKU].nil?
272
        if line[Utils::Subscriptions::SUBS_NAME].nil? && line[Utils::Subscriptions::SUBS_SKU].nil?
277 273
          all_in_one_subscription(host, existing_subscriptions, line)
278 274
        else
279 275
          single_subscription(host, existing_subscriptions, line)
......
282 278

  
283 279
      def single_subscription(host, existing_subscriptions, line)
284 280
        already_attached = false
285
        if line[SUBS_SKU]
281
        if line[Utils::Subscriptions::SUBS_SKU]
286 282
          already_attached = existing_subscriptions.detect do |subscription|
287
            line[SUBS_SKU] == subscription['product_id']
283
            line[Utils::Subscriptions::SUBS_SKU] == subscription['product_id']
288 284
          end
289
        elsif line[SUBS_NAME]
285
        elsif line[Utils::Subscriptions::SUBS_NAME]
290 286
          already_attached = existing_subscriptions.detect do |subscription|
291
            line[SUBS_NAME] == subscription['name']
287
            line[Utils::Subscriptions::SUBS_NAME] == subscription['name']
292 288
          end
293 289
        end
294 290
        if already_attached
......
324 320
        return if line[SUBSCRIPTIONS].nil? || line[SUBSCRIPTIONS].empty?
325 321

  
326 322
        subscriptions = CSV.parse_line(line[SUBSCRIPTIONS], {:skip_blanks => true}).collect do |details|
327
          (amount, sku, name, contract, account) = details.split('|')
323
          (amount, sku, name, contract, account) = split_subscription_details(details)
328 324
          {
329
            :id => katello_subscription(line[ORGANIZATION], :name => name, :contract => contract,
330
                                                            :account => account),
325
            :id => get_subscription(line[ORGANIZATION], :name => name, :contract => contract,
326
                                                        :account => account),
331 327
            :quantity => (amount.nil? || amount.empty? || amount == 'Automatic') ? 0 : amount.to_i
332 328
          }
333 329
        end
......
361 357
        end
362 358
      end
363 359

  
364
      def get_all_subscriptions(organization)
365
        @api.resource(:subscriptions).call(:index, {
366
            :per_page => 999999,
367
            'organization_id' => foreman_organization(:name => organization)
368
        })['results']
369
      end
370

  
371 360
      def iterate_hosts(csv)
372 361
        hypervisors = []
373 362
        hosts = []
......
436 425
         operatingsystem, architecture, sockets, ram, cores, sla, products]
437 426
      end
438 427

  
439
      def matches_by_sku_and_name(matches, line, subscriptions)
440
        if line[SUBS_SKU]
441
          matches = subscriptions.select do |subscription|
442
            line[SUBS_SKU] == subscription['product_id']
443
          end
444
          raise _("No subscriptions match SKU '%{sku}'") % {:sku => line[SUBS_SKU]} if matches.empty?
445
        elsif line[SUBS_NAME]
446
          matches = subscriptions.select do |subscription|
447
            line[SUBS_NAME] == subscription['name']
448
          end
449
          raise _("No subscriptions match name '%{name}'") % {:name => line[SUBS_NAME]} if matches.empty?
450
        end
451
        matches
452
      end
453

  
454
      def matches_by_type(matches, line)
455
        if line[SUBS_TYPE] == 'Red Hat' || line[SUBS_TYPE] == 'Custom'
456
          matches = matches.select do |subscription|
457
            subscription['type'] == 'NORMAL'
458
          end
459
        elsif line[SUBS_TYPE] == 'Red Hat Guest'
460
          matches = matches.select do |subscription|
461
            subscription['type'] == 'STACK_DERIVED'
462
          end
463
        elsif line[SUBS_TYPE] == 'Red Hat Temporary'
464
          matches = matches.select do |subscription|
465
            subscription['type'] == 'UNMAPPED_GUEST'
466
          end
467
        end
468
        raise _("No subscriptions match type '%{type}'") % {:type => line[SUBS_TYPE]} if matches.empty?
469
        matches
470
      end
471

  
472
      def matches_by_account(matches, line)
473
        if matches.length > 1 && line[SUBS_ACCOUNT]
474
          refined = matches.select do |subscription|
475
            line[SUBS_ACCOUNT] == subscription['account_number']
476
          end
477
          matches = refined unless refined.empty?
478
        end
479
        matches
480
      end
481

  
482
      def matches_by_contract(matches, line)
483
        if matches.length > 1 && line[SUBS_CONTRACT]
484
          refined = matches.select do |subscription|
485
            line[SUBS_CONTRACT] == subscription['contract_number']
486
          end
487
          matches = refined unless refined.empty?
488
        end
489
        matches
490
      end
491

  
492
      def matches_by_quantity(matches, line)
493
        if line[SUBS_QUANTITY] && line[SUBS_QUANTITY] != 'Automatic'
494
          refined = matches.select do |subscription|
495
            subscription['available'] == -1 || line[SUBS_QUANTITY].to_i <= subscription['available']
496
          end
497
          raise _("No '%{name}' subscription with quantity %{quantity} or more available") %
498
                    {:name => matches[0]['name'], :quantity => line[SUBS_QUANTITY]} if refined.empty?
499
          matches = refined
500
        end
501
        matches
502
      end
503 428
    end
504 429
  end
505 430
end
lib/hammer_cli_csv/puppet_reports.rb
107 107

  
108 108
          # TODO: w/ @daviddavis p-r
109 109
          #subscriptions(line).each do |subscription|
110
          #  katello_subscription(line[ORGANIZATION], :name => subscription[:number])
110
          #  get_subscription(line[ORGANIZATION], :name => subscription[:number])
111 111
          #end
112 112

  
113 113
          if !@existing[line[ORGANIZATION]].include? name
lib/hammer_cli_csv/splice.rb
264 264
        subscriptions = CSV.parse_line(line[SUBSCRIPTIONS], {:skip_blanks => true}).collect do |details|
265 265
          (amount, sku, name) = details.split('|')
266 266
          {
267
            :id => katello_subscription(line[ORGANIZATION], :name => name),
267
            :id => get_subscription(line[ORGANIZATION], :name => name),
268 268
            :quantity => (amount.nil? || amount.empty? || amount == 'Automatic') ? 0 : amount.to_i
269 269
          }
270 270
        end
lib/hammer_cli_csv/utils/subscriptions.rb
1
module HammerCLICsv
2
  module Utils
3
    module Subscriptions
4
      SUBSCRIPTIONS = 'Subscriptions'
5
      SUBS_NAME = 'Subscription Name'
6
      SUBS_TYPE = 'Subscription Type'
7
      SUBS_QUANTITY = 'Subscription Quantity'
8
      SUBS_SKU = 'Subscription SKU'
9
      SUBS_CONTRACT = 'Subscription Contract'
10
      SUBS_ACCOUNT = 'Subscription Account'
11
      SUBS_START = 'Subscription Start'
12
      SUBS_END = 'Subscription End'
13

  
14
      def get_all_subscriptions(organization)
15
        @api.resource(:subscriptions).call(:index, {
16
            :per_page => 999999,
17
            'organization_id' => foreman_organization(:name => organization)
18
        })['results']
19
      end
20

  
21
      def get_subscription(organization, options = {})
22
        @subscriptions ||= {}
23
        @subscriptions[organization] ||= {}
24

  
25
        if options[:name]
26
          return nil if options[:name].nil? || options[:name].empty?
27
          options[:id] = @subscriptions[organization][options[:name]]
28
          if !options[:id]
29
            results = @api.resource(:subscriptions).call(:index, {
30
                :per_page => 999999,
31
                'organization_id' => foreman_organization(:name => organization),
32
                'search' => "name = \"#{options[:name]}\""
33
            })
34
            raise "No subscriptions match '#{options[:name]}'" if results['subtotal'] == 0
35
            raise "Too many subscriptions match '#{options[:name]}'" if results['subtotal'] > 1
36
            subscription = results['results'][0]
37
            @subscriptions[organization][options[:name]] = subscription['id']
38
            options[:id] = @subscriptions[organization][options[:name]]
39
            raise "Subscription '#{options[:name]}' not found" if !options[:id]
40
          end
41
          result = options[:id]
42
        else
43
          return nil if options[:id].nil?
44
          options[:name] = @subscriptions.key(options[:id])
45
          if !options[:name]
46
            subscription = @api.resource(:subscriptions).call(:show, {'id' => options[:id]})
47
            raise "Subscription '#{options[:name]}' not found" if !subscription || subscription.empty?
48
            options[:name] = subscription['name']
49
            @subscriptions[options[:name]] = options[:id]
50
          end
51
          result = options[:name]
52
        end
53

  
54
        result
55
      end
56

  
57
      def matches_by_sku_and_name(matches, line, subscriptions)
58
        if line[SUBS_SKU]
59
          matches = subscriptions.select do |subscription|
60
            line[SUBS_SKU] == subscription['product_id']
61
          end
62
          raise _("No subscriptions match SKU '%{sku}'") % {:sku => line[SUBS_SKU]} if matches.empty?
63
        elsif line[SUBS_NAME]
64
          matches = subscriptions.select do |subscription|
65
            line[SUBS_NAME] == subscription['name']
66
          end
67
          raise _("No subscriptions match name '%{name}'") % {:name => line[SUBS_NAME]} if matches.empty?
68
        end
69
        matches
70
      end
71

  
72
      def matches_by_type(matches, line)
73
        if line[SUBS_TYPE] == 'Red Hat' || line[SUBS_TYPE] == 'Custom'
74
          matches = matches.select do |subscription|
75
            subscription['type'] == 'NORMAL'
76
          end
77
        elsif line[SUBS_TYPE] == 'Red Hat Guest'
78
          matches = matches.select do |subscription|
79
            subscription['type'] == 'STACK_DERIVED'
80
          end
81
        elsif line[SUBS_TYPE] == 'Red Hat Temporary'
82
          matches = matches.select do |subscription|
83
            subscription['type'] == 'UNMAPPED_GUEST'
84
          end
85
        end
86
        raise _("No subscriptions match type '%{type}'") % {:type => line[SUBS_TYPE]} if matches.empty?
87
        matches
88
      end
89

  
90
      def matches_by_account(matches, line)
91
        if matches.length > 1 && line[SUBS_ACCOUNT]
92
          refined = matches.select do |subscription|
93
            line[SUBS_ACCOUNT] == subscription['account_number']
94
          end
95
          matches = refined unless refined.empty?
96
        end
97
        matches
98
      end
99

  
100
      def matches_by_contract(matches, line)
101
        if matches.length > 1 && line[SUBS_CONTRACT]
102
          refined = matches.select do |subscription|
103
            line[SUBS_CONTRACT] == subscription['contract_number']
104
          end
105
          matches = refined unless refined.empty?
106
        end
107
        matches
108
      end
109

  
110
      def matches_by_quantity(matches, line)
111
        if line[SUBS_QUANTITY] && line[SUBS_QUANTITY] != 'Automatic'
112
          refined = matches.select do |subscription|
113
            subscription['available'] == -1 || line[SUBS_QUANTITY].to_i <= subscription['available']
114
          end
115
          raise _("No '%{name}' subscription with quantity %{quantity} or more available") %
116
            {:name => matches[0]['name'], :quantity => line[SUBS_QUANTITY]} if refined.empty?
117
          matches = refined
118
        end
119
        matches
120
      end
121

  
122
      # Subscription amount, SKU, name, contract number, and account number separated by '|'
123
      # or simply the subscription name.
124
      def split_subscription_details(details)
125
        details = details.split('|')
126
        details.length == 1 ? ['Automatic', nil, details[0], nil, nil] : details
127
      end
128
    end
129
  end
130
end
test/fixtures/vcr_cassettes/resources/activation_keys_import/create_and_update.yml
1
---
2
http_interactions:
3
- request:
4
    method: get
5
    uri: http://admin:changeme@katello:3000/api/status
6
    body:
7
      encoding: US-ASCII
8
      string: ''
9
    headers:
10
      Accept-Encoding:
11
      - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
      Accept:
13
      - '*/*'
14
      User-Agent:
15
      - Ruby
16
  response:
17
    status:
18
      code: 200
19
      message: OK
20
    headers:
21
      X-Frame-Options:
22
      - SAMEORIGIN
23
      X-Xss-Protection:
24
      - 1; mode=block
25
      X-Content-Type-Options:
26
      - nosniff
27
      Foreman-Version:
28
      - 1.13.0-develop
29
      Foreman-Api-Version:
30
      - '2'
31
      Content-Type:
32
      - application/json; charset=utf-8
33
      Apipie-Checksum:
34
      - e98945ba1db6bdbb4c25ce4988912344
35
      Etag:
36
      - W/"f536fd8685b76bb26a943d472593c93e"
37
      Cache-Control:
38
      - max-age=0, private, must-revalidate
39
      Set-Cookie:
40
      - _session_id=0e923fc3965991659c91384d374e3456; path=/; HttpOnly
41
      X-Request-Id:
42
      - 51a39dfd-4889-484d-b76b-5007572ee859
43
      X-Runtime:
44
      - '0.469822'
45
      Transfer-Encoding:
46
      - chunked
47
    body:
48
      encoding: UTF-8
49
      string: '{"result":"ok","status":200,"version":"1.13.0-develop","api_version":2}'
50
    http_version: 
51
  recorded_at: Fri, 26 Aug 2016 15:54:19 GMT
52
- request:
53
    method: get
54
    uri: http://admin:changeme@katello:3000/api/v2/plugins
55
    body:
56
      encoding: US-ASCII
57
      string: ''
58
    headers:
59
      Accept-Encoding:
60
      - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
61
      Accept:
62
      - '*/*'
63
      User-Agent:
64
      - Ruby
65
  response:
66
    status:
67
      code: 200
68
      message: OK
69
    headers:
70
      X-Frame-Options:
71
      - SAMEORIGIN
72
      X-Xss-Protection:
73
      - 1; mode=block
74
      X-Content-Type-Options:
75
      - nosniff
76
      Foreman-Version:
77
      - 1.13.0-develop
78
      Foreman-Api-Version:
79
      - '2'
80
      Content-Type:
81
      - application/json; charset=utf-8
82
      Apipie-Checksum:
83
      - e98945ba1db6bdbb4c25ce4988912344
84
      Etag:
85
      - W/"5fdeea8a610f7805000b37060cecd4be"
86
      Cache-Control:
87
      - max-age=0, private, must-revalidate
88
      Set-Cookie:
89
      - _session_id=e2f1597d8e88eb272f62a54e5a991041; path=/; HttpOnly
90
      X-Request-Id:
91
      - ec57e45d-ba63-47c9-bca1-2e795c7fb968
92
      X-Runtime:
93
      - '1.248598'
94
      Transfer-Encoding:
95
      - chunked
96
    body:
97
      encoding: ASCII-8BIT
98
      string: !binary |-
99
        ewogICJ0b3RhbCI6IDQsCiAgInN1YnRvdGFsIjogNCwKICAicGFnZSI6IDEs
100
        CiAgInBlcl9wYWdlIjogMjAsCiAgInNlYXJjaCI6IG51bGwsCiAgInNvcnQi
101
        OiB7CiAgICAiYnkiOiBudWxsLAogICAgIm9yZGVyIjogbnVsbAogIH0sCiAg
102
        InJlc3VsdHMiOiBbeyJpZCI6ImZvcmVtYW4tdGFza3MiLCJuYW1lIjoiZm9y
103
        ZW1hbi10YXNrcyIsImF1dGhvciI6Ikl2YW4gTmXEjWFzIiwiZGVzY3JpcHRp
104
        b24iOiJUaGUgZ29hbCBvZiB0aGlzIHBsdWdpbiBpcyB0byB1bmlmeSB0aGUg
105
        d2F5IG9mIHNob3dpbmcgdGFzayBzdGF0dXNlcyBhY3Jvc3MgdGhlIEZvcmVt
106
        YW4gaW5zdGFuY2UuXG5JdCBkZWZpbmVzIFRhc2sgbW9kZWwgZm9yIGtlZXBp
107
        bmcgdGhlIGluZm9ybWF0aW9uIGFib3V0IHRoZSB0YXNrcyBhbmQgTG9jayBm
108
        b3IgYXNzaWduaW5nIHRoZSB0YXNrc1xudG8gcmVzb3VyY2VzLiBUaGUgbG9j
109
        a2luZyBhbGxvd3MgZGVhbGluZyB3aXRoIHByZXZlbnRpbmcgbXVsdGlwbGUg
110
        Y29sbGlkaW5nIHRhc2tzIHRvIGJlIHJ1biBvbiB0aGVcbnNhbWUgcmVzb3Vy
111
        Y2UuIEl0IGFsc28gb3B0aW9uYWxseSBwcm92aWRlcyBEeW5mbG93IGluZnJh
112
        c3RydWN0dXJlIGZvciB1c2luZyBpdCBmb3IgbWFuYWdpbmcgdGhlIHRhc2tz
113
        LlxuIiwidXJsIjoiaHR0cHM6Ly9naXRodWIuY29tL3RoZWZvcmVtYW4vZm9y
114
        ZW1hbi10YXNrcyIsInZlcnNpb24iOiIwLjguMCJ9LHsiaWQiOiJmb3JlbWFu
115
        X2RvY2tlciIsIm5hbWUiOiJmb3JlbWFuX2RvY2tlciIsImF1dGhvciI6IkRh
116
        bmllbCBMb2JhdG8sIEFtb3MgQmVuYXJpIiwiZGVzY3JpcHRpb24iOiJQcm92
117
        aXNpb24gYW5kIG1hbmFnZSBEb2NrZXIgY29udGFpbmVycyBhbmQgaW1hZ2Vz
118
        IGZyb20gRm9yZW1hbi4iLCJ1cmwiOiJodHRwOi8vZ2l0aHViLmNvbS90aGVm
119
        b3JlbWFuL2ZvcmVtYW4tZG9ja2VyIiwidmVyc2lvbiI6IjMuMC4wIn0seyJp
120
        ZCI6ImZvcmVtYW5fcmVtb3RlX2V4ZWN1dGlvbiIsIm5hbWUiOiJmb3JlbWFu
121
        X3JlbW90ZV9leGVjdXRpb24iLCJhdXRob3IiOiJGb3JlbWFuIFJlbW90ZSBF
122
        eGVjdXRpb24gdGVhbSIsImRlc2NyaXB0aW9uIjoiQSBwbHVnaW4gYnJpbmdp
123
        bmcgcmVtb3RlIGV4ZWN1dGlvbiB0byB0aGUgRm9yZW1hbiwgY29tcGxldGlu
124
        ZyB0aGUgY29uZmlnIG1hbmFnZW1lbnQgZnVuY3Rpb25hbGl0eSB3aXRoIHJl
125
        bW90ZSBtYW5hZ2VtZW50IGZ1bmN0aW9uYWxpdHkuIiwidXJsIjoiaHR0cHM6
126
        Ly9naXRodWIuY29tL3RoZWZvcmVtYW4vZm9yZW1hbl9yZW1vdGVfZXhlY3V0
127
        aW9uIiwidmVyc2lvbiI6IjEuMC4wIn0seyJpZCI6ImthdGVsbG8iLCJuYW1l
128
        Ijoia2F0ZWxsbyIsImF1dGhvciI6Ik4vQSIsImRlc2NyaXB0aW9uIjoiQ29u
129
        dGVudCBhbmQgU3Vic2NyaXB0aW9uIE1hbmFnZW1lbnQgcGx1Z2luIGZvciBG
130
        b3JlbWFuIiwidXJsIjoiaHR0cDovL3d3dy5rYXRlbGxvLm9yZyIsInZlcnNp
131
        b24iOiIzLjIuMCJ9XQp9Cg==
132
    http_version: 
133
  recorded_at: Fri, 26 Aug 2016 15:54:20 GMT
134
- request:
135
    method: get
136
    uri: http://admin:changeme@katello:3000/katello/api/organizations?per_page=999999&search=name=%22Test%20Corporation%22
137
    body:
138
      encoding: US-ASCII
139
      string: ''
140
    headers:
141
      Accept:
142
      - application/json;version=2
143
      Accept-Encoding:
144
      - gzip, deflate
145
      Content-Type:
146
      - application/json
147
      User-Agent:
148
      - Ruby
149
  response:
150
    status:
151
      code: 200
152
      message: OK
153
    headers:
154
      X-Frame-Options:
155
      - SAMEORIGIN
156
      X-Xss-Protection:
157
      - 1; mode=block
158
      X-Content-Type-Options:
159
      - nosniff
160
      Foreman-Version:
161
      - 1.13.0-develop
162
      Foreman-Api-Version:
163
      - '2'
164
      Content-Type:
165
      - application/json; charset=utf-8
166
      Apipie-Checksum:
167
      - e98945ba1db6bdbb4c25ce4988912344
168
      Etag:
169
      - W/"dec57c653102523d2cd2de13cb7fee01"
170
      Cache-Control:
171
      - max-age=0, private, must-revalidate
172
      Set-Cookie:
173
      - _session_id=661dafbafd6cd0935691f0b384703804; path=/; HttpOnly
174
      X-Request-Id:
175
      - e91b092f-38fe-41da-9068-98e8344a3a02
176
      X-Runtime:
177
      - '0.278001'
178
      Transfer-Encoding:
179
      - chunked
180
    body:
181
      encoding: UTF-8
182
      string: |
183
        {
184
          "total": 3,
185
          "subtotal": 1,
186
          "page": 1,
187
          "per_page": 999999,
188
          "search": "name=\"Test Corporation\"",
189
          "sort": {
190
            "by": null,
191
            "order": null
192
          },
193
          "results": [{"label":"testcorp","created_at":"2016-08-16 12:46:24 UTC","updated_at":"2016-08-16 12:46:24 UTC","id":4,"name":"Test Corporation","title":"Test Corporation","description":"Testing today for a better tomorrow"}]
194
        }
195
    http_version: 
196
  recorded_at: Fri, 26 Aug 2016 15:54:20 GMT
197
- request:
198
    method: get
199
    uri: http://admin:changeme@katello:3000/apidoc/v2.json
200
    body:
201
      encoding: US-ASCII
202
      string: ''
203
    headers:
204
      Accept:
205
      - application/json
206
      Accept-Encoding:
207
      - gzip, deflate
208
      Content-Type:
209
      - application/json
210
      User-Agent:
211
      - Ruby
212
  response:
213
    status:
214
      code: 200
215
      message: OK
216
    headers:
217
      X-Frame-Options:
218
      - SAMEORIGIN
219
      X-Xss-Protection:
220
      - 1; mode=block
221
      X-Content-Type-Options:
222
      - nosniff
223
      Content-Disposition:
224
      - inline; filename="v2.json"
225
      Content-Transfer-Encoding:
226
      - binary
227
      Content-Type:
228
      - text/html
229
      Cache-Control:
230
      - private
231
      Apipie-Checksum:
232
      - e98945ba1db6bdbb4c25ce4988912344
233
      X-Request-Id:
234
      - 0ae5b134-fc2a-4c5b-8894-20d9bd8c5d60
235
      X-Runtime:
236
      - '0.151908'
237
      Transfer-Encoding:
238
      - chunked
239
    body:
240
      encoding: ASCII-8BIT
241
      string: !binary |-
242
        eyJkb2NzIjp7Im5hbWUiOiJGb3JlbWFuIiwiaW5mbyI6IlxuXHUwMDNjcFx1
243
        MDAzZVNhdGVsbGl0ZSBBUEkgdjIgaXMgY3VycmVudGx5IHRoZSBkZWZhdWx0
244
        IEFQSSB2ZXJzaW9uLlx1MDAzYy9wXHUwMDNlXG4iLCJjb3B5cmlnaHQiOiIi
245
        LCJkb2NfdXJsIjoiLi4vYXBpZG9jL3YyIiwiYXBpX3VybCI6Ii9hcGkiLCJy
246
        ZXNvdXJjZXMiOnsiaG9zdF9zdWJzY3JpcHRpb25zIjp7ImRvY191cmwiOiIu
247
        Li9hcGlkb2MvdjIvaG9zdF9zdWJzY3JpcHRpb25zIiwiYXBpX3VybCI6Ii9h
248
        cGkiLCJuYW1lIjoiSG9zdCBzdWJzY3JpcHRpb25zIiwic2hvcnRfZGVzY3Jp
249
        cHRpb24iOm51bGwsImZ1bGxfZGVzY3JpcHRpb24iOiIiLCJ2ZXJzaW9uIjoi
250
        djIiLCJmb3JtYXRzIjpudWxsLCJtZXRhZGF0YSI6bnVsbCwibWV0aG9kcyI6
251
        W3siZG9jX3VybCI6Ii4uL2FwaWRvYy92Mi9ob3N0X3N1YnNjcmlwdGlvbnMv
252
        aW5kZXgiLCJuYW1lIjoiaW5kZXgiLCJhcGlzIjpbeyJhcGlfdXJsIjoiL2Fw
253
        aS9ob3N0cy86aG9zdF9pZC9zdWJzY3JpcHRpb25zIiwiaHR0cF9tZXRob2Qi
254
        OiJHRVQiLCJzaG9ydF9kZXNjcmlwdGlvbiI6Ikxpc3QgYSBob3N0J3Mgc3Vi
255
        c2NyaXB0aW9ucyIsImRlcHJlY2F0ZWQiOm51bGx9XSwiZm9ybWF0cyI6bnVs
256
        bCwiZnVsbF9kZXNjcmlwdGlvbiI6IiIsImVycm9ycyI6W10sInBhcmFtcyI6
257
        W3sibmFtZSI6Imhvc3RfaWQiLCJmdWxsX25hbWUiOiJob3N0X2lkIiwiZGVz
258
        Y3JpcHRpb24iOiJcblx1MDAzY3BcdTAwM2VJZCBvZiB0aGUgaG9zdFx1MDAz
259
        Yy9wXHUwMDNlXG4iLCJyZXF1aXJlZCI6dHJ1ZSwiYWxsb3dfbmlsIjpmYWxz
260
        ZSwidmFsaWRhdG9yIjoiSW50ZWdlciIsImV4cGVjdGVkX3R5cGUiOiJudW1l
261
        cmljIiwibWV0YWRhdGEiOm51bGwsInNob3ciOnRydWUsInZhbGlkYXRpb25z
262
        IjpbXX1dLCJleGFtcGxlcyI6W10sIm1ldGFkYXRhIjpudWxsLCJzZWUiOltd
263
        LCJoZWFkZXJzIjpbXSwic2hvdyI6dHJ1ZX0seyJkb2NfdXJsIjoiLi4vYXBp
264
        ZG9jL3YyL2hvc3Rfc3Vic2NyaXB0aW9ucy9hdXRvX2F0dGFjaCIsIm5hbWUi
265
        OiJhdXRvX2F0dGFjaCIsImFwaXMiOlt7ImFwaV91cmwiOiIvYXBpL2hvc3Rz
266
        Lzpob3N0X2lkL3N1YnNjcmlwdGlvbnMvYXV0b19hdHRhY2giLCJodHRwX21l
267
        dGhvZCI6IlBVVCIsInNob3J0X2Rlc2NyaXB0aW9uIjoiVHJpZ2dlciBhbiBh
268
        dXRvLWF0dGFjaCBvZiBzdWJzY3JpcHRpb25zIiwiZGVwcmVjYXRlZCI6bnVs
269
        bH1dLCJmb3JtYXRzIjpudWxsLCJmdWxsX2Rlc2NyaXB0aW9uIjoiIiwiZXJy
270
        b3JzIjpbXSwicGFyYW1zIjpbeyJuYW1lIjoiaG9zdF9pZCIsImZ1bGxfbmFt
271
        ZSI6Imhvc3RfaWQiLCJkZXNjcmlwdGlvbiI6IlxuXHUwMDNjcFx1MDAzZUlk
272
        IG9mIHRoZSBob3N0XHUwMDNjL3BcdTAwM2VcbiIsInJlcXVpcmVkIjp0cnVl
273
        LCJhbGxvd19uaWwiOmZhbHNlLCJ2YWxpZGF0b3IiOiJJbnRlZ2VyIiwiZXhw
274
        ZWN0ZWRfdHlwZSI6Im51bWVyaWMiLCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6
275
        dHJ1ZSwidmFsaWRhdGlvbnMiOltdfV0sImV4YW1wbGVzIjpbXSwibWV0YWRh
276
        dGEiOm51bGwsInNlZSI6W10sImhlYWRlcnMiOltdLCJzaG93Ijp0cnVlfSx7
277
        ImRvY191cmwiOiIuLi9hcGlkb2MvdjIvaG9zdF9zdWJzY3JpcHRpb25zL2V2
278
        ZW50cyIsIm5hbWUiOiJldmVudHMiLCJhcGlzIjpbeyJhcGlfdXJsIjoiL2Fw
279
        aS9ob3N0cy86aG9zdF9pZC9zdWJzY3JpcHRpb25zL2V2ZW50cyIsImh0dHBf
280
        bWV0aG9kIjoiR0VUIiwic2hvcnRfZGVzY3JpcHRpb24iOiJMaXN0IHN1YnNj
281
        cmlwdGlvbiBldmVudHMgZm9yIHRoZSBob3N0IiwiZGVwcmVjYXRlZCI6bnVs
282
        bH1dLCJmb3JtYXRzIjpudWxsLCJmdWxsX2Rlc2NyaXB0aW9uIjoiIiwiZXJy
283
        b3JzIjpbXSwicGFyYW1zIjpbeyJuYW1lIjoiaG9zdF9pZCIsImZ1bGxfbmFt
284
        ZSI6Imhvc3RfaWQiLCJkZXNjcmlwdGlvbiI6IlxuXHUwMDNjcFx1MDAzZUlk
285
        IG9mIHRoZSBob3N0XHUwMDNjL3BcdTAwM2VcbiIsInJlcXVpcmVkIjp0cnVl
286
        LCJhbGxvd19uaWwiOmZhbHNlLCJ2YWxpZGF0b3IiOiJJbnRlZ2VyIiwiZXhw
287
        ZWN0ZWRfdHlwZSI6Im51bWVyaWMiLCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6
288
        dHJ1ZSwidmFsaWRhdGlvbnMiOltdfV0sImV4YW1wbGVzIjpbXSwibWV0YWRh
289
        dGEiOm51bGwsInNlZSI6W10sImhlYWRlcnMiOltdLCJzaG93Ijp0cnVlfSx7
290
        ImRvY191cmwiOiIuLi9hcGlkb2MvdjIvaG9zdF9zdWJzY3JpcHRpb25zL2Rl
291
        c3Ryb3kiLCJuYW1lIjoiZGVzdHJveSIsImFwaXMiOlt7ImFwaV91cmwiOiIv
292
        YXBpL2hvc3RzLzpob3N0X2lkL3N1YnNjcmlwdGlvbnMiLCJodHRwX21ldGhv
293
        ZCI6IkRFTEVURSIsInNob3J0X2Rlc2NyaXB0aW9uIjoiVW5yZWdpc3RlciB0
294
        aGUgaG9zdCBhcyBhIHN1YnNjcmlwdGlvbiBjb25zdW1lciIsImRlcHJlY2F0
295
        ZWQiOm51bGx9XSwiZm9ybWF0cyI6bnVsbCwiZnVsbF9kZXNjcmlwdGlvbiI6
296
        IiIsImVycm9ycyI6W10sInBhcmFtcyI6W3sibmFtZSI6Imhvc3RfaWQiLCJm
297
        dWxsX25hbWUiOiJob3N0X2lkIiwiZGVzY3JpcHRpb24iOiJcblx1MDAzY3Bc
298
        dTAwM2VJZCBvZiB0aGUgaG9zdFx1MDAzYy9wXHUwMDNlXG4iLCJyZXF1aXJl
299
        ZCI6dHJ1ZSwiYWxsb3dfbmlsIjpmYWxzZSwidmFsaWRhdG9yIjoiSW50ZWdl
300
        ciIsImV4cGVjdGVkX3R5cGUiOiJudW1lcmljIiwibWV0YWRhdGEiOm51bGws
301
        InNob3ciOnRydWUsInZhbGlkYXRpb25zIjpbXX1dLCJleGFtcGxlcyI6W10s
302
        Im1ldGFkYXRhIjpudWxsLCJzZWUiOltdLCJoZWFkZXJzIjpbXSwic2hvdyI6
303
        dHJ1ZX0seyJkb2NfdXJsIjoiLi4vYXBpZG9jL3YyL2hvc3Rfc3Vic2NyaXB0
304
        aW9ucy9jcmVhdGUiLCJuYW1lIjoiY3JlYXRlIiwiYXBpcyI6W3siYXBpX3Vy
305
        bCI6Ii9hcGkvaG9zdHMvc3Vic2NyaXB0aW9ucyIsImh0dHBfbWV0aG9kIjoi
306
        UE9TVCIsInNob3J0X2Rlc2NyaXB0aW9uIjoiUmVnaXN0ZXIgYSBob3N0IHdp
307
        dGggc3Vic2NyaXB0aW9uIGFuZCBpbmZvcm1hdGlvbi4iLCJkZXByZWNhdGVk
308
        IjpudWxsfV0sImZvcm1hdHMiOm51bGwsImZ1bGxfZGVzY3JpcHRpb24iOiIi
309
        LCJlcnJvcnMiOltdLCJwYXJhbXMiOlt7Im5hbWUiOiJuYW1lIiwiZnVsbF9u
310
        YW1lIjoibmFtZSIsImRlc2NyaXB0aW9uIjoiXG5cdTAwM2NwXHUwMDNlTmFt
311
        ZSBvZiB0aGUgaG9zdFx1MDAzYy9wXHUwMDNlXG4iLCJyZXF1aXJlZCI6dHJ1
312
        ZSwiYWxsb3dfbmlsIjpmYWxzZSwidmFsaWRhdG9yIjoiU3RyaW5nIiwiZXhw
313
        ZWN0ZWRfdHlwZSI6InN0cmluZyIsIm1ldGFkYXRhIjpudWxsLCJzaG93Ijp0
314
        cnVlLCJ2YWxpZGF0aW9ucyI6W119LHsibmFtZSI6InV1aWQiLCJmdWxsX25h
315
        bWUiOiJ1dWlkIiwiZGVzY3JpcHRpb24iOiJcblx1MDAzY3BcdTAwM2VVVUlE
316
        IHRvIHVzZSBmb3IgcmVnaXN0ZXJlZCBob3N0LCByYW5kb20gdXVpZCBpcyBn
317
        ZW5lcmF0ZWQgaWYgbm90IHByb3ZpZGVkXHUwMDNjL3BcdTAwM2VcbiIsInJl
318
        cXVpcmVkIjpmYWxzZSwiYWxsb3dfbmlsIjpmYWxzZSwidmFsaWRhdG9yIjoi
319
        U3RyaW5nIiwiZXhwZWN0ZWRfdHlwZSI6InN0cmluZyIsIm1ldGFkYXRhIjpu
320
        dWxsLCJzaG93Ijp0cnVlLCJ2YWxpZGF0aW9ucyI6W119LHsibmFtZSI6ImZh
321
        Y3RzIiwiZnVsbF9uYW1lIjoiZmFjdHMiLCJkZXNjcmlwdGlvbiI6IlxuXHUw
322
        MDNjcFx1MDAzZUtleS12YWx1ZSBoYXNoIG9mIHN1YnNjcmlwdGlvbi1tYW5h
323
        Z2VyIGZhY3RzLCBuZXN0aW5nIHVzZXMgYSBwZXJpb2QgZGVsaW1pdGVyICgu
324
        KVx1MDAzYy9wXHUwMDNlXG4iLCJyZXF1aXJlZCI6ZmFsc2UsImFsbG93X25p
325
        bCI6ZmFsc2UsInZhbGlkYXRvciI6Ikhhc2giLCJleHBlY3RlZF90eXBlIjoi
326
        aGFzaCIsIm1ldGFkYXRhIjpudWxsLCJzaG93Ijp0cnVlLCJ2YWxpZGF0aW9u
327
        cyI6W119LHsibmFtZSI6Imh5cGVydmlzb3JfZ3Vlc3RfdXVpZHMiLCJmdWxs
328
        X25hbWUiOiJoeXBlcnZpc29yX2d1ZXN0X3V1aWRzIiwiZGVzY3JpcHRpb24i
329
        OiJcblx1MDAzY3BcdTAwM2VVVUlEcyBvZiB0aGUgdmlydHVhbCBndWVzdHMg
330
        ZnJvbSB0aGUgaG9zdOKAmXMgaHlwZXJ2aXNvclx1MDAzYy9wXHUwMDNlXG4i
331
        LCJyZXF1aXJlZCI6ZmFsc2UsImFsbG93X25pbCI6ZmFsc2UsInZhbGlkYXRv
332
        ciI6Ik11c3QgYmUgYW4gYXJyYXkgb2YgYW55IHR5cGUiLCJleHBlY3RlZF90
333
        eXBlIjoiYXJyYXkiLCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwidmFs
334
        aWRhdGlvbnMiOltdfSx7Im5hbWUiOiJpbnN0YWxsZWRfcHJvZHVjdHMiLCJm
335
        dWxsX25hbWUiOiJpbnN0YWxsZWRfcHJvZHVjdHMiLCJkZXNjcmlwdGlvbiI6
336
        IlxuXHUwMDNjcFx1MDAzZUxpc3Qgb2YgcHJvZHVjdHMgaW5zdGFsbGVkIG9u
337
        IHRoZSBob3N0XHUwMDNjL3BcdTAwM2VcbiIsInJlcXVpcmVkIjpmYWxzZSwi
338
        YWxsb3dfbmlsIjpmYWxzZSwidmFsaWRhdG9yIjoiTXVzdCBiZSBhbiBBcnJh
339
        eSBvZiBuZXN0ZWQgZWxlbWVudHMiLCJleHBlY3RlZF90eXBlIjoiYXJyYXki
340
        LCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwidmFsaWRhdGlvbnMiOltd
341
        LCJwYXJhbXMiOlt7Im5hbWUiOiJwcm9kdWN0X2lkIiwiZnVsbF9uYW1lIjoi
342
        aW5zdGFsbGVkX3Byb2R1Y3RzW3Byb2R1Y3RfaWRdIiwiZGVzY3JpcHRpb24i
343
        OiJcblx1MDAzY3BcdTAwM2VQcm9kdWN0IGlkIGFzIGxpc3RlZCBmcm9tIGEg
344
        aG9zdOKAmXMgaW5zdGFsbGVkIHByb2R1Y3RzLCB0aGlzIGlzIG5vdCB0aGUg
345
        c2FtZSBwcm9kdWN0IGlkIGFzIHRoZSBwcm9kdWN0cyBhcGkgcmV0dXJuc1x1
346
        MDAzYy9wXHUwMDNlXG4iLCJyZXF1aXJlZCI6ZmFsc2UsImFsbG93X25pbCI6
347
        ZmFsc2UsInZhbGlkYXRvciI6IlN0cmluZyIsImV4cGVjdGVkX3R5cGUiOiJz
348
        dHJpbmciLCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwidmFsaWRhdGlv
349
        bnMiOltdfSx7Im5hbWUiOiJwcm9kdWN0X25hbWUiLCJmdWxsX25hbWUiOiJp
350
        bnN0YWxsZWRfcHJvZHVjdHNbcHJvZHVjdF9uYW1lXSIsImRlc2NyaXB0aW9u
351
        IjoiXG5cdTAwM2NwXHUwMDNlUHJvZHVjdCBuYW1lIGFzIGxpc3RlZCBmcm9t
352
        IGEgaG9zdOKAmXMgaW5zdGFsbGVkIHByb2R1Y3RzXHUwMDNjL3BcdTAwM2Vc
353
        biIsInJlcXVpcmVkIjpmYWxzZSwiYWxsb3dfbmlsIjpmYWxzZSwidmFsaWRh
354
        dG9yIjoiU3RyaW5nIiwiZXhwZWN0ZWRfdHlwZSI6InN0cmluZyIsIm1ldGFk
355
        YXRhIjpudWxsLCJzaG93Ijp0cnVlLCJ2YWxpZGF0aW9ucyI6W119LHsibmFt
356
        ZSI6ImFyY2giLCJmdWxsX25hbWUiOiJpbnN0YWxsZWRfcHJvZHVjdHNbYXJj
357
        aF0iLCJkZXNjcmlwdGlvbiI6IlxuXHUwMDNjcFx1MDAzZVByb2R1Y3QgYXJj
358
        aGl0ZWN0dXJlXHUwMDNjL3BcdTAwM2VcbiIsInJlcXVpcmVkIjpmYWxzZSwi
359
        YWxsb3dfbmlsIjpmYWxzZSwidmFsaWRhdG9yIjoiU3RyaW5nIiwiZXhwZWN0
360
        ZWRfdHlwZSI6InN0cmluZyIsIm1ldGFkYXRhIjpudWxsLCJzaG93Ijp0cnVl
361
        LCJ2YWxpZGF0aW9ucyI6W119LHsibmFtZSI6InZlcnNpb24iLCJmdWxsX25h
362
        bWUiOiJpbnN0YWxsZWRfcHJvZHVjdHNbdmVyc2lvbl0iLCJkZXNjcmlwdGlv
363
        biI6IlxuXHUwMDNjcFx1MDAzZVByb2R1Y3QgdmVyc2lvblx1MDAzYy9wXHUw
364
        MDNlXG4iLCJyZXF1aXJlZCI6ZmFsc2UsImFsbG93X25pbCI6ZmFsc2UsInZh
365
        bGlkYXRvciI6IlN0cmluZyIsImV4cGVjdGVkX3R5cGUiOiJzdHJpbmciLCJt
366
        ZXRhZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwidmFsaWRhdGlvbnMiOltdfV19
367
        LHsibmFtZSI6InJlbGVhc2VfdmVyc2lvbiIsImZ1bGxfbmFtZSI6InJlbGVh
368
        c2VfdmVyc2lvbiIsImRlc2NyaXB0aW9uIjoiXG5cdTAwM2NwXHUwMDNlUmVs
369
        ZWFzZSB2ZXJzaW9uIG9mIHRoZSBjb250ZW50IGhvc3RcdTAwM2MvcFx1MDAz
370
        ZVxuIiwicmVxdWlyZWQiOmZhbHNlLCJhbGxvd19uaWwiOmZhbHNlLCJ2YWxp
371
        ZGF0b3IiOiJTdHJpbmciLCJleHBlY3RlZF90eXBlIjoic3RyaW5nIiwibWV0
372
        YWRhdGEiOm51bGwsInNob3ciOnRydWUsInZhbGlkYXRpb25zIjpbXX0seyJu
373
        YW1lIjoic2VydmljZV9sZXZlbCIsImZ1bGxfbmFtZSI6InNlcnZpY2VfbGV2
374
        ZWwiLCJkZXNjcmlwdGlvbiI6IlxuXHUwMDNjcFx1MDAzZUEgc2VydmljZSBs
375
        ZXZlbCBmb3IgYXV0by1oZWFsaW5nIHByb2Nlc3MsIGUuZy4gU0VMRi1TVVBQ
376
        T1JUXHUwMDNjL3BcdTAwM2VcbiIsInJlcXVpcmVkIjpmYWxzZSwiYWxsb3df
377
        bmlsIjpmYWxzZSwidmFsaWRhdG9yIjoiU3RyaW5nIiwiZXhwZWN0ZWRfdHlw
378
        ZSI6InN0cmluZyIsIm1ldGFkYXRhIjpudWxsLCJzaG93Ijp0cnVlLCJ2YWxp
379
        ZGF0aW9ucyI6W119LHsibmFtZSI6ImxpZmVjeWNsZV9lbnZpcm9ubWVudF9p
380
        ZCIsImZ1bGxfbmFtZSI6ImxpZmVjeWNsZV9lbnZpcm9ubWVudF9pZCIsImRl
381
        c2NyaXB0aW9uIjoiXG5cdTAwM2NwXHUwMDNlTGlmZWN5Y2xlIEVudmlyb25t
382
        ZW50IElEXHUwMDNjL3BcdTAwM2VcbiIsInJlcXVpcmVkIjp0cnVlLCJhbGxv
383
        d19uaWwiOmZhbHNlLCJ2YWxpZGF0b3IiOiJJbnRlZ2VyIiwiZXhwZWN0ZWRf
384
        dHlwZSI6Im51bWVyaWMiLCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwi
385
        dmFsaWRhdGlvbnMiOltdfSx7Im5hbWUiOiJjb250ZW50X3ZpZXdfaWQiLCJm
386
        dWxsX25hbWUiOiJjb250ZW50X3ZpZXdfaWQiLCJkZXNjcmlwdGlvbiI6Ilxu
387
        XHUwMDNjcFx1MDAzZUNvbnRlbnQgVmlldyBJRFx1MDAzYy9wXHUwMDNlXG4i
388
        LCJyZXF1aXJlZCI6dHJ1ZSwiYWxsb3dfbmlsIjpmYWxzZSwidmFsaWRhdG9y
389
        IjoiSW50ZWdlciIsImV4cGVjdGVkX3R5cGUiOiJudW1lcmljIiwibWV0YWRh
390
        dGEiOm51bGwsInNob3ciOnRydWUsInZhbGlkYXRpb25zIjpbXX1dLCJleGFt
391
        cGxlcyI6W10sIm1ldGFkYXRhIjpudWxsLCJzZWUiOltdLCJoZWFkZXJzIjpb
392
        XSwic2hvdyI6dHJ1ZX0seyJkb2NfdXJsIjoiLi4vYXBpZG9jL3YyL2hvc3Rf
393
        c3Vic2NyaXB0aW9ucy9yZW1vdmVfc3Vic2NyaXB0aW9ucyIsIm5hbWUiOiJy
394
        ZW1vdmVfc3Vic2NyaXB0aW9ucyIsImFwaXMiOlt7ImFwaV91cmwiOiIvYXBp
395
        L2hvc3RzLzpob3N0X2lkL3N1YnNjcmlwdGlvbnMvcmVtb3ZlX3N1YnNjcmlw
396
        dGlvbnMiLCJodHRwX21ldGhvZCI6IlBVVCIsInNob3J0X2Rlc2NyaXB0aW9u
397
        IjpudWxsLCJkZXByZWNhdGVkIjpudWxsfV0sImZvcm1hdHMiOm51bGwsImZ1
398
        bGxfZGVzY3JpcHRpb24iOiIiLCJlcnJvcnMiOltdLCJwYXJhbXMiOlt7Im5h
399
        bWUiOiJob3N0X2lkIiwiZnVsbF9uYW1lIjoiaG9zdF9pZCIsImRlc2NyaXB0
400
        aW9uIjoiXG5cdTAwM2NwXHUwMDNlSWQgb2YgdGhlIGhvc3RcdTAwM2MvcFx1
401
        MDAzZVxuIiwicmVxdWlyZWQiOnRydWUsImFsbG93X25pbCI6ZmFsc2UsInZh
402
        bGlkYXRvciI6IkludGVnZXIiLCJleHBlY3RlZF90eXBlIjoibnVtZXJpYyIs
403
        Im1ldGFkYXRhIjpudWxsLCJzaG93Ijp0cnVlLCJ2YWxpZGF0aW9ucyI6W119
404
        LHsibmFtZSI6InN1YnNjcmlwdGlvbnMiLCJmdWxsX25hbWUiOiJzdWJzY3Jp
405
        cHRpb25zIiwiZGVzY3JpcHRpb24iOiJcblx1MDAzY3BcdTAwM2VBcnJheSBv
406
        ZiBzdWJzY3JpcHRpb25zIHRvIHJlbW92ZVx1MDAzYy9wXHUwMDNlXG4iLCJy
407
        ZXF1aXJlZCI6ZmFsc2UsImFsbG93X25pbCI6ZmFsc2UsInZhbGlkYXRvciI6
408
        Ik11c3QgYmUgYW4gQXJyYXkgb2YgbmVzdGVkIGVsZW1lbnRzIiwiZXhwZWN0
409
        ZWRfdHlwZSI6ImFycmF5IiwibWV0YWRhdGEiOm51bGwsInNob3ciOnRydWUs
410
        InZhbGlkYXRpb25zIjpbXSwicGFyYW1zIjpbeyJuYW1lIjoiaWQiLCJmdWxs
411
        X25hbWUiOiJzdWJzY3JpcHRpb25zW2lkXSIsImRlc2NyaXB0aW9uIjoiXG5c
412
        dTAwM2NwXHUwMDNlU3Vic2NyaXB0aW9uIFBvb2wgaWRcdTAwM2MvcFx1MDAz
413
        ZVxuIiwicmVxdWlyZWQiOnRydWUsImFsbG93X25pbCI6ZmFsc2UsInZhbGlk
414
        YXRvciI6IlN0cmluZyIsImV4cGVjdGVkX3R5cGUiOiJzdHJpbmciLCJtZXRh
415
        ZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwidmFsaWRhdGlvbnMiOltdfSx7Im5h
416
        bWUiOiJxdWFudGl0eSIsImZ1bGxfbmFtZSI6InN1YnNjcmlwdGlvbnNbcXVh
417
        bnRpdHldIiwiZGVzY3JpcHRpb24iOiJcblx1MDAzY3BcdTAwM2VJZiBzcGVj
418
        aWZpZWQsIHJlbW92ZSB0aGUgZmlyc3QgaW5zdGFuY2Ugb2YgYSBzdWJzY3Jp
419
        cHRpb24gd2l0aCBtYXRjaGluZyBpZCBhbmQgcXVhbnRpdHlcdTAwM2MvcFx1
420
        MDAzZVxuIiwicmVxdWlyZWQiOmZhbHNlLCJhbGxvd19uaWwiOmZhbHNlLCJ2
421
        YWxpZGF0b3IiOiJJbnRlZ2VyIiwiZXhwZWN0ZWRfdHlwZSI6Im51bWVyaWMi
422
        LCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwidmFsaWRhdGlvbnMiOltd
423
        fV19XSwiZXhhbXBsZXMiOltdLCJtZXRhZGF0YSI6bnVsbCwic2VlIjpbXSwi
424
        aGVhZGVycyI6W10sInNob3ciOnRydWV9LHsiZG9jX3VybCI6Ii4uL2FwaWRv
425
        Yy92Mi9ob3N0X3N1YnNjcmlwdGlvbnMvYWRkX3N1YnNjcmlwdGlvbnMiLCJu
426
        YW1lIjoiYWRkX3N1YnNjcmlwdGlvbnMiLCJhcGlzIjpbeyJhcGlfdXJsIjoi
427
        L2FwaS9ob3N0cy86aG9zdF9pZC9zdWJzY3JpcHRpb25zL2FkZF9zdWJzY3Jp
428
        cHRpb25zIiwiaHR0cF9tZXRob2QiOiJQVVQiLCJzaG9ydF9kZXNjcmlwdGlv
429
        biI6IkFkZCBhIHN1YnNjcmlwdGlvbiB0byBhIGhvc3QiLCJkZXByZWNhdGVk
430
        IjpudWxsfV0sImZvcm1hdHMiOm51bGwsImZ1bGxfZGVzY3JpcHRpb24iOiIi
431
        LCJlcnJvcnMiOltdLCJwYXJhbXMiOlt7Im5hbWUiOiJob3N0X2lkIiwiZnVs
432
        bF9uYW1lIjoiaG9zdF9pZCIsImRlc2NyaXB0aW9uIjoiXG5cdTAwM2NwXHUw
433
        MDNlSWQgb2YgdGhlIGhvc3RcdTAwM2MvcFx1MDAzZVxuIiwicmVxdWlyZWQi
434
        OnRydWUsImFsbG93X25pbCI6ZmFsc2UsInZhbGlkYXRvciI6IkludGVnZXIi
435
        LCJleHBlY3RlZF90eXBlIjoibnVtZXJpYyIsIm1ldGFkYXRhIjpudWxsLCJz
436
        aG93Ijp0cnVlLCJ2YWxpZGF0aW9ucyI6W119LHsibmFtZSI6InN1YnNjcmlw
437
        dGlvbnMiLCJmdWxsX25hbWUiOiJzdWJzY3JpcHRpb25zIiwiZGVzY3JpcHRp
438
        b24iOiJcblx1MDAzY3BcdTAwM2VBcnJheSBvZiBzdWJzY3JpcHRpb25zIHRv
439
        IGFkZFx1MDAzYy9wXHUwMDNlXG4iLCJyZXF1aXJlZCI6dHJ1ZSwiYWxsb3df
440
        bmlsIjpmYWxzZSwidmFsaWRhdG9yIjoiTXVzdCBiZSBhbiBBcnJheSBvZiBu
441
        ZXN0ZWQgZWxlbWVudHMiLCJleHBlY3RlZF90eXBlIjoiYXJyYXkiLCJtZXRh
442
        ZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwidmFsaWRhdGlvbnMiOltdLCJwYXJh
443
        bXMiOlt7Im5hbWUiOiJpZCIsImZ1bGxfbmFtZSI6InN1YnNjcmlwdGlvbnNb
444
        aWRdIiwiZGVzY3JpcHRpb24iOiJcblx1MDAzY3BcdTAwM2VTdWJzY3JpcHRp
445
        b24gUG9vbCBpZFx1MDAzYy9wXHUwMDNlXG4iLCJyZXF1aXJlZCI6dHJ1ZSwi
446
        YWxsb3dfbmlsIjpmYWxzZSwidmFsaWRhdG9yIjoiU3RyaW5nIiwiZXhwZWN0
447
        ZWRfdHlwZSI6InN0cmluZyIsIm1ldGFkYXRhIjpudWxsLCJzaG93Ijp0cnVl
448
        LCJ2YWxpZGF0aW9ucyI6W119LHsibmFtZSI6InF1YW50aXR5IiwiZnVsbF9u
449
        YW1lIjoic3Vic2NyaXB0aW9uc1txdWFudGl0eV0iLCJkZXNjcmlwdGlvbiI6
450
        IlxuXHUwMDNjcFx1MDAzZVF1YW50aXR5IG9mIHRoaXMgc3Vic2NyaXB0aW9u
451
        cyB0byBhZGRcdTAwM2MvcFx1MDAzZVxuIiwicmVxdWlyZWQiOnRydWUsImFs
452
        bG93X25pbCI6ZmFsc2UsInZhbGlkYXRvciI6Im51bWJlci4iLCJleHBlY3Rl
453
        ZF90eXBlIjoic3RyaW5nIiwibWV0YWRhdGEiOm51bGwsInNob3ciOnRydWUs
454
        InZhbGlkYXRpb25zIjpbXX1dfV0sImV4YW1wbGVzIjpbXSwibWV0YWRhdGEi
455
        Om51bGwsInNlZSI6W10sImhlYWRlcnMiOltdLCJzaG93Ijp0cnVlfSx7ImRv
456
        Y191cmwiOiIuLi9hcGlkb2MvdjIvaG9zdF9zdWJzY3JpcHRpb25zL2NvbnRl
457
        bnRfb3ZlcnJpZGUiLCJuYW1lIjoiY29udGVudF9vdmVycmlkZSIsImFwaXMi
458
        Olt7ImFwaV91cmwiOiIvYXBpL2hvc3RzLzpob3N0X2lkL3N1YnNjcmlwdGlv
459
        bnMvY29udGVudF9vdmVycmlkZSIsImh0dHBfbWV0aG9kIjoiUFVUIiwic2hv
460
        cnRfZGVzY3JpcHRpb24iOiJTZXQgY29udGVudCBvdmVycmlkZXMgZm9yIHRo
461
        ZSBob3N0IiwiZGVwcmVjYXRlZCI6bnVsbH1dLCJmb3JtYXRzIjpudWxsLCJm
462
        dWxsX2Rlc2NyaXB0aW9uIjoiIiwiZXJyb3JzIjpbXSwicGFyYW1zIjpbeyJu
463
        YW1lIjoiaG9zdF9pZCIsImZ1bGxfbmFtZSI6Imhvc3RfaWQiLCJkZXNjcmlw
464
        dGlvbiI6IlxuXHUwMDNjcFx1MDAzZUlkIG9mIHRoZSBjb250ZW50IGhvc3Rc
465
        dTAwM2MvcFx1MDAzZVxuIiwicmVxdWlyZWQiOnRydWUsImFsbG93X25pbCI6
466
        ZmFsc2UsInZhbGlkYXRvciI6IlN0cmluZyIsImV4cGVjdGVkX3R5cGUiOiJz
467
        dHJpbmciLCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwidmFsaWRhdGlv
468
        bnMiOltdfSx7Im5hbWUiOiJjb250ZW50X2xhYmVsIiwiZnVsbF9uYW1lIjoi
469
        Y29udGVudF9sYWJlbCIsImRlc2NyaXB0aW9uIjoiXG5cdTAwM2NwXHUwMDNl
470
        TGFiZWwgb2YgdGhlIGNvbnRlbnRcdTAwM2MvcFx1MDAzZVxuIiwicmVxdWly
471
        ZWQiOnRydWUsImFsbG93X25pbCI6ZmFsc2UsInZhbGlkYXRvciI6IlN0cmlu
472
        ZyIsImV4cGVjdGVkX3R5cGUiOiJzdHJpbmciLCJtZXRhZGF0YSI6bnVsbCwi
473
        c2hvdyI6dHJ1ZSwidmFsaWRhdGlvbnMiOltdfSx7Im5hbWUiOiJ2YWx1ZSIs
474
        ImZ1bGxfbmFtZSI6InZhbHVlIiwiZGVzY3JpcHRpb24iOiJcblx1MDAzY3Bc
475
        dTAwM2VPdmVycmlkZSB0byDigJh5ZXPigJksIOKAmG5v4oCZLCBvciDigJhk
476
        ZWZhdWx04oCZXHUwMDNjL3BcdTAwM2VcbiIsInJlcXVpcmVkIjp0cnVlLCJh
477
        bGxvd19uaWwiOmZhbHNlLCJ2YWxpZGF0b3IiOiJNdXN0IGJlIG9uZSBvZjog
478
        XHUwMDNjY29kZVx1MDAzZTBcdTAwM2MvY29kZVx1MDAzZSwgXHUwMDNjY29k
479
        ZVx1MDAzZTFcdTAwM2MvY29kZVx1MDAzZSwgXHUwMDNjY29kZVx1MDAzZVN0
480
        cmluZ1x1MDAzYy9jb2RlXHUwMDNlLiIsImV4cGVjdGVkX3R5cGUiOiJzdHJp
481
        bmciLCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwidmFsaWRhdGlvbnMi
482
        OltdfV0sImV4YW1wbGVzIjpbXSwibWV0YWRhdGEiOm51bGwsInNlZSI6W10s
483
        ImhlYWRlcnMiOltdLCJzaG93Ijp0cnVlfSx7ImRvY191cmwiOiIuLi9hcGlk
484
        b2MvdjIvaG9zdF9zdWJzY3JpcHRpb25zL3Byb2R1Y3RfY29udGVudCIsIm5h
485
        bWUiOiJwcm9kdWN0X2NvbnRlbnQiLCJhcGlzIjpbeyJhcGlfdXJsIjoiL2Fw
486
        aS9ob3N0cy86aG9zdF9pZC9zdWJzY3JpcHRpb25zL3Byb2R1Y3RfY29udGVu
487
        dCIsImh0dHBfbWV0aG9kIjoiR0VUIiwic2hvcnRfZGVzY3JpcHRpb24iOiJH
488
        ZXQgY29udGVudCBhbmQgb3ZlcnJpZGVzIGZvciB0aGUgaG9zdCIsImRlcHJl
489
        Y2F0ZWQiOm51bGx9XSwiZm9ybWF0cyI6bnVsbCwiZnVsbF9kZXNjcmlwdGlv
490
        biI6IiIsImVycm9ycyI6W10sInBhcmFtcyI6W3sibmFtZSI6Imhvc3RfaWQi
491
        LCJmdWxsX25hbWUiOiJob3N0X2lkIiwiZGVzY3JpcHRpb24iOiJcblx1MDAz
492
        Y3BcdTAwM2VJZCBvZiB0aGUgaG9zdFx1MDAzYy9wXHUwMDNlXG4iLCJyZXF1
493
        aXJlZCI6dHJ1ZSwiYWxsb3dfbmlsIjpmYWxzZSwidmFsaWRhdG9yIjoiU3Ry
494
        aW5nIiwiZXhwZWN0ZWRfdHlwZSI6InN0cmluZyIsIm1ldGFkYXRhIjpudWxs
495
        LCJzaG93Ijp0cnVlLCJ2YWxpZGF0aW9ucyI6W119XSwiZXhhbXBsZXMiOltd
496
        LCJtZXRhZGF0YSI6bnVsbCwic2VlIjpbXSwiaGVhZGVycyI6W10sInNob3ci
497
        OnRydWV9XSwiaGVhZGVycyI6W119LCJob3N0cyI6eyJkb2NfdXJsIjoiLi4v
498
        YXBpZG9jL3YyL2hvc3RzIiwiYXBpX3VybCI6Ii9hcGkiLCJuYW1lIjoiSG9z
499
        dHMiLCJzaG9ydF9kZXNjcmlwdGlvbiI6bnVsbCwiZnVsbF9kZXNjcmlwdGlv
500
        biI6bnVsbCwidmVyc2lvbiI6InYyIiwiZm9ybWF0cyI6bnVsbCwibWV0YWRh
501
        dGEiOm51bGwsIm1ldGhvZHMiOlt7ImRvY191cmwiOiIuLi9hcGlkb2MvdjIv
502
        aG9zdHMvaW5kZXgiLCJuYW1lIjoiaW5kZXgiLCJhcGlzIjpbeyJhcGlfdXJs
503
        IjoiL2FwaS9ob3N0cyIsImh0dHBfbWV0aG9kIjoiR0VUIiwic2hvcnRfZGVz
504
        Y3JpcHRpb24iOiJMaXN0IGFsbCBob3N0cyIsImRlcHJlY2F0ZWQiOm51bGx9
505
        LHsiYXBpX3VybCI6Ii9hcGkvaG9zdGdyb3Vwcy86aG9zdGdyb3VwX2lkL2hv
506
        c3RzIiwiaHR0cF9tZXRob2QiOiJHRVQiLCJzaG9ydF9kZXNjcmlwdGlvbiI6
507
        Ikxpc3QgYWxsIGhvc3RzIGZvciBhIGhvc3QgZ3JvdXAiLCJkZXByZWNhdGVk
508
        IjpudWxsfSx7ImFwaV91cmwiOiIvYXBpL2xvY2F0aW9ucy86bG9jYXRpb25f
509
        aWQvaG9zdHMiLCJodHRwX21ldGhvZCI6IkdFVCIsInNob3J0X2Rlc2NyaXB0
510
        aW9uIjoiTGlzdCBob3N0cyBwZXIgbG9jYXRpb24iLCJkZXByZWNhdGVkIjpu
511
        dWxsfSx7ImFwaV91cmwiOiIvYXBpL29yZ2FuaXphdGlvbnMvOm9yZ2FuaXph
512
        dGlvbl9pZC9ob3N0cyIsImh0dHBfbWV0aG9kIjoiR0VUIiwic2hvcnRfZGVz
513
        Y3JpcHRpb24iOiJMaXN0IGhvc3RzIHBlciBvcmdhbml6YXRpb24iLCJkZXBy
514
        ZWNhdGVkIjpudWxsfSx7ImFwaV91cmwiOiIvYXBpL2Vudmlyb25tZW50cy86
515
        ZW52aXJvbm1lbnRfaWQvaG9zdHMiLCJodHRwX21ldGhvZCI6IkdFVCIsInNo
516
        b3J0X2Rlc2NyaXB0aW9uIjoiTGlzdCBob3N0cyBwZXIgZW52aXJvbm1lbnQi
517
        LCJkZXByZWNhdGVkIjpudWxsfV0sImZvcm1hdHMiOm51bGwsImZ1bGxfZGVz
518
        Y3JpcHRpb24iOiIiLCJlcnJvcnMiOltdLCJwYXJhbXMiOlt7Im5hbWUiOiJo
519
        b3N0Z3JvdXBfaWQiLCJmdWxsX25hbWUiOiJob3N0Z3JvdXBfaWQiLCJkZXNj
520
        cmlwdGlvbiI6IlxuXHUwMDNjcFx1MDAzZUlEIG9mIGhvc3QgZ3JvdXBcdTAw
521
        M2MvcFx1MDAzZVxuIiwicmVxdWlyZWQiOmZhbHNlLCJhbGxvd19uaWwiOmZh
522
        bHNlLCJ2YWxpZGF0b3IiOiJTdHJpbmciLCJleHBlY3RlZF90eXBlIjoic3Ry
523
        aW5nIiwibWV0YWRhdGEiOm51bGwsInNob3ciOnRydWUsInZhbGlkYXRpb25z
524
        IjpbXX0seyJuYW1lIjoibG9jYXRpb25faWQiLCJmdWxsX25hbWUiOiJsb2Nh
525
        dGlvbl9pZCIsImRlc2NyaXB0aW9uIjoiXG5cdTAwM2NwXHUwMDNlSUQgb2Yg
526
        bG9jYXRpb25cdTAwM2MvcFx1MDAzZVxuIiwicmVxdWlyZWQiOmZhbHNlLCJh
527
        bGxvd19uaWwiOmZhbHNlLCJ2YWxpZGF0b3IiOiJTdHJpbmciLCJleHBlY3Rl
528
        ZF90eXBlIjoic3RyaW5nIiwibWV0YWRhdGEiOm51bGwsInNob3ciOnRydWUs
529
        InZhbGlkYXRpb25zIjpbXX0seyJuYW1lIjoib3JnYW5pemF0aW9uX2lkIiwi
530
        ZnVsbF9uYW1lIjoib3JnYW5pemF0aW9uX2lkIiwiZGVzY3JpcHRpb24iOiJc
531
        blx1MDAzY3BcdTAwM2VJRCBvZiBvcmdhbml6YXRpb25cdTAwM2MvcFx1MDAz
532
        ZVxuIiwicmVxdWlyZWQiOmZhbHNlLCJhbGxvd19uaWwiOmZhbHNlLCJ2YWxp
533
        ZGF0b3IiOiJTdHJpbmciLCJleHBlY3RlZF90eXBlIjoic3RyaW5nIiwibWV0
534
        YWRhdGEiOm51bGwsInNob3ciOnRydWUsInZhbGlkYXRpb25zIjpbXX0seyJu
535
        YW1lIjoiZW52aXJvbm1lbnRfaWQiLCJmdWxsX25hbWUiOiJlbnZpcm9ubWVu
536
        dF9pZCIsImRlc2NyaXB0aW9uIjoiXG5cdTAwM2NwXHUwMDNlSUQgb2YgZW52
537
        aXJvbm1lbnRcdTAwM2MvcFx1MDAzZVxuIiwicmVxdWlyZWQiOmZhbHNlLCJh
538
        bGxvd19uaWwiOmZhbHNlLCJ2YWxpZGF0b3IiOiJTdHJpbmciLCJleHBlY3Rl
539
        ZF90eXBlIjoic3RyaW5nIiwibWV0YWRhdGEiOm51bGwsInNob3ciOnRydWUs
540
        InZhbGlkYXRpb25zIjpbXX0seyJuYW1lIjoic2VhcmNoIiwiZnVsbF9uYW1l
541
        Ijoic2VhcmNoIiwiZGVzY3JpcHRpb24iOiJcblx1MDAzY3BcdTAwM2VmaWx0
542
        ZXIgcmVzdWx0c1x1MDAzYy9wXHUwMDNlXG4iLCJyZXF1aXJlZCI6ZmFsc2Us
543
        ImFsbG93X25pbCI6ZmFsc2UsInZhbGlkYXRvciI6IlN0cmluZyIsImV4cGVj
544
        dGVkX3R5cGUiOiJzdHJpbmciLCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6dHJ1
545
        ZSwidmFsaWRhdGlvbnMiOltdfSx7Im5hbWUiOiJvcmRlciIsImZ1bGxfbmFt
546
        ZSI6Im9yZGVyIiwiZGVzY3JpcHRpb24iOiJcblx1MDAzY3BcdTAwM2Vzb3J0
547
        IHJlc3VsdHNcdTAwM2MvcFx1MDAzZVxuIiwicmVxdWlyZWQiOmZhbHNlLCJh
548
        bGxvd19uaWwiOmZhbHNlLCJ2YWxpZGF0b3IiOiJTdHJpbmciLCJleHBlY3Rl
549
        ZF90eXBlIjoic3RyaW5nIiwibWV0YWRhdGEiOm51bGwsInNob3ciOnRydWUs
550
        InZhbGlkYXRpb25zIjpbXX0seyJuYW1lIjoicGFnZSIsImZ1bGxfbmFtZSI6
551
        InBhZ2UiLCJkZXNjcmlwdGlvbiI6IlxuXHUwMDNjcFx1MDAzZXBhZ2luYXRl
552
        IHJlc3VsdHNcdTAwM2MvcFx1MDAzZVxuIiwicmVxdWlyZWQiOmZhbHNlLCJh
553
        bGxvd19uaWwiOmZhbHNlLCJ2YWxpZGF0b3IiOiJTdHJpbmciLCJleHBlY3Rl
554
        ZF90eXBlIjoic3RyaW5nIiwibWV0YWRhdGEiOm51bGwsInNob3ciOnRydWUs
555
        InZhbGlkYXRpb25zIjpbXX0seyJuYW1lIjoicGVyX3BhZ2UiLCJmdWxsX25h
556
        bWUiOiJwZXJfcGFnZSIsImRlc2NyaXB0aW9uIjoiXG5cdTAwM2NwXHUwMDNl
557
        bnVtYmVyIG9mIGVudHJpZXMgcGVyIHJlcXVlc3RcdTAwM2MvcFx1MDAzZVxu
558
        IiwicmVxdWlyZWQiOmZhbHNlLCJhbGxvd19uaWwiOmZhbHNlLCJ2YWxpZGF0
559
        b3IiOiJTdHJpbmciLCJleHBlY3RlZF90eXBlIjoic3RyaW5nIiwibWV0YWRh
560
        dGEiOm51bGwsInNob3ciOnRydWUsInZhbGlkYXRpb25zIjpbXX1dLCJleGFt
561
        cGxlcyI6W10sIm1ldGFkYXRhIjpudWxsLCJzZWUiOltdLCJoZWFkZXJzIjpb
562
        XSwic2hvdyI6dHJ1ZX0seyJkb2NfdXJsIjoiLi4vYXBpZG9jL3YyL2hvc3Rz
563
        L3Nob3ciLCJuYW1lIjoic2hvdyIsImFwaXMiOlt7ImFwaV91cmwiOiIvYXBp
564
        L2hvc3RzLzppZCIsImh0dHBfbWV0aG9kIjoiR0VUIiwic2hvcnRfZGVzY3Jp
565
        cHRpb24iOiJTaG93IGEgaG9zdCIsImRlcHJlY2F0ZWQiOm51bGx9XSwiZm9y
566
        bWF0cyI6bnVsbCwiZnVsbF9kZXNjcmlwdGlvbiI6IiIsImVycm9ycyI6W10s
567
        InBhcmFtcyI6W3sibmFtZSI6ImlkIiwiZnVsbF9uYW1lIjoiaWQiLCJkZXNj
568
        cmlwdGlvbiI6IiIsInJlcXVpcmVkIjp0cnVlLCJhbGxvd19uaWwiOmZhbHNl
569
        LCJ2YWxpZGF0b3IiOiJNdXN0IGJlIGFuIGlkZW50aWZpZXIsIHN0cmluZyBm
570
        cm9tIDEgdG8gMTI4IGNoYXJhY3RlcnMgY29udGFpbmluZyBvbmx5IGFscGhh
571
        bnVtZXJpYyBjaGFyYWN0ZXJzLCBkb3QoLiksIHNwYWNlLCB1bmRlcnNjb3Jl
572
        KF8pLCBoeXBlbigtKSB3aXRoIG5vIGxlYWRpbmcgb3IgdHJhaWxpbmcgc3Bh
573
        Y2UuIiwiZXhwZWN0ZWRfdHlwZSI6InN0cmluZyIsIm1ldGFkYXRhIjpudWxs
574
        LCJzaG93Ijp0cnVlLCJ2YWxpZGF0aW9ucyI6W119XSwiZXhhbXBsZXMiOltd
575
        LCJtZXRhZGF0YSI6bnVsbCwic2VlIjpbXSwiaGVhZGVycyI6W10sInNob3ci
576
        OnRydWV9LHsiZG9jX3VybCI6Ii4uL2FwaWRvYy92Mi9ob3N0cy9jcmVhdGUi
577
        LCJuYW1lIjoiY3JlYXRlIiwiYXBpcyI6W3siYXBpX3VybCI6Ii9hcGkvaG9z
578
        dHMiLCJodHRwX21ldGhvZCI6IlBPU1QiLCJzaG9ydF9kZXNjcmlwdGlvbiI6
579
        IkNyZWF0ZSBhIGhvc3QiLCJkZXByZWNhdGVkIjpudWxsfV0sImZvcm1hdHMi
580
        Om51bGwsImZ1bGxfZGVzY3JpcHRpb24iOiIiLCJlcnJvcnMiOltdLCJwYXJh
581
        bXMiOlt7Im5hbWUiOiJob3N0IiwiZnVsbF9uYW1lIjoiaG9zdCIsImRlc2Ny
582
        aXB0aW9uIjoiIiwicmVxdWlyZWQiOnRydWUsImFsbG93X25pbCI6ZmFsc2Us
583
        InZhbGlkYXRvciI6Ikhhc2giLCJleHBlY3RlZF90eXBlIjoiaGFzaCIsIm1l
584
        dGFkYXRhIjpudWxsLCJzaG93Ijp0cnVlLCJ2YWxpZGF0aW9ucyI6W10sInBh
585
        cmFtcyI6W3sibmFtZSI6Im5hbWUiLCJmdWxsX25hbWUiOiJob3N0W25hbWVd
586
        IiwiZGVzY3JpcHRpb24iOiIiLCJyZXF1aXJlZCI6dHJ1ZSwiYWxsb3dfbmls
587
        IjpmYWxzZSwidmFsaWRhdG9yIjoiU3RyaW5nIiwiZXhwZWN0ZWRfdHlwZSI6
588
        InN0cmluZyIsIm1ldGFkYXRhIjpudWxsLCJzaG93Ijp0cnVlLCJ2YWxpZGF0
589
        aW9ucyI6W119LHsibmFtZSI6ImxvY2F0aW9uX2lkIiwiZnVsbF9uYW1lIjoi
590
        aG9zdFtsb2NhdGlvbl9pZF0iLCJkZXNjcmlwdGlvbiI6IlxuXHUwMDNjcFx1
591
        MDAzZXJlcXVpcmVkIGlmIGxvY2F0aW9ucyBhcmUgZW5hYmxlZFx1MDAzYy9w
592
        XHUwMDNlXG4iLCJyZXF1aXJlZCI6dHJ1ZSwiYWxsb3dfbmlsIjpmYWxzZSwi
593
        dmFsaWRhdG9yIjoibnVtYmVyLiIsImV4cGVjdGVkX3R5cGUiOiJzdHJpbmci
594
        LCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwidmFsaWRhdGlvbnMiOltd
595
        fSx7Im5hbWUiOiJvcmdhbml6YXRpb25faWQiLCJmdWxsX25hbWUiOiJob3N0
596
        W29yZ2FuaXphdGlvbl9pZF0iLCJkZXNjcmlwdGlvbiI6IlxuXHUwMDNjcFx1
597
        MDAzZXJlcXVpcmVkIGlmIG9yZ2FuaXphdGlvbnMgYXJlIGVuYWJsZWRcdTAw
598
        M2MvcFx1MDAzZVxuIiwicmVxdWlyZWQiOnRydWUsImFsbG93X25pbCI6ZmFs
599
        c2UsInZhbGlkYXRvciI6Im51bWJlci4iLCJleHBlY3RlZF90eXBlIjoic3Ry
600
        aW5nIiwibWV0YWRhdGEiOm51bGwsInNob3ciOnRydWUsInZhbGlkYXRpb25z
601
        IjpbXX0seyJuYW1lIjoiZW52aXJvbm1lbnRfaWQiLCJmdWxsX25hbWUiOiJo
602
        b3N0W2Vudmlyb25tZW50X2lkXSIsImRlc2NyaXB0aW9uIjoiXG5cdTAwM2Nw
603
        XHUwMDNlcmVxdWlyZWQgaWYgaG9zdCBpcyBtYW5hZ2VkIGFuZCB2YWx1ZSBp
604
        cyBub3QgaW5oZXJpdGVkIGZyb20gaG9zdCBncm91cFx1MDAzYy9wXHUwMDNl
605
        XG4iLCJyZXF1aXJlZCI6ZmFsc2UsImFsbG93X25pbCI6dHJ1ZSwidmFsaWRh
606
        dG9yIjoiU3RyaW5nIiwiZXhwZWN0ZWRfdHlwZSI6InN0cmluZyIsIm1ldGFk
607
        YXRhIjpudWxsLCJzaG93Ijp0cnVlLCJ2YWxpZGF0aW9ucyI6W119LHsibmFt
608
        ZSI6ImlwIiwiZnVsbF9uYW1lIjoiaG9zdFtpcF0iLCJkZXNjcmlwdGlvbiI6
609
        IlxuXHUwMDNjcFx1MDAzZW5vdCByZXF1aXJlZCBpZiB1c2luZyBhIHN1Ym5l
610
        dCB3aXRoIERIQ1AgQ2Fwc3VsZVx1MDAzYy9wXHUwMDNlXG4iLCJyZXF1aXJl
611
        ZCI6ZmFsc2UsImFsbG93X25pbCI6dHJ1ZSwidmFsaWRhdG9yIjoiU3RyaW5n
612
        IiwiZXhwZWN0ZWRfdHlwZSI6InN0cmluZyIsIm1ldGFkYXRhIjpudWxsLCJz
613
        aG93Ijp0cnVlLCJ2YWxpZGF0aW9ucyI6W119LHsibmFtZSI6Im1hYyIsImZ1
614
        bGxfbmFtZSI6Imhvc3RbbWFjXSIsImRlc2NyaXB0aW9uIjoiXG5cdTAwM2Nw
615
        XHUwMDNlcmVxdWlyZWQgZm9yIG1hbmFnZWQgaG9zdCB0aGF0IGlzIGJhcmUg
616
        bWV0YWwsIG5vdCByZXF1aXJlZCBpZiBpdOKAmXMgYSB2aXJ0dWFsIG1hY2hp
617
        bmVcdTAwM2MvcFx1MDAzZVxuIiwicmVxdWlyZWQiOmZhbHNlLCJhbGxvd19u
618
        aWwiOnRydWUsInZhbGlkYXRvciI6IlN0cmluZyIsImV4cGVjdGVkX3R5cGUi
619
        OiJzdHJpbmciLCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwidmFsaWRh
620
        dGlvbnMiOltdfSx7Im5hbWUiOiJhcmNoaXRlY3R1cmVfaWQiLCJmdWxsX25h
621
        bWUiOiJob3N0W2FyY2hpdGVjdHVyZV9pZF0iLCJkZXNjcmlwdGlvbiI6Ilxu
622
        XHUwMDNjcFx1MDAzZXJlcXVpcmVkIGlmIGhvc3QgaXMgbWFuYWdlZCBhbmQg
623
        dmFsdWUgaXMgbm90IGluaGVyaXRlZCBmcm9tIGhvc3QgZ3JvdXBcdTAwM2Mv
624
        cFx1MDAzZVxuIiwicmVxdWlyZWQiOmZhbHNlLCJhbGxvd19uaWwiOnRydWUs
625
        InZhbGlkYXRvciI6Im51bWJlci4iLCJleHBlY3RlZF90eXBlIjoic3RyaW5n
626
        IiwibWV0YWRhdGEiOm51bGwsInNob3ciOnRydWUsInZhbGlkYXRpb25zIjpb
627
        XX0seyJuYW1lIjoiZG9tYWluX2lkIiwiZnVsbF9uYW1lIjoiaG9zdFtkb21h
628
        aW5faWRdIiwiZGVzY3JpcHRpb24iOiJcblx1MDAzY3BcdTAwM2VyZXF1aXJl
629
        ZCBpZiBob3N0IGlzIG1hbmFnZWQgYW5kIHZhbHVlIGlzIG5vdCBpbmhlcml0
630
        ZWQgZnJvbSBob3N0IGdyb3VwXHUwMDNjL3BcdTAwM2VcbiIsInJlcXVpcmVk
631
        IjpmYWxzZSwiYWxsb3dfbmlsIjp0cnVlLCJ2YWxpZGF0b3IiOiJudW1iZXIu
632
        IiwiZXhwZWN0ZWRfdHlwZSI6InN0cmluZyIsIm1ldGFkYXRhIjpudWxsLCJz
633
        aG93Ijp0cnVlLCJ2YWxpZGF0aW9ucyI6W119LHsibmFtZSI6InJlYWxtX2lk
634
        IiwiZnVsbF9uYW1lIjoiaG9zdFtyZWFsbV9pZF0iLCJkZXNjcmlwdGlvbiI6
635
        IiIsInJlcXVpcmVkIjpmYWxzZSwiYWxsb3dfbmlsIjp0cnVlLCJ2YWxpZGF0
636
        b3IiOiJudW1iZXIuIiwiZXhwZWN0ZWRfdHlwZSI6InN0cmluZyIsIm1ldGFk
637
        YXRhIjpudWxsLCJzaG93Ijp0cnVlLCJ2YWxpZGF0aW9ucyI6W119LHsibmFt
638
        ZSI6InB1cHBldF9wcm94eV9pZCIsImZ1bGxfbmFtZSI6Imhvc3RbcHVwcGV0
639
        X3Byb3h5X2lkXSIsImRlc2NyaXB0aW9uIjoiIiwicmVxdWlyZWQiOmZhbHNl
640
        LCJhbGxvd19uaWwiOnRydWUsInZhbGlkYXRvciI6Im51bWJlci4iLCJleHBl
641
        Y3RlZF90eXBlIjoic3RyaW5nIiwibWV0YWRhdGEiOm51bGwsInNob3ciOnRy
642
        dWUsInZhbGlkYXRpb25zIjpbXX0seyJuYW1lIjoicHVwcGV0Y2xhc3NfaWRz
643
        IiwiZnVsbF9uYW1lIjoiaG9zdFtwdXBwZXRjbGFzc19pZHNdIiwiZGVzY3Jp
644
        cHRpb24iOiIiLCJyZXF1aXJlZCI6ZmFsc2UsImFsbG93X25pbCI6dHJ1ZSwi
645
        dmFsaWRhdG9yIjoiTXVzdCBiZSBhbiBhcnJheSBvZiBhbnkgdHlwZSIsImV4
646
        cGVjdGVkX3R5cGUiOiJhcnJheSIsIm1ldGFkYXRhIjpudWxsLCJzaG93Ijp0
647
        cnVlLCJ2YWxpZGF0aW9ucyI6W119LHsibmFtZSI6Im9wZXJhdGluZ3N5c3Rl
648
        bV9pZCIsImZ1bGxfbmFtZSI6Imhvc3Rbb3BlcmF0aW5nc3lzdGVtX2lkXSIs
649
        ImRlc2NyaXB0aW9uIjoiXG5cdTAwM2NwXHUwMDNlcmVxdWlyZWQgaWYgaG9z
650
        dCBpcyBtYW5hZ2VkIGFuZCB2YWx1ZSBpcyBub3QgaW5oZXJpdGVkIGZyb20g
651
        aG9zdCBncm91cFx1MDAzYy9wXHUwMDNlXG4iLCJyZXF1aXJlZCI6ZmFsc2Us
652
        ImFsbG93X25pbCI6dHJ1ZSwidmFsaWRhdG9yIjoiU3RyaW5nIiwiZXhwZWN0
653
        ZWRfdHlwZSI6InN0cmluZyIsIm1ldGFkYXRhIjpudWxsLCJzaG93Ijp0cnVl
654
        LCJ2YWxpZGF0aW9ucyI6W119LHsibmFtZSI6Im1lZGl1bV9pZCIsImZ1bGxf
655
        bmFtZSI6Imhvc3RbbWVkaXVtX2lkXSIsImRlc2NyaXB0aW9uIjoiXG5cdTAw
656
        M2NwXHUwMDNlcmVxdWlyZWQgaWYgbm90IGltYWdlZCBiYXNlZCBwcm92aXNp
657
        b25pbmcgYW5kIGhvc3QgaXMgbWFuYWdlZCBhbmQgdmFsdWUgaXMgbm90IGlu
658
        aGVyaXRlZCBmcm9tIGhvc3QgZ3JvdXBcdTAwM2MvcFx1MDAzZVxuIiwicmVx
659
        dWlyZWQiOmZhbHNlLCJhbGxvd19uaWwiOnRydWUsInZhbGlkYXRvciI6IlN0
660
        cmluZyIsImV4cGVjdGVkX3R5cGUiOiJzdHJpbmciLCJtZXRhZGF0YSI6bnVs
661
        bCwic2hvdyI6dHJ1ZSwidmFsaWRhdGlvbnMiOltdfSx7Im5hbWUiOiJwdGFi
662
        bGVfaWQiLCJmdWxsX25hbWUiOiJob3N0W3B0YWJsZV9pZF0iLCJkZXNjcmlw
663
        dGlvbiI6IlxuXHUwMDNjcFx1MDAzZXJlcXVpcmVkIGlmIGhvc3QgaXMgbWFu
664
        YWdlZCBhbmQgY3VzdG9tIHBhcnRpdGlvbiBoYXMgbm90IGJlZW4gZGVmaW5l
665
        ZFx1MDAzYy9wXHUwMDNlXG4iLCJyZXF1aXJlZCI6ZmFsc2UsImFsbG93X25p
666
        bCI6dHJ1ZSwidmFsaWRhdG9yIjoibnVtYmVyLiIsImV4cGVjdGVkX3R5cGUi
667
        OiJzdHJpbmciLCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwidmFsaWRh
668
        dGlvbnMiOltdfSx7Im5hbWUiOiJzdWJuZXRfaWQiLCJmdWxsX25hbWUiOiJo
669
        b3N0W3N1Ym5ldF9pZF0iLCJkZXNjcmlwdGlvbiI6IlxuXHUwMDNjcFx1MDAz
670
        ZXJlcXVpcmVkIGlmIGhvc3QgaXMgbWFuYWdlZCBhbmQgdmFsdWUgaXMgbm90
671
        IGluaGVyaXRlZCBmcm9tIGhvc3QgZ3JvdXBcdTAwM2MvcFx1MDAzZVxuIiwi
672
        cmVxdWlyZWQiOmZhbHNlLCJhbGxvd19uaWwiOnRydWUsInZhbGlkYXRvciI6
673
        Im51bWJlci4iLCJleHBlY3RlZF90eXBlIjoic3RyaW5nIiwibWV0YWRhdGEi
674
        Om51bGwsInNob3ciOnRydWUsInZhbGlkYXRpb25zIjpbXX0seyJuYW1lIjoi
675
        Y29tcHV0ZV9yZXNvdXJjZV9pZCIsImZ1bGxfbmFtZSI6Imhvc3RbY29tcHV0
676
        ZV9yZXNvdXJjZV9pZF0iLCJkZXNjcmlwdGlvbiI6IlxuXHUwMDNjcFx1MDAz
677
        ZW5pbCBtZWFucyBob3N0IGlzIGJhcmUgbWV0YWxcdTAwM2MvcFx1MDAzZVxu
678
        IiwicmVxdWlyZWQiOmZhbHNlLCJhbGxvd19uaWwiOnRydWUsInZhbGlkYXRv
679
        ciI6Im51bWJlci4iLCJleHBlY3RlZF90eXBlIjoic3RyaW5nIiwibWV0YWRh
680
        dGEiOm51bGwsInNob3ciOnRydWUsInZhbGlkYXRpb25zIjpbXX0seyJuYW1l
681
        Ijoicm9vdF9wYXNzIiwiZnVsbF9uYW1lIjoiaG9zdFtyb290X3Bhc3NdIiwi
682
        ZGVzY3JpcHRpb24iOiJcblx1MDAzY3BcdTAwM2VyZXF1aXJlZCBpZiBob3N0
683
        IGlzIG1hbmFnZWQgYW5kIHZhbHVlIGlzIG5vdCBpbmhlcml0ZWQgZnJvbSBo
684
        b3N0IGdyb3VwIG9yIGRlZmF1bHQgcGFzc3dvcmQgaW4gc2V0dGluZ3NcdTAw
685
        M2MvcFx1MDAzZVxuIiwicmVxdWlyZWQiOmZhbHNlLCJhbGxvd19uaWwiOnRy
686
        dWUsInZhbGlkYXRvciI6IlN0cmluZyIsImV4cGVjdGVkX3R5cGUiOiJzdHJp
687
        bmciLCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwidmFsaWRhdGlvbnMi
688
        OltdfSx7Im5hbWUiOiJtb2RlbF9pZCIsImZ1bGxfbmFtZSI6Imhvc3RbbW9k
689
        ZWxfaWRdIiwiZGVzY3JpcHRpb24iOiIiLCJyZXF1aXJlZCI6ZmFsc2UsImFs
690
        bG93X25pbCI6dHJ1ZSwidmFsaWRhdG9yIjoibnVtYmVyLiIsImV4cGVjdGVk
691
        X3R5cGUiOiJzdHJpbmciLCJtZXRhZGF0YSI6bnVsbCwic2hvdyI6dHJ1ZSwi
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff