infrawrench-bulk_instances 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +15 -0
- data/lib/infrawrench/bulk_instances/version.rb +1 -1
- data/lib/infrawrench/bulk_instances.rb +45 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 35025be8d677ed34cdfea296faca613c02d6ffe5c88d35266ad33fc36947d704
|
|
4
|
+
data.tar.gz: 3035dee6a0a3f8f86923ab7fb1b1c16c02fbc0e2aff9798a18d4640b4518138c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fd9380c0871c15a34ebe92328f868d6347f6a3b6ce3722a137318d44c48b70cc22573fc38d696a9f66584ea604e97feacfeeecd3772bf87d6285ba93167d11fe
|
|
7
|
+
data.tar.gz: 33c0e9e0a4e9855840c34f2a93d4d4903a8f813d495daadf782e0057ba3b9df45f34c2f17699f155a7dd509ad62629cf603f046c07f9f9dea9c1510a684da852
|
data/README.md
CHANGED
|
@@ -69,6 +69,21 @@ variant fields. On other platforms they are `""`, unless the platform has a fiel
|
|
|
69
69
|
Requires Ruby 3.2 or later, and liblzma (part of macOS and of practically every
|
|
70
70
|
Linux distribution; `xz-utils`/`xz` otherwise) to decompress downloads.
|
|
71
71
|
|
|
72
|
+
## One instance
|
|
73
|
+
|
|
74
|
+
`Infrawrench::BulkInstances.fetch_aws_instance(platform, instance_type, ...)` fetches a single
|
|
75
|
+
instance from the Infrawrench API instead of downloading the platform's whole bundle. It returns
|
|
76
|
+
the same `AWSInstance` that `get` does, or `nil` if the platform has no instance with that name:
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
m5 = Infrawrench::BulkInstances.fetch_aws_instance("ec2", "m5.large")
|
|
80
|
+
m5&.pricing&.on_demand&.length
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
It takes `token:` like the bundle download, and `base_url:` for where the API is served from
|
|
84
|
+
(`https://app.infrawrench.com` by default). Nothing is cached. The API syncs each new bundle within
|
|
85
|
+
about half an hour of it being published, so it can briefly trail `download_aws_pricing_data`.
|
|
86
|
+
|
|
72
87
|
## Caching
|
|
73
88
|
|
|
74
89
|
The bundle is downloaded xz-compressed (about 20 MB) and kept decompressed (about
|
|
@@ -17,6 +17,7 @@ module Infrawrench
|
|
|
17
17
|
# AWS instance attributes and pricing (EC2, RDS, ElastiCache and more), with full history, from Infrawrench.
|
|
18
18
|
module BulkInstances
|
|
19
19
|
DEFAULT_BASE_URL = "https://instances-bundles.infrawrench.com"
|
|
20
|
+
DEFAULT_API_URL = "https://app.infrawrench.com"
|
|
20
21
|
USER_AGENT = "infrawrench/bulk-instances, ruby, 1.0"
|
|
21
22
|
|
|
22
23
|
# What Net::HTTP raises when the server cannot be reached or the connection breaks.
|
|
@@ -128,10 +129,53 @@ module Infrawrench
|
|
|
128
129
|
AWSPricingData.new(JSON.parse(json, freeze: true))
|
|
129
130
|
end
|
|
130
131
|
|
|
132
|
+
# Fetches one instance from the Infrawrench API, without downloading the platform's bundle.
|
|
133
|
+
# Nothing is cached.
|
|
134
|
+
#
|
|
135
|
+
# The result is the same as <tt>download_aws_pricing_data(platform).get(instance_type)</tt>, from
|
|
136
|
+
# whichever bundle the API last synced, which can trail the newest bundle by up to half an hour.
|
|
137
|
+
#
|
|
138
|
+
# @param platform [String, Symbol] One of AWS_PLATFORMS, e.g. +"rds"+, or any other lowercase platform name.
|
|
139
|
+
# @param instance_type [String] The instance type, e.g. +"m5.large"+.
|
|
140
|
+
# @param token [String, nil] Your Infrawrench API token. Defaults to the +INFRAWRENCH_API_KEY+ environment variable.
|
|
141
|
+
# @param base_url [String, nil] Where the Infrawrench API is served from. Defaults to https://app.infrawrench.com
|
|
142
|
+
# @return [AWSInstance, nil] +nil+ if the platform has no instance with that name.
|
|
143
|
+
# @raise [AWSPricingDataError]
|
|
144
|
+
def fetch_aws_instance(platform, instance_type, token: nil, base_url: nil)
|
|
145
|
+
unless (platform.is_a?(String) || platform.is_a?(Symbol)) && platform.match?(/\A[a-z0-9]+\z/)
|
|
146
|
+
raise AWSPricingDataError, %("#{platform}" is not a platform name.)
|
|
147
|
+
end
|
|
148
|
+
raise AWSPricingDataError, "The instance type is empty." if instance_type.to_s.empty?
|
|
149
|
+
|
|
150
|
+
token = ENV.fetch("INFRAWRENCH_API_KEY", nil) if token.nil?
|
|
151
|
+
if token.nil? || token.empty?
|
|
152
|
+
raise AWSPricingDataError, "No Infrawrench API token: pass `token:` or set INFRAWRENCH_API_KEY."
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
base_url = (base_url || DEFAULT_API_URL).sub(%r{/+\z}, "")
|
|
156
|
+
# Percent-encoded, with spaces as %20: a + in a path is a plus.
|
|
157
|
+
name = URI.encode_www_form_component(instance_type.to_s).gsub("+", "%20")
|
|
158
|
+
begin
|
|
159
|
+
json = download("#{base_url}/api/v1/aws-bulk-pricing/#{platform}/#{name}", token, &:read_body)
|
|
160
|
+
rescue AWSPricingDataError => e
|
|
161
|
+
return nil if e.status == 404
|
|
162
|
+
|
|
163
|
+
raise
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# The bundle's tables cut down to what this instance uses, and its row renumbered to match.
|
|
167
|
+
value = JSON.parse(json.to_s.dup.force_encoding(Encoding::UTF_8), freeze: true)
|
|
168
|
+
bundle = value.slice("offer", "compression_table", "regions", "variant_keys", "variants", "reserved_terms")
|
|
169
|
+
bundle["snapshots"] = []
|
|
170
|
+
bundle["instances"] = { value["name"] => value["instance"] }
|
|
171
|
+
AWSPricingData.new(bundle).get(value["name"])
|
|
172
|
+
end
|
|
173
|
+
|
|
131
174
|
private
|
|
132
175
|
|
|
133
176
|
# GETs +url+ and yields the successful response, retrying the 503 the bundles Worker
|
|
134
|
-
# answers when it cannot reach the Infrawrench API
|
|
177
|
+
# answers when it cannot reach the Infrawrench API (and the API answers when it cannot
|
|
178
|
+
# reach its store).
|
|
135
179
|
def download(url, token)
|
|
136
180
|
uri = URI(url)
|
|
137
181
|
(1..).each do |attempt|
|