diff options
author | Jake Buchholz <tomalok@gmail.com> | 2019-06-03 17:35:07 -0700 |
---|---|---|
committer | Mike Crute <mike@crute.us> | 2019-07-05 12:51:09 -0700 |
commit | 8f563aa4f1b33651a87399e73bfcf82fef858605 (patch) | |
tree | 654c3084070771425d8d1515f0f5318cbb32916c | |
parent | d28214fc5054199efa2046ed95c5e4e891c6b521 (diff) | |
download | alpine-ec2-ami-8f563aa4f1b33651a87399e73bfcf82fef858605.tar.bz2 alpine-ec2-ami-8f563aa4f1b33651a87399e73bfcf82fef858605.tar.xz alpine-ec2-ami-8f563aa4f1b33651a87399e73bfcf82fef858605.zip |
more changes based on review...
* Makefile - improve/fix check for required make vars
* resolve-profile.py.in
+ build a list of all regions & probe to see which ones are enabled (unknown if special subscription regions like ap-northeast-3 would show up in this list)
+ expand 'ami_regions' 'ALL' meta key to all enabled regions, 'ALL' key's value is preserved (that is, a value of None or False will disable all regions)
+ warn/remove regions in profile config that are found to be disabled.
+ improve checks for [None, False] values
-rw-r--r-- | Makefile | 19 | ||||
-rw-r--r-- | profiles/alpine.conf | 19 | ||||
-rw-r--r-- | profiles/test.conf | 4 | ||||
-rw-r--r-- | scripts/resolve-profile.py.in | 48 |
4 files changed, 65 insertions, 25 deletions
@@ -12,20 +12,29 @@ LEVEL := | |||
12 | PACKER := packer | 12 | PACKER := packer |
13 | export PACKER | 13 | export PACKER |
14 | 14 | ||
15 | require_var = $(if $(value $1),,$(error $1=... required)) | 15 | |
16 | check_defined = \ | ||
17 | $(strip $(foreach 1,$1, \ | ||
18 | $(call __check_defined,$1,$(strip $(value 2))))) | ||
19 | __check_defined = \ | ||
20 | $(if $(value $1),, \ | ||
21 | $(error Undefined $1$(if $2, ($2))$(if $(value @), \ | ||
22 | required by target `$@'))) | ||
23 | |||
16 | 24 | ||
17 | .PHONY: amis prune release-readme clean | 25 | .PHONY: amis prune release-readme clean |
18 | 26 | ||
19 | amis: build build/packer.json build/profile/$(PROFILE) build/update-release.py | 27 | amis: build build/packer.json build/profile/$(PROFILE) build/update-release.py |
20 | @:$(call require_var, PROFILE) | 28 | @:$(call check_defined, PROFILE, target profile name) |
21 | build/make-amis $(PROFILE) $(BUILDS) | 29 | build/make-amis $(PROFILE) $(BUILDS) |
22 | 30 | ||
23 | prune: build build/prune-amis.py | 31 | prune: build build/prune-amis.py |
24 | @:$(call require_var, LEVEL) | 32 | @:$(call check_defined, LEVEL, pruning level) |
25 | @:$(call require_var, PROFILE) | 33 | @:$(call check_defined, PROFILE, target profile name) |
26 | build/prune-amis.py $(LEVEL) $(PROFILE) $(BUILD) | 34 | build/prune-amis.py $(LEVEL) $(PROFILE) $(BUILD) |
27 | 35 | ||
28 | release-readme: build build/gen-release-readme.py | 36 | release-readme: build build/gen-release-readme.py |
37 | @:$(call check_defined, PROFILE, target profile name) | ||
29 | @:$(call require_var, PROFILE) | 38 | @:$(call require_var, PROFILE) |
30 | build/gen-release-readme.py $(PROFILE) | 39 | build/gen-release-readme.py $(PROFILE) |
31 | 40 | ||
@@ -39,7 +48,7 @@ build/packer.json: build packer.conf | |||
39 | build/.py3/bin/pyhocon -i packer.conf -f json > build/packer.json | 48 | build/.py3/bin/pyhocon -i packer.conf -f json > build/packer.json |
40 | 49 | ||
41 | build/profile/$(PROFILE): build build/resolve-profile.py $(CORE_PROFILES) $(TARGET_PROFILES) | 50 | build/profile/$(PROFILE): build build/resolve-profile.py $(CORE_PROFILES) $(TARGET_PROFILES) |
42 | @:$(call require_var, PROFILE) | 51 | @:$(call check_defined, PROFILE, target profile name) |
43 | build/resolve-profile.py $(PROFILE) | 52 | build/resolve-profile.py $(PROFILE) |
44 | 53 | ||
45 | %.py: %.py.in build | 54 | %.py: %.py.in build |
diff --git a/profiles/alpine.conf b/profiles/alpine.conf index 3727753..b5ada55 100644 --- a/profiles/alpine.conf +++ b/profiles/alpine.conf | |||
@@ -18,24 +18,7 @@ alpine { | |||
18 | all = true # these AMIs are publicly available | 18 | all = true # these AMIs are publicly available |
19 | } | 19 | } |
20 | ami_regions { | 20 | ami_regions { |
21 | #ap-east-1 = true # needs to be enabled first | 21 | ALL = true |
22 | ap-northeast-1 = true | ||
23 | ap-northeast-2 = true | ||
24 | #ap-northeast-3 = false # available by subscription only | ||
25 | ap-southeast-1 = true | ||
26 | ap-southeast-2 = true | ||
27 | ap-south-1 = true | ||
28 | ca-central-1 = true | ||
29 | eu-central-1 = true | ||
30 | eu-north-1 = true | ||
31 | eu-west-1 = true | ||
32 | eu-west-2 = true | ||
33 | eu-west-3 = true | ||
34 | sa-east-1 = true | ||
35 | us-east-1 = true | ||
36 | us-east-2 = true | ||
37 | us-west-1 = true | ||
38 | us-west-2 = true | ||
39 | } | 22 | } |
40 | } | 23 | } |
41 | 24 | ||
diff --git a/profiles/test.conf b/profiles/test.conf index eb7f2a3..b4ecab8 100644 --- a/profiles/test.conf +++ b/profiles/test.conf | |||
@@ -15,6 +15,10 @@ test { | |||
15 | ami_desc_prefix = "Alpine Test " | 15 | ami_desc_prefix = "Alpine Test " |
16 | build_region = "us-west-2" | 16 | build_region = "us-west-2" |
17 | build_subnet = "subnet-033a30d7b5220d177" | 17 | build_subnet = "subnet-033a30d7b5220d177" |
18 | ami_regions { | ||
19 | us-west-1 = true | ||
20 | ap-east-1 = true | ||
21 | } | ||
18 | } | 22 | } |
19 | 23 | ||
20 | # Build definitions | 24 | # Build definitions |
diff --git a/scripts/resolve-profile.py.in b/scripts/resolve-profile.py.in index d784cf3..5aca4d7 100644 --- a/scripts/resolve-profile.py.in +++ b/scripts/resolve-profile.py.in | |||
@@ -5,6 +5,8 @@ import json | |||
5 | import os | 5 | import os |
6 | import shutil | 6 | import shutil |
7 | import sys | 7 | import sys |
8 | import boto3 | ||
9 | from botocore.exceptions import ClientError | ||
8 | from datetime import datetime, timedelta | 10 | from datetime import datetime, timedelta |
9 | from pyhocon import ConfigFactory | 11 | from pyhocon import ConfigFactory |
10 | 12 | ||
@@ -47,13 +49,39 @@ def fold(fdict, ffmt): | |||
47 | fkey = fkey.strip('"') # complex keys may be in quotes | 49 | fkey = fkey.strip('"') # complex keys may be in quotes |
48 | if fval is True: | 50 | if fval is True: |
49 | folded += ffmt[0] + fkey | 51 | folded += ffmt[0] + fkey |
50 | elif not (fval is None or fval is False): | 52 | elif fval not in [None, False]: |
51 | folded += ffmt.format(fkey, fval) | 53 | folded += ffmt.format(fkey, fval) |
52 | return folded[1:] | 54 | return folded[1:] |
53 | 55 | ||
54 | 56 | ||
57 | # list of AWS regions, and whether they're enabled | ||
58 | all_regions = {} | ||
59 | AWS = boto3.session.Session() | ||
60 | sys.stderr.write("\n>>> Determining region availability...") | ||
61 | sys.stderr.flush() | ||
62 | for region in AWS.get_available_regions('ec2'): | ||
63 | ec2 = AWS.client('ec2', region_name=region) | ||
64 | try: | ||
65 | ec2.describe_regions() | ||
66 | except ClientError as e: | ||
67 | if e.response['Error']['Code'] == 'AuthFailure': | ||
68 | sys.stderr.write('-') | ||
69 | sys.stderr.flush() | ||
70 | all_regions[region] = False | ||
71 | continue | ||
72 | elif e.response['Error']['Code'] == 'UnauthorizedOperation': | ||
73 | # have access to the region, but not to ec2:DescribeRegions | ||
74 | pass | ||
75 | else: | ||
76 | raise | ||
77 | sys.stderr.write('+') | ||
78 | sys.stderr.flush() | ||
79 | all_regions[region] = True | ||
80 | sys.stderr.write("\n") | ||
81 | |||
55 | # parse/resolve HOCON profile's builds' config | 82 | # parse/resolve HOCON profile's builds' config |
56 | for build, cfg in BUILDS.items(): | 83 | for build, cfg in BUILDS.items(): |
84 | sys.stderr.write(f">>> Resolving configuration for '{build}'\n") | ||
57 | build_dir = os.path.join(PROFILE_DIR, build) | 85 | build_dir = os.path.join(PROFILE_DIR, build) |
58 | 86 | ||
59 | # make a fresh profile build directory | 87 | # make a fresh profile build directory |
@@ -75,6 +103,22 @@ for build, cfg in BUILDS.items(): | |||
75 | if cfg['revision'] == '@NOW@': | 103 | if cfg['revision'] == '@NOW@': |
76 | cfg['revision'] = NOW.strftime('%Y%m%d%H%M%S') | 104 | cfg['revision'] = NOW.strftime('%Y%m%d%H%M%S') |
77 | 105 | ||
106 | # 'ALL' region expansion (or retraction) | ||
107 | if 'ALL' in cfg['ami_regions']: | ||
108 | all_val = cfg['ami_regions']['ALL'] | ||
109 | if all_val not in [None, False]: | ||
110 | cfg['ami_regions'] = all_regions | ||
111 | else: | ||
112 | cfg['ami_regions'] = {} | ||
113 | else: | ||
114 | # warn/remove disabled regions | ||
115 | for region, enabled in all_regions.items(): | ||
116 | if enabled is not False or region not in cfg['ami_regions']: | ||
117 | continue | ||
118 | if cfg['ami_regions'][region] not in [None, False]: | ||
119 | sys.stderr.write(f"*** WARNING: skipping disabled region {region}\n") | ||
120 | cfg['ami_regions'][region] = False | ||
121 | |||
78 | # fold dict vars to scalars | 122 | # fold dict vars to scalars |
79 | for foldkey, foldfmt in FOLD_DICTS.items(): | 123 | for foldkey, foldfmt in FOLD_DICTS.items(): |
80 | cfg[foldkey] = fold(cfg[foldkey], foldfmt) | 124 | cfg[foldkey] = fold(cfg[foldkey], foldfmt) |
@@ -85,7 +129,7 @@ for build, cfg in BUILDS.items(): | |||
85 | if lvl is True: | 129 | if lvl is True: |
86 | # service in default runlevel | 130 | # service in default runlevel |
87 | lvls['default'].append(svc) | 131 | lvls['default'].append(svc) |
88 | elif not (lvl is None or lvl is False): | 132 | elif lvl not in [None, False]: |
89 | # service in specified runlevel (skip svc when false/null) | 133 | # service in specified runlevel (skip svc when false/null) |
90 | if lvl not in lvls.keys(): | 134 | if lvl not in lvls.keys(): |
91 | lvls[lvl] = [] | 135 | lvls[lvl] = [] |