fog-aws 3.5.2 → 3.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +16 -3
  4. data/LICENSE.md +1 -1
  5. data/README.md +39 -6
  6. data/bin/console +14 -0
  7. data/bin/setup +8 -0
  8. data/fog-aws.gemspec +2 -2
  9. data/lib/fog/aws.rb +4 -0
  10. data/lib/fog/aws/elasticache.rb +4 -2
  11. data/lib/fog/aws/elb.rb +1 -1
  12. data/lib/fog/aws/elbv2.rb +72 -0
  13. data/lib/fog/aws/models/compute/flavors.rb +1544 -122
  14. data/lib/fog/aws/models/compute/snapshot.rb +7 -6
  15. data/lib/fog/aws/models/compute/vpc.rb +7 -1
  16. data/lib/fog/aws/models/storage/directory.rb +0 -1
  17. data/lib/fog/aws/models/storage/file.rb +3 -0
  18. data/lib/fog/aws/parsers/compute/create_snapshot.rb +1 -1
  19. data/lib/fog/aws/parsers/compute/create_subnet.rb +33 -6
  20. data/lib/fog/aws/parsers/compute/describe_subnets.rb +33 -6
  21. data/lib/fog/aws/parsers/dns/create_hosted_zone.rb +1 -1
  22. data/lib/fog/aws/parsers/dns/get_hosted_zone.rb +3 -3
  23. data/lib/fog/aws/parsers/dns/list_hosted_zones.rb +3 -1
  24. data/lib/fog/aws/parsers/elbv2/create_load_balancer.rb +88 -0
  25. data/lib/fog/aws/parsers/elbv2/describe_listeners.rb +110 -0
  26. data/lib/fog/aws/parsers/elbv2/describe_load_balancers.rb +88 -0
  27. data/lib/fog/aws/parsers/elbv2/describe_tags.rb +53 -0
  28. data/lib/fog/aws/parsers/elbv2/empty.rb +10 -0
  29. data/lib/fog/aws/parsers/storage/get_object_tagging.rb +33 -0
  30. data/lib/fog/aws/parsers/sts/assume_role_with_web_identity.rb +1 -1
  31. data/lib/fog/aws/requests/compute/create_vpc.rb +2 -2
  32. data/lib/fog/aws/requests/elbv2/add_tags.rb +45 -0
  33. data/lib/fog/aws/requests/elbv2/create_load_balancer.rb +160 -0
  34. data/lib/fog/aws/requests/elbv2/describe_listeners.rb +38 -0
  35. data/lib/fog/aws/requests/elbv2/describe_load_balancers.rb +100 -0
  36. data/lib/fog/aws/requests/elbv2/describe_tags.rb +50 -0
  37. data/lib/fog/aws/requests/elbv2/remove_tags.rb +45 -0
  38. data/lib/fog/aws/requests/storage/get_object_tagging.rb +41 -0
  39. data/lib/fog/aws/requests/storage/put_object_tagging.rb +42 -0
  40. data/lib/fog/aws/requests/sts/assume_role_with_web_identity.rb +7 -6
  41. data/lib/fog/aws/storage.rb +2 -0
  42. data/lib/fog/aws/version.rb +1 -1
  43. data/tests/parsers/elbv2/create_load_balancer_tests.rb +48 -0
  44. data/tests/parsers/elbv2/describe_listeners_tests.rb +76 -0
  45. data/tests/parsers/elbv2/describe_load_balancers_tests.rb +54 -0
  46. data/tests/parsers/elbv2/describe_tags_tests.rb +35 -0
  47. data/tests/requests/compute/vpc_tests.rb +6 -0
  48. data/tests/requests/elbv2/helper.rb +66 -0
  49. data/tests/requests/elbv2/load_balancer_tests.rb +50 -0
  50. metadata +35 -10
@@ -7,12 +7,13 @@ module Fog
7
7
  attribute :description
8
8
  attribute :encrypted
9
9
  attribute :progress
