aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Crute <mike@crute.us>2020-05-29 20:58:53 -0700
committerMike Crute <mike@crute.us>2020-05-29 20:58:53 -0700
commitb53492723dc99400d0caac6b6c007adf2f9af6fb (patch)
tree8634d6fbeac1d7a61b5e00980bd01b5895dc9c85
parent5b2f32c9c854ab30178cb78bc2272f2c71d0a60e (diff)
downloadalpine-ec2-ami-b53492723dc99400d0caac6b6c007adf2f9af6fb.tar.bz2
alpine-ec2-ami-b53492723dc99400d0caac6b6c007adf2f9af6fb.tar.xz
alpine-ec2-ami-b53492723dc99400d0caac6b6c007adf2f9af6fb.zip
Migrate full ami build to builder script
-rw-r--r--Makefile60
-rw-r--r--README.md21
-rwxr-xr-xscripts/builder.py61
3 files changed, 54 insertions, 88 deletions
diff --git a/Makefile b/Makefile
deleted file mode 100644
index e6f879c..0000000
--- a/Makefile
+++ /dev/null
@@ -1,60 +0,0 @@
1# vim: ts=8 noet:
2
3NVME_SCRIPTS := $(subst scripts/,build/,$(wildcard scripts/nvme/*))
4CORE_PROFILES := $(wildcard profiles/*/*)
5TARGET_PROFILES := $(wildcard profiles/*.conf)
6
7PROFILE :=
8BUILD :=
9BUILDS := $(BUILD)
10LEVEL :=
11
12# by default, use the 'packer' in the path
13PACKER := packer
14export PACKER
15
16
17check_defined = \
18 $(strip $(foreach 1,$1, \
19 $(call __check_defined,$1,$(strip $(value 2)))))
20__check_defined = \
21 $(if $(value $1),, \
22 $(error Undefined $1$(if $2, ($2))$(if $(value @), \
23 required by target `$@')))
24
25
26.PHONY: amis prune release-readme clean
27
28amis: build/packer.json build/profile/$(PROFILE) build
29 @:$(call check_defined, PROFILE, target profile name)
30 build/builder make-amis $(PROFILE) $(BUILDS)
31
32prune: build
33 @:$(call check_defined, LEVEL, pruning level)
34 @:$(call check_defined, PROFILE, target profile name)
35 build/builder prune-amis $(LEVEL) $(PROFILE) $(BUILD)
36
37release-readme: releases/README.md
38releases/README.md: build
39 @:$(call check_defined, PROFILE, target profile name)
40 @:$(call require_var, PROFILE)
41 build/builder gen-release-readme $(PROFILE)
42
43build:
44 python3 -m venv build
45 [ -d build/profile ] || mkdir -p build/profile
46 build/bin/pip install -U pip pyhocon pyyaml boto3
47
48 echo -e "#!/bin/sh\n$$(pwd)/build/bin/python scripts/builder.py \$$@" > $@
49 chmod +x $@
50
51build/packer.json: packer.conf build
52 build/builder convert-packer-config
53
54.PHONY: build/profile/$(PROFILE)
55build/profile/$(PROFILE): build $(CORE_PROFILES) $(TARGET_PROFILES)
56 @:$(call check_defined, PROFILE, target profile name)
57 build/builder resolve-profiles $(PROFILE)
58
59clean:
60 rm -rf build
diff --git a/README.md b/README.md
index 55f9a35..bedfe94 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,6 @@ include as much detailed information as possible.
36 36
37* [Packer](https://packer.io) >= 1.4.1 37* [Packer](https://packer.io) >= 1.4.1
38* [Python 3.x](https://python.org) (3.7 is known to work) 38* [Python 3.x](https://python.org) (3.7 is known to work)
39* `make` (GNU Make is known to work)
40* an AWS account with an existing subnet in an AWS Virtual Private Cloud 39* an AWS account with an existing subnet in an AWS Virtual Private Cloud
41 40
42### Profile Configuration 41### Profile Configuration
@@ -59,18 +58,12 @@ two methods on the list.*
59 58
60To build all build targets in a target profile, simply... 59To build all build targets in a target profile, simply...
61``` 60```
62make PROFILE=<profile> 61./scripts/builder.py amis <profile>
63``` 62```
64 63
65You can also build specfic build targets within a profile: 64You can also build specfic build targets within a profile:
66``` 65```
67make PROFILE=<profile> BUILDS="<build1> <build2>" 66./scripts/builder.py amis <profile> <build1> <build2>
68```
69
70If the `packer` binary is not in your `PATH`, or you would like to specify a
71different one, use...
72```
73make PACKER=<packer-path> PROFILE=<profile>
74``` 67```
75 68
76Before each build, new Alpine Linux *releases* are detected and the version's 69Before each build, new Alpine Linux *releases* are detected and the version's
@@ -98,7 +91,7 @@ pruning:
98 91
99To prune a profile (or optionally one build target of a profile)... 92To prune a profile (or optionally one build target of a profile)...
100``` 93```
101make prune LEVEL=<level> PROFILE=<profile> [BUILD=<build>] 94./scripts/builder.py prune-amis <profile> [<build>]
102``` 95```
103 96
104Any AMIs in the account which are "unknown" (to the profile/build target, at 97Any AMIs in the account which are "unknown" (to the profile/build target, at
@@ -110,14 +103,14 @@ This make target updates the [releases README](releases/README.md), primarily
110for updating the list of our pre-built AMIs. This may-or-may-not be useful for 103for updating the list of our pre-built AMIs. This may-or-may-not be useful for
111other target profiles. 104other target profiles.
112``` 105```
113make release-readme PROFILE=<profile> 106./scripts/builder.py gen-release-readme <profile>
114``` 107```
115 108
116### Cleaning up the Build Environment 109### Cleaning up the Build Environment
117 110
118`make clean` will remove the temporary `build` subdirectory, which contains the 111`git clean -dxf` will remove the temporary `build` subdirectory, which contains
119resolved profile and Packer configs, the Python virtual environment, and other 112the resolved profile and Packer configs, the Python virtual environment, and
120temporary build-related artifacts. 113other temporary build-related artifacts.
121 114
122## Caveats 115## Caveats
123 116
diff --git a/scripts/builder.py b/scripts/builder.py
index 7491e25..021016b 100755
--- a/scripts/builder.py
+++ b/scripts/builder.py
@@ -287,8 +287,7 @@ class MakeAMIs:
287 print(text, end="") 287 print(text, end="")
288 288
289 if res.returncode == 0: 289 if res.returncode == 0:
290 subprocess.run([os.path.join(root, "build", "builder"), 290 UpdateReleases().update_readme(args.profile, build, root)
291 "update-releases", args.profile, build])
292 else: 291 else:
293 if "is used by an existing AMI" in out.getvalue(): 292 if "is used by an existing AMI" in out.getvalue():
294 continue 293 continue
@@ -537,17 +536,20 @@ class ResolveProfiles:
537 parser.add_argument( 536 parser.add_argument(
538 "profile", help="name of profile to build", nargs="*") 537 "profile", help="name of profile to build", nargs="*")
539 538
540 def run(self, args, root): 539 def resolve_profiles(self, profiles, root):
541 builder = ConfigBuilder( 540 builder = ConfigBuilder(
542 os.path.join(root, "profiles"), 541 os.path.join(root, "profiles"),
543 os.path.join(root, "build", "profile")) 542 os.path.join(root, "build", "profile"))
544 543
545 if args.profile: 544 if profiles:
546 for profile in args.profile: 545 for profile in profiles:
547 builder.build_profile(profile) 546 builder.build_profile(profile)
548 else: 547 else:
549 builder.build_all() 548 builder.build_all()
550 549
550 def run(self, args, root):
551 self.resolve_profiles(args.profile, root)
552
551 553
552class UpdateReleases: 554class UpdateReleases:
553 """Update release YAML 555 """Update release YAML
@@ -566,18 +568,21 @@ class UpdateReleases:
566 return dict(zip(parsed[0::2], parsed[1::2])) 568 return dict(zip(parsed[0::2], parsed[1::2]))
567 569
568 def run(self, args, root): 570 def run(self, args, root):
571 self.update_readme(args.profile, args.build, root)
572
573 def update_readme(self, profile, build, root):
569 release_dir = os.path.join(root, "releases") 574 release_dir = os.path.join(root, "releases")
570 if not os.path.exists(release_dir): 575 if not os.path.exists(release_dir):
571 os.makedirs(release_dir) 576 os.makedirs(release_dir)
572 577
573 release_yaml = os.path.join(release_dir, f"{args.profile}.yaml") 578 release_yaml = os.path.join(release_dir, f"{profile}.yaml")
574 releases = {} 579 releases = {}
575 if os.path.exists(release_yaml): 580 if os.path.exists(release_yaml):
576 with open(release_yaml, "r") as data: 581 with open(release_yaml, "r") as data:
577 releases = yaml.safe_load(data) 582 releases = yaml.safe_load(data)
578 583
579 manifest_json = os.path.join( 584 manifest_json = os.path.join(
580 root, "build", "profile", args.profile, args.build, 585 root, "build", "profile", profile, build,
581 "manifest.json") 586 "manifest.json")
582 with open(manifest_json, "r") as data: 587 with open(manifest_json, "r") as data:
583 manifest = json.load(data) 588 manifest = json.load(data)
@@ -585,16 +590,16 @@ class UpdateReleases:
585 data = manifest["builds"][0]["custom_data"] 590 data = manifest["builds"][0]["custom_data"]
586 release = data["release"] 591 release = data["release"]
587 592
588 if args.build not in releases: 593 if build not in releases:
589 releases[args.build] = {} 594 releases[build] = {}
590 595
591 if release not in releases[args.build]: 596 if release not in releases[build]:
592 releases[args.build][release] = {} 597 releases[build][release] = {}
593 598
594 releases[args.build][release][data["ami_name"]] = { 599 releases[build][release][data["ami_name"]] = {
595 "description": data["ami_desc"], 600 "description": data["ami_desc"],
596 "profile": args.profile, 601 "profile": profile,
597 "profile_build": args.build, 602 "profile_build": build,
598 "version": data["version"], 603 "version": data["version"],
599 "release": release, 604 "release": release,
600 "arch": data["arch"], 605 "arch": data["arch"],
@@ -628,6 +633,34 @@ class ConvertPackerJSON:
628 source, dest, "json", 2, False) 633 source, dest, "json", 2, False)
629 634
630 635
636class FullBuild:
637 """Make all of the AMIs for a profile
638 """
639
640 command_name = "amis"
641
642 @staticmethod
643 def add_args(parser):
644 parser.add_argument("--region", "-r", default="us-west-2",
645 help="region to use for build")
646 parser.add_argument("profile", help="name of profile to build")
647 parser.add_argument("builds", nargs="*",
648 help="name of builds within a profile to build")
649
650 def run(self, args, root):
651 print("Converting packer.conf to JSON...", file=sys.stderr)
652 ConvertPackerJSON().run(args, root)
653
654 print("Resolving profiles...", file=sys.stderr)
655 ResolveProfiles().resolve_profiles([args.profile], root)
656
657 print("Running packer...", file=sys.stderr)
658 MakeAMIs().run(args, root)
659
660 print("Updating release readme...", file=sys.stderr)
661 GenReleaseReadme().run(args, root)
662
663
631def find_repo_root(): 664def find_repo_root():
632 path = os.getcwd() 665 path = os.getcwd()
633 666