build.sh: Bump DATE to 20140206
[dockerfile.git] / build.sh
1 #!/bin/sh
2 #
3 # Copyright (C) 2013 W. Trevor King <wking@tremily.us>
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are met:
7 #
8 # * Redistributions of source code must retain the above copyright notice, this
9 # list of conditions and the following disclaimer.
10 #
11 # * Redistributions in binary form must reproduce the above copyright notice,
12 # this list of conditions and the following disclaimer in the documentation
13 # and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 # POSSIBILITY OF SUCH DAMAGE.
26
27 AUTHOR="${AUTHOR:-W. Trevor King <wking@tremily.us>}"
28 NAMESPACE="${NAMESPACE:-wking}"
29 DATE="${DATE:-20140206}"
30 MIRROR="${MIRROR:-http://distfiles.gentoo.org/}"
31 ARCH_URL="${ARCH_URL:-${MIRROR}releases/amd64/current-stage3/}"
32 STAGE3="${STAGE3:-stage3-amd64-${DATE}.tar.bz2}"
33 STAGE3_CONTENTS="${STAGE3_CONTENTS:-${STAGE3}.CONTENTS}"
34 STAGE3_DIGESTS="${STAGE3_DIGESTS:-${STAGE3}.DIGESTS.asc}"
35 PORTAGE_URL="${PORTAGE_URL:-${MIRROR}snapshots/}"
36 PORTAGE="${PORTAGE:-portage-${DATE}.tar.xz}"
37 PORTAGE_SIG="${PORTAGE_SIG:-${PORTAGE}.gpgsig}"
38
39 DOCKER_IO=$(command -v docker.io)
40 DOCKER="${DOCKER:-${DOCKER_IO:-docker}}"
41
42 REPOS="${REPOS:-
43         portage
44         gentoo-portage
45         gentoo-en-us
46         gentoo-syslog
47         gentoo-java
48         buildbot
49         elasticsearch
50         memcached
51         nginx
52         nginx-proxy
53         kibana
54         postgresql
55         redis
56         stunnel
57         }"
58
59 die()
60 {
61         echo "$1"
62         exit 1
63 }
64
65 msg()
66 {
67         echo "$@"
68 }
69
70 REALPATH="${REALPATH:-$(command -v realpath)}"
71 if [ -z "${REALPATH}" ]; then
72         READLINK="${READLINK:-$(command -v readlink)}"
73         if [ -n "${READLINK}" ]; then
74                 REALPATH="${READLINK} -f"
75         else
76                 die "need realpath or readlink to canonicalize paths"
77         fi
78 fi
79
80 # Does "${NAMESPACE}/${REPO}:${DATE}" exist?
81 # Returns 0 (exists) or 1 (missing).
82 #
83 # Arguments:
84 #
85 # 1: REPO
86 repo_exists()
87 {
88         REPO="${1}"
89         IMAGES=$("${DOCKER}" images "${NAMESPACE}/${REPO}")
90         MATCHES=$(echo "${IMAGES}" | grep "${DATE}")
91         if [ -z "${MATCHES}" ]; then
92                 return 1
93         fi
94         return 0
95 }
96
97 # If they don't already exist:
98 #
99 # * download the stage3 and
100 # * create "${NAMESPACE}/gentoo:${DATE}"
101 #
102 # Forcibly tag "${NAMESPACE}/gentoo:${DATE}" with "latest"
103 import_stage3()
104 {
105         msg "import stage3"
106         if ! repo_exists gentoo; then
107                 # import stage3 image from Gentoo mirrors
108
109                 for FILE in "${STAGE3}" "${STAGE3_CONTENTS}" "${STAGE3_DIGESTS}"; do
110                         if [ ! -f "downloads/${FILE}" ]; then
111                                 wget -O "downloads/${FILE}" "${ARCH_URL}${FILE}"
112                         fi
113                 done
114
115                 gpg --verify "downloads/${STAGE3_DIGESTS}" || die "insecure digests"
116                 SHA512_HASHES=$(grep -A1 SHA512 "downloads/${STAGE3_DIGESTS}" | grep -v '^--')
117                 SHA512_CHECK=$(cd downloads/ && (echo "${SHA512_HASHES}" | sha512sum -c))
118                 SHA512_FAILED=$(echo "${SHA512_CHECK}" | grep FAILED)
119                 if [ -n "${SHA512_FAILED}" ]; then
120                         die "${SHA512_FAILED}"
121                 fi
122
123                 msg "import ${NAMESPACE}/gentoo:${DATE}"
124                 "${DOCKER}" import - "${NAMESPACE}/gentoo:${DATE}" < "downloads/${STAGE3}" || die "failed to import"
125         fi
126
127         msg "tag ${NAMESPACE}/gentoo:latest"
128         "${DOCKER}" tag -f "${NAMESPACE}/gentoo:${DATE}" "${NAMESPACE}/gentoo:latest" || die "failed to tag"
129 }
130
131 # If they don't already exist:
132 #
133 # * download a portage snapshot and
134 # * create "${NAMESPACE}/portage-import:${DATE}"
135 #
136 # Forcibly tag "${NAMESPACE}/portage-import:${DATE}" with "latest"
137 import_portage()
138 {
139         msg "import portage"
140         if ! repo_exists portage-import; then
141                 # import portage image from Gentoo mirrors
142
143                 for FILE in "${PORTAGE}" "${PORTAGE_SIG}"; do
144                         if [ ! -f "downloads/${FILE}" ]; then
145                                 wget -O "downloads/${FILE}" "${PORTAGE_URL}${FILE}"
146                         fi
147                 done
148
149                 gpg --verify "downloads/${PORTAGE_SIG}" "downloads/${PORTAGE}" || die "insecure digests"
150
151                 msg "import ${NAMESPACE}/portage-import:${DATE}"
152                 "${DOCKER}" import - "${NAMESPACE}/portage-import:${DATE}" < "downloads/${PORTAGE}" || die "failed to import"
153         fi
154
155         msg "tag ${NAMESPACE}/portage-import:latest"
156         "${DOCKER}" tag -f "${NAMESPACE}/portage-import:${DATE}" "${NAMESPACE}/portage-import:latest" || die "failed to tag"
157 }
158
159 # extract Busybox for the portage image
160 #
161 # Arguments:
162 #
163 # 1: SUBDIR target subdirectory for the busybox binary
164 extract_busybox()
165 {
166         SUBDIR="${1}"
167         msg "extract Busybox binary to ${SUBDIR}"
168         THIS_DIR=$(dirname $($REALPATH $0))
169         CONTAINER="${NAMESPACE}-gentoo-${DATE}-extract-busybox"
170         "${DOCKER}" run -name "${CONTAINER}" -v "${THIS_DIR}/${SUBDIR}/":/tmp "${NAMESPACE}/gentoo:${DATE}" cp /bin/busybox /tmp/
171         "${DOCKER}" rm "${CONTAINER}"
172 }
173
174 # If it doesn't already exist:
175 #
176 # * create "${NAMESPACE}/${REPO}:${DATE}" from
177 #   "${REPO}/Dockerfile.template"
178 #
179 # Forcibly tag "${NAMESPACE}/${REPO}:${DATE}" with "latest"
180 #
181 # Arguments:
182 #
183 # 1: REPO
184 build_repo()
185 {
186         REPO="${1}"
187         msg "build repo ${REPO}"
188         if ! repo_exists "${REPO}"; then
189                 if [ "${REPO}" = portage ]; then
190                         extract_busybox "${REPO}"
191                 fi
192
193                 env -i \
194                         NAMESPACE="${NAMESPACE}" \
195                         TAG="${DATE}" \
196                         MAINTAINER="${AUTHOR}" \
197                         envsubst '
198                                 ${NAMESPACE}
199                                 ${TAG}
200                                 ${MAINTAINER}
201                                 ' \
202                                 < "${REPO}/Dockerfile.template" > "${REPO}/Dockerfile"
203
204                 msg "build ${NAMESPACE}/${REPO}:${DATE}"
205                 "${DOCKER}" build -t "${NAMESPACE}/${REPO}:${DATE}" "${REPO}" || die "failed to build"
206         fi
207         msg "tag ${NAMESPACE}/${REPO}:latest"
208         "${DOCKER}" tag -f "${NAMESPACE}/${REPO}:${DATE}" "${NAMESPACE}/${REPO}:latest" || die "failed to tag"
209 }
210
211 build()
212 {
213         import_stage3
214         import_portage
215
216         for REPO in ${REPOS}; do
217                 build_repo "${REPO}"
218         done
219 }
220
221 missing()
222 {
223         for REPO in gentoo portage-import ${REPOS}; do
224                 if ! repo_exists "${REPO}"; then
225                         msg "${REPO}"
226                 fi
227         done
228 }
229
230 ACTION="${1:-build}"
231
232 case "${ACTION}" in
233 build) build ;;
234 missing) missing ;;
235 --help) msg "usage: ${0} [--help] {build|missing}" ;;
236 *) die "invalid action '${ACTION}'" ;;
237 esac