10
- attribute :created_at, :aliases => 'startTime'
11
- attribute :owner_id, :aliases => 'ownerId'
12
- attribute :state, :aliases => 'status'
13
- attribute :tags, :aliases => 'tagSet'
14
- attribute :volume_id, :aliases => 'volumeId'
15
- attribute :volume_size, :aliases => 'volumeSize'
10
+ attribute :created_at, :aliases => 'startTime'
11
+ attribute :owner_id, :aliases => 'ownerId'
12
+ attribute :state, :aliases => 'status'
13
+ attribute :tags, :aliases => 'tagSet'
14
+ attribute :volume_id, :aliases => 'volumeId'
15
+ attribute :volume_size, :aliases => 'volumeSize'
16
+ attribute :status_message, :aliases => 'statusMessage'
16
17
 
17
18
  def destroy
18
19
  requires :id
@@ -106,7 +106,13 @@ module Fog
106
106
 
107
107
  def save
108
108
  requires :cidr_block
109
- data = service.create_vpc(cidr_block, { 'AmazonProvidedIpv6CidrBlock' => amazon_provided_ipv_6_cidr_block }).body['vpcSet'].first
109
+
110
+ options = {
111
+ 'AmazonProvidedIpv6CidrBlock' => amazon_provided_ipv_6_cidr_block,
112
+ 'InstanceTenancy' => tenancy
113
+ }
114
+
115
+ data = service.create_vpc(cidr_block, options).body['vpcSet'].first
110
116
  new_attributes = data.reject {|key,value| key == 'requestId'}
111
117
  new_attributes = data.reject {|key,value| key == 'requestId' || key == 'tagSet' }
112
118
  merge_attributes(new_attributes)
@@ -12,7 +12,6 @@ module Fog
12
12
  identity :key, :aliases => ['Name', 'name']
13
13
 
14
14
  attribute :creation_date, :aliases => 'CreationDate', :type => 'time'
15
- attribute :location, :aliases => 'LocationConstraint', :type => 'string'
16
15
 
17
16
  def acl=(new_acl)
18
17
  unless VALID_ACLS.include?(new_acl)
@@ -25,6 +25,7 @@ module Fog
25
25
  attribute :encryption_key, :aliases => 'x-amz-server-side-encryption-customer-key'
26
26
  attribute :version, :aliases => 'x-amz-version-id'
27
27
  attribute :kms_key_id, :aliases => 'x-amz-server-side-encryption-aws-kms-key-id'
28
+ attribute :tags, :aliases => 'x-amz-tagging'
28
29
 
29
30
  # @note Chunk size to use for multipart uploads.
30
31
  # Use small chunk sizes to minimize memory. E.g. 5242880 = 5mb
@@ -192,6 +193,7 @@ module Fog
192
193
  # @option options [String] expires sets number of seconds before AWS Object expires.
193
194
  # @option options [String] storage_class sets x-amz-storage-class HTTP header. Defaults to 'STANDARD'. Or, 'REDUCED_REDUNDANCY'
194
195
  # @option options [String] encryption sets HTTP encryption header. Set to 'AES256' to encrypt files at rest on S3
196
+ # @option options [String] tags sets x-amz-tagging HTTP header. For example, 'Org-Id=1' or 'Org-Id=1&Service=MyService'
195
197
  # @return [Boolean] true if no errors
196
198
  #
197
199
  def save(options = {})
@@ -208,6 +210,7 @@ module Fog
208
210
  options['Expires'] = expires if expires
209
211
  options.merge!(metadata)
210
212
  options['x-amz-storage-class'] = storage_class if storage_class
213
+ options['x-amz-tagging'] = tags if tags
211
214
  options.merge!(encryption_headers)
212
215
 
213
216
  # With a single PUT operation you can upload objects up to 5 GB in size. Automatically set MP for larger objects.
@@ -5,7 +5,7 @@ module Fog
5
5
  class CreateSnapshot < Fog::Parsers::Base
6
6
  def end_element(name)
7
7
  case name
8
- when 'description', 'ownerId', 'progress', 'snapshotId', 'status', 'volumeId'
8
+ when 'description', 'ownerId', 'progress', 'snapshotId', 'status', 'volumeId', 'statusMessage'
9
9
  @response[name] = value
10
10
  when 'requestId'
11
11
  @response[name] = value
@@ -7,6 +7,10 @@ module Fog
7
7
  @subnet = { 'tagSet' => {} }
8
8
  @response = { 'subnet' => [] }
