1function supported_osarch { 2 # Arguments: 3 # $1 - osarch - example, linux/amd64 4 # 5 # Returns: 6 # 0 - supported 7 # * - not supported 8 local osarch="$1" 9 for valid in $(go tool dist list) 10 do 11 if test "${osarch}" = "${valid}" 12 then 13 return 0 14 fi 15 done 16 return 1 17} 18 19function refresh_docker_images { 20 # Arguments: 21 # $1 - Path to top level Consul source 22 # $2 - Which make target to invoke (optional) 23 # 24 # Return: 25 # 0 - success 26 # * - failure 27 28 if ! test -d "$1" 29 then 30 err "ERROR: '$1' is not a directory. refresh_docker_images must be called with the path to the top level source as the first argument'" 31 return 1 32 fi 33 34 local sdir="$1" 35 local targets="$2" 36 37 test -n "${targets}" || targets="docker-images" 38 39 make -C "${sdir}" ${targets} 40 return $? 41} 42 43function build_ui { 44 # Arguments: 45 # $1 - Path to the top level Consul source 46 # $2 - The docker image to run the build within (optional) 47 # $3 - Version override 48 # 49 # Returns: 50 # 0 - success 51 # * - error 52 # 53 # Notes: 54 # Use the GIT_COMMIT environment variable to pass off to the build 55 # Use the GIT_COMMIT_YEAR environment variable to pass off to the build 56 57 if ! test -d "$1" 58 then 59 err "ERROR: '$1' is not a directory. build_ui must be called with the path to the top level source as the first argument'" 60 return 1 61 fi 62 63 local image_name=${UI_BUILD_CONTAINER_DEFAULT} 64 if test -n "$2" 65 then 66 image_name="$2" 67 fi 68 69 local sdir="$1" 70 local ui_dir="${1}/ui" 71 72 # parse the version 73 version=$(parse_version "${sdir}") 74 75 if test -n "$3" 76 then 77 version="$3" 78 fi 79 80 local commit_hash="${GIT_COMMIT}" 81 if test -z "${commit_hash}" 82 then 83 commit_hash=$(git rev-parse --short HEAD) 84 fi 85 86 local commit_year="${GIT_COMMIT_YEAR}" 87 if test -z "${commit_year}" 88 then 89 commit_year=$(git show -s --format=%cd --date=format:%Y HEAD) 90 fi 91 92 local logo_type="${CONSUL_BINARY_TYPE}" 93 if test "$logo_type" != "oss" 94 then 95 logo_type="enterprise" 96 fi 97 98 # make sure we run within the ui dir 99 pushd ${ui_dir} > /dev/null 100 101 status "Creating the UI Build Container with image: ${image_name} and version '${version}'" 102 local container_id=$(docker create -it -e "CONSUL_GIT_SHA=${commit_hash}" -e "CONSUL_COPYRIGHT_YEAR=${commit_year}" -e "CONSUL_VERSION=${version}" -e "CONSUL_BINARY_TYPE=${CONSUL_BINARY_TYPE}" ${image_name}) 103 local ret=$? 104 if test $ret -eq 0 105 then 106 status "Copying the source from '${ui_dir}' to /consul-src within the container" 107 ( 108 tar -c $(ls -A | grep -v "^(node_modules\|dist\|tmp)") | docker cp - ${container_id}:/consul-src && 109 status "Running build in container" && docker start -i ${container_id} && 110 rm -rf ${1}/ui/dist && 111 status "Copying back artifacts" && docker cp ${container_id}:/consul-src/packages/consul-ui/dist ${1}/ui/dist 112 ) 113 ret=$? 114 docker rm ${container_id} > /dev/null 115 fi 116 117 # Check the version is baked in correctly 118 if test ${ret} -eq 0 119 then 120 local ui_vers=$(ui_version "${1}/ui/dist/index.html") 121 if test "${version}" != "${ui_vers}" 122 then 123 err "ERROR: UI version mismatch. Expecting: '${version}' found '${ui_vers}'" 124 ret=1 125 fi 126 fi 127 128 # Check the logo is baked in correctly 129 if test ${ret} -eq 0 130 then 131 local ui_logo_type=$(ui_logo_type "${1}/ui/dist/index.html") 132 if test "${logo_type}" != "${ui_logo_type}" 133 then 134 err "ERROR: UI logo type mismatch. Expecting: '${logo_type}' found '${ui_logo_type}'" 135 ret=1 136 fi 137 fi 138 139 # Copy UI over ready to be packaged into the binary 140 if test ${ret} -eq 0 141 then 142 rm -rf ${1}/pkg/web_ui 143 mkdir -p ${1}/pkg 144 cp -r ${1}/ui/dist ${1}/pkg/web_ui 145 fi 146 147 popd > /dev/null 148 return $ret 149} 150 151function build_assetfs { 152 # Arguments: 153 # $1 - Path to the top level Consul source 154 # $2 - The docker image to run the build within (optional) 155 # 156 # Returns: 157 # 0 - success 158 # * - error 159 # 160 # Note: 161 # The GIT_COMMIT and GIT_DIRTY environment variables will be used if present 162 163 if ! test -d "$1" 164 then 165 err "ERROR: '$1' is not a directory. build_assetfs must be called with the path to the top level source as the first argument'" 166 return 1 167 fi 168 169 local sdir="$1" 170 local image_name=${GO_BUILD_CONTAINER_DEFAULT} 171 if test -n "$2" 172 then 173 image_name="$2" 174 fi 175 176 pushd ${sdir} > /dev/null 177 status "Creating the Go Build Container with image: ${image_name}" 178 local container_id=$(docker create -it -e GIT_COMMIT=${GIT_COMMIT} -e GIT_DIRTY=${GIT_DIRTY} ${image_name} make static-assets ASSETFS_PATH=bindata_assetfs.go) 179 local ret=$? 180 if test $ret -eq 0 181 then 182 status "Copying the sources from '${sdir}/(pkg/web_ui|GNUmakefile)' to /consul/pkg" 183 ( 184 tar -c pkg/web_ui GNUmakefile | docker cp - ${container_id}:/consul && 185 status "Running build in container" && docker start -i ${container_id} && 186 status "Copying back artifacts" && docker cp ${container_id}:/consul/bindata_assetfs.go ${sdir}/agent/uiserver/bindata_assetfs.go 187 ) 188 ret=$? 189 docker rm ${container_id} > /dev/null 190 fi 191 popd >/dev/null 192 return $ret 193} 194 195function build_consul_post { 196 # Arguments 197 # $1 - Path to the top level Consul source 198 # $2 - Subdirectory under pkg/bin (Optional) 199 # 200 # Returns: 201 # 0 - success 202 # * - error 203 # 204 # Notes: 205 # pkg/bin is where to place binary packages 206 # pkg.bin.new is where the just built binaries are located 207 # bin is where to place the local systems versions 208 209 if ! test -d "$1" 210 then 211 err "ERROR: '$1' is not a directory. build_consul_post must be called with the path to the top level source as the first argument'" 212 return 1 213 fi 214 215 local sdir="$1" 216 217 local extra_dir_name="$2" 218 local extra_dir="" 219 220 if test -n "${extra_dir_name}" 221 then 222 extra_dir="${extra_dir_name}/" 223 fi 224 225 pushd "${sdir}" > /dev/null 226 227 # recreate the pkg dir 228 rm -r pkg/bin/${extra_dir}* 2> /dev/null 229 mkdir -p pkg/bin/${extra_dir} 2> /dev/null 230 231 # move all files in pkg.new into pkg 232 cp -r pkg.bin.new/${extra_dir}* pkg/bin/${extra_dir} 233 rm -r pkg.bin.new 234 235 DEV_PLATFORM="./pkg/bin/${extra_dir}$(go env GOOS)_$(go env GOARCH)" 236 for F in $(find ${DEV_PLATFORM} -mindepth 1 -maxdepth 1 -type f 2>/dev/null) 237 do 238 # recreate the bin dir 239 rm -r bin/* 2> /dev/null 240 mkdir -p bin 2> /dev/null 241 242 cp ${F} bin/ 243 cp ${F} ${MAIN_GOPATH}/bin 244 done 245 246 popd > /dev/null 247 248 return 0 249} 250 251function build_consul { 252 # Arguments: 253 # $1 - Path to the top level Consul source 254 # $2 - Subdirectory to put binaries in under pkg/bin (optional - must specify if needing to specify the docker image) 255 # $3 - The docker image to run the build within (optional) 256 # 257 # Returns: 258 # 0 - success 259 # * - error 260 # 261 # Note: 262 # The GOLDFLAGS and GOTAGS environment variables will be used if set 263 # If the CONSUL_DEV environment var is truthy only the local platform/architecture is built. 264 # If the XC_OS or the XC_ARCH environment vars are present then only those platforms/architectures 265 # will be built. Otherwise all supported platform/architectures are built 266 267 if ! test -d "$1" 268 then 269 err "ERROR: '$1' is not a directory. build_consul must be called with the path to the top level source as the first argument'" 270 return 1 271 fi 272 273 local sdir="$1" 274 local extra_dir_name="$2" 275 local extra_dir="" 276 local image_name=${GO_BUILD_CONTAINER_DEFAULT} 277 if test -n "$3" 278 then 279 image_name="$3" 280 fi 281 282 pushd ${sdir} > /dev/null 283 if is_set "${CONSUL_DEV}" 284 then 285 if test -z "${XC_OS}" 286 then 287 XC_OS=$(go env GOOS) 288 fi 289 290 if test -z "${XC_ARCH}" 291 then 292 XC_ARCH=$(go env GOARCH) 293 fi 294 fi 295 XC_OS=${XC_OS:-"solaris darwin freebsd linux windows"} 296 XC_ARCH=${XC_ARCH:-"386 amd64 arm arm64"} 297 298 if test -n "${extra_dir_name}" 299 then 300 extra_dir="${extra_dir_name}/" 301 fi 302 303 # figure out if the compiler supports modules 304 local use_modules=0 305 if go help modules >/dev/null 2>&1 306 then 307 use_modules=1 308 elif test -n "${GO111MODULE}" 309 then 310 use_modules=1 311 fi 312 313 local volume_mount= 314 if is_set "${use_modules}" 315 then 316 status "Ensuring Go modules are up to date" 317 # ensure our go module cache is correct 318 go_mod_assert || return 1 319 # setup to bind mount our hosts module cache into the container 320 volume_mount="--mount=type=bind,source=${MAIN_GOPATH}/pkg/mod,target=/go/pkg/mod" 321 fi 322 323 status "Creating the Go Build Container with image: ${image_name}" 324 local container_id=$(docker create -it \ 325 ${volume_mount} \ 326 -e CGO_ENABLED=0 \ 327 -e GOLDFLAGS="${GOLDFLAGS}" \ 328 -e GOTAGS="${GOTAGS}" \ 329 ${image_name} \ 330 ./build-support/scripts/build-local.sh -o "${XC_OS}" -a "${XC_ARCH}") 331 ret=$? 332 333 if test $ret -eq 0 334 then 335 status "Copying the source from '${sdir}' to /consul" 336 ( 337 tar -c $(ls | grep -v "^(ui\|website\|bin\|pkg\|.git)") | docker cp - ${container_id}:/consul && 338 status "Running build in container" && 339 docker start -i ${container_id} && 340 status "Copying back artifacts" && 341 docker cp ${container_id}:/consul/pkg/bin pkg.bin.new 342 ) 343 ret=$? 344 docker rm ${container_id} > /dev/null 345 346 if test $ret -eq 0 347 then 348 build_consul_post "${sdir}" "${extra_dir_name}" 349 ret=$? 350 else 351 rm -r pkg.bin.new 2> /dev/null 352 fi 353 fi 354 popd > /dev/null 355 return $ret 356} 357 358function build_consul_local { 359 # Arguments: 360 # $1 - Path to the top level Consul source 361 # $2 - Space separated string of OSes to build. If empty will use env vars for determination. 362 # $3 - Space separated string of architectures to build. If empty will use env vars for determination. 363 # $4 - Subdirectory to put binaries in under pkg/bin (optional) 364 # 365 # Returns: 366 # 0 - success 367 # * - error 368 # 369 # Note: 370 # The GOLDFLAGS and GOTAGS environment variables will be used if set 371 # If the CONSUL_DEV environment var is truthy only the local platform/architecture is built. 372 # If the XC_OS or the XC_ARCH environment vars are present then only those platforms/architectures 373 # will be built. Otherwise all supported platform/architectures are built 374 # The GOXPARALLEL environment variable is used if set 375 376 if ! test -d "$1" 377 then 378 err "ERROR: '$1' is not a directory. build_consul must be called with the path to the top level source as the first argument'" 379 return 1 380 fi 381 382 local sdir="$1" 383 local build_os="$2" 384 local build_arch="$3" 385 local extra_dir_name="$4" 386 local extra_dir="" 387 388 if test -n "${extra_dir_name}" 389 then 390 extra_dir="${extra_dir_name}/" 391 fi 392 393 pushd ${sdir} > /dev/null 394 if is_set "${CONSUL_DEV}" 395 then 396 if test -z "${XC_OS}" 397 then 398 XC_OS=$(go env GOOS) 399 fi 400 401 if test -z "${XC_ARCH}" 402 then 403 XC_ARCH=$(go env GOARCH) 404 fi 405 fi 406 XC_OS=${XC_OS:-"solaris darwin freebsd linux windows"} 407 XC_ARCH=${XC_ARCH:-"386 amd64 arm arm64"} 408 409 if test -z "${build_os}" 410 then 411 build_os="${XC_OS}" 412 fi 413 414 if test -z "${build_arch}" 415 then 416 build_arch="${XC_ARCH}" 417 fi 418 419 status_stage "==> Building Consul - OSes: ${build_os}, Architectures: ${build_arch}" 420 mkdir pkg.bin.new 2> /dev/null 421 422 status "Building sequentially with go install" 423 for os in ${build_os} 424 do 425 for arch in ${build_arch} 426 do 427 outdir="pkg.bin.new/${extra_dir}${os}_${arch}" 428 osarch="${os}/${arch}" 429 430 if ! supported_osarch "${osarch}" 431 then 432 continue 433 fi 434 echo "---> ${osarch}" 435 436 mkdir -p "${outdir}" 437 GOBIN_EXTRA="" 438 if test "${os}" != "$(go env GOHOSTOS)" -o "${arch}" != "$(go env GOHOSTARCH)" 439 then 440 GOBIN_EXTRA="${os}_${arch}/" 441 fi 442 binname="consul" 443 if [ $os == "windows" ];then 444 binname="consul.exe" 445 fi 446 debug_run env CGO_ENABLED=0 GOOS=${os} GOARCH=${arch} go install -ldflags "${GOLDFLAGS}" -tags "${GOTAGS}" && cp "${MAIN_GOPATH}/bin/${GOBIN_EXTRA}${binname}" "${outdir}/${binname}" 447 if test $? -ne 0 448 then 449 err "ERROR: Failed to build Consul for ${osarch}" 450 rm -r pkg.bin.new 451 return 1 452 fi 453 done 454 done 455 456 build_consul_post "${sdir}" "${extra_dir_name}" 457 if test $? -ne 0 458 then 459 err "ERROR: Failed postprocessing Consul binaries" 460 return 1 461 fi 462 return 0 463} 464