9
9
  @tag = {}
10
+ @ipv6_cidr_block_association = {}
11
+ @in_tag_set = false
12
+ @in_ipv6_cidr_block_association_set = false
13
+ @in_cidr_block_state = false
10
14
  end
11
15
 
12
16
  def start_element(name, attrs = [])
@@ -14,19 +18,42 @@ module Fog
14
18
  case name
15
19
  when 'tagSet'
16
20
  @in_tag_set = true
21
+ when 'ipv6CidrBlockAssociationSet'
22
+ @in_ipv6_cidr_block_association_set = true
23
+ when 'ipv6CidrBlockState'
24
+ @in_cidr_block_state = true
17
25
  end
18
26
  end
19
27
 
20
28
  def end_element(name)
21
29
  if @in_tag_set
22
30
  case name
31
+ when 'item'
32
+ @subnet['tagSet'][@tag['key']] = @tag['value']
33
+ @tag = {}
34
+ when 'key', 'value'
35
+ @tag[name] = value
36
+ when 'tagSet'
37
+ @in_tag_set = false
38
+ end
39
+ elsif @in_ipv6_cidr_block_association_set
40
+ if @in_cidr_block_state
41
+ case name
42
+ when 'state'
43
+ @ipv6_cidr_block_association['ipv6CidrBlockState'] = { name => value }
44
+ when 'ipv6CidrBlockState'
45
+ @in_cidr_block_state = false
46
+ end
47
+ else
48
+ case name
23
49
  when 'item'
24
- @subnet['tagSet'][@tag['key']] = @tag['value']
25
- @tag = {}
26
- when 'key', 'value'
27
- @tag[name] = value
28
- when 'tagSet'
29
- @in_tag_set = false
50
+ @subnet['ipv6CidrBlockAssociationSet'] = @ipv6_cidr_block_association
51
+ @ipv6_cidr_block_association = {}
52
+ when 'ipv6CidrBlock', 'associationId'
53
+ @ipv6_cidr_block_association[name] = value
54
+ when 'ipv6CidrBlockAssociationSet'
55
+ @in_ipv6_cidr_block_association_set = false
56
+ end
30
57
  end
31
58
  else
32
59
  case name
@@ -7,6 +7,10 @@ module Fog
7
7
  @subnet = { 'tagSet' => {} }
8
8
  @response = { 'subnetSet' => [] }
9
9
  @tag = {}
10
+ @ipv6_cidr_block_association = {}
11
+ @in_tag_set = false
12
+ @in_ipv6_cidr_block_association_set = false
13
+ @in_cidr_block_state = false
10
14
  end
11
15
 
12
16
  def start_element(name, attrs = [])
@@ -14,19 +18,42 @@ module Fog
14
18
  case name
15
19
  when 'tagSet'
16
20
  @in_tag_set = true
21
+ when 'ipv6CidrBlockAssociationSet'
22
+ @in_ipv6_cidr_block_association_set = true
23
+ when 'ipv6CidrBlockState'
24
+ @in_cidr_block_state = true
17
25
  end
18
26
  end
19
27
 
20
28
  def end_element(name)
21
29
  if @in_tag_set
22
30
  case name
31
+ when 'item'
32
+ @subnet['tagSet'][@tag['key']] = @tag['value']
33
+ @tag = {}
34
+ when 'key', 'value'
35
+ @tag[name] = value
36
+ when 'tagSet'
37
+ @in_tag_set = false
38
+ end
39
+ elsif @in_ipv6_cidr_block_association_set
40
+ if @in_cidr_block_state
41
+ case name
42
+ when 'state'
43
+ @ipv6_cidr_block_association['ipv6CidrBlockState'] = { name => value }
44
+ when 'ipv6CidrBlockState'
45
+ @in_cidr_block_state = false
46
+ end
47
+ else
48
+ case name
23
49
  when 'item'
24
- @subnet['tagSet'][@tag['key']] = @tag['value']
25
- @tag = {}
26
- when 'key', 'value'
27
- @tag[name] = value
28
- when 'tagSet'
29
- @in_tag_set = false
50
+ @subnet['ipv6CidrBlockAssociationSet'] = @ipv6_cidr_block_association
51
+ @ipv6_cidr_block_association = {}
52
+ when 'ipv6CidrBlock', 'associationId'
53
+ @ipv6_cidr_block_association[name] = value
54
+ when 'ipv6CidrBlockAssociationSet'
55
+ @in_ipv6_cidr_block_association_set = false
56
+ end
30
57
  end
31
58
  else
32
59
  case name
@@ -16,7 +16,7 @@ module Fog
16
16
  case name
17
17
  when 'Id'
18
18
  @hosted_zone[name] = value.sub('/hostedzone/', '')
19
- when 'Name', 'CallerReference', 'Comment'
19
+ when 'Name', 'CallerReference', 'Comment', 'PrivateZone'
20
20
  @hosted_zone[name]= value
21
21
  when 'HostedZone'
22
22
  @response['HostedZone'] = @hosted_zone
@@ -17,14 +17,14 @@ module Fog
17
17
  case name
18
18
  when 'Id'
19
19
  @hosted_zone[name]= value.sub('/hostedzone/', '')
20
- when 'Name', 'CallerReference', 'Comment', 'PrivateZone', 'Config', 'ResourceRecordSetCount'
20
+ when 'Name', 'CallerReference', 'Comment', 'PrivateZone', 'Config'
21
21
  @hosted_zone[name]= value
22
+ when 'ResourceRecordSetCount'
23
+ @hosted_zone['ResourceRecordSetCount'] = value.to_i
22
24
  when 'HostedZone'
23
25
  @response['HostedZone'] = @hosted_zone
24
26
  @hosted_zone = {}
25
27
  @section = :name_servers
26
- when 'ResourceRecordSetCount'
27
- @response['ResourceRecordSetCount'] = value.to_i
28
28
  end
29
29
  elsif @section == :name_servers
30
30
  case name
@@ -13,8 +13,10 @@ module Fog
13
13
  case name
14
14
  when 'Id'
15
15
  @zone[name] = value.sub('/hostedzone/', '')
16
- when 'Name', 'CallerReference', 'Comment'
16
+ when 'Name', 'CallerReference', 'Comment', 'PrivateZone'
17
17
  @zone[name] = value
18
+ when 'ResourceRecordSetCount'
19
+ @zone['ResourceRecordSetCount'] = value.to_i
18
20
  when 'HostedZone'
19
21
  @hosted_zones << @zone
20
22
  @zone = {}
@@ -0,0 +1,88 @@
1
+ module Fog
2
+ module Parsers
3
+ module AWS
4
+ module ELBV2
5
+ class CreateLoadBalancer < Fog::Parsers::Base
6
+ def reset
7
+ reset_load_balancer
8
+ reset_availability_zone
9
+ @load_balancer_addresses = {}
10
+ @state = {}
11
+ @results = { 'LoadBalancers' => [] }
12
+ @response = { 'CreateLoadBalancerResult' => {}, 'ResponseMetadata' => {} }
13
+ end
14
+
15
+ def reset_load_balancer
16
+ @load_balancer = { 'SecurityGroups' => [], 'AvailabilityZones' => [] }
17
+ end
18
+
19
+ def reset_availability_zone
20
+ @availability_zone = { 'LoadBalancerAddresses' => [] }
21
+ end
22
+
23
+ def start_element(name, attrs = [])
24
+ super
25
+ case name
26
+ when 'AvailabilityZones'
27
+ @in_availability_zones = true
28
+ when 'LoadBalancerAddresses'
29
+ @in_load_balancer_addresses = true
30
+ when 'SecurityGroups'
31
+ @in_security_groups = true
32
+ when 'State'
33
+ @in_state = true
34
+ end
35
+ end
36
+
37
+ def end_element(name)
38
+ case name
39
+ when 'member'
40
+ if @in_availability_zones && @in_load_balancer_addresses
41
+ @availability_zone['LoadBalancerAddresses'] << @load_balancer_addresses
42
+ elsif @in_availability_zones
43
+ @load_balancer['AvailabilityZones'] << @availability_zone
44
+ reset_availability_zone
45
+ elsif @in_security_groups
46
+ @load_balancer['SecurityGroups'] << value
47
+ else
48
+ @results['LoadBalancers'] << @load_balancer
49
+ reset_load_balancer
50
+ end
51
+ when 'SubnetId', 'ZoneName'
52
+ @availability_zone[name] = value
53
+ when 'IpAddress', 'AllocationId'
54
+ @load_balancer_addresses[name] = value
55
+
56
+ when 'CanonicalHostedZoneName', 'CanonicalHostedZoneNameID', 'LoadBalancerName', 'DNSName', 'Scheme', 'Type',
57
+ 'LoadBalancerArn', 'IpAddressType', 'CanonicalHostedZoneId', 'VpcId'
58
+ @load_balancer[name] = value
59
+ when 'CreatedTime'
60
+ @load_balancer[name] = Time.parse(value)
61
+
62
+ when 'LoadBalancerAddresses'
63
+ @in_load_balancer_addresses = false
64
+ when 'AvailabilityZones'
65
+ @in_availability_zones = false
66
+ when 'SecurityGroups'
67
+ @in_security_groups = false
68
+ when 'State'
69
+ @in_state = false
70
+ @load_balancer[name] = @state
71
+ @state = {}
72
+ when 'Code'
73
+ @state[name] = value
74
+
75
+ when 'RequestId'
76
+ @response['ResponseMetadata'][name] = value
77
+
78
+ when 'NextMarker'
79
+ @results['NextMarker'] = value
80
+ when 'CreateLoadBalancerResponse'
81
+ @response['CreateLoadBalancerResult'] = @results
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,110 @@
1
+ module Fog
2
+ module Parsers
3
+ module AWS
4
+ module ELBV2
5
+ class DescribeListeners < Fog::Parsers::Base
6
+ def reset
7
+ reset_listener
8
+ @default_action = {}
9
+ @certificate = {}
10
+ @config = {}
11
+ @target_groups = []
12
+ @target_group = {}
13
+ @target_group_stickiness_config = {}
14
+ @results = { 'Listeners' => [] }
15
+ @response = { 'DescribeListenersResult' => {}, 'ResponseMetadata' => {} }
16
+ end
17
+
18
+ def reset_listener
19
+ @listener= { 'DefaultActions' => [], 'Certificates' => [] }
20
+ end
21
+
22
+ def start_element(name, attrs = [])
23
+ super
24
+ case name
25
+ when 'DefaultActions'
26
+ @in_default_actions = true
27
+ when 'Certificates'
28
+ @in_certificates = true
29
+ when 'TargetGroups'
30
+ @in_target_groups = true
31
+ when 'TargetGroupStickinessConfig'
32
+ @in_target_group_stickiness_config = true
33
+ end
34
+ end
35
+
36
+ def end_element(name)
37
+ if @in_default_actions
38
+ case name
39
+ when 'member'
40
+ if @in_target_groups
41
+ @target_groups << @target_group
42
+ @target_group = {}
43
+ else
44
+ @listener['DefaultActions'] << @default_action
45
+ @default_action = {}
46
+ end
47
+ when 'TargetGroupArn'
48
+ if @in_target_groups
49
+ @target_group[name] = value
50
+ else
51
+ @default_action[name] = value
52
+ end
53
+ when 'Weight'
54
+ @target_group[name] = value
55
+ when 'Type', 'Order'
56
+ @default_action[name] = value
57
+ when 'Path', 'Protocol', 'Port', 'Query', 'Host', 'StatusCode', 'ContentType',
58
+ 'MessageBody', 'StatusCode'
59
+ @config[name] = value
60
+ when 'RedirectConfig', 'ForwardConfig', 'FixedResponseConfig'
61
+ @default_action[name] = @config
62
+ @config = {}
63
+ when 'DurationSeconds', 'Enabled'
64
+ @target_group_stickiness_config[name] = value
65
+ when 'DefaultActions'
66
+ @in_default_actions = false
67
+ when 'TargetGroupStickinessConfig'
68
+ if @in_target_group_stickiness_config
69
+ @config['TargetGroupStickinessConfig'] = @target_group_stickiness_config
70
+ @in_target_group_stickiness_config = false
71
+ @target_group_stickiness_config = {}
72
+ end
73
+ when 'TargetGroups'
74
+ @config['TargetGroups'] = @target_groups
75
+ @in_target_groups = false
76
+ @target_groups = []
77
+ end
78
+ else
79
+ case name
80
+ when 'member'
81
+ if @in_certificates
82
+ @listener['Certificates'] << @certificate
83
+ @certificate = {}
84
+ else
85
+ @results['Listeners'] << @listener
86
+ reset_listener
87
+ end
88
+ when 'LoadBalancerArn', 'Protocol', 'Port', 'ListenerArn', 'SslPolicy'
89
+ @listener[name] = value
90
+ when 'CertificateArn'
91
+ @certificate[name] = value
92
+ when 'Certificates'
93
+ @in_certificates = false
94
+
95
+ when 'RequestId'
96
+ @response['ResponseMetadata'][name] = value
97
+
98
+ when 'NextMarker'
99
+ @results['NextMarker'] = value
100
+
101
+ when 'DescribeListenersResponse'
102
+ @response['DescribeListenersResult'] = @results
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,88 @@
1
+ module Fog
2
+ module Parsers
3
+ module AWS
4
+ module ELBV2
5
+ class DescribeLoadBalancers < Fog::Parsers::Base
6
+ def reset
7
+ reset_load_balancer
8
+ reset_availability_zone
9
+ @load_balancer_addresses = {}
10
+ @state = {}
11
+ @results = { 'LoadBalancers' => [] }
12
+ @response = { 'DescribeLoadBalancersResult' => {}, 'ResponseMetadata' => {} }
13
+ end
14
+
15
+ def reset_load_balancer
16
+ @load_balancer = { 'SecurityGroups' => [], 'AvailabilityZones' => [] }
17
+ end
18
+
19
+ def reset_availability_zone
20
+ @availability_zone = { 'LoadBalancerAddresses' => [] }
21
+ end
22
+
23
+ def start_element(name, attrs = [])
24
+ super
25
+ case name
26
+ when 'AvailabilityZones'
27
+ @in_availability_zones = true
28
+ when 'LoadBalancerAddresses'
29
+ @in_load_balancer_addresses = true
30
+ when 'SecurityGroups'
31
+ @in_security_groups = true
32
+ when 'State'
33
+ @in_state = true
34
+ end
35
+ end
36
+
37
+ def end_element(name)
38
+ case name
39
+ when 'member'
40
+ if @in_availability_zones && @in_load_balancer_addresses
41
+ @availability_zone['LoadBalancerAddresses'] << @load_balancer_addresses
42
+ elsif @in_availability_zones
43
+ @load_balancer['AvailabilityZones'] << @availability_zone
44
+ reset_availability_zone
45
+ elsif @in_security_groups
46
+ @load_balancer['SecurityGroups'] << value
47
+ else
48
+ @results['LoadBalancers'] << @load_balancer
49
+ reset_load_balancer
50
+ end
51
+ when 'SubnetId', 'ZoneName'
52
+ @availability_zone[name] = value
53
+ when 'IpAddress', 'AllocationId'
54
+ @load_balancer_addresses[name] = value
55
+
56
+ when 'CanonicalHostedZoneName', 'CanonicalHostedZoneNameID', 'LoadBalancerName', 'DNSName', 'Scheme', 'Type',
57
+ 'LoadBalancerArn', 'IpAddressType', 'CanonicalHostedZoneId', 'VpcId'
58
+ @load_balancer[name] = value
59
+ when 'CreatedTime'
60
+ @load_balancer[name] = Time.parse(value)
61
+
62
+ when 'LoadBalancerAddresses'
63
+ @in_load_balancer_addresses = false
64
+ when 'AvailabilityZones'
65
+ @in_availability_zones = false
66
+ when 'SecurityGroups'
67
+ @in_security_groups = false
68
+ when 'State'
69
+ @in_state = false
70
+ @load_balancer[name] = @state
71
+ @state = {}
72
+ when 'Code'
73
+ @state[name] = value
74
+
75
+ when 'RequestId'
76
+ @response['ResponseMetadata'][name] = value
77
+
78
+ when 'NextMarker'
79
+ @results['NextMarker'] = value
80
+ when 'DescribeLoadBalancersResponse'
81
+ @response['DescribeLoadBalancersResult'] = @results
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end