commit f2b0a5e7c731d993fc7822dcdd95bc8367b84a75 Author: Danny Bessems Date: Wed Feb 22 21:24:42 2023 +0100 Test dependencies diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..898ea09 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,31 @@ +kind: pipeline +type: kubernetes +name: 'CAPI ImageBuilder' + +volumes: +- name: output + claim: + name: flexvolsmb-drone-output +- name: scratch + claim: + name: flexvolsmb-drone-scratch + +steps: +- name: Debugging information + image: bv11-cr01.bessems.eu/library/packer-extended + commands: + - ansible --version + - ovftool --version + - packer --version + - yamllint --version +- name: Build CAPV image(s) + image: bv11-cr01.bessems.eu/library/packer-extended + pull: always + commands: + - | + make deps + + + volumes: + - name: output + path: /output diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..ef5b8bb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,33 @@ +--- +name: Bug report +about: Tell us about a problem you are experiencing + +--- + +**What steps did you take and what happened:** +[A clear and concise description on how to REPRODUCE the bug.] + + +**What did you expect to happen:** + + +**Anything else you would like to add:** +[Miscellaneous information that will assist in solving the issue.] + + +**Environment:** + +Project ([Image Builder for Cluster API](https://github.com/kubernetes-sigs/image-builder/tree/master/images/capi), [kube-deploy/imagebuilder](https://github.com/kubernetes-sigs/image-builder/tree/master/images/kube-deploy/imagebuilder), [konfigadm](https://github.com/kubernetes-sigs/image-builder/tree/master/images/konfigadm)): + +Additional info for Image Builder for Cluster API related issues: + +- OS (e.g. from `/etc/os-release`, or `cmd /c ver`): +- Packer Version: +- Packer Provider: +- Ansible Version: +- Cluster-api version (if using): +- Kubernetes version: (use `kubectl version`): + +/kind bug +[One or more /area label. See https://github.com/kubernetes-sigs/cluster-api/labels?q=area for the list of labels] + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..3669dbf --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. + +/kind feature + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..cf21d55 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,6 @@ +What this PR does / why we need it: + +Which issue(s) this PR fixes (optional, in fixes #(, fixes #, ...) format, will close the issue(s) when PR gets merged): Fixes # + +**Additional context** +Add any other context for the reviewers \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..32fa9a3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,46 @@ +# syntax=docker/dockerfile:1.1-experimental + +# Copyright 2020 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG BASE_IMAGE=docker.io/library/ubuntu:latest +FROM $BASE_IMAGE + +RUN apt-get update && apt-get install -y apt-transport-https ca-certificates python3-pip curl wget git rsync vim unzip build-essential \ + && useradd -ms /bin/bash imagebuilder \ + && apt-get purge --auto-remove -y \ + && rm -rf /var/lib/apt/lists/* + +ARG ARCH +ARG PASSED_IB_VERSION + +USER imagebuilder +WORKDIR /home/imagebuilder/ + +COPY --chown=imagebuilder:imagebuilder ansible ansible/ +COPY --chown=imagebuilder:imagebuilder ansible.cfg ansible.cfg +COPY --chown=imagebuilder:imagebuilder cloudinit cloudinit/ +COPY --chown=imagebuilder:imagebuilder hack hack/ +COPY --chown=imagebuilder:imagebuilder packer packer/ +COPY --chown=imagebuilder:imagebuilder Makefile Makefile +COPY --chown=imagebuilder:imagebuilder azure_targets.sh azure_targets.sh + +ENV PATH="/home/imagebuilder/.local/bin:${PATH}" +ENV PACKER_ARGS '' +ENV PACKER_VAR_FILES '' +ENV IB_VERSION "${PASSED_IB_VERSION}" + +RUN make deps + +ENTRYPOINT [ "/usr/bin/make" ] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..89db5d3 --- /dev/null +++ b/Makefile @@ -0,0 +1,938 @@ +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# If you update this file, please follow +# https://suva.sh/posts/well-documented-makefiles + +# Ensure Make is run with bash shell as some syntax below is bash-specific +SHELL := /usr/bin/env bash + +.DEFAULT_GOAL := help + +# This option is for running docker manifest command +export DOCKER_CLI_EXPERIMENTAL := enabled +export PATH := $(PATH):$(CURDIR)/.local/bin + +export IB_VERSION ?= $(shell git describe --dirty) + +## -------------------------------------- +## Help +## -------------------------------------- +##@ Helpers +help: ## Display this help + @echo NOTE + @echo ' The "build-node-ova" targets have analogue "clean-node-ova" targets for' + @echo ' cleaning artifacts created from building OVAs using a local' + @echo ' hypervisor.' + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-35s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +.PHONY: version +version: ## Display version of image-builder + @echo $(IB_VERSION) + +## -------------------------------------- +## Dependencies +## -------------------------------------- +##@ Dependencies + +.PHONY: deps +deps: ## Installs/checks all dependencies +deps: deps-ami deps-azure deps-do deps-gce deps-ova deps-qemu deps-raw deps-oci deps-osc deps-vbox deps-powervs deps-nutanix + +.PHONY: deps-ami +deps-ami: ## Installs/checks dependencies for AMI builds +deps-ami: + hack/ensure-ansible.sh + hack/ensure-ansible-windows.sh + hack/ensure-packer.sh + hack/ensure-goss.sh + +.PHONY: deps-azure +deps-azure: ## Installs/checks dependencies for Azure builds +deps-azure: + hack/ensure-ansible.sh + hack/ensure-ansible-windows.sh + hack/ensure-packer.sh + hack/ensure-jq.sh + hack/ensure-azure-cli.sh + hack/ensure-goss.sh + +.PHONY: deps-do +deps-do: ## Installs/checks dependencies for DigitalOcean builds +deps-do: + hack/ensure-ansible.sh + hack/ensure-packer.sh + +.PHONY: deps-osc +deps-osc: ## Installs/checks dependencies for Outscale builds +deps-osc: + hack/ensure-ansible.sh + hack/ensure-packer.sh + hack/ensure-goss.sh + packer plugins install github.com/outscale/outscale + +.PHONY: deps-gce +deps-gce: ## Installs/checks dependencies for GCE builds +deps-gce: + hack/ensure-ansible.sh + hack/ensure-packer.sh + hack/ensure-goss.sh + +.PHONY: deps-ova +deps-ova: ## Installs/checks dependencies for OVA builds +deps-ova: + hack/ensure-ansible.sh + hack/ensure-ansible-windows.sh + hack/ensure-packer.sh + hack/ensure-goss.sh + hack/ensure-ovftool.sh + +.PHONY: deps-qemu +deps-qemu: ## Installs/checks dependencies for QEMU builds +deps-qemu: + hack/ensure-ansible.sh + hack/ensure-packer.sh + hack/ensure-goss.sh + +.PHONY: deps-raw +deps-raw: ## Installs/checks dependencies for RAW builds +deps-raw: + hack/ensure-ansible.sh + hack/ensure-packer.sh + hack/ensure-goss.sh + +.PHONY: deps-oci +deps-oci: ## Installs/checks dependencies for OCI builds +deps-oci: + hack/ensure-ansible.sh + hack/ensure-packer.sh + packer plugins install github.com/hashicorp/oracle + +.PHONY: deps-vbox +deps-vbox: ## Installs/checks dependencies for VirtualBox builds +deps-vbox: + hack/ensure-ansible.sh + hack/ensure-ansible-windows.sh + hack/ensure-packer.sh + hack/ensure-goss.sh + +.PHONY: deps-powervs +deps-powervs: +deps-powervs: + hack/ensure-ansible.sh + hack/ensure-packer.sh + hack/ensure-goss.sh + hack/ensure-powervs.sh + +.PHONY: deps-ignition +deps-ignition: ## Installs/checks dependencies for generating Ignition files +deps-ignition: + hack/ensure-jq.sh + hack/ensure-ct.sh + +.PHONY: deps-nutanix +deps-nutanix: ## Installs/checks dependencies for Nutanix builds +deps-nutanix: + hack/ensure-ansible.sh + hack/ensure-packer.sh + hack/ensure-goss.sh + +## -------------------------------------- +## Container variables +## -------------------------------------- +REGISTRY ?= gcr.io/$(shell gcloud config get-value project) +STAGING_REGISTRY := gcr.io/k8s-staging-scl-image-builder +IMAGE_NAME ?= cluster-node-image-builder +CONTROLLER_IMG ?= $(REGISTRY)/$(IMAGE_NAME) +TAG ?= dev +ARCH ?= amd64 +BASE_IMAGE ?= docker.io/library/ubuntu:focal + +## -------------------------------------- +## Packer flags +## -------------------------------------- + +# Set Packer color to true if not already set in env variables +# Only valid for builds +ifneq (,$(findstring build-, $(MAKECMDGOALS))) + # A build target + PACKER_COLOR ?= true + PACKER_FLAGS += -color=$(PACKER_COLOR) +endif + +# If FOREGROUND=1 then Packer will set headless to false, causing local builds +# to build in the foreground, with a UI. This is very useful when debugging new +# platforms or issues with existing ones. +ifeq (1,$(strip $(FOREGROUND))) +PACKER_FLAGS += -var="headless=false" +endif + +# If ON_ERROR_ASK=1 then Packer will set -on-error to ask, causing the Packer +# build to pause when any error happens, instead of simply exiting. This is +# useful when debugging unknown issues logging into the remote machine via ssh. +ifeq (1,$(strip $(ON_ERROR_ASK))) +PACKER_FLAGS += -on-error=ask +endif + +# ssh_private_key_file and ssh_public_key are needed to pass ssh keypair +# from its host to the packer guest machine, so boot managers like ignition +# could make use of the key in its config. +# SSH_PRIVATE_KEY_FILE is name of the file that contains the private key. +# SSH_PUBLIC_KEY_FILE is name of the file that contains the public key. +ifneq (,$(strip $(SSH_PRIVATE_KEY_FILE))) +PACKER_FLAGS += -var ssh_private_key_file="$(SSH_PRIVATE_KEY_FILE)" +endif + +ifneq (,$(strip $(SSH_PUBLIC_KEY_FILE))) +PACKER_FLAGS += -var ssh_public_key="$(shell cat ${SSH_PUBLIC_KEY_FILE})" +endif + +# Since OpenSSH 9.0+ 'scp' uses SFTP protocol instead of legacy SCP protocol, which causes building errors like: +# +# bash: line 1: /usr/lib/sftp-server: No such file or directory\nscp: Connection closed\r\n"" +# +# However, -O option is not available in older OpenSSH version, so we cannot always set it as an option to use. +# To provide better out-of-the-box experience for users with newer versions of OpenSSH, we conditionally ensure +# -O is used when used OpenSSH version requires it. +# +# See https://github.com/kubernetes-sigs/image-builder/issues/859 and +# https://github.com/hashicorp/packer-plugin-ansible/issues/100 for more details. +ifeq ($(shell test $$(ssh -V 2>&1 | cut -d _ -f2 | cut -d . -f1) -ge 9; echo $$?),0) + # Use ?= to retain possible existing value of environment variable. If it is already declared, we assume user to be + # aware of OpenSSH version they use and it is up to the user to specify "-O" option as well if needed. + export ANSIBLE_SCP_EXTRA_ARGS ?= "-O" +endif + +# If DEBUG=1 then Packer will set -debug, enabling debug mode for builds, providing +# more verbose logging +ifeq (1,$(strip $(DEBUG))) +PACKER_FLAGS += -debug +endif + +# We want the var files passed to Packer to have a specific order, because the +# precenence of the variables they contain depends on the order. Files listed +# later on the CLI have higher precedence. We want the common var files found in +# packer/config to be listed first, then the var files that specific to the +# provider, then any user-supplied var files so that a user can override what +# they need to. + +# A list of variable files given to Packer to configure things like the versions +# of Kubernetes, CNI, and ContainerD to install. Any additional files from the +# environment are appended. +COMMON_NODE_VAR_FILES := packer/config/kubernetes.json \ + packer/config/cni.json \ + packer/config/containerd.json \ + packer/config/wasm-shims.json \ + packer/config/ansible-args.json \ + packer/config/goss-args.json \ + packer/config/common.json \ + packer/config/additional_components.json + +COMMON_WINDOWS_VAR_FILES := packer/config/kubernetes.json \ + packer/config/windows/kubernetes.json \ + packer/config/containerd.json \ + packer/config/windows/containerd.json \ + packer/config/windows/docker.json \ + packer/config/windows/ansible-args-windows.json \ + packer/config/common.json \ + packer/config/windows/common.json \ + packer/config/windows/cloudbase-init.json \ + packer/config/goss-args.json \ + packer/config/additional_components.json + +COMMON_POWERVS_VAR_FILES := packer/config/kubernetes.json \ + packer/config/ppc64le/kubernetes.json \ + packer/config/cni.json \ + packer/config/ppc64le/cni.json \ + packer/config/containerd.json \ + packer/config/ppc64le/containerd.json \ + packer/config/ansible-args.json \ + packer/config/goss-args.json \ + packer/config/common.json \ + packer/config/ppc64le/common.json \ + packer/config/additional_components.json + +# Initialize a list of flags to pass to Packer. This includes any existing flags +# specified by PACKER_FLAGS, as well as prefixing the list with the variable +# files from COMMON_VAR_FILES, with each file prefixed by -var-file=. +# +# Any existing values from PACKER_FLAGS take precendence over variable files. +PACKER_NODE_FLAGS := $(foreach f,$(abspath $(COMMON_NODE_VAR_FILES)),-var-file="$(f)" ) \ + $(PACKER_FLAGS) +ABSOLUTE_PACKER_VAR_FILES := $(foreach f,$(abspath $(PACKER_VAR_FILES)),-var-file="$(f)" ) +PACKER_WINDOWS_NODE_FLAGS := $(foreach f,$(abspath $(COMMON_WINDOWS_VAR_FILES)),-var-file="$(f)" ) \ + $(PACKER_FLAGS) +PACKER_POWERVS_NODE_FLAGS := $(foreach f,$(abspath $(COMMON_POWERVS_VAR_FILES)),-var-file="$(f)" ) \ + $(PACKER_FLAGS) + +## -------------------------------------- +## Platform and version combinations +## -------------------------------------- +CENTOS_VERSIONS := centos-7 +FLATCAR_VERSIONS := flatcar +PHOTON_VERSIONS := photon-3 photon-4 +RHEL_VERSIONS := rhel-7 rhel-8 +ROCKYLINUX_VERSIONS := rockylinux-8 +UBUNTU_VERSIONS := ubuntu-1804 ubuntu-2004 ubuntu-2004-efi ubuntu-2204 +WINDOWS_VERSIONS := windows-2019 windows-2004 windows-2022 + +# Set Flatcar Container Linux channel and version if not supplied +FLATCAR_CHANNEL ?= stable +FLATCAR_VERSION ?= current +ifeq ($(FLATCAR_VERSION),current) +override FLATCAR_VERSION := $(shell hack/image-grok-latest-flatcar-version.sh $(FLATCAR_CHANNEL)) +endif + +export FLATCAR_CHANNEL FLATCAR_VERSION + +PLATFORMS_AND_VERSIONS := $(CENTOS_VERSIONS) \ + $(PHOTON_VERSIONS) \ + $(RHEL_VERSIONS) \ + $(ROCKYLINUX_VERSIONS) \ + $(UBUNTU_VERSIONS) \ + $(FLATCAR_VERSIONS) \ + $(WINDOWS_VERSIONS) + +NODE_OVA_LOCAL_BUILD_NAMES := $(addprefix node-ova-local-,$(PLATFORMS_AND_VERSIONS)) +NODE_OVA_LOCAL_VMX_BUILD_NAMES := $(addprefix node-ova-local-vmx-,$(PLATFORMS_AND_VERSIONS)) +NODE_OVA_LOCAL_BASE_BUILD_NAMES := $(addprefix node-ova-local-base-,$(PLATFORMS_AND_VERSIONS)) +NODE_OVA_VSPHERE_BUILD_NAMES := $(addprefix node-ova-vsphere-,$(PLATFORMS_AND_VERSIONS)) +NODE_OVA_VSPHERE_BASE_BUILD_NAMES := $(addprefix node-ova-vsphere-base-,$(PLATFORMS_AND_VERSIONS)) +NODE_OVA_VSPHERE_CLONE_BUILD_NAMES := $(addprefix node-ova-vsphere-clone-,$(PLATFORMS_AND_VERSIONS)) + +AMI_BUILD_NAMES ?= ami-centos-7 ami-ubuntu-1804 ami-ubuntu-2004 ami-ubuntu-2204 ami-amazon-2 ami-flatcar ami-windows-2019 ami-windows-2004 ami-rockylinux-8 ami-rhel-8 +GCE_BUILD_NAMES ?= gce-ubuntu-1804 gce-ubuntu-2004 gce-ubuntu-2204 + +# Make needs these lists to be space delimited, no quotes +VHD_TARGETS := $(shell grep VHD_TARGETS azure_targets.sh | sed 's/VHD_TARGETS=//' | tr -d \") +SIG_TARGETS := $(shell grep SIG_TARGETS azure_targets.sh | sed 's/SIG_TARGETS=//' | tr -d \") +SIG_GEN2_TARGETS := $(shell grep SIG_GEN2_TARGETS azure_targets.sh | sed 's/SIG_GEN2_TARGETS=//' | tr -d \") +AZURE_BUILD_VHD_NAMES ?= $(addprefix azure-vhd-,$(VHD_TARGETS)) +AZURE_BUILD_SIG_NAMES ?= $(addprefix azure-sig-,$(SIG_TARGETS)) +AZURE_BUILD_SIG_GEN2_NAMES ?= $(addsuffix -gen2,$(addprefix azure-sig-,$(SIG_GEN2_TARGETS))) + +OCI_BUILD_NAMES ?= oci-ubuntu-1804 oci-ubuntu-2004 oci-ubuntu-2204 oci-oracle-linux-8 oci-oracle-linux-9 oci-windows-2019 oci-windows-2022 + +DO_BUILD_NAMES ?= do-centos-7 do-ubuntu-1804 do-ubuntu-2004 + +OSC_BUILD_NAMES ?= osc-ubuntu-2004 + +QEMU_BUILD_NAMES ?= qemu-ubuntu-1804 qemu-ubuntu-2004 qemu-ubuntu-2204 qemu-centos-7 qemu-ubuntu-2004-efi qemu-rhel-8 qemu-rockylinux-8 qemu-flatcar +QEMU_KUBEVIRT_BUILD_NAMES := $(addprefix kubevirt-,$(QEMU_BUILD_NAMES)) + +RAW_BUILD_NAMES ?= raw-ubuntu-1804 raw-ubuntu-2004 raw-ubuntu-2004-efi raw-flatcar +VBOX_BUILD_NAMES ?= vbox-windows-2019 + +POWERVS_BUILD_NAMES ?= powervs-centos-8 + +NUTANIX_BUILD_NAMES ?= nutanix-ubuntu-2004 nutanix-ubuntu-2204 nutanix-rockylinux-8 nutanix-rockylinux-9 nutanix-flatcar nutanix-windows-2022 + +## -------------------------------------- +## Dynamic build targets +## -------------------------------------- +NODE_OVA_LOCAL_BUILD_TARGETS := $(addprefix build-,$(NODE_OVA_LOCAL_BUILD_NAMES)) +NODE_OVA_LOCAL_VMX_BUILD_TARGETS := $(addprefix build-,$(NODE_OVA_LOCAL_VMX_BUILD_NAMES)) +NODE_OVA_LOCAL_BASE_BUILD_TARGETS := $(addprefix build-,$(NODE_OVA_LOCAL_BASE_BUILD_NAMES)) +NODE_OVA_LOCAL_VALIDATE_TARGETS := $(addprefix validate-,$(NODE_OVA_LOCAL_BUILD_NAMES)) +NODE_OVA_VSPHERE_BUILD_TARGETS := $(addprefix build-,$(NODE_OVA_VSPHERE_BUILD_NAMES)) +NODE_OVA_VSPHERE_BASE_BUILD_TARGETS := $(addprefix build-,$(NODE_OVA_VSPHERE_BASE_BUILD_NAMES)) +NODE_OVA_VSPHERE_CLONE_BUILD_TARGETS := $(addprefix build-,$(NODE_OVA_VSPHERE_CLONE_BUILD_NAMES)) +AMI_BUILD_TARGETS := $(addprefix build-,$(AMI_BUILD_NAMES)) +AMI_VALIDATE_TARGETS := $(addprefix validate-,$(AMI_BUILD_NAMES)) +GCE_BUILD_TARGETS := $(addprefix build-,$(GCE_BUILD_NAMES)) +GCE_VALIDATE_TARGETS := $(addprefix validate-,$(GCE_BUILD_NAMES)) +AZURE_BUILD_VHD_TARGETS := $(addprefix build-,$(AZURE_BUILD_VHD_NAMES)) +AZURE_VALIDATE_VHD_TARGETS := $(addprefix validate-,$(AZURE_BUILD_VHD_NAMES)) +AZURE_BUILD_SIG_TARGETS := $(addprefix build-,$(AZURE_BUILD_SIG_NAMES)) +AZURE_BUILD_SIG_GEN2_TARGETS := $(addprefix build-,$(AZURE_BUILD_SIG_GEN2_NAMES)) +AZURE_VALIDATE_SIG_TARGETS := $(addprefix validate-,$(AZURE_BUILD_SIG_NAMES)) +AZURE_VALIDATE_SIG_GEN2_TARGETS := $(addprefix validate-,$(AZURE_BUILD_SIG_GEN2_NAMES)) +DO_BUILD_TARGETS := $(addprefix build-,$(DO_BUILD_NAMES)) +DO_VALIDATE_TARGETS := $(addprefix validate-,$(DO_BUILD_NAMES)) +QEMU_BUILD_TARGETS := $(addprefix build-,$(QEMU_BUILD_NAMES)) +QEMU_VALIDATE_TARGETS := $(addprefix validate-,$(QEMU_BUILD_NAMES)) +QEMU_KUBEVIRT_BUILD_TARGETS := $(addprefix build-,$(QEMU_KUBEVIRT_BUILD_NAMES)) +QEMU_KUBEVIRT_VALIDATE_TARGETS := $(addprefix validate-,$(QEMU_KUBEVIRT_BUILD_NAMES)) +RAW_BUILD_TARGETS := $(addprefix build-,$(RAW_BUILD_NAMES)) +RAW_VALIDATE_TARGETS := $(addprefix validate-,$(RAW_BUILD_NAMES)) +OCI_BUILD_TARGETS := $(addprefix build-,$(OCI_BUILD_NAMES)) +OCI_VALIDATE_TARGETS := $(addprefix validate-,$(OCI_BUILD_NAMES)) +OSC_BUILD_TARGETS := $(addprefix build-,$(OSC_BUILD_NAMES)) +OSC_VALIDATE_TARGETS := $(addprefix validate-,$(OSC_BUILD_NAMES)) +VBOX_BUILD_TARGETS := $(addprefix build-,$(VBOX_BUILD_NAMES)) +VBOX_VALIDATE_TARGETS := $(addprefix validate-,$(VBOX_BUILD_NAMES)) +POWERVS_BUILD_TARGETS := $(addprefix build-,$(POWERVS_BUILD_NAMES)) +POWERVS_VALIDATE_TARGETS := $(addprefix validate-,$(POWERVS_BUILD_NAMES)) +NUTANIX_BUILD_TARGETS := $(addprefix build-,$(NUTANIX_BUILD_NAMES)) +NUTANIX_VALIDATE_TARGETS := $(addprefix validate-,$(NUTANIX_BUILD_NAMES)) + +.PHONY: $(NODE_OVA_LOCAL_BUILD_TARGETS) +$(NODE_OVA_LOCAL_BUILD_TARGETS): deps-ova + # This uses a packer file builder to input unattend variables into a json file to be consumed by the python script before running the vmware-iso provisioner + $(if $(findstring windows,$@),packer build $(PACKER_WINDOWS_NODE_FLAGS) -var-file="packer/ova/packer-common.json" -var-file="$(abspath packer/ova/$(subst build-node-ova-local-,,$@).json)" -only=file $(ABSOLUTE_PACKER_VAR_FILES) packer/ova/packer-windows.json,) + $(if $(findstring windows,$@),hack/windows-ova-unattend.py --unattend-file='./packer/ova/windows/$(subst build-node-ova-local-,,$@)/autounattend.xml',) + packer build $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="packer/ova/packer-common.json" -var-file="$(abspath packer/ova/$(subst build-node-ova-local-,,$@).json)" -except=vsphere -only=vmware-iso $(ABSOLUTE_PACKER_VAR_FILES) packer/ova/packer-$(if $(findstring windows,$@),windows,node).json + +.PHONY: $(NODE_OVA_LOCAL_VALIDATE_TARGETS) +$(NODE_OVA_LOCAL_VALIDATE_TARGETS): deps-ova + packer validate $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="packer/ova/packer-common.json" -var-file="$(abspath packer/ova/$(subst validate-node-ova-local-,,$@).json)" -except=vsphere -only=vmware-iso $(ABSOLUTE_PACKER_VAR_FILES) packer/ova/packer-$(if $(findstring windows,$@),windows,node).json + +.PHONY: $(NODE_OVA_LOCAL_VMX_BUILD_TARGETS) +$(NODE_OVA_LOCAL_VMX_BUILD_TARGETS): deps-ova + packer build $(PACKER_NODE_FLAGS) -var-file="packer/ova/packer-common.json" -var-file="$(abspath packer/ova/$(subst build-node-ova-local-vmx-,,$@).json)" -var-file="packer/ova/vmx.json" -except=vsphere -except=vmware-iso -only=vmware-vmx $(ABSOLUTE_PACKER_VAR_FILES) packer/ova/packer-node.json + +.PHONY: $(NODE_OVA_LOCAL_BASE_BUILD_TARGETS) +$(NODE_OVA_LOCAL_BASE_BUILD_TARGETS): deps-ova + packer build $(PACKER_NODE_FLAGS) -var-file="packer/ova/packer-common.json" -var-file="$(abspath packer/ova/$(subst build-node-ova-local-base-,,$@).json)" -except=vsphere -except=vmware-iso -except=vmware-vmx -only=vmware-iso-base $(ABSOLUTE_PACKER_VAR_FILES) packer/ova/packer-node.json + +.PHONY: $(NODE_OVA_VSPHERE_BUILD_TARGETS) +$(NODE_OVA_VSPHERE_BUILD_TARGETS): deps-ova + # This uses a packer file builder to input unattend variables into a json file to be consumed by the python script before running the vsphere provisioner + $(if $(findstring windows,$@),packer build $(PACKER_WINDOWS_NODE_FLAGS) -var-file="packer/ova/packer-common.json" -var-file="$(abspath packer/ova/$(subst build-node-ova-vsphere-,,$@).json)" -only=file $(ABSOLUTE_PACKER_VAR_FILES) packer/ova/packer-windows.json,) + $(if $(findstring windows,$@),hack/windows-ova-unattend.py --unattend-file='./packer/ova/windows/$(subst build-node-ova-vsphere-,,$@)/autounattend.xml',) + packer build $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="packer/ova/packer-common.json" -var-file="$(abspath packer/ova/$(subst build-node-ova-vsphere-,,$@).json)" -var-file="packer/ova/vsphere.json" -except=local -only=vsphere-iso $(ABSOLUTE_PACKER_VAR_FILES) -only=vsphere packer/ova/packer-$(if $(findstring windows,$@),windows,node).json + +.PHONY: $(NODE_OVA_VSPHERE_BASE_BUILD_TARGETS) +$(NODE_OVA_VSPHERE_BASE_BUILD_TARGETS): deps-ova + packer build $(PACKER_NODE_FLAGS) -var-file="packer/ova/packer-common.json" -var-file="$(abspath packer/ova/$(subst build-node-ova-vsphere-base-,,$@).json)" -var-file="packer/ova/vsphere.json" -except=local -except=manifest -except=vsphere -only=vsphere-iso-base $(ABSOLUTE_PACKER_VAR_FILES) packer/ova/packer-node.json + +.PHONY: $(NODE_OVA_VSPHERE_CLONE_BUILD_TARGETS) +$(NODE_OVA_VSPHERE_CLONE_BUILD_TARGETS): deps-ova + packer build $(PACKER_NODE_FLAGS) -var-file="packer/ova/packer-common.json" -var-file="$(abspath packer/ova/$(subst build-node-ova-vsphere-clone-,,$@).json)" -var-file="packer/ova/vsphere.json" -except=local -only=vsphere-clone $(ABSOLUTE_PACKER_VAR_FILES) packer/ova/packer-node.json + +.PHONY: $(AMI_BUILD_TARGETS) +$(AMI_BUILD_TARGETS): deps-ami + packer build $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="$(abspath packer/ami/$(subst build-ami-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/ami/packer$(if $(findstring windows,$@),-windows,).json + +.PHONY: $(AMI_VALIDATE_TARGETS) +$(AMI_VALIDATE_TARGETS): deps-ami + packer validate $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="$(abspath packer/ami/$(subst validate-ami-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/ami/packer$(if $(findstring windows,$@),-windows,).json + +.PHONY: $(GCE_BUILD_TARGETS) +$(GCE_BUILD_TARGETS): deps-gce + packer build $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/gce/$(subst build-gce-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/gce/packer.json + +.PHONY: $(GCE_VALIDATE_TARGETS) +$(GCE_VALIDATE_TARGETS): deps-gce + packer validate $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/gce/$(subst validate-gce-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/gce/packer.json + +.PHONY: $(AZURE_BUILD_VHD_TARGETS) +$(AZURE_BUILD_VHD_TARGETS): deps-azure + . $(abspath packer/azure/scripts/init-vhd.sh) && packer build $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="$(abspath packer/azure/azure-config.json)" -var-file="$(abspath packer/azure/azure-vhd.json)" -var-file="$(abspath packer/azure/$(subst build-azure-vhd-,,$@).json)" -only="$(subst build-azure-,,$@)" $(ABSOLUTE_PACKER_VAR_FILES) packer/azure/packer$(findstring -windows,$@).json + +.PHONY: $(AZURE_VALIDATE_VHD_TARGETS) +$(AZURE_VALIDATE_VHD_TARGETS): deps-azure + packer validate $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="$(abspath packer/azure/azure-config.json)" -var-file="$(abspath packer/azure/azure-vhd.json)" -var-file="$(abspath packer/azure/$(subst validate-azure-vhd-,,$@).json)" -only="$(subst validate-azure-,,$@)" $(ABSOLUTE_PACKER_VAR_FILES) packer/azure/packer$(findstring -windows,$@).json + +.PHONY: $(AZURE_BUILD_SIG_TARGETS) +$(AZURE_BUILD_SIG_TARGETS): deps-azure + . $(abspath packer/azure/scripts/init-sig.sh) $(subst build-azure-sig-,,$@) && packer build $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="$(abspath packer/azure/azure-config.json)" -var-file="$(abspath packer/azure/azure-sig.json)" -var-file="$(abspath packer/azure/$(subst build-azure-sig-,,$@).json)" -only="$(subst build-azure-,,$@)" $(ABSOLUTE_PACKER_VAR_FILES) packer/azure/packer$(findstring -windows,$@).json + +.PHONY: $(AZURE_BUILD_SIG_GEN2_TARGETS) +$(AZURE_BUILD_SIG_GEN2_TARGETS): deps-azure + . $(abspath packer/azure/scripts/init-sig.sh) $(subst build-azure-sig-,,$@) && packer build $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="$(abspath packer/azure/azure-config.json)" -var-file="$(abspath packer/azure/azure-sig-gen2.json)" -var-file="$(abspath packer/azure/$(subst build-azure-sig-,,$@).json)" -only="$(subst build-azure-,,$@)" $(ABSOLUTE_PACKER_VAR_FILES) packer/azure/packer$(findstring -windows,$@).json + +.PHONY: $(AZURE_VALIDATE_SIG_TARGETS) +$(AZURE_VALIDATE_SIG_TARGETS): deps-azure + packer validate $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="$(abspath packer/azure/azure-config.json)" -var-file="$(abspath packer/azure/azure-sig.json)" -var-file="$(abspath packer/azure/$(subst validate-azure-sig-,,$@).json)" -only="$(subst validate-azure-,,$@)" $(ABSOLUTE_PACKER_VAR_FILES) packer/azure/packer$(findstring -windows,$@).json + +.PHONY: $(AZURE_VALIDATE_SIG_GEN2_TARGETS) +$(AZURE_VALIDATE_SIG_GEN2_TARGETS): deps-azure + packer validate $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="$(abspath packer/azure/azure-config.json)" -var-file="$(abspath packer/azure/azure-sig-gen2.json)" -var-file="$(abspath packer/azure/$(subst validate-azure-sig-,,$@).json)" -only="$(subst validate-azure-,,$@)" $(ABSOLUTE_PACKER_VAR_FILES) packer/azure/packer$(findstring windows,$@).json + +.PHONY: $(DO_BUILD_TARGETS) +$(DO_BUILD_TARGETS): deps-do + packer build $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/digitalocean/$(subst build-do-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/digitalocean/packer.json + +.PHONY: $(DO_VALIDATE_TARGETS) +$(DO_VALIDATE_TARGETS): deps-do + packer validate $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/digitalocean/$(subst validate-do-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/digitalocean/packer.json + +.PHONY: $(QEMU_BUILD_TARGETS) +$(QEMU_BUILD_TARGETS): deps-qemu + packer build $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/qemu/$(subst build-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/qemu/packer.json + +.PHONY: $(QEMU_VALIDATE_TARGETS) +$(QEMU_VALIDATE_TARGETS): deps-qemu + packer validate $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/qemu/$(subst validate-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/qemu/packer.json + +.PHONY: $(QEMU_KUBEVIRT_BUILD_TARGETS) +$(QEMU_KUBEVIRT_BUILD_TARGETS): deps-qemu + packer build $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/qemu/$(subst build-kubevirt-,,$@).json)" --var 'kubevirt=true' $(ABSOLUTE_PACKER_VAR_FILES) packer/qemu/packer.json + +.PHONY: $(QEMU_KUBEVIRT_VALIDATE_TARGETS) +$(QEMU_KUBEVIRT_VALIDATE_TARGETS): deps-qemu + packer validate $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/qemu/$(subst validate-kubevirt-,,$@).json)" --var 'kubevirt=true' $(ABSOLUTE_PACKER_VAR_FILES) packer/qemu/packer.json + +.PHONY: $(RAW_BUILD_TARGETS) +$(RAW_BUILD_TARGETS): deps-raw + packer build $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/raw/$(subst build-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/raw/packer.json + +.PHONY: $(RAW_VALIDATE_TARGETS) +$(RAW_VALIDATE_TARGETS): deps-raw + packer validate $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/raw/$(subst validate-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/raw/packer.json + +.PHONY: $(OCI_BUILD_TARGETS) +$(OCI_BUILD_TARGETS): deps-oci + $(if $(findstring windows,$@),./packer/oci/scripts/set_bootstrap.sh,) + packer build $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="$(abspath packer/oci/$(subst build-oci-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/oci/packer$(findstring -windows,$@).json + $(if $(findstring windows,$@),./packer/oci/scripts/unset_bootstrap.sh,) + +.PHONY: $(OCI_VALIDATE_TARGETS) +$(OCI_VALIDATE_TARGETS): deps-oci + packer validate $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/oci/$(subst validate-oci-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/oci/packer.json + +.PHONY: $(OSC_BUILD_TARGETS) +$(OSC_BUILD_TARGETS): deps-osc + packer build $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/outscale/$(subst build-osc-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/outscale/packer.json + +.PHONY: $(OSC_VALIDATE_TARGETS) +$(OSC_VALIDATE_TARGETS): deps-osc + packer validate $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/outscale/$(subst validate-osc-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/outscale/packer.json + +.PHONY: $(VBOX_BUILD_TARGETS) +$(VBOX_BUILD_TARGETS): deps-vbox + packer build $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="packer/vbox/packer-common.json" -var-file="$(abspath packer/vbox/$(subst build-vbox-,,$@).json)" -only=virtualbox-iso $(ABSOLUTE_PACKER_VAR_FILES) packer/vbox/packer-$(if $(findstring windows,$@),windows).json + +.PHONY: $(VBOX_VALIDATE_TARGETS) +$(VBOX_VALIDATE_TARGETS): deps-vbox + packer validate $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="packer/vbox/packer-common.json" -var-file="$(abspath packer/vbox/$(subst validate-vbox-,,$@).json)" -only=virtualbox-iso $(ABSOLUTE_PACKER_VAR_FILES) packer/vbox/packer-$(if $(findstring windows,$@),windows).json + +.PHONY: $(POWERVS_BUILD_TARGETS) +$(POWERVS_BUILD_TARGETS): deps-powervs + packer build $(PACKER_POWERVS_NODE_FLAGS) -var-file="$(abspath packer/powervs/$(subst build-powervs-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) -except=flatcar packer/powervs/packer.json + +.PHONY: $(POWERVS_VALIDATE_TARGETS) +$(POWERVS_VALIDATE_TARGETS): deps-powervs + packer validate $(PACKER_POWERVS_NODE_FLAGS) -var-file="$(abspath packer/powervs/$(subst validate-powervs-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) -except=flatcar packer/powervs/packer.json + +.PHONY: $(NUTANIX_BUILD_TARGETS) +$(NUTANIX_BUILD_TARGETS): deps-nutanix + packer init packer/nutanix/config.pkr.hcl + packer build $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="packer/nutanix/nutanix.json" -var-file="$(abspath packer/nutanix/$(subst build-nutanix-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/nutanix/packer$(if $(findstring windows,$@),-windows,).json + +.PHONY: $(NUTANIX_VALIDATE_TARGETS) +$(NUTANIX_VALIDATE_TARGETS): deps-nutanix + packer init packer/nutanix/config.pkr.hcl + packer validate $(if $(findstring windows,$@),$(PACKER_WINDOWS_NODE_FLAGS),$(PACKER_NODE_FLAGS)) -var-file="packer/nutanix/nutanix.json" -var-file="$(abspath packer/nutanix/$(subst validate-nutanix-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/nutanix/packer$(if $(findstring windows,$@),-windows,).json + +## -------------------------------------- +## Dynamic clean targets +## -------------------------------------- +NODE_OVA_LOCAL_CLEAN_TARGETS := $(subst build-,clean-,$(NODE_OVA_LOCAL_BUILD_TARGETS)) +.PHONY: $(NODE_OVA_LOCAL_CLEAN_TARGETS) +$(NODE_OVA_LOCAL_CLEAN_TARGETS): + rm -fr output/$(subst clean-node-ova-local-,,$@)-kube* + +QEMU_CLEAN_TARGETS := $(subst build-,clean-,$(QEMU_BUILD_TARGETS)) +.PHONY: $(QEMU_CLEAN_TARGETS) +$(QEMU_CLEAN_TARGETS): + rm -fr output/$(subst clean-qemu-,,$@)-kube* + +RAW_CLEAN_TARGETS := $(subst build-,clean-,$(RAW_BUILD_TARGETS)) +.PHONY: $(RAW_CLEAN_TARGETS) +$(RAW_CLEAN_TARGETS): + rm -fr output/$(subst clean-raw-,,$@)-kube* + +VBOX_CLEAN_TARGETS := $(subst build-,clean-,$(VBOX_BUILD_TARGETS)) +.PHONY: $(VBOX_CLEAN_TARGETS) +$(VBOX_CLEAN_TARGETS): + rm -fr output/$(subst clean-vbox-,,$@)-kube* + +## -------------------------------------- +## Document dynamic build targets +## -------------------------------------- +##@ Builds +build-ami-amazon-2: ## Builds Amazon-2 Linux AMI +build-ami-centos-7: ## Builds CentOS 7 AMI +build-ami-ubuntu-1804: ## Builds Ubuntu 18.04 AMI +build-ami-ubuntu-2004: ## Builds Ubuntu 20.04 AMI +build-ami-ubuntu-2204: ## Builds Ubuntu 22.04 AMI +build-ami-rockylinux-8: ## Builds RockyLinux 8 AMI +build-ami-rhel-8: ## Builds RHEL-8 AMI +build-ami-flatcar: ## Builds Flatcar +build-ami-windows-2019: ## Build Windows Server 2019 AMI Packer config +build-ami-windows-2004: ## Build Windows Server 2004 SAC AMI Packer config +build-ami-all: $(AMI_BUILD_TARGETS) ## Builds all AMIs + +build-azure-sig-ubuntu-1804: ## Builds Ubuntu 18.04 Azure managed image in Shared Image Gallery +build-azure-sig-ubuntu-2004: ## Builds Ubuntu 20.04 Azure managed image in Shared Image Gallery +build-azure-sig-ubuntu-2204: ## Builds Ubuntu 22.04 Azure managed image in Shared Image Gallery +build-azure-sig-centos-7: ## Builds CentOS 7 Azure managed image in Shared Image Gallery +build-azure-sig-rhel-8: ## Builds RHEL 8 Azure managed image in Shared Image Gallery +build-azure-sig-windows-2019: ## Builds Windows Server 2019 Azure managed image in Shared Image Gallery +build-azure-sig-windows-2019-containerd: ## Builds Windows Server 2019 with containerd Azure managed image in Shared Image Gallery +build-azure-sig-windows-2022-containerd: ## Builds Windows Server 2022 with containerd Azure managed image in Shared Image Gallery +build-azure-sig-windows-2004: ## Builds Windows Server 2004 SAC Azure managed image in Shared Image Gallery +build-azure-vhd-ubuntu-1804: ## Builds Ubuntu 18.04 VHD image for Azure +build-azure-vhd-ubuntu-2004: ## Builds Ubuntu 20.04 VHD image for Azure +build-azure-vhd-ubuntu-2204: ## Builds Ubuntu 22.04 VHD image for Azure +build-azure-vhd-centos-7: ## Builds CentOS 7 VHD image for Azure +build-azure-vhd-rhel-8: ## Builds RHEL 8 VHD image for Azure +build-azure-vhd-windows-2019: ## Builds for Windows Server 2019 +build-azure-vhd-windows-2019-containerd: ## Builds for Windows Server 2019 with containerd +build-azure-vhd-windows-2022-containerd: ## Builds for Windows Server 2022 with containerd +build-azure-vhd-windows-2004: ## Builds for Windows Server 2004 SAC +build-azure-sig-centos-7-gen2: ## Builds CentOS Gen2 managed image in Shared Image Gallery +build-azure-sig-flatcar: ## Builds Flatcar Azure managed image in Shared Image Gallery +build-azure-sig-flatcar-gen2: ## Builds Flatcar Azure Gen2 managed image in Shared Image Gallery +build-azure-sig-ubuntu-1804-gen2: ## Builds Ubuntu 18.04 Gen2 managed image in Shared Image Gallery +build-azure-sig-ubuntu-2004-gen2: ## Builds Ubuntu 20.04 Gen2 managed image in Shared Image Gallery +build-azure-sig-ubuntu-2204-gen2: ## Builds Ubuntu 22.04 Gen2 managed image in Shared Image Gallery +build-azure-vhds: $(AZURE_BUILD_VHD_TARGETS) ## Builds all Azure VHDs +build-azure-sigs: $(AZURE_BUILD_SIG_TARGETS) $(AZURE_BUILD_SIG_GEN2_TARGETS) ## Builds all Azure Shared Image Gallery images + +build-do-ubuntu-1804: ## Builds Ubuntu 18.04 DigitalOcean Snapshot +build-do-ubuntu-2004: ## Builds Ubuntu 20.04 DigitalOcean Snapshot +build-do-centos-7: ## Builds Centos 7 DigitalOcean Snapshot +build-do-all: $(DO_BUILD_TARGETS) ## Builds all DigitalOcean Snapshot + +build-gce-ubuntu-1804: ## Builds the GCE ubuntu-1804 image +build-gce-ubuntu-2004: ## Builds the GCE ubuntu-2004 image +build-gce-ubuntu-2204: ## Builds the GCE ubuntu-2204 image +build-gce-all: $(GCE_BUILD_TARGETS) ## Builds all GCE image + +build-node-ova-local-centos-7: ## Builds CentOS 7 Node OVA w local hypervisor +build-node-ova-local-flatcar: ## Builds Flatcar stable Node OVA w local hypervisor +build-node-ova-local-photon-3: ## Builds Photon 3 Node OVA w local hypervisor +build-node-ova-local-photon-4: ## Builds Photon 4 Node OVA w local hypervisor +build-node-ova-local-rhel-7: ## Builds RHEL 7 Node OVA w local hypervisor +build-node-ova-local-rhel-8: ## Builds RHEL 8 Node OVA w local hypervisor +build-node-ova-local-rockylinux-8: ## Builds RockyLinux 8 Node OVA w local hypervisor +build-node-ova-local-ubuntu-1804: ## Builds Ubuntu 18.04 Node OVA w local hypervisor +build-node-ova-local-ubuntu-2004: ## Builds Ubuntu 20.04 Node OVA w local hypervisor +build-node-ova-local-windows-2019: ## Builds for Windows Server 2019 Node OVA w local hypervisor +build-node-ova-local-windows-2004: ## Builds for Windows Server 2004 SAC Node OVA w local hypervisor +build-node-ova-local-all: $(NODE_OVA_LOCAL_BUILD_TARGETS) ## Builds all Node OVAs w local hypervisor + +build-node-ova-vsphere-centos-7: ## Builds CentOS 7 Node OVA and template on vSphere +build-node-ova-vsphere-flatcar: ## Builds Flatcar stable Node OVA and template on vSphere +build-node-ova-vsphere-photon-3: ## Builds Photon 3 Node OVA and template on vSphere +build-node-ova-vsphere-photon-4: ## Builds Photon 4 Node OVA and template on vSphere +build-node-ova-vsphere-rhel-7: ## Builds RHEL 7 Node OVA and template on vSphere +build-node-ova-vsphere-rhel-8: ## Builds RHEL 8 Node OVA and template on vSphere +build-node-ova-vsphere-rockylinux-8: ## Builds RockyLinux 8 Node OVA and template on vSphere +build-node-ova-vsphere-ubuntu-1804: ## Builds Ubuntu 18.04 Node OVA and template on vSphere +build-node-ova-vsphere-ubuntu-2004: ## Builds Ubuntu 20.04 Node OVA and template on vSphere +build-node-ova-vsphere-ubuntu-2204: ## Builds Ubuntu 22.04 Node OVA and template on vSphere +build-node-ova-vsphere-windows-2019: ## Builds for Windows Server 2019 and template on vSphere +build-node-ova-vsphere-windows-2004: ## Builds for Windows Server 2004 SAC and template on vSphere +build-node-ova-vsphere-windows-2022: ## Builds for Windows Server 2022 template on vSphere +build-node-ova-vsphere-ubuntu-2004-efi: ## Builds Ubuntu 20.04 Node OVA and template on vSphere that EFI boots +build-node-ova-vsphere-all: $(NODE_OVA_VSPHERE_BUILD_TARGETS) ## Builds all Node OVAs and templates on vSphere + +build-node-ova-vsphere-clone-centos-7: ## Builds CentOS 7 Node OVA and template on vSphere +build-node-ova-vsphere-clone-photon-3: ## Builds Photon 3 Node OVA and template on vSphere +build-node-ova-vsphere-clone-photon-4: ## Builds Photon 4 Node OVA and template on vSphere +build-node-ova-vsphere-clone-rhel-7: ## Builds RHEL 7 Node OVA and template on vSphere +build-node-ova-vsphere-clone-rhel-8: ## Builds RHEL 8 Node OVA and template on vSphere +build-node-ova-vsphere-clone-rockylinux-8: ## Builds RockyLinux 8 Node OVA and template on vSphere +build-node-ova-vsphere-clone-ubuntu-1804: ## Builds Ubuntu 18.04 Node OVA and template on vSphere +build-node-ova-vsphere-clone-ubuntu-2004: ## Builds Ubuntu 20.04 Node OVA and template on vSphere +build-node-ova-vsphere-clone-ubuntu-2204: ## Builds Ubuntu 22.04 Node OVA and template on vSphere +build-node-ova-vsphere-clone-all: $(NODE_OVA_VSPHERE_CLONE_BUILD_TARGETS) ## Builds all Node OVAs and templates on vSphere + +build-node-ova-vsphere-base-centos-7: ## Builds base CentOS 7 Node OVA and template on vSphere +build-node-ova-vsphere-base-photon-3: ## Builds base Photon 3 Node OVA and template on vSphere +build-node-ova-vsphere-base-photon-4: ## Builds base Photon 4 Node OVA and template on vSphere +build-node-ova-vsphere-base-rhel-7: ## Builds base RHEL 7 Node OVA and template on vSphere +build-node-ova-vsphere-base-rhel-8: ## Builds base RHEL 8 Node OVA and template on vSphere +build-node-ova-vsphere-base-rockylinux-8: ## Builds base RockyLinux 8 Node OVA and template on vSphere +build-node-ova-vsphere-base-ubuntu-1804: ## Builds base Ubuntu 18.04 Node OVA and template on vSphere +build-node-ova-vsphere-base-ubuntu-2004: ## Builds base Ubuntu 20.04 Node OVA and template on vSphere +build-node-ova-vsphere-base-ubuntu-2204: ## Builds base Ubuntu 22.04 Node OVA and template on vSphere +build-node-ova-vsphere-base-all: $(NODE_OVA_VSPHERE_BASE_BUILD_TARGETS) ## Builds all base Node OVAs and templates on vSphere + +build-node-ova-local-vmx-photon-3: ## Builds Photon 3 Node OVA from VMX file w local hypervisor +build-node-ova-local-vmx-photon-4: ## Builds Photon 4 Node OVA from VMX file w local hypervisor +build-node-ova-local-vmx-centos-7: ## Builds Centos 7 Node OVA from VMX file w local hypervisor +build-node-ova-local-vmx-rhel-7: ## Builds RHEL 7 Node OVA from VMX file w local hypervisor +build-node-ova-local-vmx-rhel-8: ## Builds RHEL 8 Node OVA from VMX file w local hypervisor +build-node-ova-local-vmx-rockylinux-8: ## Builds RockyLinux 8 Node OVA from VMX file w local hypervisor +build-node-ova-local-vmx-ubuntu-1804: ## Builds Ubuntu 18.04 Node OVA from VMX file w local hypervisor +build-node-ova-local-vmx-ubuntu-2004: ## Builds Ubuntu 20.04 Node OVA from VMX file w local hypervisor + +build-node-ova-local-base-photon-3: ## Builds Photon 3 Base Node OVA w local hypervisor +build-node-ova-local-base-photon-4: ## Builds Photon 4 Base Node OVA w local hypervisor +build-node-ova-local-base-centos-7: ## Builds Centos 7 Base Node OVA w local hypervisor +build-node-ova-local-base-rhel-7: ## Builds RHEL 7 Base Node OVA w local hypervisor +build-node-ova-local-base-rhel-8: ## Builds RHEL 8 Base Node OVA w local hypervisor +build-node-ova-local-base-rockylinux-8: ## Builds RockyLinux 8 Base Node OVA w local hypervisor +build-node-ova-local-base-ubuntu-1804: ## Builds Ubuntu 18.04 Base Node OVA w local hypervisor +build-node-ova-local-base-ubuntu-2004: ## Builds Ubuntu 20.04 Base Node OVA w local hypervisor + +build-qemu-flatcar: ## Builds Flatcar QEMU image +build-qemu-ubuntu-1804: ## Builds Ubuntu 18.04 QEMU image +build-qemu-ubuntu-2004: ## Builds Ubuntu 20.04 QEMU image +build-qemu-ubuntu-2004-efi: ## Builds Ubuntu 20.04 QEMU image that EFI boots +build-qemu-ubuntu-2204: ## Builds Ubuntu 22.04 QEMU image +build-qemu-centos-7: ## Builds CentOS 7 QEMU image +build-qemu-rhel-8: ## Builds RHEL 8 QEMU image +build-qemu-rockylinux-8: ## Builds Rocky 8 QEMU image +build-qemu-all: $(QEMU_BUILD_TARGETS) ## Builds all Qemu images + +build-raw-flatcar: ## Builds Flatcar RAW image +build-raw-ubuntu-1804: ## Builds Ubuntu 18.04 RAW image +build-raw-ubuntu-2004: ## Builds Ubuntu 20.04 RAW image +build-raw-ubuntu-2004-efi: ## Builds Ubuntu 20.04 RAW image that EFI boots +build-raw-all: $(RAW_BUILD_TARGETS) ## Builds all RAW images + +build-oci-ubuntu-1804: ## Builds the OCI ubuntu-1804 image +build-oci-ubuntu-2004: ## Builds the OCI ubuntu-2004 image +build-oci-ubuntu-2204: ## Builds the OCI ubuntu-2204 image +build-oci-oracle-linux-8: ## Builds the OCI Oracle Linux 8.x image +build-oci-oracle-linux-9: ## Builds the OCI Oracle Linux 9.x image +build-oci-windows-2019: ## Builds the OCI Windows Server 2019 image +build-oci-windows-2022: ## Builds the OCI Windows Server 2022 image +build-oci-all: $(OCI_BUILD_TARGETS) ## Builds all OCI image + +build-osc-ubuntu-2004: ## Builds Ubuntu 20.04 Outscale Snapshot +build-osc-all: $(OSC_BUILD_TARGETS) ## Builds all Outscale Snapshot + +build-vbox-windows-2019: ## Builds for Windows Server 2019 Node VirtualBox w local hypervisor +build-vbox-all: $(VBOX_BUILD_TARGETS) ## Builds all Qemu images + +build-nutanix-ubuntu-2004: ## Builds the Nutanix ubuntu-2004 image +build-nutanix-ubuntu-2204: ## Builds the Nutanix ubuntu-2204 image +build-nutanix-rockylinux-8: ## Builds the Nutanix Rocky Linux 8 image +build-nutanix-rockylinux-9: ## Builds the Nutanix Rocky Linux 9 image +build-nutanix-flatcar: ## Builds the Nutanix Flatcar image +build-nutanix-windows-2022: ## Builds the Nutanix Windows 2022 image +build-nutanix-all: $(NUTANIX_BUILD_TARGETS) ## Builds all Nutanix image + +## -------------------------------------- +## Document dynamic validate targets +## -------------------------------------- +##@ Validate packer config +validate-ami-amazon-2: ## Validates Amazon-2 Linux AMI Packer config +validate-ami-centos-7: ## Validates CentOS 7 AMI Packer config +validate-ami-rockylinux-8: ## Validates RockyLinux 8 AMI Packer config +validate-ami-rhel-8: ## Validates RHEL-8 AMI Packer config +validate-ami-flatcar: ## Validates Flatcar AMI Packer config +validate-ami-ubuntu-1804: ## Validates Ubuntu 18.04 AMI Packer config +validate-ami-ubuntu-2004: ## Validates Ubuntu 20.04 AMI Packer config +validate-ami-ubuntu-2204: ## Validates Ubuntu 22.04 AMI Packer config +validate-ami-windows-2019: ## Validates Windows Server 2019 AMI Packer config +validate-ami-windows-2004: ## Validates Windows Server 2004 SAC AMI Packer config +validate-ami-all: $(AMI_VALIDATE_TARGETS) ## Validates all AMIs Packer config + +validate-azure-sig-centos-7: ## Validates CentOS 7 Azure managed image in Shared Image Gallery Packer config +validate-azure-sig-rhel-8: ## Validates RHEL 8 Azure managed image in Shared Image Gallery Packer config +validate-azure-sig-ubuntu-1804: ## Validates Ubuntu 18.04 Azure managed image in Shared Image Gallery Packer config +validate-azure-sig-ubuntu-2004: ## Validates Ubuntu 20.04 Azure managed image in Shared Image Gallery Packer config +validate-azure-sig-ubuntu-2204: ## Validates Ubuntu 22.04 Azure managed image in Shared Image Gallery Packer config +validate-azure-sig-windows-2019: ## Validate Windows Server 2019 Azure managed image in Shared Image Gallery Packer config +validate-azure-sig-windows-2019-containerd: ## Validate Windows Server 2019 with containerd Azure managed image in Shared Image Gallery Packer config +validate-azure-sig-windows-2022-containerd: ## Validate Windows Server 2022 with containerd Azure managed image in Shared Image Gallery Packer config +validate-azure-sig-windows-2004: ## Validate Windows Server 2004 SAC Azure managed image in Shared Image Gallery Packer config +validate-azure-vhd-centos-7: ## Validates CentOS 7 VHD image Azure Packer config +validate-azure-vhd-rhel-8: ## Validates RHEL 8 VHD image Azure Packer config +validate-azure-vhd-ubuntu-1804: ## Validates Ubuntu 18.04 VHD image Azure Packer config +validate-azure-vhd-ubuntu-2004: ## Validates Ubuntu 20.04 VHD image Azure Packer config +validate-azure-vhd-ubuntu-2204: ## Validates Ubuntu 22.04 VHD image Azure Packer config +validate-azure-vhd-windows-2019: ## Validate Windows Server 2019 VHD image Azure Packer config +validate-azure-vhd-windows-2019-containerd: ## Validate Windows Server 2019 VHD with containerd image Azure Packer config +validate-azure-vhd-windows-2022-containerd: ## Validate Windows Server 2022 VHD with containerd image Azure Packer config +validate-azure-vhd-windows-2004: ## Validate Windows Server 2004 SAC VHD image Azure Packer config +validate-azure-sig-centos-7-gen2: ## Validates CentOS 7 Azure managed image in Shared Image Gallery Packer config +validate-azure-sig-ubuntu-1804-gen2: ## Validates Ubuntu 18.04 Azure managed image in Shared Image Gallery Packer config +validate-azure-sig-ubuntu-2004-gen2: ## Validates Ubuntu 20.04 Azure managed image in Shared Image Gallery Packer config +validate-azure-sig-ubuntu-2204-gen2: ## Validates Ubuntu 22.04 Azure managed image in Shared Image Gallery Packer config +validate-azure-all: $(AZURE_VALIDATE_SIG_TARGETS) $(AZURE_VALIDATE_VHD_TARGETS) $(AZURE_VALIDATE_SIG_GEN2_TARGETS) ## Validates all images for Azure Packer config + +validate-do-ubuntu-1804: ## Validates Ubuntu 18.04 DigitalOcean Snapshot Packer config +validate-do-ubuntu-2004: ## Validates Ubuntu 20.04 DigitalOcean Snapshot Packer config +validate-do-centos-7: ## Validates Centos 7 DigitalOcean Snapshot Packer config +validate-do-all: $(DO_VALIDATE_TARGETS) ## Validates all DigitalOcean Snapshot Packer config + +validate-gce-ubuntu-1804: ## Validates Ubuntu 18.04 GCE Snapshot Packer config +validate-gce-ubuntu-2004: ## Validates Ubuntu 20.04 GCE Snapshot Packer config +validate-gce-ubuntu-2204: ## Validates Ubuntu 22.04 GCE Snapshot Packer config +validate-gce-all: $(GCE_VALIDATE_TARGETS) ## Validates all GCE Snapshot Packer config + +validate-node-ova-local-centos-7: ## Validates CentOS 7 Node OVA Packer config w local hypervisor +validate-node-ova-local-flatcar: ## Validates Flatcar stable Node OVA Packer config w local hypervisor +validate-node-ova-local-photon-3: ## Validates Photon 3 Node OVA Packer config w local hypervisor +validate-node-ova-local-photon-4: ## Validates Photon 4 Node OVA Packer config w local hypervisor +validate-node-ova-local-rhel-7: ## Validates RHEL 7 Node OVA Packer config w local hypervisor +validate-node-ova-local-rhel-8: ## Validates RHEL 8 Node OVA Packer config w local hypervisor +validate-node-ova-local-rockylinux-8: ## Validates RockyLinux 8 Node OVA Packer config w local hypervisor +validate-node-ova-local-ubuntu-1804: ## Validates Ubuntu 18.04 Node OVA Packer config w local hypervisor +validate-node-ova-local-ubuntu-2004: ## Validates Ubuntu 20.04 Node OVA Packer config w local hypervisor +validate-node-ova-local-ubuntu-2204: ## Validates Ubuntu 22.04 Node OVA Packer config w local hypervisor +validate-node-ova-local-windows-2019: ## Validates Windows Server 2019 Node OVA Packer config w local hypervisor +validate-node-ova-local-windows-2004: ## Validates Windows Server 2004 SAC Node OVA Packer config w local hypervisor +validate-node-ova-local-windows-2022: ## Validates Windows Server 2022 Node OVA Packer config w local hypervisor +validate-node-ova-local-all: $(NODE_OVA_LOCAL_VALIDATE_TARGETS) ## Validates all Node OVAs Packer config w local hypervisor + +validate-node-ova-local-vmx-photon-3: ## Validates Photon 3 Node OVA from VMX file w local hypervisor +validate-node-ova-local-vmx-photon-4: ## Validates Photon 4 Node OVA from VMX file w local hypervisor +validate-node-ova-local-vmx-centos-7: ## Validates Centos 7 Node OVA from VMX file w local hypervisor +validate-node-ova-local-vmx-rhel-7: ## Validates RHEL 7 Node OVA from VMX file w local hypervisor +validate-node-ova-local-vmx-rhel-8: ## Validates RHEL 8 Node OVA from VMX file w local hypervisor +validate-node-ova-local-vmx-rockylinux-8: ## Validates RockyLinux 8 Node OVA from VMX file w local hypervisor +validate-node-ova-local-vmx-ubuntu-1804: ## Validates Ubuntu 18.04 Node OVA from VMX file w local hypervisor +validate-node-ova-local-vmx-ubuntu-2004: ## Validates Ubuntu 20.04 Node OVA from VMX file w local hypervisor +validate-node-ova-local-vmx-ubuntu-2204: ## Validates Ubuntu 22.04 Node OVA from VMX file w local hypervisor + +validate-node-ova-local-base-photon-3: ## Validates Photon 3 Base Node OVA w local hypervisor +validate-node-ova-local-base-photon-4: ## Validates Photon 4 Base Node OVA w local hypervisor +validate-node-ova-local-base-centos-7: ## Validates Centos 7 Base Node OVA w local hypervisor +validate-node-ova-local-base-rhel-7: ## Validates RHEL 7 Base Node OVA w local hypervisor +validate-node-ova-local-base-rhel-8: ## Validates RHEL 8 Base Node OVA w local hypervisor +validate-node-ova-local-base-rockylinux-8: ## Validates RockyLinux 8 Base Node OVA w local hypervisor +validate-node-ova-local-base-ubuntu-1804: ## Validates Ubuntu 18.04 Base Node OVA w local hypervisor +validate-node-ova-local-base-ubuntu-2004: ## Validates Ubuntu 20.04 Base Node OVA w local hypervisor +validate-node-ova-local-base-ubuntu-2204: ## Validates Ubuntu 22.04 Base Node OVA w local hypervisor + +validate-qemu-flatcar: ## Validates Flatcar QEMU image packer config +validate-qemu-ubuntu-1804: ## Validates Ubuntu 18.04 QEMU image packer config +validate-qemu-ubuntu-2004: ## Validates Ubuntu 20.04 QEMU image packer config +validate-qemu-ubuntu-2004-efi: ## Validates Ubuntu 20.04 QEMU EFI image packer config +validate-qemu-ubuntu-2204: ## Validates Ubuntu 22.04 QEMU image packer config +validate-qemu-centos-7: ## Validates CentOS 7 QEMU image packer config +validate-qemu-rhel-8: ## Validates RHEL 8 QEMU image +validate-qemu-rockylinux-8: ## Validates Rocky Linux 8 QEMU image packer config +validate-qemu-all: $(QEMU_VALIDATE_TARGETS) ## Validates all Qemu Packer config + +validate-raw-flatcar: ## Validates Flatcar RAW image packer config +validate-raw-ubuntu-1804: ## Validates Ubuntu 18.04 RAW image packer config +validate-raw-ubuntu-2004: ## Validates Ubuntu 20.04 RAW image packer config +validate-raw-ubuntu-2004-efi: ## Validates Ubuntu 20.04 RAW EFI image packer config +validate-raw-all: $(RAW_VALIDATE_TARGETS) ## Validates all RAW Packer config + +validate-oci-ubuntu-1804: ## Validates the OCI ubuntu-1804 image packer config +validate-oci-ubuntu-2004: ## Validates the OCI ubuntu-2004 image packer config +validate-oci-ubuntu-2204: ## Validates the OCI ubuntu-2204 image packer config +validate-oci-oracle-linux-8: ## Validates the OCI Oracle Linux 8.x image packer config +validate-oci-oracle-linux-9: ## Validates the OCI Oracle Linux 9.x image packer config +validate-oci-windows-2019: ## Validates the OCI Windows 2019 image packer config +validate-oci-windows-2022: ## Validates the OCI Windows 2022 image packer config +validate-oci-all: $(OCI_VALIDATE_TARGETS) ## Validates all OCI image packer config + +validate-osc-ubuntu-2004: ## Validates Ubuntu 20.04 Outscale Snapshot Packer config +validate-osc-all: $(OSC_VALIDATE_TARGETS) ## Validates all Outscale Snapshot Packer config + +validate-vbox-windows-2019: ## Validates Windows Server 2019 Node VirtualBox Packer config w local hypervisor +validate-vbox-all: $(VBOX_VALIDATE_TARGETS) ## Validates all RAW Packer config + +validate-powervs-centos-8: ## Validates the PowerVS CentOS image packer config +validate-powervs-all: $(POWERVS_VALIDATE_TARGETS) ## Validates all PowerVS Packer config + +validate-nutanix-ubuntu-2004: ## Validates Ubuntu 20.04 Nutanix Packer config +validate-nutanix-ubuntu-2204: ## Validates Ubuntu 22.04 Nutanix Packer config +validate-nutanix-rockylinux-8: ## Validates Rocky Linux 8 Nutanix Packer config +validate-nutanix-rockylinux-9: ## Validates the Nutanix Rocky Linux 9 Nutanix Packer config +validate-nutanix-flatcar: ## Validates the Nutanix Flatcar Nutanix Packer config +validate-nutanix-windows-2022: ## Validates Windows Server 2022 Nutanix Packer config +validate-nutanix-all: $(NUTANIX_VALIDATE_TARGETS) ## Validates all Nutanix Packer config + +validate-all: validate-ami-all \ + validate-azure-all \ + validate-do-all \ + validate-gce-all \ + validate-node-ova-local-all \ + validate-qemu-all \ + validate-raw-all \ + validate-oci-all \ + validate-osc-all \ + validate-vbox-all \ + validate-powervs-all \ + validate-nutanix-all +validate-all: ## Validates the Packer config for all build targets + +## -------------------------------------- +## Clean targets +## -------------------------------------- +##@ Cleaning +.PHONY: clean +clean: ## Removes all image output directories and packer image cache +clean: $(NODE_OVA_LOCAL_CLEAN_TARGETS) $(QEMU_CLEAN_TARGETS) $(VBOX_CLEAN_TARGETS) clean-packer-cache + +.PHONY: clean-ova +clean-ova: ## Removes all ova image output directories (see NOTE at top of help) +clean-ova: $(NODE_OVA_LOCAL_CLEAN_TARGETS) + +.PHONY: clean-qemu +clean-qemu: ## Removes all qemu image output directories (see NOTE at top of help) +clean-qemu: $(QEMU_CLEAN_TARGETS) + +.PHONY: clean-raw +clean-raw: ## Removes all raw image output directories (see NOTE at top of help) +clean-raw: $(RAW_CLEAN_TARGETS) + +.PHONY: clean-vbox +clean-vbox: ## Removes all vbox image output directories (see NOTE at top of help) +clean-vbox: $(VBOX_CLEAN_TARGETS) + +.PHONY: clean-packer-cache +clean-packer-cache: ## Removes the packer cache +clean-packer-cache: + rm -fr packer_cache/* + +## -------------------------------------- +## Docker targets +## -------------------------------------- +##@ Docker + +.PHONY: docker-pull-prerequisites +docker-pull-prerequisites: + # We must pre-pull images https://github.com/moby/buildkit/issues/1271 + docker pull docker/dockerfile:1.1-experimental + docker pull $(BASE_IMAGE) + +.PHONY: docker-build +docker-build: docker-pull-prerequisites ## Build the docker image for controller-manager + DOCKER_BUILDKIT=1 docker build --build-arg PASSED_IB_VERSION=$(IB_VERSION) --build-arg ARCH=$(ARCH) --build-arg BASE_IMAGE=$(BASE_IMAGE) . -t $(CONTROLLER_IMG)-$(ARCH):$(TAG) + +.PHONY: docker-push +docker-push: ## Push the docker image + docker push $(CONTROLLER_IMG)-$(ARCH):$(TAG) + +## -------------------------------------- +## Test targets +## -------------------------------------- +##@ Testing +.PHONY: test-azure +test-azure: ## Run the tests for Azure builders + $(abspath packer/azure/scripts/ci-azure-e2e.sh) + +## -------------------------------------- +## Release targets +## -------------------------------------- +##@ Release + +.PHONY: release-staging +release-staging: ## Builds and push container images to the staging bucket. + TAG=$(IB_VERSION) REGISTRY=$(STAGING_REGISTRY) $(MAKE) docker-build docker-push + +## -------------------------------------- +## Sort JSON +## -------------------------------------- +##@ Sort JSON + +.PHONY: json-sort +json_files = $(shell find . -type f -name "*.json" | sort -u) +json-sort: ## Sort all JSON files alphabetically + @for f in $(json_files); do (cat "$$f" | jq -S '.' >> "$$f".sorted && mv "$$f".sorted "$$f") || exit 1 ; done + + +## -------------------------------------- +## Ignition +## -------------------------------------- +##@ Ignition +.PHONY: gen-ignition +ignition_files = bootstrap +gen-ignition: deps-ignition ## Generates Ignition files from CLC + for f in $(ignition_files); do (ct < packer/files/flatcar/clc/$$f.yaml | jq '.' > packer/files/flatcar/ignition/$$f.json) || exit 1; done diff --git a/OWNERS b/OWNERS new file mode 100644 index 0000000..07fe5a6 --- /dev/null +++ b/OWNERS @@ -0,0 +1,4 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - cluster-api-maintainers diff --git a/README.md b/README.md new file mode 100644 index 0000000..0e18f69 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Image Builder for Cluster API + +The Image Builder can be used to build images intended for use with Kubernetes [CAPI](https://cluster-api.sigs.k8s.io/) providers. Each provider has its own format of images that it can work with. For example, AWS instances use AMIs, and vSphere uses OVAs. + +For detailed documentation, see https://image-builder.sigs.k8s.io/capi/capi.html. diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..b086976 --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,20 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[defaults] +remote_tmp = /tmp/.ansible +display_skipped_hosts = False + +[ssh_connection] +pipelining = False diff --git a/ansible/.gitignore b/ansible/.gitignore new file mode 100644 index 0000000..7e99e36 --- /dev/null +++ b/ansible/.gitignore @@ -0,0 +1 @@ +*.pyc \ No newline at end of file diff --git a/ansible/firstboot.yml b/ansible/firstboot.yml new file mode 100644 index 0000000..c5d91e3 --- /dev/null +++ b/ansible/firstboot.yml @@ -0,0 +1,43 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- hosts: all + become: yes + vars: + firstboot_custom_roles_pre: "" + firstboot_custom_roles_post: "" + + tasks: + - include_role: + name: "{{ role }}" + loop: "{{ firstboot_custom_roles_pre.split() }}" + loop_control: + loop_var: role + when: firstboot_custom_roles_pre != "" + - include_role: + name: firstboot + - include_role: + name: "{{ role }}" + loop: "{{ firstboot_custom_roles_post.split() }}" + loop_control: + loop_var: role + when: firstboot_custom_roles_post != "" + + environment: + http_proxy: "{{ http_proxy | default('') }}" + https_proxy: "{{ https_proxy | default('') }}" + no_proxy: "{{ no_proxy | default('') }}" + HTTP_PROXY: "{{ http_proxy | default('') }}" + HTTPS_PROXY: "{{ https_proxy | default('') }}" + NO_PROXY: "{{ no_proxy | default('') }}" diff --git a/ansible/node.yml b/ansible/node.yml new file mode 100644 index 0000000..15aa53d --- /dev/null +++ b/ansible/node.yml @@ -0,0 +1,56 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- hosts: all + become: yes + vars: + node_custom_roles_pre: "" + node_custom_roles_post: "" + custom_role_names: "" + + tasks: + - include_role: + name: "{{ role }}" + loop: "{{ node_custom_roles_pre.split() }}" + loop_control: + loop_var: role + when: node_custom_roles_pre != "" + - include_role: + name: node + - include_role: + name: providers + - include_role: + name: containerd + - include_role: + name: kubernetes + - include_role: + name: load_additional_components + when: load_additional_components | bool + - include_role: + name: "{{ role }}" + loop: "{{ custom_role_names.split() + node_custom_roles_post.split() }}" + loop_control: + loop_var: role + when: custom_role_names != "" or node_custom_roles_post != "" + - include_role: + name: sysprep + + environment: + http_proxy: "{{ http_proxy | default('') }}" + https_proxy: "{{ https_proxy | default('') }}" + no_proxy: "{{ no_proxy | default('') }}" + HTTP_PROXY: "{{ http_proxy | default('') }}" + HTTPS_PROXY: "{{ https_proxy | default('') }}" + NO_PROXY: "{{ no_proxy | default('') }}" + PYTHONPATH: "{{ python_path }}" diff --git a/ansible/python.yml b/ansible/python.yml new file mode 100644 index 0000000..023ddc0 --- /dev/null +++ b/ansible/python.yml @@ -0,0 +1,32 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- hosts: all + # Gathering facts requires Python to be available, so it's a chicken and egg + # problem as this playbook installs Python. + gather_facts: no + become: yes + + tasks: + - include_role: + name: python + + environment: + http_proxy: "{{ http_proxy | default('') }}" + https_proxy: "{{ https_proxy | default('') }}" + no_proxy: "{{ no_proxy | default('') }}" + HTTP_PROXY: "{{ http_proxy | default('') }}" + HTTPS_PROXY: "{{ https_proxy | default('') }}" + NO_PROXY: "{{ no_proxy | default('') }}" + PYTHONPATH: "{{ python_path }}" diff --git a/ansible/roles/containerd/defaults/main.yml b/ansible/roles/containerd/defaults/main.yml new file mode 100644 index 0000000..fe1a8c5 --- /dev/null +++ b/ansible/roles/containerd/defaults/main.yml @@ -0,0 +1,15 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +containerd_config_file: "etc/containerd/config.toml" diff --git a/ansible/roles/containerd/tasks/debian.yml b/ansible/roles/containerd/tasks/debian.yml new file mode 100644 index 0000000..f2969d5 --- /dev/null +++ b/ansible/roles/containerd/tasks/debian.yml @@ -0,0 +1,18 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Install libseccomp2 package + apt: + name: libseccomp2 + state: present \ No newline at end of file diff --git a/ansible/roles/containerd/tasks/main.yml b/ansible/roles/containerd/tasks/main.yml new file mode 100644 index 0000000..c7c5df2 --- /dev/null +++ b/ansible/roles/containerd/tasks/main.yml @@ -0,0 +1,169 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- import_tasks: debian.yml + when: ansible_os_family == "Debian" + +- import_tasks: redhat.yml + when: ansible_os_family == "RedHat" + +- import_tasks: photon.yml + when: ansible_os_family == "VMware Photon OS" + +# TODO(vincepri): Use deb/rpm packages once available. +# See https://github.com/containerd/containerd/issues/1508 for context. +- name: download containerd + get_url: + url: "{{ containerd_url }}" + checksum: "sha256:{{ containerd_sha256 }}" + dest: /tmp/containerd.tar.gz + mode: 0600 + +- name: download containerd-wasm-shims + get_url: + url: "{{ containerd_wasm_shims_url }}" + checksum: "sha256:{{ containerd_wasm_shims_sha256 }}" + dest: /tmp/containerd_wasm_shims.tar.gz + mode: 0600 + when: containerd_wasm_shims_runtimes | length > 0 + +- name: Create a directory if it does not exist + file: + path: "{{ sysusr_prefix }}/bin" + state: directory + mode: 0755 + +# TODO(vincepri): This unpacks the entire tar in the root directory +# we should find a better way to check what's being unpacked and where. +- name: unpack containerd + unarchive: + remote_src: True + src: /tmp/containerd.tar.gz + dest: / + extra_opts: + - --no-overwrite-dir + when: ansible_os_family != "Flatcar" + +# install containerd Wasm shims when the runtimes are not empty -- current known runtimes are 'slight' and 'spin' +# see: https://github.com/kubernetes-sigs/image-builder/pull/1037 +- name: unpack containerd-wasm-shims + unarchive: + remote_src: True + src: /tmp/containerd_wasm_shims.tar.gz + dest: "{{ sysusr_prefix }}/bin" + extra_opts: + - --no-overwrite-dir + when: ansible_os_family != "Flatcar" and (containerd_wasm_shims_runtimes | length > 0) + +- name: unpack containerd for Flatcar to /opt/bin + unarchive: + remote_src: True + src: /tmp/containerd.tar.gz + dest: / + extra_opts: + - --absolute-names + - --transform + - 's@usr@opt@' + - --transform + - 's@sbin@bin@' + - --transform + - 's@opt/local@opt@' + when: ansible_os_family == "Flatcar" + +# install containerd Wasm shims when the runtimes are not empty -- current known runtimes are 'slight' and 'spin' +# see: https://github.com/kubernetes-sigs/image-builder/pull/1037 +- name: unpack containerd-wasm-shims for Flatcar to /opt/bin + unarchive: + remote_src: True + src: /tmp/containerd_wasm_shims.tar.gz + dest: "{{ sysusr_prefix }}/bin" + extra_opts: + - --no-overwrite-dir + when: ansible_os_family == "Flatcar" and (containerd_wasm_shims_runtimes | length > 0) + +# Remove /opt/cni directory, as we will install cni later +- name: delete /opt/cni directory + file: + path: /opt/cni + state: absent + +# Remove /etc/cni directory, as we will configure cni later +- name: delete /etc/cni directory + file: + path: /etc/cni + state: absent + +- name: Creates unit file directory + file: + path: /etc/systemd/system/containerd.service.d + state: directory + +- name: Create systemd unit drop-in file for containerd to run from /opt/bin + template: + dest: /etc/systemd/system/containerd.service.d/10-opt-bin-custom.conf + src: etc/systemd/system/containerd-flatcar.conf + mode: 0600 + when: ansible_os_family == "Flatcar" + +- name: Create containerd memory pressure drop in file + template: + dest: /etc/systemd/system/containerd.service.d/memory-pressure.conf + src: etc/systemd/system/containerd.service.d/memory-pressure.conf + mode: 0644 + +- name: Create containerd max tasks drop in file + template: + dest: /etc/systemd/system/containerd.service.d/max-tasks.conf + src: etc/systemd/system/containerd.service.d/max-tasks.conf + mode: 0644 + +- name: Create containerd http proxy conf file if needed + template: + dest: /etc/systemd/system/containerd.service.d/http-proxy.conf + src: etc/systemd/system/containerd.service.d/http-proxy.conf + mode: 0644 + when: http_proxy is defined or https_proxy is defined + +- name: Creates containerd config directory + file: + path: /etc/containerd + state: directory + +- name: Copy in containerd config file {{ containerd_config_file }} + template: + dest: /etc/containerd/config.toml + src: "{{ containerd_config_file }}" + mode: 0644 + +- name: Copy in crictl config + template: + dest: /etc/crictl.yaml + src: etc/crictl.yaml + +- name: start containerd service + systemd: + name: containerd + daemon_reload: yes + enabled: True + state: restarted + +- name: delete tarball + file: + path: /tmp/containerd.tar.gz + state: absent + +- name: delete tarball + file: + path: /tmp/containerd_wasm_shims.tar.gz + state: absent diff --git a/ansible/roles/containerd/tasks/photon.yml b/ansible/roles/containerd/tasks/photon.yml new file mode 100644 index 0000000..b5f21e3 --- /dev/null +++ b/ansible/roles/containerd/tasks/photon.yml @@ -0,0 +1,16 @@ +# Copyright 2019 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Install libseccomp package + command: tdnf install libseccomp -y diff --git a/ansible/roles/containerd/tasks/redhat.yml b/ansible/roles/containerd/tasks/redhat.yml new file mode 100644 index 0000000..f144a1e --- /dev/null +++ b/ansible/roles/containerd/tasks/redhat.yml @@ -0,0 +1,19 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Install libseccomp package + yum: + name: libseccomp + state: present + lock_timeout: 60 diff --git a/ansible/roles/containerd/templates/etc/containerd/config.toml b/ansible/roles/containerd/templates/etc/containerd/config.toml new file mode 100644 index 0000000..2e77c0c --- /dev/null +++ b/ansible/roles/containerd/templates/etc/containerd/config.toml @@ -0,0 +1,33 @@ +## template: jinja + +# Use config version 2 to enable new configuration fields. +# Config file is parsed as version 1 by default. +version = 2 + +{% if 'imports' not in containerd_additional_settings | b64decode %} +imports = ["/etc/containerd/conf.d/*.toml"] +{% endif %} + +[plugins] + [plugins."io.containerd.grpc.v1.cri"] + sandbox_image = "{{ pause_image }}" +{% if kubernetes_semver is version('v1.21.0', '>=') %} + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] + runtime_type = "io.containerd.runc.v2" + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] + SystemdCgroup = true +{% if 'spin' in containerd_wasm_shims_runtimes %} + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.spin] + runtime_type = "io.containerd.spin.v1" +{% endif %} +{% if 'slight' in containerd_wasm_shims_runtimes %} + [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.slight] + runtime_type = "io.containerd.slight.v1" +{% endif %} +{% endif %} +{% if packer_builder_type.startswith('azure') %} + [plugins."io.containerd.grpc.v1.cri".registry.headers] + X-Meta-Source-Client = ["azure/capz"] +{% endif %} + +{{containerd_additional_settings | b64decode}} diff --git a/ansible/roles/containerd/templates/etc/crictl.yaml b/ansible/roles/containerd/templates/etc/crictl.yaml new file mode 100644 index 0000000..0c2b3fd --- /dev/null +++ b/ansible/roles/containerd/templates/etc/crictl.yaml @@ -0,0 +1 @@ +runtime-endpoint: unix://{{ containerd_cri_socket }} diff --git a/ansible/roles/containerd/templates/etc/systemd/system/containerd-flatcar.conf b/ansible/roles/containerd/templates/etc/systemd/system/containerd-flatcar.conf new file mode 100644 index 0000000..192af7f --- /dev/null +++ b/ansible/roles/containerd/templates/etc/systemd/system/containerd-flatcar.conf @@ -0,0 +1,6 @@ +[Service] +Environment=PATH=/opt/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin +ExecStartPre=mkdir -p /run/docker/libcontainerd +ExecStartPre=ln -fs /run/containerd/containerd.sock /run/docker/libcontainerd/docker-containerd.sock +ExecStart= +ExecStart=/opt/bin/containerd --config /etc/containerd/config.toml diff --git a/ansible/roles/containerd/templates/etc/systemd/system/containerd.service.d/http-proxy.conf b/ansible/roles/containerd/templates/etc/systemd/system/containerd.service.d/http-proxy.conf new file mode 100644 index 0000000..90e8a8e --- /dev/null +++ b/ansible/roles/containerd/templates/etc/systemd/system/containerd.service.d/http-proxy.conf @@ -0,0 +1,10 @@ +[Service] +{% if http_proxy %} +Environment="HTTP_PROXY={{ http_proxy }}" +{% endif %} +{% if https_proxy %} +Environment="HTTPS_PROXY={{ https_proxy }}" +{% endif %} +{% if no_proxy %} +Environment="NO_PROXY={{ no_proxy }}" +{% endif %} diff --git a/ansible/roles/containerd/templates/etc/systemd/system/containerd.service.d/max-tasks.conf b/ansible/roles/containerd/templates/etc/systemd/system/containerd.service.d/max-tasks.conf new file mode 100644 index 0000000..14aaeaa --- /dev/null +++ b/ansible/roles/containerd/templates/etc/systemd/system/containerd.service.d/max-tasks.conf @@ -0,0 +1,3 @@ +[Service] +# Do not limit the number of tasks that can be spawned by containerd +TasksMax=infinity diff --git a/ansible/roles/containerd/templates/etc/systemd/system/containerd.service.d/memory-pressure.conf b/ansible/roles/containerd/templates/etc/systemd/system/containerd.service.d/memory-pressure.conf new file mode 100644 index 0000000..4345fa7 --- /dev/null +++ b/ansible/roles/containerd/templates/etc/systemd/system/containerd.service.d/memory-pressure.conf @@ -0,0 +1,8 @@ +[Service] +# Decreases the likelihood that containerd is killed due to memory +# pressure. +# +# Please see the following link for more information about the +# OOMScoreAdjust configuration property: +# https://www.freedesktop.org/software/systemd/man/systemd.exec.html#OOMScoreAdjust= +OOMScoreAdjust=-999 diff --git a/ansible/roles/firstboot/README.md b/ansible/roles/firstboot/README.md new file mode 100644 index 0000000..6c06e79 --- /dev/null +++ b/ansible/roles/firstboot/README.md @@ -0,0 +1,2 @@ +This role is to be used for operating systems that require some operations +that require a reboot. diff --git a/ansible/roles/firstboot/defaults b/ansible/roles/firstboot/defaults new file mode 120000 index 0000000..58e5f3d --- /dev/null +++ b/ansible/roles/firstboot/defaults @@ -0,0 +1 @@ +../node/defaults \ No newline at end of file diff --git a/ansible/roles/firstboot/meta/main.yml b/ansible/roles/firstboot/meta/main.yml new file mode 100644 index 0000000..9873725 --- /dev/null +++ b/ansible/roles/firstboot/meta/main.yml @@ -0,0 +1,26 @@ +# Copyright 2022 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +dependencies: + - role: setup + vars: + rpms: "" + debs: "" + when: ansible_os_family == "VMware Photon OS" + + - role: setup + vars: + rpms: "{{ ( ( common_rpms + rh7_rpms + lookup('vars', 'common_' + build_target + '_rpms') ) if (ansible_os_family == 'RedHat' and ansible_distribution_major_version == '7') else ( common_rpms + rh8_rpms + lookup('vars', 'common_' + build_target + '_rpms') ) ) }}" + debs: "{{ common_debs + lookup('vars', 'common_' + build_target + '_debs') }}" + when: packer_builder_type is search('qemu') diff --git a/ansible/roles/firstboot/tasks/main.yaml b/ansible/roles/firstboot/tasks/main.yaml new file mode 100644 index 0000000..c4ec519 --- /dev/null +++ b/ansible/roles/firstboot/tasks/main.yaml @@ -0,0 +1,19 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- include_tasks: photon.yml + when: ansible_os_family == "VMware Photon OS" + +- include_tasks: qemu.yml + when: packer_builder_type is search('qemu') diff --git a/ansible/roles/firstboot/tasks/photon.yml b/ansible/roles/firstboot/tasks/photon.yml new file mode 100644 index 0000000..4f211fa --- /dev/null +++ b/ansible/roles/firstboot/tasks/photon.yml @@ -0,0 +1,24 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# no-op task just to have something for the role to do. Right now +# all the work happens in the setup role +# - meta: noop + +- name: Set transparent huge pages to madvise + lineinfile: + path: /boot/photon.cfg + backrefs: yes + regexp: "^(?!.*transparent_hugepage=madvise)(photon_cmdline.*)" + line: '\1 transparent_hugepage=madvise' diff --git a/ansible/roles/firstboot/tasks/qemu.yml b/ansible/roles/firstboot/tasks/qemu.yml new file mode 100644 index 0000000..d00d1d3 --- /dev/null +++ b/ansible/roles/firstboot/tasks/qemu.yml @@ -0,0 +1,17 @@ +# Copyright 2022 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# no-op task just to have something for the role to do. Right now +# all the work happens in the setup role +- meta: noop diff --git a/ansible/roles/kubernetes/defaults/main.yml b/ansible/roles/kubernetes/defaults/main.yml new file mode 100644 index 0000000..aa5057a --- /dev/null +++ b/ansible/roles/kubernetes/defaults/main.yml @@ -0,0 +1,41 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +kubernetes_goarch: "amd64" + +kubernetes_bins: +- kubeadm +- kubectl +- kubelet + +kubernetes_primary_imgs: +- kube-apiserver.tar +- kube-controller-manager.tar +- kube-scheduler.tar +- kube-proxy.tar + +kubernetes_additional_imgs: +- pause.tar +- coredns.tar +- etcd.tar + +kubernetes_load_additional_imgs: false + +kubernetes_imgs: "{{ kubernetes_primary_imgs | union(kubernetes_additional_imgs) if kubernetes_load_additional_imgs | bool else kubernetes_primary_imgs }}" + +kubernetes_cni_http_checksum: "sha1:{{ kubernetes_cni_http_source }}/{{ kubernetes_cni_semver }}/cni-plugins-{{ kubernetes_goarch }}-{{ kubernetes_cni_semver }}.tgz.sha1" + +kubeadm_template: "etc/kubeadm.yml" + +kubelet_extra_args: "--pod-infra-container-image={{ pause_image }}" \ No newline at end of file diff --git a/ansible/roles/kubernetes/tasks/crictl-url.yml b/ansible/roles/kubernetes/tasks/crictl-url.yml new file mode 100644 index 0000000..9ae4f81 --- /dev/null +++ b/ansible/roles/kubernetes/tasks/crictl-url.yml @@ -0,0 +1,54 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Download crictl checksum + get_url: + url: "{{ crictl_sha256 }}" + dest: /tmp/crictl.tar.gz.sha256 + mode: 0600 + +- name: Register checksum value for crictl + slurp: + src: /tmp/crictl.tar.gz.sha256 + register: csum + +- name: download crictl + vars: + sha256: "{{ csum['content'] | b64decode | trim }}" + get_url: + url: "{{ crictl_url }}" + checksum: "sha256:{{ sha256 }}" + dest: /tmp/crictl.tar.gz + mode: 0600 + +- name: Create "{{ sysusrlocal_prefix }}/bin" directory + file: + state: directory + path: "{{ sysusrlocal_prefix }}/bin" + mode: 0755 + owner: root + group: root + +- name: unpack crictl + unarchive: + remote_src: True + src: /tmp/crictl.tar.gz + dest: "{{ sysusrlocal_prefix }}/bin" + extra_opts: + - --no-overwrite-dir + +- name: Remove crictl tarball + file: + state: absent + path: /tmp/crictl.tar.gz diff --git a/ansible/roles/kubernetes/tasks/debian.yml b/ansible/roles/kubernetes/tasks/debian.yml new file mode 100644 index 0000000..9c491e1 --- /dev/null +++ b/ansible/roles/kubernetes/tasks/debian.yml @@ -0,0 +1,36 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Add the Kubernetes repo key + apt_key: + url: "{{ kubernetes_deb_gpg_key }}" + state: present + +- name: Add the Kubernetes repo + apt_repository: + repo: "deb {{ kubernetes_deb_repo }} main" + update_cache: True + state: present + mode: 0644 + filename: kubernetes + +- name: Install Kubernetes + apt: + name: "{{ packages }}" + vars: + packages: + - "kubelet={{ kubernetes_deb_version }}" + - "kubeadm={{ kubernetes_deb_version }}" + - "kubectl={{ kubernetes_deb_version }}" + - "kubernetes-cni={{ kubernetes_cni_deb_version }}" diff --git a/ansible/roles/kubernetes/tasks/ecrpull.yml b/ansible/roles/kubernetes/tasks/ecrpull.yml new file mode 100644 index 0000000..ec5c403 --- /dev/null +++ b/ansible/roles/kubernetes/tasks/ecrpull.yml @@ -0,0 +1,29 @@ +# TODO: This task will be deprecated once https://github.com/containerd/cri/issues/1131 is fixed +- name: Create kubeadm config file + template: + dest: /etc/kubeadm.yml + src: etc/kubeadm.yml + mode: 0600 + +- name: Get images list + shell: 'kubeadm config images list --config /etc/kubeadm.yml' + register: images_list + +- name: Log into ECR + command: > + aws ecr get-authorization-token + --registry-ids {{ kubernetes_container_registry.split('.')[0] }} + --region {{ kubernetes_container_registry.split('.')[3] }} + --output text + --query 'authorizationData[].authorizationToken' + register: credentials + +- name: Pull images + command: "crictl pull --creds {{ credentials.stdout | b64decode }} {{ item }}" + loop: "{{ images_list.stdout_lines }}" + +- name: Delete kubeadm config + file: + path: /etc/kubeadm.yml + state: absent + when: ansible_os_family != "Flatcar" diff --git a/ansible/roles/kubernetes/tasks/kubeadmpull.yml b/ansible/roles/kubernetes/tasks/kubeadmpull.yml new file mode 100644 index 0000000..c8fcc0d --- /dev/null +++ b/ansible/roles/kubernetes/tasks/kubeadmpull.yml @@ -0,0 +1,14 @@ +- name: Create kubeadm config file + template: + dest: /etc/kubeadm.yml + src: "{{ kubeadm_template }}" + mode: 0600 + +- name: Kubeadm pull images + shell: 'kubeadm config images pull --config /etc/kubeadm.yml --cri-socket {{ containerd_cri_socket }}' + +- name: Delete kubeadm config + file: + path: /etc/kubeadm.yml + state: absent + when: ansible_os_family != "Flatcar" diff --git a/ansible/roles/kubernetes/tasks/main.yml b/ansible/roles/kubernetes/tasks/main.yml new file mode 100644 index 0000000..36d973b --- /dev/null +++ b/ansible/roles/kubernetes/tasks/main.yml @@ -0,0 +1,75 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- import_tasks: debian.yml + when: kubernetes_source_type == "pkg" and ansible_os_family == "Debian" + +- import_tasks: redhat.yml + when: kubernetes_source_type == "pkg" and ansible_os_family == "RedHat" + +- import_tasks: photon.yml + when: kubernetes_source_type == "pkg" and ansible_os_family == "VMware Photon OS" + +- name: Symlink cri-tools + file: + src: "/usr/local/bin/{{ item }}" + dest: "/usr/bin/{{ item }}" + mode: 0777 + state: link + force: yes + loop: + - ctr + - crictl + - critest + when: ansible_os_family != "Flatcar" + +- import_tasks: url.yml + when: kubernetes_source_type == "http" and kubernetes_cni_source_type == "http" + +# must include crictl-url.yml after installing containerd, +# as the cri-containerd tarball also includes crictl. +- import_tasks: crictl-url.yml + when: crictl_source_type == "http" + +- name: Create kubelet default config file + template: + src: etc/sysconfig/kubelet + dest: "{{ '/etc/default/kubelet' if ansible_os_family == 'Debian' else '/etc/sysconfig/kubelet'}}" + owner: root + group: root + mode: 0644 + +- name: Enable kubelet service + systemd: + name: kubelet + daemon_reload: yes + enabled: True + state: stopped + +- name: Create the Kubernetes version file + template: + dest: /etc/kubernetes-version + src: etc/kubernetes-version + mode: 0644 + +# TODO: This section will be deprecated once https://github.com/containerd/cri/issues/1131 is fixed. It is used to support ECR with containerd. +- name: Check if Kubernetes container registry is using Amazon ECR + set_fact: + ecr: '{{ kubernetes_container_registry is regex("^[0-9]{12}.dkr.ecr.[^.]+.amazonaws.com$") }}' + +- import_tasks: kubeadmpull.yml + when: (kubernetes_source_type == "pkg" and ecr != true) or ansible_os_family == "Flatcar" + +- import_tasks: ecrpull.yml + when: kubernetes_source_type != "http" and ecr == true diff --git a/ansible/roles/kubernetes/tasks/photon.yml b/ansible/roles/kubernetes/tasks/photon.yml new file mode 100644 index 0000000..ebae5d3 --- /dev/null +++ b/ansible/roles/kubernetes/tasks/photon.yml @@ -0,0 +1,24 @@ +# Copyright 2019 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Add the kubernetes repo + template: + dest: /etc/yum.repos.d/kubernetes.repo + src: etc/yum.repos.d/kubernetes.repo + mode: 0644 + +- name: Install Kubernetes + command: tdnf install {{ packages }} --nogpgcheck -y + vars: + packages: "kubelet-{{ kubernetes_rpm_version }} kubeadm-{{ kubernetes_rpm_version }} kubectl-{{ kubernetes_rpm_version }} kubernetes-cni-{{kubernetes_cni_rpm_version }}" diff --git a/ansible/roles/kubernetes/tasks/redhat.yml b/ansible/roles/kubernetes/tasks/redhat.yml new file mode 100644 index 0000000..3f5eb85 --- /dev/null +++ b/ansible/roles/kubernetes/tasks/redhat.yml @@ -0,0 +1,34 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Add the Kubernetes repo + yum_repository: + name: kubernetes + description: the kubernetes yum repo + baseurl: "{{ kubernetes_rpm_repo }}" + gpgcheck: "{{ kubernetes_rpm_gpg_check }}" + gpgkey: "{{ kubernetes_rpm_gpg_key }}" + +- name: Install Kubernetes + yum: + name: "{{ packages }}" + allow_downgrade: True + state: present + lock_timeout: 60 + vars: + packages: + - "kubelet-{{ kubernetes_rpm_version }}" + - "kubeadm-{{ kubernetes_rpm_version }}" + - "kubectl-{{ kubernetes_rpm_version }}" + - "kubernetes-cni-{{kubernetes_cni_rpm_version }}" diff --git a/ansible/roles/kubernetes/tasks/url.yml b/ansible/roles/kubernetes/tasks/url.yml new file mode 100644 index 0000000..4176db4 --- /dev/null +++ b/ansible/roles/kubernetes/tasks/url.yml @@ -0,0 +1,115 @@ +# Copyright 2019 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Create CNI directory + file: + state: directory + path: /opt/cni/bin + mode: 0755 + owner: root + group: root + +- name: Download CNI tarball + get_url: + url: "{{ kubernetes_cni_http_source }}/{{ kubernetes_cni_semver }}/cni-plugins-linux-{{ kubernetes_goarch }}-{{ kubernetes_cni_semver }}.tgz" + checksum: "{{ kubernetes_cni_http_checksum }}" + dest: /tmp/cni.tar.gz + mode: 0755 + owner: root + group: root + +- name: Install CNI + unarchive: + remote_src: yes + dest: /opt/cni/bin + src: /tmp/cni.tar.gz + +- name: Remove CNI tarball + file: + state: absent + path: /tmp/cni.tar.gz + +- name: Download Kubernetes binaries + get_url: + url: "{{ kubernetes_http_source }}/{{ kubernetes_semver }}/bin/linux/{{ kubernetes_goarch }}/{{ item }}" + # TODO(akutz) Write a script to separately download the checksum + # and verify the associated file using the correct + # checksum file format + #checksum: "sha1:{{ kubernetes_http_source }}/bin/linux/amd64/{{ item }}.sha1" + dest: "{{ sysusr_prefix }}/bin/{{ item }}" + mode: 0755 + owner: root + group: root + loop: "{{ kubernetes_bins }}" + +- name: Download Kubernetes images + get_url: + url: "{{ kubernetes_http_source }}/{{ kubernetes_semver }}/bin/linux/{{ kubernetes_goarch }}/{{ item }}" + # TODO(akutz) Write a script to separately download the checksum + # and verify the associated file using the correct + # checksum file format + #checksum: "sha1:{{ kubernetes_http_source }}/bin/linux/amd64/{{ item }}.sha1" + dest: "/tmp/{{ item }}" + mode: 0600 + loop: "{{ kubernetes_imgs }}" + +- name: Load Kubernetes images + shell: 'CONTAINERD_NAMESPACE="k8s.io" {{ sysusr_prefix }}/bin/ctr --address={{ containerd_cri_socket }} images import /tmp/{{ item }}' + loop: "{{ kubernetes_imgs }}" + +- name: Remove Kubernetes images + file: + state: absent + path: "/tmp/{{ item }}" + loop: "{{ kubernetes_imgs }}" + +- name: Create Kubernetes manifests directory + file: + state: directory + path: /etc/kubernetes/manifests + mode: 0755 + owner: root + group: root + +- name: Create kubelet sysconfig directory + file: + state: directory + path: /etc/sysconfig + mode: 0755 + owner: root + group: root + +- name: Create kubelet drop-in directory + file: + state: directory + path: "{{ systemd_prefix }}/system/kubelet.service.d" + mode: 0755 + owner: root + group: root + +- name: Create kubelet kubeadm drop-in file + template: + src: usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf + dest: "{{ systemd_prefix }}/system/kubelet.service.d/10-kubeadm.conf" + owner: root + group: root + mode: 0644 + +- name: Create kubelet systemd file + template: + src: usr/lib/systemd/system/kubelet.service + dest: "{{ systemd_prefix }}/system/kubelet.service" + owner: root + group: root + mode: 0644 diff --git a/ansible/roles/kubernetes/templates/etc/kubeadm.yml b/ansible/roles/kubernetes/templates/etc/kubeadm.yml new file mode 100644 index 0000000..e21303a --- /dev/null +++ b/ansible/roles/kubernetes/templates/etc/kubeadm.yml @@ -0,0 +1,11 @@ +apiVersion: kubeadm.k8s.io/v1beta2 +kind: ClusterConfiguration +imageRepository: {{ kubernetes_container_registry }} +kubernetesVersion: {{ kubernetes_semver }} +dns: + imageRepository: {{ kubernetes_container_registry }}/coredns +--- +apiVersion: kubeadm.k8s.io/v1beta2 +kind: InitConfiguration +nodeRegistration: + criSocket: {{ containerd_cri_socket }} diff --git a/ansible/roles/kubernetes/templates/etc/kubernetes-version b/ansible/roles/kubernetes/templates/etc/kubernetes-version new file mode 100644 index 0000000..06f9cac --- /dev/null +++ b/ansible/roles/kubernetes/templates/etc/kubernetes-version @@ -0,0 +1 @@ +{{ kubernetes_semver }} \ No newline at end of file diff --git a/ansible/roles/kubernetes/templates/etc/sysconfig/kubelet b/ansible/roles/kubernetes/templates/etc/sysconfig/kubelet new file mode 100644 index 0000000..290bb5a --- /dev/null +++ b/ansible/roles/kubernetes/templates/etc/sysconfig/kubelet @@ -0,0 +1 @@ +KUBELET_EXTRA_ARGS={{ kubelet_extra_args }} \ No newline at end of file diff --git a/ansible/roles/kubernetes/templates/etc/yum.repos.d/kubernetes.repo b/ansible/roles/kubernetes/templates/etc/yum.repos.d/kubernetes.repo new file mode 100644 index 0000000..0a6904c --- /dev/null +++ b/ansible/roles/kubernetes/templates/etc/yum.repos.d/kubernetes.repo @@ -0,0 +1,7 @@ +[kubernetes] +name=kubernetes +description=the kubernetes yum repo +baseurl={{ kubernetes_rpm_repo }} +gpgcheck={{ kubernetes_rpm_gpg_check }} +gpgkey={{ kubernetes_rpm_gpg_key }} +enabled=1 diff --git a/ansible/roles/kubernetes/templates/usr/lib/systemd/system/kubelet.service b/ansible/roles/kubernetes/templates/usr/lib/systemd/system/kubelet.service new file mode 100644 index 0000000..28ab711 --- /dev/null +++ b/ansible/roles/kubernetes/templates/usr/lib/systemd/system/kubelet.service @@ -0,0 +1,14 @@ +[Unit] +Description=kubelet: The Kubernetes Node Agent +Documentation=https://kubernetes.io/docs/home/ +Wants=network-online.target +After=network-online.target + +[Service] +ExecStart={{ sysusr_prefix }}/bin/kubelet +Restart=always +StartLimitInterval=0 +RestartSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/ansible/roles/kubernetes/templates/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf b/ansible/roles/kubernetes/templates/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf new file mode 100644 index 0000000..165becb --- /dev/null +++ b/ansible/roles/kubernetes/templates/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf @@ -0,0 +1,11 @@ +# Note: This dropin only works with kubeadm and kubelet v1.11+ +[Service] +Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf" +Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml" +# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically +EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env +# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use +# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file. +EnvironmentFile=-/etc/sysconfig/kubelet +ExecStart= +ExecStart={{ sysusr_prefix }}/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS diff --git a/ansible/roles/load_additional_components/defaults/main.yml b/ansible/roles/load_additional_components/defaults/main.yml new file mode 100644 index 0000000..44aa745 --- /dev/null +++ b/ansible/roles/load_additional_components/defaults/main.yml @@ -0,0 +1,22 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- + +additional_registry_images: "" +additional_registry_images_list: "" +additional_url_images: "" +additional_url_images_list: "" +additional_executables: "" +additional_executables_list: "" +additional_executables_destination_path: "" \ No newline at end of file diff --git a/ansible/roles/load_additional_components/tasks/executables.yml b/ansible/roles/load_additional_components/tasks/executables.yml new file mode 100644 index 0000000..77e5adb --- /dev/null +++ b/ansible/roles/load_additional_components/tasks/executables.yml @@ -0,0 +1,22 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Download additional executables + get_url: + url: "{{ item }}" + dest: "{{ additional_executables_destination_path }}" + mode: 0711 + loop: "{{ additional_executables_list.split(',') }}" + retries: 5 + delay: 3 \ No newline at end of file diff --git a/ansible/roles/load_additional_components/tasks/main.yml b/ansible/roles/load_additional_components/tasks/main.yml new file mode 100644 index 0000000..8b06531 --- /dev/null +++ b/ansible/roles/load_additional_components/tasks/main.yml @@ -0,0 +1,23 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- import_tasks: executables.yml + when: additional_executables | bool + +- import_tasks: registry.yml + when: additional_registry_images | bool + +- import_tasks: url.yml + when: additional_url_images | bool + diff --git a/ansible/roles/load_additional_components/tasks/registry.yml b/ansible/roles/load_additional_components/tasks/registry.yml new file mode 100644 index 0000000..2e25045 --- /dev/null +++ b/ansible/roles/load_additional_components/tasks/registry.yml @@ -0,0 +1,19 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Pull additional images from registry + shell: 'CONTAINERD_NAMESPACE="k8s.io" {{ sysusr_prefix }}/bin/ctr --address={{ containerd_cri_socket }} images pull {{ item }}' + loop: "{{ additional_registry_images_list.split(',') }}" + retries: 5 + delay: 3 diff --git a/ansible/roles/load_additional_components/tasks/url.yml b/ansible/roles/load_additional_components/tasks/url.yml new file mode 100644 index 0000000..05b361c --- /dev/null +++ b/ansible/roles/load_additional_components/tasks/url.yml @@ -0,0 +1,37 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Create temporary download dir + file: + path: /tmp/images + state: directory + +- name: Download additional images from url + get_url: + url: "{{ item }}" + dest: "/tmp/images/" + mode: 0600 + register: images + loop: "{{ additional_url_images_list.split(',') }}" + retries: 5 + delay: 3 + +- name: Load additional images + shell: 'CONTAINERD_NAMESPACE="k8s.io" {{ sysusr_prefix }}/bin/ctr --address={{ containerd_cri_socket }} images import --no-unpack {{ item.dest }}' + loop: "{{ images.results }}" + +- name: Remove downloaded files + file: + state: absent + path: "/tmp/images" diff --git a/ansible/roles/node/defaults/main.yml b/ansible/roles/node/defaults/main.yml new file mode 100644 index 0000000..08bdb0d --- /dev/null +++ b/ansible/roles/node/defaults/main.yml @@ -0,0 +1,118 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +common_rpms: +- audit +- ca-certificates +- conntrack-tools +- chrony +- curl +- jq +- python3-pip +- socat +- sysstat +- yum-utils + +# Used for AmazonLinux-2 distributions +al2_rpms: +- ebtables +- python-netifaces +- python-requests + +# Used for RedHat based distributions == 7 (ex. RHEL-7, CentOS-7 etc.) +rh7_rpms: +- ebtables +- python-netifaces +- python-requests + +# Used for RedHat based distributions == 8 (ex. RHEL-8, RockyLinux-8 etc.) +rh8_rpms: +- nftables +- python3-netifaces +- python3-requests + +common_debs: +- auditd +- apt-transport-https +- conntrack +- chrony +- curl +- ebtables +- jq +- gnupg +- libnetfilter-acct1 +- libnetfilter-cttimeout1 +- libnetfilter-log1 +- python3-distutils +- python3-netifaces +- python3-pip +- socat + +common_photon_rpms: +- audit +- apparmor-parser +- conntrack-tools +- chrony +- dbus-python3 +- distrib-compat +- ebtables +- net-tools +- openssl-c_rehash +- python3-pygobject +- python3-pip +- rng-tools +- socat +- tar +- unzip +- curl + +photon_3_rpms: +- python-netifaces +- python-requests +- jq + +# Creating photon_4_rpms for adding future packages if needed. +# Since empty list errors out, jq is added. +photon_4_rpms: +- jq + +common_virt_rpms: +- open-vm-tools + +common_virt_debs: +- linux-cloud-tools-virtual +- linux-tools-virtual +- open-vm-tools + +common_virt_photon_rpms: +- open-vm-tools + +common_raw_rpms: [] + +common_raw_debs: +- linux-cloud-tools-generic +- linux-tools-generic + +common_raw_photon_rpms: [] + +#photon does not have backward compatibility for legacy distro behavior for sysctl.conf by default +#as it uses systemd-sysctl. set this var so we can use for sysctl conf file value. +sysctl_conf_file: "{{ '/etc/sysctl.d/99-sysctl.conf' if ansible_os_family == 'VMware Photon OS' else '/etc/sysctl.conf' }}" + +pause_image: "registry.k8s.io/pause:3.9" +containerd_additional_settings: null +leak_local_mdns_to_dns: false +build_target: "virt" +cloud_cfg_file: "/etc/cloud/cloud.cfg" +external_binary_path: "{{ '/opt/bin' if ansible_os_family == 'Flatcar' else '/usr/local/bin' }}" diff --git a/ansible/roles/node/files/etc/audit/rules.d/containerd.rules b/ansible/roles/node/files/etc/audit/rules.d/containerd.rules new file mode 100644 index 0000000..1d1a3d4 --- /dev/null +++ b/ansible/roles/node/files/etc/audit/rules.d/containerd.rules @@ -0,0 +1,10 @@ +-w /var/lib/containerd/ -p rwxa -k containerd +-w /etc/containerd/ -p rwxa -k containerd +-w /etc/systemd/system/containerd.service -p rwxa -k containerd +-w /etc/systemd/system/containerd.service.d/ -p rwxa -k containerd +-w /run/containerd/ -p rwxa -k containerd +-w /usr/local/bin/containerd-shim -p rwxa -k containerd +-w /usr/local/bin/containerd-shim-runc-v1 -p rwxa -k containerd +-w /usr/local/bin/containerd-shim-runc-v2 -p rwxa -k containerd +-w /usr/local/sbin/runc -p rwxa -k containerd +-w /usr/local/bin/containerd -p rwxa -k containerd diff --git a/ansible/roles/node/files/etc/audit/rules.d/containerd.rules-flatcar b/ansible/roles/node/files/etc/audit/rules.d/containerd.rules-flatcar new file mode 100644 index 0000000..2add8c1 --- /dev/null +++ b/ansible/roles/node/files/etc/audit/rules.d/containerd.rules-flatcar @@ -0,0 +1,10 @@ +-w /var/lib/containerd/ -p rwxa -k containerd +-w /etc/containerd/ -p rwxa -k containerd +-w /etc/systemd/system/containerd.service -p rwxa -k containerd +-w /etc/systemd/system/containerd.service.d/ -p rwxa -k containerd +-w /run/containerd/ -p rwxa -k containerd +-w /opt/bin/containerd-shim -p rwxa -k containerd +-w /opt/bin/containerd-shim-runc-v1 -p rwxa -k containerd +-w /opt/bin/containerd-shim-runc-v2 -p rwxa -k containerd +-w /opt/bin/runc -p rwxa -k containerd +-w /opt/bin/containerd -p rwxa -k containerd diff --git a/ansible/roles/node/files/usr/local/bin/etcd-network-tuning.sh b/ansible/roles/node/files/usr/local/bin/etcd-network-tuning.sh new file mode 100755 index 0000000..0371381 --- /dev/null +++ b/ansible/roles/node/files/usr/local/bin/etcd-network-tuning.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Copyright 2022 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit # exits immediately on any unexpected error (does not bypass traps) +set -o nounset # will error if variables are used without first being defined +set -o pipefail # any non-zero exit code in a piped command causes the pipeline to fail with that code + +trap on_exit ERR +on_exit() { + echo "Error setting etcd network tuning parameters for interface: ${DEV}" | systemd-cat -p emerg -t etcd-tuning +} + +if [ "$#" -ne 1 ]; then + echo "Error: Usage: $0 " | systemd-cat -p emerg -t etcd-tuning + exit 1 +fi + +DEV=$1 +echo "Setting etcd network tuning parameters for interface: ${DEV}" | systemd-cat -p info -t etcd-tuning +tc qdisc add dev ${DEV} root handle 1: prio bands 3 +tc filter add dev ${DEV} parent 1: protocol ip prio 1 u32 match ip sport 2380 0xffff flowid 1:1 +tc filter add dev ${DEV} parent 1: protocol ip prio 1 u32 match ip dport 2380 0xffff flowid 1:1 +tc filter add dev ${DEV} parent 1: protocol ip prio 2 u32 match ip sport 2379 0xffff flowid 1:1 +tc filter add dev ${DEV} parent 1: protocol ip prio 2 u32 match ip dport 2379 0xffff flowid 1:1 + diff --git a/ansible/roles/node/meta/main.yml b/ansible/roles/node/meta/main.yml new file mode 100644 index 0000000..62fb141 --- /dev/null +++ b/ansible/roles/node/meta/main.yml @@ -0,0 +1,38 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +dependencies: + - role: setup + vars: + rpms: "{{ common_rpms + al2_rpms + lookup('vars', 'common_' + build_target + '_rpms') }}" + debs: "{{ common_debs }}" + when: ansible_distribution == "Amazon" + + - role: setup + vars: + rpms: "{{ common_rpms }}" + debs: "{{ common_debs }}" + when: packer_builder_type == "oracle-oci" and ansible_architecture == "aarch64" + + - role: setup + vars: + rpms: "{{ ( common_photon_rpms + photon_3_rpms + lookup('vars', 'common_' + build_target + '_photon_rpms') ) if (ansible_os_family == 'VMware Photon OS' and ansible_distribution_major_version == '3') else (common_photon_rpms + photon_4_rpms + lookup('vars', 'common_' + build_target + '_photon_rpms')) }}" + when: ansible_distribution == "VMware Photon OS" + + - role: setup + vars: + rpms: "{{ ( ( common_rpms + rh7_rpms + lookup('vars', 'common_' + build_target + '_rpms') ) if (ansible_os_family == 'RedHat' and ansible_distribution_major_version == '7') else ( common_rpms + rh8_rpms + lookup('vars', 'common_' + build_target + '_rpms') ) ) }}" + debs: "{{ common_debs + lookup('vars', 'common_' + build_target + '_debs') }}" + when: ansible_distribution != "VMware Photon OS" and ansible_distribution != "Amazon" and not (packer_builder_type == "oracle-oci" and ansible_architecture == "aarch64") and + not packer_builder_type is search('qemu') diff --git a/ansible/roles/node/tasks/amazonLinux2.yml b/ansible/roles/node/tasks/amazonLinux2.yml new file mode 100644 index 0000000..aa2bc33 --- /dev/null +++ b/ansible/roles/node/tasks/amazonLinux2.yml @@ -0,0 +1,28 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +- name: Ensure sysstat is running and comes on at reboot + service: + name: sysstat + state: started + enabled: yes + +# images need to be immutable once built +# https://aws.amazon.com/amazon-linux-ami/faqs/ +- name: Disable security updates on boot + lineinfile: + path: "{{ cloud_cfg_file }}" + regexp: "^repo_upgrade: security" + line: 'repo_upgrade: none' diff --git a/ansible/roles/node/tasks/main.yml b/ansible/roles/node/tasks/main.yml new file mode 100644 index 0000000..a010193 --- /dev/null +++ b/ansible/roles/node/tasks/main.yml @@ -0,0 +1,133 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- import_tasks: photon.yml + when: ansible_os_family == "VMware Photon OS" + +- import_tasks: amazonLinux2.yml + when: ansible_distribution == "Amazon" + +# This is required until https://github.com/ansible/ansible/issues/77537 is fixed and used. +- name: Override Flatcar's OS family + set_fact: + ansible_os_family: Flatcar + when: ansible_os_family == "Flatcar Container Linux by Kinvolk" + tags: + - facts + +- name: Ensure overlay module is present + modprobe: + name: overlay + state: present + +- name: Ensure br_netfilter module is present + modprobe: + name: br_netfilter + state: present + +- name: Persist required kernel modules + copy: + content: | + overlay + br_netfilter + dest: /etc/modules-load.d/kubernetes.conf + mode: 0644 + +- name: Set and persist kernel params + sysctl: + name: "{{ item.param }}" + value: "{{ item.val }}" + state: present + sysctl_set: yes + sysctl_file: "{{ sysctl_conf_file }}" + reload: yes + loop: + - { param: net.bridge.bridge-nf-call-iptables, val: 1 } + - { param: net.bridge.bridge-nf-call-ip6tables, val: 1 } + - { param: net.ipv4.ip_forward, val: 1 } + - { param: net.ipv6.conf.all.forwarding, val: 1 } + - { param: net.ipv6.conf.all.disable_ipv6, val: 0 } + - { param: net.ipv4.tcp_congestion_control, val: bbr } + - { param: vm.overcommit_memory, val: 1 } + - { param: kernel.panic, val: 10 } + - { param: kernel.panic_on_oops, val: 1 } + +- name: Disable swap memory + shell: | + swapoff -a + when: ansible_memory_mb.swap.total != 0 + +- name: Edit fstab file to disable swap + shell: sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab + when: ansible_memory_mb.swap.total != 0 + +- name: Disable conntrackd service + systemd: + name: conntrackd + state: stopped + enabled: false + when: ansible_os_family != "Debian" and ansible_os_family != "Flatcar" + +- name: Ensure auditd is running and comes on at reboot + service: + name: auditd + state: started + enabled: yes + +- name: configure auditd rules for containerd + copy: + src: etc/audit/rules.d/containerd.rules + dest: /etc/audit/rules.d/containerd.rules + owner: root + group: root + mode: 0644 + when: ansible_os_family != "Flatcar" + +- name: configure auditd rules for containerd (Flatcar) + copy: + src: etc/audit/rules.d/containerd.rules-flatcar + dest: /etc/audit/rules.d/containerd.rules + owner: root + group: root + mode: 0644 + when: ansible_os_family == "Flatcar" + +- name: Ensure reverse packet filtering is set as strict + sysctl: + name: net.ipv4.conf.all.rp_filter + value: "1" + state: present + sysctl_set: yes + reload: yes + when: ansible_distribution == "Ubuntu" + +- name: Set transparent huge pages to madvise + lineinfile: + path: /etc/default/grub + backrefs: yes + regexp: "^(?!.*transparent_hugepage=madvise)(GRUB_CMDLINE_LINUX=.*)(\"$)" + line: '\1 transparent_hugepage=madvise"' + when: ansible_os_family == "RedHat" + +- name: Copy udev etcd network tuning rules + template: + src: etc/udev/rules.d/90-etcd-tuning.rules + dest: /etc/udev/rules.d/90-etcd-tuning.rules + mode: 0744 + +- name: Copy etcd network tuning script + copy: + src: usr/local/bin/etcd-network-tuning.sh + dest: "{{ external_binary_path }}/etcd-network-tuning.sh" + mode: 0755 diff --git a/ansible/roles/node/tasks/photon.yml b/ansible/roles/node/tasks/photon.yml new file mode 100644 index 0000000..ecf76ba --- /dev/null +++ b/ansible/roles/node/tasks/photon.yml @@ -0,0 +1,53 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +- name: Leak mDNS to DNS (cloud-init-nics) (enable .local domain lookups) + ini_file: + path: /etc/systemd/network/10-cloud-init-nics.network + section: Network + option: Domains + value: "~local" + when: leak_local_mdns_to_dns + +- name: Leak mDNS to DNS (dhcp) (enable .local domain lookups) + ini_file: + path: /etc/systemd/network/99-dhcp-en.network + section: Network + option: Domains + value: "~local" + when: leak_local_mdns_to_dns + +- name: Double TCP small queue limit to be the same as Ubuntu + sysctl: + name: net.ipv4.tcp_limit_output_bytes + value: "524288" + state: present + sysctl_set: yes + reload: yes + sysctl_file: "{{ sysctl_conf_file }}" + +- name: Disable Apparmor service + systemd: + name: apparmor + daemon_reload: yes + enabled: false + state: stopped + +- name: Disable Apparmor in kernel + lineinfile: + path: /boot/photon.cfg + backrefs: yes + regexp: "^(?!.*apparmor=0)(photon_cmdline.*)" + line: '\1 apparmor=0' diff --git a/ansible/roles/node/templates/etc/udev/rules.d/90-etcd-tuning.rules b/ansible/roles/node/templates/etc/udev/rules.d/90-etcd-tuning.rules new file mode 100644 index 0000000..f010162 --- /dev/null +++ b/ansible/roles/node/templates/etc/udev/rules.d/90-etcd-tuning.rules @@ -0,0 +1,15 @@ +# Copyright 2022 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ACTION=="add", SUBSYSTEM=="net", SUBSYSTEMS=="pci|xen|vmbus" RUN+="{{ external_binary_path }}/etcd-network-tuning.sh $name" diff --git a/ansible/roles/providers/defaults/main.yml b/ansible/roles/providers/defaults/main.yml new file mode 100644 index 0000000..66825bc --- /dev/null +++ b/ansible/roles/providers/defaults/main.yml @@ -0,0 +1,17 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +networkd_dispatcher_download_url: "https://gitlab.com/craftyguy/networkd-dispatcher/-/archive/2.1/networkd-dispatcher-2.1.tar.bz2" +packer_builder_type: "" +build_target: "virt" diff --git a/ansible/roles/providers/files/etc/azure/iptables b/ansible/roles/providers/files/etc/azure/iptables new file mode 100644 index 0000000..a79b6df --- /dev/null +++ b/ansible/roles/providers/files/etc/azure/iptables @@ -0,0 +1,8 @@ +*filter +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +-A FORWARD -d 168.63.129.16/32 -p tcp -m tcp --dport 80 -m comment --comment "block traffic to 168.63.129.16 for cve-2021-27075" -j DROP +-A OUTPUT -d 168.63.129.16/32 -p tcp -m owner --uid-owner 0 -j ACCEPT +-A OUTPUT -d 168.63.129.16/32 -p tcp -m conntrack --ctstate INVALID,NEW -j DROP +COMMIT diff --git a/ansible/roles/providers/files/etc/cloud/cloud.cfg.d/05_logging.cfg b/ansible/roles/providers/files/etc/cloud/cloud.cfg.d/05_logging.cfg new file mode 100644 index 0000000..02f0107 --- /dev/null +++ b/ansible/roles/providers/files/etc/cloud/cloud.cfg.d/05_logging.cfg @@ -0,0 +1,67 @@ +## This yaml formated config file handles setting +## logger information. The values that are necessary to be set +## are seen at the bottom. The top '_log' are only used to remove +## redundency in a syslog and fallback-to-file case. +## +## The 'log_cfgs' entry defines a list of logger configs +## Each entry in the list is tried, and the first one that +## works is used. If a log_cfg list entry is an array, it will +## be joined with '\n'. +_log: + - &log_base | + [loggers] + keys=root,cloudinit + + [handlers] + keys=consoleHandler,cloudLogHandler + + [formatters] + keys=simpleFormatter,arg0Formatter + + [logger_root] + level=DEBUG + formatter=arg0Formatter + handlers=consoleHandler,cloudLogHandler + + [logger_cloudinit] + level=DEBUG + qualname=cloudinit + handlers= + propagate=1 + + [handler_consoleHandler] + class=StreamHandler + level=WARNING + formatter=arg0Formatter + args=(sys.stderr,) + + [formatter_arg0Formatter] + format=%(asctime)s - %(filename)s[%(levelname)s]: %(message)s + + [formatter_simpleFormatter] + format=[CLOUDINIT]%(asctime)s - %(filename)s[%(levelname)s]: %(message)s + - &log_file | + [handler_cloudLogHandler] + class=FileHandler + level=DEBUG + formatter=arg0Formatter + args=('/var/log/cloud-init.log',) + - &log_syslog | + [handler_cloudLogHandler] + class=handlers.SysLogHandler + level=DEBUG + formatter=simpleFormatter + args=("/dev/log", handlers.SysLogHandler.LOG_USER) + +log_cfgs: +# These will be joined into a string that defines the configuration + - [ *log_base, *log_syslog ] +# These will be joined into a string that defines the configuration + - [ *log_base, *log_file ] +# A file path can also be used +# - /etc/log.conf + +# this tells cloud-init to redirect its stdout and stderr to +# 'tee -a /var/log/cloud-init-output.log' so the user can see output +# there without needing to look on the console. +output: {all: '| python3 -c ''import sys,time;sys.stdout.write("".join(( " ".join((time.strftime("[%Y-%m-%d %H:%M:%S]", time.localtime()), line)) for line in sys.stdin )))'' | tee -a /var/log/cloud-init-output.log'} diff --git a/ansible/roles/providers/files/etc/cloud/cloud.cfg.d/99_metadata.cfg b/ansible/roles/providers/files/etc/cloud/cloud.cfg.d/99_metadata.cfg new file mode 100644 index 0000000..57b3ea0 --- /dev/null +++ b/ansible/roles/providers/files/etc/cloud/cloud.cfg.d/99_metadata.cfg @@ -0,0 +1,2 @@ +disable-ec2-metadata: false +datasource_list: [ Outscale ] diff --git a/ansible/roles/providers/files/etc/networkd-dispatcher/no-carrier.d/20-chrony.j2 b/ansible/roles/providers/files/etc/networkd-dispatcher/no-carrier.d/20-chrony.j2 new file mode 100644 index 0000000..0a08273 --- /dev/null +++ b/ansible/roles/providers/files/etc/networkd-dispatcher/no-carrier.d/20-chrony.j2 @@ -0,0 +1,26 @@ +#!/bin/bash + +# This is a networkd-dispatcher script for chronyd to handle its NTP +# sources. It sets the NTP sources online or offline when a network +# interface is configured or removed. On DHCP change, chrony will +# update its NTP sources passed from DHCP options. + +export LC_ALL=C + +DHCP_SERVER_FILE={{ server_dir }}/chrony.servers.$IFACE + +clear_servers_from_dhcp() { + if [ -f "$DHCP_SERVER_FILE" ]; then + rm -f "$DHCP_SERVER_FILE" + {{ chrony_helper_dir }}/chrony-helper update-daemon || : + fi +} + +if [ "$STATE" = "no-carrier" ]; then + clear_servers_from_dhcp + # The onoffline command tells chronyd to switch all sources to + # the online (routable) or offline (off) status according to the current network configuration. + chronyc onoffline > /dev/null 2>&1 +fi + +exit 0 \ No newline at end of file diff --git a/ansible/roles/providers/files/etc/networkd-dispatcher/off.d/20-chrony.j2 b/ansible/roles/providers/files/etc/networkd-dispatcher/off.d/20-chrony.j2 new file mode 100644 index 0000000..9e276b4 --- /dev/null +++ b/ansible/roles/providers/files/etc/networkd-dispatcher/off.d/20-chrony.j2 @@ -0,0 +1,26 @@ +#!/bin/bash + +# This is a networkd-dispatcher script for chronyd to handle its NTP +# sources. It sets the NTP sources online or offline when a network +# interface is configured or removed. On DHCP change, chrony will +# update its NTP sources passed from DHCP options. + +export LC_ALL=C + +DHCP_SERVER_FILE={{ server_dir }}/chrony.servers.$IFACE + +clear_servers_from_dhcp() { + if [ -f "$DHCP_SERVER_FILE" ]; then + rm -f "$DHCP_SERVER_FILE" + {{ chrony_helper_dir }}/chrony-helper update-daemon || : + fi +} + +if [ "$STATE" = "off" ]; then + clear_servers_from_dhcp + # The onoffline command tells chronyd to switch all sources to + # the online (routable) or offline (off) status according to the current network configuration. + chronyc onoffline > /dev/null 2>&1 +fi + +exit 0 \ No newline at end of file diff --git a/ansible/roles/providers/files/etc/networkd-dispatcher/routable.d/20-chrony.j2 b/ansible/roles/providers/files/etc/networkd-dispatcher/routable.d/20-chrony.j2 new file mode 100644 index 0000000..c67dbda --- /dev/null +++ b/ansible/roles/providers/files/etc/networkd-dispatcher/routable.d/20-chrony.j2 @@ -0,0 +1,27 @@ +#!/bin/bash + +# This is a networkd-dispatcher script for chronyd to handle its NTP +# sources. It sets the NTP sources online or offline when a network +# interface is configured or removed. On DHCP change, chrony will +# update its NTP sources passed from DHCP options. + +export LC_ALL=C + +DHCP_SERVER_FILE={{ server_dir }}/chrony.servers.$IFACE + +add_servers_from_dhcp() { + if [ -f "$DHCP_SERVER_FILE" ]; then + rm -f "$DHCP_SERVER_FILE" + fi + echo "$json" | jq -r 'select(.NTP !=null) .NTP[]' >> $DHCP_SERVER_FILE + {{ chrony_helper_dir }}/chrony-helper update-daemon || : +} + +if [ "$STATE" = "routable" ]; then + add_servers_from_dhcp + # The onoffline command tells chronyd to switch all sources to + # the online (routable) or offline (off) status according to the current network configuration. + chronyc onoffline > /dev/null 2>&1 +fi + +exit 0 \ No newline at end of file diff --git a/ansible/roles/providers/files/etc/systemd/system/cloud-config.service.d/boot-order.conf b/ansible/roles/providers/files/etc/systemd/system/cloud-config.service.d/boot-order.conf new file mode 100644 index 0000000..cdd794f --- /dev/null +++ b/ansible/roles/providers/files/etc/systemd/system/cloud-config.service.d/boot-order.conf @@ -0,0 +1,3 @@ +[Unit] +After=containerd.service +Wants=containerd.service \ No newline at end of file diff --git a/ansible/roles/providers/files/etc/systemd/system/cloud-final.service.d/boot-order.conf b/ansible/roles/providers/files/etc/systemd/system/cloud-final.service.d/boot-order.conf new file mode 100644 index 0000000..cdd794f --- /dev/null +++ b/ansible/roles/providers/files/etc/systemd/system/cloud-final.service.d/boot-order.conf @@ -0,0 +1,3 @@ +[Unit] +After=containerd.service +Wants=containerd.service \ No newline at end of file diff --git a/ansible/roles/providers/files/etc/systemd/system/modify-cloud-init-cfg.service b/ansible/roles/providers/files/etc/systemd/system/modify-cloud-init-cfg.service new file mode 100644 index 0000000..f4253b6 --- /dev/null +++ b/ansible/roles/providers/files/etc/systemd/system/modify-cloud-init-cfg.service @@ -0,0 +1,12 @@ +[Unit] +Description=Modify cloud-init config +After=cloud-final.service +AssertFileIsExecutable=/usr/local/bin/modify-cloud-init-cfg.sh + +[Install] +WantedBy=cloud-init.target + +[Service] +Type=simple +ExecStart=/usr/local/bin/modify-cloud-init-cfg.sh +SuccessExitStatus=0 \ No newline at end of file diff --git a/ansible/roles/providers/files/etc/vmware-tools/tools.conf b/ansible/roles/providers/files/etc/vmware-tools/tools.conf new file mode 100644 index 0000000..f2b63ed --- /dev/null +++ b/ansible/roles/providers/files/etc/vmware-tools/tools.conf @@ -0,0 +1,3 @@ +[guestinfo] +exclude-nics=antrea-*,cali*,cilium*,lxc*,ovs-system,br*,flannel*,veth*,vxlan_sys_*,genev_sys_*,gre_sys_*,stt_sys_*,????????-?????? + diff --git a/ansible/roles/providers/files/tmp/cloud-init_22.2-outscale.deb b/ansible/roles/providers/files/tmp/cloud-init_22.2-outscale.deb new file mode 100644 index 0000000..39af940 Binary files /dev/null and b/ansible/roles/providers/files/tmp/cloud-init_22.2-outscale.deb differ diff --git a/ansible/roles/providers/files/usr/lib/python3/dist-packages/cloudinit/feature_overrides.py b/ansible/roles/providers/files/usr/lib/python3/dist-packages/cloudinit/feature_overrides.py new file mode 100644 index 0000000..fa96e17 --- /dev/null +++ b/ansible/roles/providers/files/usr/lib/python3/dist-packages/cloudinit/feature_overrides.py @@ -0,0 +1 @@ +ERROR_ON_USER_DATA_FAILURE = False diff --git a/ansible/roles/providers/files/usr/libexec/chrony-helper b/ansible/roles/providers/files/usr/libexec/chrony-helper new file mode 100644 index 0000000..bc99c7c --- /dev/null +++ b/ansible/roles/providers/files/usr/libexec/chrony-helper @@ -0,0 +1,251 @@ +#!/bin/bash +# This script configures running chronyd to use NTP servers obtained from +# DHCP and _ntp._udp DNS SRV records. Files with servers from DHCP are managed +# externally (e.g. by a dhclient script). Files with servers from DNS SRV +# records are updated here using the dig utility. The script can also list +# and set static sources in the chronyd configuration file. + +chronyc=/usr/bin/chronyc +chrony_conf=/etc/chrony.conf +chrony_service=chronyd.service +helper_dir=/var/run/chrony-helper +added_servers_file=$helper_dir/added_servers + +network_sysconfig_file=/etc/sysconfig/network +dhclient_servers_files=/var/lib/dhclient/chrony.servers.* +dnssrv_servers_files=$helper_dir/dnssrv@* +dnssrv_timer_prefix=chrony-dnssrv@ + +chrony_command() { + $chronyc -a -n -m "$1" +} + +is_running() { + chrony_command "tracking" &> /dev/null +} + +is_update_needed() { + for file in $dhclient_servers_files $dnssrv_servers_files \ + $added_servers_file; do + [ -e "$file" ] && return 0 + done + return 1 +} + +update_daemon() { + local all_servers_with_args all_servers added_servers + + if ! is_running; then + rm -f $added_servers_file + return 0 + fi + + all_servers_with_args=$( + cat $dhclient_servers_files $dnssrv_servers_files 2> /dev/null) + + all_servers=$( + echo "$all_servers_with_args" | + while read server serverargs; do + echo "$server" + done | sort -u) + added_servers=$( ( + cat $added_servers_file 2> /dev/null + echo "$all_servers_with_args" | + while read server serverargs; do + [ -z "$server" ] && continue + chrony_command "add server $server $serverargs" &> /dev/null && + echo "$server" + done) | sort -u) + + comm -23 <(echo -n "$added_servers") <(echo -n "$all_servers") | + while read server; do + chrony_command "delete $server" &> /dev/null + done + + added_servers=$(comm -12 <(echo -n "$added_servers") <(echo -n "$all_servers")) + + [ -n "$added_servers" ] && echo "$added_servers" > $added_servers_file || + rm -f $added_servers_file +} + +get_dnssrv_servers() { + local name=$1 + + if ! command -v dig &> /dev/null; then + echo "Missing dig (DNS lookup utility)" >&2 + return 1 + fi + + ( + . $network_sysconfig_file &> /dev/null + + output=$(dig "$name" srv +short +ndots=2 +search 2> /dev/null) + [ $? -ne 0 ] && return 0 + + echo "$output" | while read prio weight port target; do + server=${target%.} + [ -z "$server" ] && continue + echo "$server port $port ${NTPSERVERARGS:-iburst}" + done + ) +} + +check_dnssrv_name() { + local name=$1 + + if [ -z "$name" ]; then + echo "No DNS SRV name specified" >&2 + return 1 + fi + + if [ "${name:0:9}" != _ntp._udp ]; then + echo "DNS SRV name $name doesn't start with _ntp._udp" >&2 + return 1 + fi +} + +update_dnssrv_servers() { + local name=$1 + local srv_file=$helper_dir/dnssrv@$name servers + + check_dnssrv_name "$name" || return 1 + + servers=$(get_dnssrv_servers "$name") + [ -n "$servers" ] && echo "$servers" > "$srv_file" || rm -f "$srv_file" +} + +set_dnssrv_timer() { + local state=$1 name=$2 + local srv_file=$helper_dir/dnssrv@$name servers + local timer=$dnssrv_timer_prefix$(systemd-escape "$name").timer + + check_dnssrv_name "$name" || return 1 + + if [ "$state" = enable ]; then + systemctl enable "$timer" + systemctl start "$timer" + elif [ "$state" = disable ]; then + systemctl stop "$timer" + systemctl disable "$timer" + rm -f "$srv_file" + fi +} + +list_dnssrv_timers() { + systemctl --all --full -t timer list-units | grep "^$dnssrv_timer_prefix" | \ + sed "s|^$dnssrv_timer_prefix\(.*\)\.timer.*|\1|" | + while read -r name; do + systemd-escape --unescape "$name" + done +} + +prepare_helper_dir() { + mkdir -p $helper_dir + exec 100> $helper_dir/lock + if ! flock -w 20 100; then + echo "Failed to lock $helper_dir" >&2 + return 1 + fi +} + +is_source_line() { + local pattern="^[ \t]*(server|pool|peer|refclock)[ \t]+[^ \t]+" + [[ "$1" =~ $pattern ]] +} + +list_static_sources() { + while read line; do + is_source_line "$line" && echo "$line" || : + done < $chrony_conf +} + +set_static_sources() { + local new_config tmp_conf + + new_config=$( + sources=$( + while read line; do + is_source_line "$line" && echo "$line" + done) + + while read line; do + if ! is_source_line "$line"; then + echo "$line" + continue + fi + + tmp_sources=$( + local removed=0 + + echo "$sources" | while read line2; do + [ "$removed" -ne 0 -o "$line" != "$line2" ] && \ + echo "$line2" || removed=1 + done) + + [ "$sources" == "$tmp_sources" ] && continue + sources=$tmp_sources + echo "$line" + done < $chrony_conf + + echo "$sources" + ) + + tmp_conf=${chrony_conf}.tmp + + cp -a $chrony_conf $tmp_conf && + echo "$new_config" > $tmp_conf && + mv $tmp_conf $chrony_conf || return 1 + + systemctl try-restart $chrony_service +} + +print_help() { + echo "Usage: $0 COMMAND" + echo + echo "Commands:" + echo " update-daemon" + echo " update-dnssrv-servers NAME" + echo " enable-dnssrv NAME" + echo " disable-dnssrv NAME" + echo " list-dnssrv" + echo " list-static-sources" + echo " set-static-sources < sources.list" + echo " is-running" + echo " command CHRONYC-COMMAND" +} + +case "$1" in + update-daemon|add-dhclient-servers|remove-dhclient-servers) + is_update_needed || exit 0 + prepare_helper_dir && update_daemon + ;; + update-dnssrv-servers) + prepare_helper_dir && update_dnssrv_servers "$2" && update_daemon + ;; + enable-dnssrv) + set_dnssrv_timer enable "$2" + ;; + disable-dnssrv) + set_dnssrv_timer disable "$2" && prepare_helper_dir && update_daemon + ;; + list-dnssrv) + list_dnssrv_timers + ;; + list-static-sources) + list_static_sources + ;; + set-static-sources) + set_static_sources + ;; + is-running) + is_running + ;; + command|forced-command) + chrony_command "$2" + ;; + *) + print_help + exit 2 +esac + +exit $? \ No newline at end of file diff --git a/ansible/roles/providers/files/usr/local/bin/modify-cloud-init-cfg.sh b/ansible/roles/providers/files/usr/local/bin/modify-cloud-init-cfg.sh new file mode 100644 index 0000000..e6c70f4 --- /dev/null +++ b/ansible/roles/providers/files/usr/local/bin/modify-cloud-init-cfg.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +sed -i 's/preserve_hostname'":"' false/preserve_hostname'":"' true/' /etc/cloud/cloud.cfg \ No newline at end of file diff --git a/ansible/roles/providers/tasks/aws.yml b/ansible/roles/providers/tasks/aws.yml new file mode 100644 index 0000000..6078d14 --- /dev/null +++ b/ansible/roles/providers/tasks/aws.yml @@ -0,0 +1,74 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: upgrade pip to latest + pip: + name: pip + executable: pip3 + state: latest + +- name: install aws clients + pip: + name: "{{ packages }}" + executable: pip3 + vars: + packages: + - awscli + when: ansible_distribution != "Amazon" + +# Remove after https://github.com/aws/amazon-ssm-agent/issues/235 is fixed. +- name: install aws agents RPM on Redhat distributions + package: + name: "{{ item }}" + state: present + disable_gpg_check: true + with_items: + - "{{ amazon_ssm_agent_rpm }}" + when: + - ansible_os_family == "RedHat" + - ansible_distribution != "Amazon" + +- name: install aws agents RPM + package: + name: "{{ item }}" + state: present + with_items: + - amazon-ssm-agent + - awscli + when: ansible_distribution == "Amazon" + +- name: Ensure ssm agent is running RPM + service: + name: amazon-ssm-agent + state: started + enabled: yes + when: ansible_os_family == "RedHat" + +- name: install aws agents Ubuntu + shell: snap install amazon-ssm-agent --classic + when: ansible_distribution == "Ubuntu" + +- name: Ensure ssm agent is running Ubuntu + service: + name: snap.amazon-ssm-agent.amazon-ssm-agent.service + state: started + enabled: yes + when: ansible_distribution == "Ubuntu" + +- name: Disable Hyper-V KVP protocol daemon on Ubuntu + systemd: + name: hv-kvp-daemon + state: stopped + enabled: false + when: ansible_os_family == "Debian" diff --git a/ansible/roles/providers/tasks/azure.yml b/ansible/roles/providers/tasks/azure.yml new file mode 100644 index 0000000..b3c84b4 --- /dev/null +++ b/ansible/roles/providers/tasks/azure.yml @@ -0,0 +1,67 @@ +# Copyright 2019 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- import_tasks: redhat.yml + when: ansible_os_family == "RedHat" + +- import_tasks: debian.yml + when: ansible_os_family == "Debian" + +- name: Configure PTP + lineinfile: + path: /etc/chrony/chrony.conf + create: yes + line: refclock PHC /dev/ptp0 poll 3 dpoll -2 offset 0 + +- name: Ensure makestep parameter set as per Azure recommendation + lineinfile: + path: /etc/chrony/chrony.conf + regexp: '^makestep' + line: makestep 1.0 -1 + +- name: Install iptables persistence + apt: + name: "{{ packages }}" + state: present + force_apt_get: yes + vars: + packages: + - iptables-persistent + when: ansible_os_family == "Debian" + +- name: Block traffic to 168.63.129.16 port 80 for cve-2021-27075 + copy: + src: files/etc/azure/iptables + dest: /etc/iptables/rules.v4 + owner: root + group: root + mode: 0644 + when: ansible_os_family == "Debian" + +- name: Load iptable rules from file + community.general.iptables_state: + state: restored + path: /etc/iptables/rules.v4 + when: ansible_os_family == "Debian" + +- name: Install netbase and nfs-common + apt: + name: "{{ packages }}" + state: present + force_apt_get: yes + vars: + packages: + - netbase + - nfs-common + when: ansible_os_family == "Debian" diff --git a/ansible/roles/providers/tasks/cloudstack.yml b/ansible/roles/providers/tasks/cloudstack.yml new file mode 100644 index 0000000..e222d10 --- /dev/null +++ b/ansible/roles/providers/tasks/cloudstack.yml @@ -0,0 +1,39 @@ +# Copyright 2022 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Add CloudStack Datasource + copy: + dest: /etc/cloud/cloud.cfg.d/cloudstack.cfg + content: |- + datasource_list: ['CloudStack'] + datasource: + CloudStack: + max_wait: 120 + timeout: 50 + owner: root + group: root + mode: 0644 + +- name: Run dracut cmd to regenerate initramfs with all drivers - needed when converting to different hypervisor templates + shell: dracut --force --no-hostonly + when: ansible_os_family == "RedHat" + +- name: Add draut cmd to regenerate initramfs with only necessary drivers on first boot + lineinfile: + state: present + path: /etc/cloud/cloud.cfg.d/cloudstack.cfg + line: |- + bootcmd: + - dracut --force + when: ansible_os_family == "RedHat" diff --git a/ansible/roles/providers/tasks/debian.yml b/ansible/roles/providers/tasks/debian.yml new file mode 100644 index 0000000..63a0b45 --- /dev/null +++ b/ansible/roles/providers/tasks/debian.yml @@ -0,0 +1,34 @@ +# Copyright 2019 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: upgrade pip to latest + pip: + name: pip + executable: pip3 + state: latest + +- name: upgrade pyOpenSSL and cryptography + pip: + name: + - pyOpenSSL==22.0.* + - cryptography==38.0.* + executable: pip3 + +- name: install Azure clients + pip: + executable: pip3 + name: "{{ packages }}" + vars: + packages: + - azure-cli diff --git a/ansible/roles/providers/tasks/googlecompute.yml b/ansible/roles/providers/tasks/googlecompute.yml new file mode 100644 index 0000000..815534e --- /dev/null +++ b/ansible/roles/providers/tasks/googlecompute.yml @@ -0,0 +1,47 @@ +# Copyright 2019 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Download gcloud SDK + get_url: + url: https://sdk.cloud.google.com/ + dest: /tmp/install-gcloud.sh + mode: 0700 + +- name: Execute install-gcloud.sh + shell: bash -o errexit -o pipefail /tmp/install-gcloud.sh --disable-prompts --install-dir=/ + +- name: Remove install-gcloud.sh + file: + path: /tmp/install-gcloud.sh + state: absent + +- name: Find all files in /google-cloud-sdk/bin/ + find: + paths: /google-cloud-sdk/bin/ + register: find + +- name: Create symlinks to /bin + become: True + file: + src: "{{ item.path }}" + path: "/bin/{{ item.path | basename }}" + state: link + with_items: "{{ find.files }}" + +- name: Disable Hyper-V KVP protocol daemon on Ubuntu + systemd: + name: hv-kvp-daemon + state: stopped + enabled: false + when: ansible_os_family == "Debian" diff --git a/ansible/roles/providers/tasks/main.yml b/ansible/roles/providers/tasks/main.yml new file mode 100644 index 0000000..17eba0f --- /dev/null +++ b/ansible/roles/providers/tasks/main.yml @@ -0,0 +1,120 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- include_tasks: aws.yml + when: packer_builder_type.startswith('amazon') + +- include_tasks: azure.yml + when: packer_builder_type.startswith('azure') + +- include_tasks: outscale.yml + when: packer_builder_type.startswith('outscale') + +- include_tasks: vmware.yml + when: packer_builder_type is search('vmware') or + packer_builder_type is search('vsphere') + +- include_tasks: googlecompute.yml + when: packer_builder_type.startswith('googlecompute') + +- include_tasks: oci.yml + when: packer_builder_type.startswith('oracle-oci') + +- include_tasks: qemu.yml + when: packer_builder_type is search('qemu') and + build_target is not search('raw') + +- include_tasks: cloudstack.yml + when: packer_builder_type is search('qemu') and + provider is defined and + provider is search('cloudstack') + +- include_tasks: raw.yml + when: packer_builder_type is search('qemu') and + build_target is search('raw') + +- include_tasks: nutanix.yml + when: packer_builder_type is search('nutanix') + +# Create a boot order configuration +# b/w containerd and cloud final, cloud config services + +- name: Creates unit file directory for cloud-final + file: + path: /etc/systemd/system/cloud-final.service.d + state: directory + +- name: Create cloud-final boot order drop in file + copy: + dest: /etc/systemd/system/cloud-final.service.d/boot-order.conf + src: etc/systemd/system/cloud-final.service.d/boot-order.conf + owner: root + group: root + mode: "0755" + +- name: Creates unit file directory for cloud-config + file: + path: /etc/systemd/system/cloud-config.service.d + state: directory + +- name: Create cloud-final boot order drop in file + copy: + dest: /etc/systemd/system/cloud-config.service.d/boot-order.conf + src: etc/systemd/system/cloud-config.service.d/boot-order.conf + owner: root + group: root + mode: "0755" + +# Some OS might disable cloud-final service on boot (rhel 7). +# Enable all cloud-init services on boot. +- name: Make sure all cloud init services are enabled + service: + name: "{{ item }}" + enabled: yes + with_items: + - cloud-final + - cloud-config + - cloud-init + - cloud-init-local + when: ansible_os_family != "Flatcar" + +- name: Create cloud-init config file + copy: + src: files/etc/cloud/cloud.cfg.d/05_logging.cfg + dest: /etc/cloud/cloud.cfg.d/05_logging.cfg + owner: root + group: root + mode: 0644 + when: ansible_os_family != "Flatcar" + +- name: set cloudinit feature flags + copy: + src: usr/lib/python3/dist-packages/cloudinit/feature_overrides.py + dest: /usr/lib/python3/dist-packages/cloudinit/feature_overrides.py + owner: root + group: root + mode: 0644 + when: ansible_os_family == "Debian" + +- name: Ensure chrony is running + systemd: + enabled: yes + state: started + daemon_reload: yes + name: chronyd + when: (packer_builder_type.startswith('amazon') or + packer_builder_type.startswith('azure') or + packer_builder_type is search('vmware') or + packer_builder_type is search('vsphere')) and + ansible_os_family != "Flatcar" diff --git a/ansible/roles/providers/tasks/nutanix.yml b/ansible/roles/providers/tasks/nutanix.yml new file mode 100644 index 0000000..9d3c0bc --- /dev/null +++ b/ansible/roles/providers/tasks/nutanix.yml @@ -0,0 +1,76 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Install cloud-init packages + apt: + name: "{{ packages }}" + state: present + force_apt_get: yes + vars: + packages: + - cloud-init + - cloud-guest-utils + - cloud-initramfs-copymods + - cloud-initramfs-dyn-netconf + when: ansible_os_family == "Debian" + +- name: Install cloud-init packages + yum: + name: "{{ packages }}" + state: present + vars: + packages: + - cloud-init + - cloud-utils-growpart + when: ansible_os_family == "RedHat" + +- name: Install CSI prerequisites on Ubuntu + apt: + name: "{{ packages }}" + state: present + force_apt_get: yes + vars: + packages: + - nfs-common + - open-iscsi + - lvm2 + - xfsprogs + when: ansible_os_family == "Debian" + +- name: Install CSI prerequisites on RedHat + yum: + name: "{{ packages }}" + state: present + vars: + packages: + - iscsi-initiator-utils + - nfs-utils + - lvm2 + - xfsprogs + when: ansible_os_family == "RedHat" + +- name: Enable iSCSI initiator daemon on Ubuntu or RedHat + systemd: + name: iscsid + state: started + enabled: true + when: ansible_os_family == "Debian" or + ansible_os_family == "RedHat" + +- name: Disable Hyper-V KVP protocol daemon on Ubuntu + systemd: + name: hv-kvp-daemon + state: stopped + enabled: false + when: ansible_os_family == "Debian" diff --git a/ansible/roles/providers/tasks/oci.yml b/ansible/roles/providers/tasks/oci.yml new file mode 100644 index 0000000..c6ce64b --- /dev/null +++ b/ansible/roles/providers/tasks/oci.yml @@ -0,0 +1,34 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Remove the default input reject all iptable rule + lineinfile: + path: /etc/iptables/rules.v4 + state: absent + regexp: "-A INPUT -j REJECT --reject-with icmp-host-prohibited" + when: ansible_distribution == "Ubuntu" + +- name: Remove the default input reject all iptable rule + lineinfile: + path: /etc/iptables/rules.v4 + state: absent + regexp: "-A FORWARD -j REJECT --reject-with icmp-host-prohibited" + when: ansible_distribution == "Ubuntu" + +- name: Disable firewalld service + systemd: + name: firewalld + state: stopped + enabled: false + when: ansible_distribution == "OracleLinux" \ No newline at end of file diff --git a/ansible/roles/providers/tasks/outscale.yml b/ansible/roles/providers/tasks/outscale.yml new file mode 100644 index 0000000..985b01c --- /dev/null +++ b/ansible/roles/providers/tasks/outscale.yml @@ -0,0 +1,24 @@ +- name: Download cloud-int outscale package for Ubuntu + copy: + src: files/tmp/cloud-init_22.2-outscale.deb + dest: /tmp/cloud-init_22.2-outscale.deb + owner: root + group: root + mode: 0755 + when: ansible_distribution == "Ubuntu" + +- name: Install cloud-init outscale package + apt: + deb: /tmp/cloud-init_22.2-outscale.deb + force: True + force_apt_get: True + when: ansible_distribution == "Ubuntu" + +- name: Change cloud-init metadata outscale config in Ubuntu + copy: + src: files/etc/cloud/cloud.cfg.d/99_metadata.cfg + dest: /etc/cloud/cloud.cfg.d/99_metadata.cfg + owner: root + group: root + mode: 0644 + when: ansible_distribution == "Ubuntu" diff --git a/ansible/roles/providers/tasks/qemu.yml b/ansible/roles/providers/tasks/qemu.yml new file mode 100644 index 0000000..23575f7 --- /dev/null +++ b/ansible/roles/providers/tasks/qemu.yml @@ -0,0 +1,49 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Install cloud-init packages + apt: + name: "{{ packages }}" + state: present + force_apt_get: yes + vars: + packages: + - cloud-init + - cloud-guest-utils + - cloud-initramfs-copymods + - cloud-initramfs-dyn-netconf + when: ansible_os_family == "Debian" + +- name: Install cloud-init packages + yum: + name: "{{ packages }}" + state: present + vars: + packages: + - cloud-init + - cloud-utils-growpart + when: ansible_os_family == "RedHat" + +#- name: Unlock password +# replace: +# path: /etc/cloud/cloud.cfg +# regexp: '(?i)lock_passwd: True' +# replace: 'lock_passwd: False' + +- name: Disable Hyper-V KVP protocol daemon on Ubuntu + systemd: + name: hv-kvp-daemon + state: stopped + enabled: false + when: ansible_os_family == "Debian" diff --git a/ansible/roles/providers/tasks/raw.yml b/ansible/roles/providers/tasks/raw.yml new file mode 100644 index 0000000..d52a270 --- /dev/null +++ b/ansible/roles/providers/tasks/raw.yml @@ -0,0 +1,57 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Install cloud-init packages + apt: + name: "{{ packages }}" + state: present + force_apt_get: yes + vars: + packages: + - cloud-init + - cloud-guest-utils + - cloud-initramfs-copymods + - cloud-initramfs-dyn-netconf + when: ansible_os_family == "Debian" + +- name: Install cloud-init packages + yum: + name: "{{ packages }}" + state: present + vars: + packages: + - cloud-init + - cloud-utils-growpart + when: ansible_os_family == "RedHat" + +#- name: Unlock password +# replace: +# path: /etc/cloud/cloud.cfg +# regexp: '(?i)lock_passwd: True' +# replace: 'lock_passwd: False' + +- name: Symlink /usr/libexec/cloud-init to /usr/lib/cloud-init + file: + src: /usr/libexec/cloud-init + dest: /usr/lib/cloud-init + mode: 0777 + state: link + when: ansible_os_family == "RedHat" + +- name: Disable Hyper-V KVP protocol daemon on Ubuntu + systemd: + name: hv-kvp-daemon + state: stopped + enabled: false + when: ansible_os_family == "Debian" diff --git a/ansible/roles/providers/tasks/redhat.yml b/ansible/roles/providers/tasks/redhat.yml new file mode 100644 index 0000000..7c3f8f9 --- /dev/null +++ b/ansible/roles/providers/tasks/redhat.yml @@ -0,0 +1,30 @@ +# Copyright 2019 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: import the Microsoft repository key + command: rpm --import https://packages.microsoft.com/keys/microsoft.asc + +- name: Add the yum repository for the azure cli + yum_repository: + name: azure_cli + description: Azure CLI + baseurl: https://packages.microsoft.com/yumrepos/azure-cli + gpgkey: https://packages.microsoft.com/keys/microsoft.asc + gpgcheck: yes + enabled: yes + +- name: install Azure CLI + package: + name: azure-cli + state: present diff --git a/ansible/roles/providers/tasks/vmware-photon.yml b/ansible/roles/providers/tasks/vmware-photon.yml new file mode 100644 index 0000000..a609141 --- /dev/null +++ b/ansible/roles/providers/tasks/vmware-photon.yml @@ -0,0 +1,79 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +- name: Install cloud-init and tools for VMware Photon OS + command: tdnf install {{ packages }} -y + vars: + packages: "cloud-init cloud-utils python3-netifaces" + +- name: Remove cloud-init /etc/cloud/cloud.cfg.d/99-disable-networking-config.cfg + file: + path: /etc/cloud/cloud.cfg.d/99-disable-networking-config.cfg + state: absent + +- name: Install networkd-dispatcher service (Download from source) + unarchive: + src: "{{ networkd_dispatcher_download_url }}" + dest: /tmp + remote_src: yes + +- name: Create needed directories + file: + path: "{{ item.dir }}" + state: directory + loop: + - { dir: /etc/conf.d } + - { dir: /etc/networkd-dispatcher/carrier.d } + - { dir: /etc/networkd-dispatcher/configured.d } + - { dir: /etc/networkd-dispatcher/configuring.d } + - { dir: /etc/networkd-dispatcher/degraded.d } + - { dir: /etc/networkd-dispatcher/dormant.d } + - { dir: /etc/networkd-dispatcher/no-carrier.d } + - { dir: /etc/networkd-dispatcher/off.d } + - { dir: /etc/networkd-dispatcher/routable.d } + +- name: Install networkd-dispatcher service (Move files) + command: mv "{{ item.src }}" "{{ item.dest }}" + loop: + - { src: /tmp/networkd-dispatcher-2.1/networkd-dispatcher, dest: /usr/bin } + - { src: /tmp/networkd-dispatcher-2.1/networkd-dispatcher.service, dest: /etc/systemd/system } + - { src: /tmp/networkd-dispatcher-2.1/networkd-dispatcher.conf, dest: /etc/conf.d } + +- name: Install networkd-dispatcher service (Run networkd-dispatcher) + systemd: + name: networkd-dispatcher + state: started + enabled: yes + +- name: Copy networkd-dispatcher scripts to add DHCP provided NTP servers + template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + mode: a+x + vars: + server_dir: "/var/lib/dhclient" + chrony_helper_dir: "/usr/libexec" + loop: + - { src: files/etc/networkd-dispatcher/routable.d/20-chrony.j2, dest: /etc/networkd-dispatcher/routable.d/20-chrony } + - { src: files/etc/networkd-dispatcher/off.d/20-chrony.j2, dest: /etc/networkd-dispatcher/off.d/20-chrony } + - { src: files/etc/networkd-dispatcher/no-carrier.d/20-chrony.j2, dest: /etc/networkd-dispatcher/no-carrier.d/20-chrony } + +- name: Copy chrony-helper script + copy: + src: files/usr/libexec/chrony-helper + dest: /usr/libexec/chrony-helper + owner: root + group: root + mode: a+x diff --git a/ansible/roles/providers/tasks/vmware-redhat.yml b/ansible/roles/providers/tasks/vmware-redhat.yml new file mode 100644 index 0000000..0047e90 --- /dev/null +++ b/ansible/roles/providers/tasks/vmware-redhat.yml @@ -0,0 +1,51 @@ +# Copyright 2022 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +- name: Install cloud-init packages + yum: + name: "{{ packages }}" + state: present + vars: + packages: + - cloud-init + - cloud-utils-growpart + - python2-pip + +# pip on CentOS needs to be upgraded, but since it's still +# Python 2.7, need < 21.0 +- name: Upgrade pip + pip: + name: pip<21.0 + state: forcereinstall + when: ansible_distribution_major_version == '7' + +# Directly installing Guestinfo datasource is needed so long as +# cloud-init is < 21.3 +- name: Download cloud-init datasource for VMware Guestinfo + get_url: + url: '{{ guestinfo_datasource_script }}' + dest: /tmp/cloud-init-vmware.sh + mode: 0700 + +- name: Execute cloud-init-vmware.sh + shell: bash -o errexit -o pipefail /tmp/cloud-init-vmware.sh + environment: + REPO_SLUG: '{{ guestinfo_datasource_slug }}' + GIT_REF: '{{ guestinfo_datasource_ref }}' + +- name: Remove cloud-init-vmware.sh + file: + path: /tmp/cloud-init-vmware.sh + state: absent diff --git a/ansible/roles/providers/tasks/vmware-ubuntu.yml b/ansible/roles/providers/tasks/vmware-ubuntu.yml new file mode 100644 index 0000000..f9aacdb --- /dev/null +++ b/ansible/roles/providers/tasks/vmware-ubuntu.yml @@ -0,0 +1,45 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +- name: Install cloud-init packages + apt: + name: "{{ packages }}" + state: present + force_apt_get: yes + vars: + packages: + - cloud-init + - cloud-guest-utils + - cloud-initramfs-copymods + - cloud-initramfs-dyn-netconf + +- name: Disable Hyper-V KVP protocol daemon on Ubuntu + systemd: + name: hv-kvp-daemon + state: stopped + enabled: false + +- name: Copy networkd-dispatcher scripts to add DHCP provided NTP servers + template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + mode: a+x + vars: + server_dir: "/var/lib/dhcp" + chrony_helper_dir: "/usr/lib/chrony" + loop: + - { src: files/etc/networkd-dispatcher/routable.d/20-chrony.j2, dest: /etc/networkd-dispatcher/routable.d/20-chrony } + - { src: files/etc/networkd-dispatcher/off.d/20-chrony.j2, dest: /etc/networkd-dispatcher/off.d/20-chrony } + - { src: files/etc/networkd-dispatcher/no-carrier.d/20-chrony.j2, dest: /etc/networkd-dispatcher/no-carrier.d/20-chrony } diff --git a/ansible/roles/providers/tasks/vmware.yml b/ansible/roles/providers/tasks/vmware.yml new file mode 100644 index 0000000..00478a9 --- /dev/null +++ b/ansible/roles/providers/tasks/vmware.yml @@ -0,0 +1,57 @@ +# Copyright 2019 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- include_tasks: vmware-photon.yml + when: ansible_os_family == "VMware Photon OS" + +- include_tasks: vmware-ubuntu.yml + when: ansible_os_family == "Debian" + +- include_tasks: vmware-redhat.yml + when: ansible_os_family == "RedHat" + +- name: Create provider vmtools config drop-in file + copy: + src: files/etc/vmware-tools/tools.conf + dest: /etc/vmware-tools/tools.conf + owner: root + group: root + mode: 0644 + when: ansible_os_family != "Flatcar" + +- name: Create service to modify cloud-init config + copy: + src: files/etc/systemd/system/modify-cloud-init-cfg.service + dest: /etc/systemd/system/modify-cloud-init-cfg.service + owner: root + group: root + mode: 0644 + when: ansible_os_family != "Flatcar" + +- name: Copy cloud-init modification script + copy: + src: files/usr/local/bin/modify-cloud-init-cfg.sh + dest: /usr/local/bin/modify-cloud-init-cfg.sh + owner: root + group: root + mode: 0755 + when: ansible_os_family != "Flatcar" + +- name: Enable modify-cloud-init-cfg.service + systemd: + name: modify-cloud-init-cfg.service + daemon_reload: yes + enabled: True + state: stopped + when: ansible_os_family != "Flatcar" diff --git a/ansible/roles/python/defaults/main.yml b/ansible/roles/python/defaults/main.yml new file mode 100644 index 0000000..ee1d14b --- /dev/null +++ b/ansible/roles/python/defaults/main.yml @@ -0,0 +1,19 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +pypy_python_version: "3.6" +pypy_version: "7.2.0" +pypy_download_path: "/tmp/pypy.tar.bz2" +pypy_install_path: "/opt" diff --git a/ansible/roles/python/tasks/flatcar.yml b/ansible/roles/python/tasks/flatcar.yml new file mode 100644 index 0000000..54e8bfa --- /dev/null +++ b/ansible/roles/python/tasks/flatcar.yml @@ -0,0 +1,30 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Check if pypy is installed + raw: "[ -f {{ pypy_install_path }}/pypy/bin/pypy ] && echo 'true' || echo 'false'" + register: pypy_installed + +- name: Install pypy + block: + - name: Download pypy archive + raw: "curl https://github.com/squeaky-pl/portable-pypy/releases/download/pypy{{ pypy_python_version }}-{{ pypy_version }}/pypy{{ pypy_python_version }}-{{ pypy_version }}-linux_x86_64-portable.tar.bz2 -L --output {{ pypy_download_path }}" + - name: Extract archive + raw: "tar -xjf {{ pypy_download_path }} -C {{ pypy_install_path }}" + - name: Rename pypy folder + raw: "mv {{ pypy_install_path }}/pypy{{ pypy_python_version }}-{{ pypy_version }}-linux_x86_64-portable/ {{ pypy_install_path }}/pypy" + - name: Delete downloaded archive + raw: "rm -f {{ pypy_download_path }}" + when: + - pypy_installed.stdout_lines[0] == "false" diff --git a/ansible/roles/python/tasks/main.yml b/ansible/roles/python/tasks/main.yml new file mode 100644 index 0000000..b111aba --- /dev/null +++ b/ansible/roles/python/tasks/main.yml @@ -0,0 +1,22 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Get distribution name from lsb-release + raw: "grep DISTRIB_ID /etc/lsb-release || echo '/etc/lsb-release not found'" + register: distrib_id + +- include_tasks: flatcar.yml + # We can't use ansible_os_family fact here for consistency, as facts gathering + # is disabled in the playbook which includes this role. See playbook for more details. + when: distrib_id.stdout_lines[0] is search("Flatcar") diff --git a/ansible/roles/setup/defaults/main.yml b/ansible/roles/setup/defaults/main.yml new file mode 100644 index 0000000..82ba314 --- /dev/null +++ b/ansible/roles/setup/defaults/main.yml @@ -0,0 +1,27 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +debs: "" +extra_debs: "" +pinned_debs: [] + +redhat_epel_rpm: "https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm" +epel_rpm_gpg_key: "https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7" +rpms: "" +extra_rpms: "" + +disable_public_repos: false +external_binary_path: "{{ '/opt/bin' if ansible_os_family == 'Flatcar' else '/usr/local/bin' }}" +extra_repos: "" +pip_conf_file: "" diff --git a/ansible/roles/setup/files/etc/systemd/system-environment-generators/10-flatcar-path b/ansible/roles/setup/files/etc/systemd/system-environment-generators/10-flatcar-path new file mode 100755 index 0000000..1b34da6 --- /dev/null +++ b/ansible/roles/setup/files/etc/systemd/system-environment-generators/10-flatcar-path @@ -0,0 +1,3 @@ +#!/bin/bash +. /etc/profile +echo "PATH=$PATH" diff --git a/ansible/roles/setup/files/etc/systemd/system/usr-libexec.mount b/ansible/roles/setup/files/etc/systemd/system/usr-libexec.mount new file mode 100644 index 0000000..cd0dedf --- /dev/null +++ b/ansible/roles/setup/files/etc/systemd/system/usr-libexec.mount @@ -0,0 +1,11 @@ +[Unit] +Description=Kubernetes flex volume plugin directory + +[Mount] +What=overlay +Where=/usr/libexec +Type=overlay +Options=lowerdir=/usr/libexec,workdir=/opt/libexec.work,upperdir=/opt/libexec + +[Install] +WantedBy=multi-user.target diff --git a/ansible/roles/setup/tasks/bootstrap-flatcar.yml b/ansible/roles/setup/tasks/bootstrap-flatcar.yml new file mode 100644 index 0000000..a2468d2 --- /dev/null +++ b/ansible/roles/setup/tasks/bootstrap-flatcar.yml @@ -0,0 +1,28 @@ +--- +# Flatcar ships without Python installed + +- name: Check if bootstrap is needed + raw: stat /opt/bin/.bootstrapped + register: need_bootstrap + environment: {} + failed_when: false + changed_when: false + tags: + - facts + +- name: Set the ansible_python_interpreter fact + set_fact: + ansible_python_interpreter: "{{ external_binary_path }}/python" + tags: + - facts + +# Some tasks are not compatible with Flatcar, so to centralize and deduplicate the logic of checking +# if we run on Flatcar, we define it here. +# +# This is required until https://github.com/ansible/ansible/issues/77537 is fixed and used. +- name: Override Flatcar's OS family + set_fact: + ansible_os_family: Flatcar + when: ansible_os_family == "Flatcar Container Linux by Kinvolk" + tags: + - facts diff --git a/ansible/roles/setup/tasks/debian.yml b/ansible/roles/setup/tasks/debian.yml new file mode 100644 index 0000000..5b306e7 --- /dev/null +++ b/ansible/roles/setup/tasks/debian.yml @@ -0,0 +1,105 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Put templated sources.list in place + template: + src: etc/apt/sources.list.j2 + dest: /etc/apt/sources.list + mode: 0644 + # OCI Base images have the required apt sources list embedded inside the image, adding the sources list + # from this repo leads to build failures(especially in Arm), hence ignoring the step. + when: packer_builder_type != "oracle-oci" + +- name: Put templated apt.conf.d/90proxy in place when defined + template: + src: etc/apt/apt.conf.d/90proxy + dest: /etc/apt/apt.conf.d/90proxy + mode: 0644 + when: http_proxy is defined or https_proxy is defined + +- name: Ensure cloud-final is in a running state + service: + name: cloud-final + state: started + check_mode: yes + register: cloudfinalstatus + until: cloudfinalstatus.status.ActiveState == "active" + retries: 5 + delay: 10 + when: packer_builder_type == "oracle-oci" and extra_repos != "" + +- name: Find existing repo files + find: + depth: 1 + paths: + - /etc/apt + - /etc/apt/sources.list.d + patterns: '*.list' + register: repo_files + when: disable_public_repos|bool + +- name: Disable repos + command: "mv {{ item.path }} {{ item.path }}.disabled" + loop: "{{ repo_files.files }}" + when: disable_public_repos|bool + +- name: Install extra repos + copy: + src: "{{ item }}" + dest: "/etc/apt/sources.list.d/{{ item | basename }}" + mode: 0644 + loop: "{{ extra_repos.split() }}" + when: extra_repos != "" + +- name: perform a dist-upgrade + apt: + force_apt_get: True + update_cache: True + upgrade: dist + register: apt_lock_status + until: apt_lock_status is not failed + retries: 5 + delay: 10 + +- name: install baseline dependencies + apt: + force_apt_get: True + update_cache: True + name: "{{ debs }}" + state: latest + register: apt_lock_status + until: apt_lock_status is not failed + retries: 5 + delay: 10 + +- name: install extra debs + apt: + force_apt_get: True + name: "{{ extra_debs.split() }}" + state: latest + register: apt_lock_status + until: apt_lock_status is not failed + retries: 5 + delay: 10 + +- name: install pinned debs + apt: + force_apt_get: True + name: "{{ pinned_debs }}" + state: present + force: yes + register: apt_lock_status + until: apt_lock_status is not failed + retries: 5 + delay: 10 diff --git a/ansible/roles/setup/tasks/flatcar.yml b/ansible/roles/setup/tasks/flatcar.yml new file mode 100644 index 0000000..ec842d5 --- /dev/null +++ b/ansible/roles/setup/tasks/flatcar.yml @@ -0,0 +1,55 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- include_tasks: bootstrap-flatcar.yml + +- name: Create /opt/libexec overlay directories + file: + path: "{{ item }}" + state: directory + with_items: + - /opt/libexec + - /opt/libexec.work + +- name: Create usr-libexec.mount unit + copy: + src: etc/systemd/system/usr-libexec.mount + dest: /etc/systemd/system/usr-libexec.mount + owner: root + group: root + mode: "0644" + +- name: Enable usr-libexec.mount unit + systemd: + daemon_reload: yes + enabled: yes + name: usr-libexec.mount + +- name: Create system-environment-generators directory + file: + path: /etc/systemd/system-environment-generators + state: directory + +- name: Add env generator that includes system PATH on service path + copy: + src: etc/systemd/system-environment-generators/10-flatcar-path + dest: /etc/systemd/system-environment-generators/10-flatcar-path + owner: root + group: root + mode: "0755" + +- name: Enable systemd-timesyncd unit + systemd: + enabled: yes + name: systemd-timesyncd.service diff --git a/ansible/roles/setup/tasks/main.yml b/ansible/roles/setup/tasks/main.yml new file mode 100644 index 0000000..ca48161 --- /dev/null +++ b/ansible/roles/setup/tasks/main.yml @@ -0,0 +1,36 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- import_tasks: debian.yml + when: ansible_os_family == "Debian" + +- import_tasks: flatcar.yml + # This task overrides ansible_os_family to "Flatcar" as a workaround for + # regression between Flatcar and Ansible, so rest of the code can use just + # "Flatcar" for comparison, which is the correct value. + when: ansible_os_family in ["Flatcar", "Flatcar Container Linux by Kinvolk"] + +- import_tasks: redhat.yml + when: ansible_os_family == "RedHat" + +- import_tasks: photon.yml + when: ansible_os_family == "VMware Photon OS" + +# Copy in pip config file when defined +- name: Install pip config file + copy: + src: "{{ pip_conf_file }}" + dest: /etc/pip.conf + mode: 0644 + when: pip_conf_file != "" diff --git a/ansible/roles/setup/tasks/photon.yml b/ansible/roles/setup/tasks/photon.yml new file mode 100644 index 0000000..239b96e --- /dev/null +++ b/ansible/roles/setup/tasks/photon.yml @@ -0,0 +1,61 @@ +# Copyright 2019 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: add bash_profile + template: + dest: /home/builder/.bash_profile + src: photon_bash_profile + mode: 0600 + owner: builder + group: builder + +- import_tasks: rpm_repos.yml + +- name: Perform a tdnf distro-sync + command: tdnf distro-sync -y --refresh + register: distro + changed_when: '"Nothing to do" not in distro.stderr' + +- name: Concatenate the Photon RPMs + set_fact: + photon_rpms: "{{ rpms | join(' ') }}" + +- name: install baseline dependencies + command: tdnf install {{ photon_rpms }} -y + when: photon_rpms != "" + +- name: install extra RPMs + command: tdnf install {{ extra_rpms }} -y + when: extra_rpms != "" + +# Default size of 1G is insufficient when downloading additional components +- name: Increase tmpfs size + mount: + path: /tmp + src: "tmpfs" + fstype: tmpfs + opts: "size=5G" + state: remounted + +- name: reset iptables rules input + replace: + path: /etc/systemd/scripts/ip4save + regexp: 'INPUT DROP' + replace: 'INPUT ACCEPT' + +- name: reset ip6tables rules input + replace: + path: /etc/systemd/scripts/ip6save + regexp: 'INPUT DROP' + replace: 'INPUT ACCEPT' diff --git a/ansible/roles/setup/tasks/redhat.yml b/ansible/roles/setup/tasks/redhat.yml new file mode 100644 index 0000000..2914fa8 --- /dev/null +++ b/ansible/roles/setup/tasks/redhat.yml @@ -0,0 +1,54 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: RHEL subscription + redhat_subscription: + state: present + username: "{{ lookup('env', 'RHSM_USER') }}" + password: "{{ lookup('env', 'RHSM_PASS') }}" + auto_attach: true + when: ansible_distribution == "RedHat" + +- name: import epel gpg key + rpm_key: + state: present + key: "{{ epel_rpm_gpg_key }}" + when: epel_rpm_gpg_key != "" + +- name: add epel repo + yum: + name: "{{ redhat_epel_rpm }}" + state: present + lock_timeout: 60 + when: redhat_epel_rpm != "" + +- import_tasks: rpm_repos.yml + +- name: perform a yum update + yum: + name: '*' + state: latest + lock_timeout: 60 + +- name: install baseline dependencies + yum: + name: "{{ rpms }}" + state: present + lock_timeout: 60 + +- name: install extra rpms + yum: + name: "{{ extra_rpms.split() }}" + state: present + lock_timeout: 60 diff --git a/ansible/roles/setup/tasks/rpm_repos.yml b/ansible/roles/setup/tasks/rpm_repos.yml new file mode 100644 index 0000000..6de5c1a --- /dev/null +++ b/ansible/roles/setup/tasks/rpm_repos.yml @@ -0,0 +1,34 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Find existing repo files + find: + depth: 1 + paths: /etc/yum.repos.d + patterns: '*.repo' + register: repo_files + when: disable_public_repos|bool + +- name: Disable repos + command: "mv {{ item.path }} {{ item.path }}.disabled" + loop: "{{ repo_files.files }}" + when: disable_public_repos|bool + +- name: Install extra repos + copy: + src: "{{ item }}" + dest: "/etc/yum.repos.d/{{ item | basename }}" + mode: 0644 + loop: "{{ extra_repos.split() }}" + when: extra_repos != "" diff --git a/ansible/roles/setup/templates/etc/apt/apt.conf.d/90proxy b/ansible/roles/setup/templates/etc/apt/apt.conf.d/90proxy new file mode 100644 index 0000000..9ce93c3 --- /dev/null +++ b/ansible/roles/setup/templates/etc/apt/apt.conf.d/90proxy @@ -0,0 +1,8 @@ +Acquire { +{% if http_proxy %} + http::Proxy "{{ http_proxy }}"; +{% endif %} +{% if https_proxy %} + https::Proxy "{{ https_proxy }}"; +{% endif %} +} \ No newline at end of file diff --git a/ansible/roles/setup/templates/etc/apt/sources.list.j2 b/ansible/roles/setup/templates/etc/apt/sources.list.j2 new file mode 100644 index 0000000..7df6804 --- /dev/null +++ b/ansible/roles/setup/templates/etc/apt/sources.list.j2 @@ -0,0 +1,4 @@ +deb http://us.archive.ubuntu.com/ubuntu {{ ansible_distribution_release }} main restricted universe +deb http://us.archive.ubuntu.com/ubuntu {{ ansible_distribution_release }}-updates main restricted universe +deb http://us.archive.ubuntu.com/ubuntu {{ ansible_distribution_release }}-backports main restricted universe +deb http://security.ubuntu.com/ubuntu {{ ansible_distribution_release }}-security main restricted universe diff --git a/ansible/roles/setup/templates/photon_bash_profile b/ansible/roles/setup/templates/photon_bash_profile new file mode 100644 index 0000000..5a1a919 --- /dev/null +++ b/ansible/roles/setup/templates/photon_bash_profile @@ -0,0 +1,2 @@ +PATH=$PATH:/usr/sbin:/usr/local/sbin +export PATH diff --git a/ansible/roles/sysprep/defaults/main.yml b/ansible/roles/sysprep/defaults/main.yml new file mode 100644 index 0000000..326dfd5 --- /dev/null +++ b/ansible/roles/sysprep/defaults/main.yml @@ -0,0 +1,17 @@ +# Copyright 2019 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +extra_repos: "" +pip_conf_file: "" +remove_extra_repos: false diff --git a/ansible/roles/sysprep/files/etc/hosts b/ansible/roles/sysprep/files/etc/hosts new file mode 100644 index 0000000..593cbd9 --- /dev/null +++ b/ansible/roles/sysprep/files/etc/hosts @@ -0,0 +1,2 @@ +127.0.0.1 localhost localhost.local +::1 localhost ip6-localhost ip6-loopback diff --git a/ansible/roles/sysprep/files/etc/netplan/51-kubevirt-netplan.yaml b/ansible/roles/sysprep/files/etc/netplan/51-kubevirt-netplan.yaml new file mode 100644 index 0000000..c6f9327 --- /dev/null +++ b/ansible/roles/sysprep/files/etc/netplan/51-kubevirt-netplan.yaml @@ -0,0 +1,7 @@ +network: + version: 2 + ethernets: + id0: + match: + name: enp*s* + dhcp4: true diff --git a/ansible/roles/sysprep/tasks/debian.yml b/ansible/roles/sysprep/tasks/debian.yml new file mode 100644 index 0000000..05f3a3c --- /dev/null +++ b/ansible/roles/sysprep/tasks/debian.yml @@ -0,0 +1,95 @@ +# Copyright 2019 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Define file modes + set_fact: + last_log_mode: "0664" + machine_id_mode: "0644" + +- name: apt-mark all installed packages + shell: dpkg-query -f '${binary:Package}\n' -W | xargs apt-mark hold + +- name: Remove extra repos + file: + path: "/etc/apt/sources.list.d/{{ item | basename }}" + state: absent + loop: "{{ extra_repos.split() }}" + when: remove_extra_repos and extra_repos != "" + +- name: Find disabled repo files + find: + depth: 1 + paths: + - /etc/apt + - /etc/apt/sources.list.d + patterns: '*.list.disabled' + register: repo_files + when: disable_public_repos|default(false)|bool and reenable_public_repos|default(true)|bool + +- name: Enable repos + command: "mv {{ item.path }} {{ item.path | regex_replace('.disabled') }}" + loop: "{{ repo_files.files }}" + when: disable_public_repos|default(false)|bool and reenable_public_repos|default(true)|bool + +- name: Remove templated apt.conf.d/90proxy used for http(s)_proxy support + file: + path: etc/apt/apt.conf.d/90proxy + state: absent + when: http_proxy is defined or https_proxy is defined + +- name: Stop auditing + service: + name: rsyslog + state: stopped + +- name: Remove apt package caches + apt: + autoclean: yes + autoremove: yes + force_apt_get: yes + +- name: Remove apt package lists + file: + state: "{{ item.state }}" + path: "{{ item.path }}" + owner: root + group: root + mode: "{{ item.mode }}" + loop: + - { path: /var/lib/apt/lists, state: absent, mode: "0755" } + - { path: /var/lib/apt/lists, state: directory, mode: "0755" } + +- name: Disable apt-daily services + systemd: + name: "{{ item }}" + state: stopped + enabled: false + loop: + - apt-daily.timer + - apt-daily-upgrade.timer + +- name: Get installed packages + package_facts: + +- name: Disable unattended upgrades if installed + systemd: + name: unattended-upgrades + state: stopped + enabled: false + when: "'unattended-upgrades' in ansible_facts.packages" + +- name: Reset network interface IDs + file: + state: absent + path: /etc/udev/rules.d/70-persistent-net.rules diff --git a/ansible/roles/sysprep/tasks/flatcar.yml b/ansible/roles/sysprep/tasks/flatcar.yml new file mode 100644 index 0000000..8854d29 --- /dev/null +++ b/ansible/roles/sysprep/tasks/flatcar.yml @@ -0,0 +1,57 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Define file modes + set_fact: + last_log_mode: "0644" + machine_id_mode: "0444" + +- name: Invalidate the machine-id file for systemd to reevaluate presets + file: + path: /etc/machine-id + state: absent + +- name: Stop and mask update-engine to freeze the image version + systemd: + name: update-engine + state: stopped + enabled: no + masked: yes + +- name: Stop and mask the locksmith reboot manager since it depends on update-engine + systemd: + name: locksmithd + state: stopped + enabled: no + masked: yes + +- name: Mask docker + systemd: + name: "{{ item }}" + state: stopped + enabled: no + masked: yes + with_items: + - docker.socket + - docker.service + +- name: Set cgroup v1 to match the cgroupfs driver in containerd and kubelet + shell: | + echo 'set linux_append="$linux_append systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"' >> /usr/share/oem/grub.cfg + when: kubernetes_semver is version('v1.21.0', '<') + +- name: Set oem_id in grub + shell: | + echo 'set oem_id="{{oem_id}}"' >> /usr/share/oem/grub.cfg + when: (oem_id is defined) and (oem_id != "") diff --git a/ansible/roles/sysprep/tasks/main.yml b/ansible/roles/sysprep/tasks/main.yml new file mode 100644 index 0000000..04a07ad --- /dev/null +++ b/ansible/roles/sysprep/tasks/main.yml @@ -0,0 +1,234 @@ +# Copyright 2019 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- import_tasks: debian.yml + when: ansible_os_family == "Debian" + +- import_tasks: flatcar.yml + when: ansible_os_family == "Flatcar" + +- import_tasks: redhat.yml + when: ansible_os_family == "RedHat" + +- import_tasks: photon.yml + when: ansible_os_family == "VMware Photon OS" + +- name: Remove containerd http proxy conf file if needed + file: + path: /etc/systemd/system/containerd.service.d/http-proxy.conf + state: absent + when: http_proxy is defined or https_proxy is defined + +- name: Remove pip conf file if needed + file: + path: /etc/pip.conf + state: absent + when: remove_extra_repos and pip_conf_file != "" + +- name: Truncate machine id + file: + state: "{{ item.state }}" + path: "{{ item.path }}" + owner: root + group: root + mode: "{{ item.mode }}" + loop: + - { path: /etc/machine-id, state: absent, mode: "{{ machine_id_mode }}" } + - { path: /etc/machine-id, state: touch, mode: "{{ machine_id_mode }}" } + when: ansible_os_family != "Flatcar" + +- name: Truncate hostname file + file: + state: "{{ item.state }}" + path: "{{ item.path }}" + owner: root + group: root + mode: "{{ item.mode }}" + loop: + - { path: /etc/hostname, state: absent, mode: "0644" } + - { path: /etc/hostname, state: touch, mode: "0644" } + +- name: Set hostname + hostname: + name: localhost.local + when: ansible_os_family != "VMware Photon OS" and ansible_os_family != "Flatcar" and packer_build_name != "nutanix" + +- name: Reset hosts file + copy: + src: files/etc/hosts + dest: /etc/hosts + owner: root + group: root + mode: "0644" + +- name: Truncate audit logs + file: + state: "{{ item.state }}" + path: "{{ item.path }}" + owner: root + group: utmp + mode: "{{ item.mode }}" + loop: + - { path: /var/log/wtmp, state: absent, mode: "0664" } + - { path: /var/log/lastlog, state: absent, mode: "{{ last_log_mode }}" } + - { path: /var/log/wtmp, state: touch, mode: "0664" } + - { path: /var/log/lastlog, state: touch, mode: "{{ last_log_mode }}" } + +- name: Remove cloud-init lib dir and logs + file: + state: absent + path: "{{ item }}" + loop: + - /var/lib/cloud + - /var/log/cloud-init.log + - /var/log/cloud-init-output.log + - /var/run/cloud-init + +# A shallow search in /tmp and /var/tmp is used to declare which files or +# directories will be removed as part of resetting temp space. The reason +# a state absent->directory task isn't used is because Ansible's own data +# directory on the remote host(s) is /tmp/.ansible. Thus, by removing /tmp, +# Ansible can no longer access the remote host. +- name: Find temp files + find: + depth: 1 + file_type: any + paths: + - /tmp + - /var/tmp + pattern: '*' + register: temp_files + +- name: Reset temp space + file: + state: absent + path: "{{ item.path }}" + loop: "{{ temp_files.files }}" + +- name: Find netplan files + find: + depth: 1 + file_type: any + paths: + - /lib/netplan + - /etc/netplan + - /run/netplan + pattern: '*.yaml' + register: netplan_files + +- name: Delete netplan files + file: + state: absent + path: "{{ item.path }}" + loop: "{{ netplan_files.files }}" + when: netplan_files.files is defined and (netplan_files.files|length>0) + +- name: Create netplan for KubeVirt + vars: + kubevirt: "{{ lookup('env', 'KUBEVIRT') }}" + copy: + src: files/etc/netplan/51-kubevirt-netplan.yaml + dest: /etc/netplan/51-kubevirt-netplan.yaml + mode: "0644" + when: ansible_os_family == "Debian" and kubevirt == "true" + +- name: Find SSH host keys + find: + path: /etc/ssh + pattern: 'ssh_host_*' + register: ssh_host_keys + +- name: Remove SSH host keys + file: + state: absent + path: "{{ item.path }}" + loop: "{{ ssh_host_keys.files }}" + +- name: Remove SSH authorized users + file: + state: absent + path: "{{ item.path }}" + loop: + - { path: /root/.ssh/authorized_keys } + - { path: "/home/{{ ansible_env.SUDO_USER | default(ansible_user_id) }}/.ssh/authorized_keys" } + when: ansible_os_family != "Flatcar" + +- name: Remove SSH authorized users for Flatcar + file: + state: absent + path: "{{ item.path }}" + loop: + - { path: /root/.ssh/authorized_keys } + when: ansible_os_family == "Flatcar" + + +- name: Truncate all remaining log files in /var/log + shell: + cmd: | + find /var/log -type f -iname '*.log' | xargs truncate -s 0 + when: ansible_os_family != "Flatcar" + +- name: Delete all logrotated log zips + shell: + cmd: | + find /var/log -type f -name '*.gz' -exec rm {} + + when: ansible_os_family != "Flatcar" + +- name: Remove swapfile + file: + state: "{{ item.state }}" + path: "{{ item.path }}" + loop: + - { path: /swapfile, state: absent } + - { path: /mnt/resource/swapfile, state: absent } + when: ansible_memory_mb.swap.total != 0 + +- name: Truncate shell history + file: + state: absent + path: "{{ item.path }}" + loop: + - { path: /root/.bash_history } + - { path: "/home/{{ ansible_env.SUDO_USER | default(ansible_user_id) }}/.bash_history" } + +- name: Rotate journalctl to archive logs + shell: + cmd: | + journalctl --rotate + when: not ( ansible_os_family == "RedHat" and ansible_distribution_major_version|int <= 7 ) + +- name: Remove archived journalctl logs + shell: + cmd: | + journalctl -m --vacuum-time=1s + +- name: Ensure ignition runs on next boot + file: + state: touch + path: /boot/flatcar/first_boot + owner: root + group: root + when: ansible_os_family == "Flatcar" + +- name: Remove any default Ignition files used by Packer + file: + state: absent + path: /usr/share/oem/config.ign + when: ansible_os_family == "Flatcar" + +- name: start ssh + systemd: + name: ssh + enabled: yes + when: ansible_os_family == "Debian" diff --git a/ansible/roles/sysprep/tasks/photon.yml b/ansible/roles/sysprep/tasks/photon.yml new file mode 100644 index 0000000..4a626bc --- /dev/null +++ b/ansible/roles/sysprep/tasks/photon.yml @@ -0,0 +1,50 @@ +# Copyright 2019 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Define file modes + set_fact: + last_log_mode: "0644" + machine_id_mode: "0444" + +- name: set hostname + command: hostnamectl set-hostname localhost.local + +- name: Remove the kickstart log + file: + state: absent + path: /root/anaconda-ks.cfg + +- name: Get installed packages + shell: tdnf list installed | cut -d ' ' -f 1 + register: packages + +- name: create a package list + set_fact: + package_list: "{{ packages.stdout_lines | join(' ') }}" + +- name: exclude packages from upgrade + lineinfile: + path: /etc/tdnf/tdnf.conf + regexp: '^excludepkgs=' + line: excludepkgs={{ package_list }} + +- import_tasks: rpm_repos.yml + +- name: Remove tdnf package caches + command: /usr/bin/tdnf -y clean all + +- name: Lock root account + user: + name: root + password_lock: yes diff --git a/ansible/roles/sysprep/tasks/redhat.yml b/ansible/roles/sysprep/tasks/redhat.yml new file mode 100644 index 0000000..5886192 --- /dev/null +++ b/ansible/roles/sysprep/tasks/redhat.yml @@ -0,0 +1,79 @@ +# Copyright 2019 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Define file modes + set_fact: + last_log_mode: "0644" + machine_id_mode: "0444" + +- name: Get installed packages + package_facts: + +- name: create the package list + set_fact: + package_list: "{{ ansible_facts.packages.keys() | join(' ') }}" + +- name: exclude the packages from upgrades + lineinfile: + path: /etc/yum.conf + regexp: '^exclude=' + line: exclude={{ package_list }} + +- import_tasks: rpm_repos.yml + +# Oracle Linux does not have temp-disk-swapfile service +- name: Disable swap service and ensure it is masked + systemd: + name: temp-disk-swapfile + enabled: no + masked: yes + when: ansible_memory_mb.swap.total != 0 and ansible_distribution_major_version|int <= 7 + +- name: Disable swap service and ensure it is masked on RHEL 8 + systemd: + name: swap.target + enabled: no + masked: yes + when: ansible_memory_mb.swap.total != 0 and ansible_distribution_major_version|int == 8 + +- name: Remove RHEL subscription + block: + - name: enable repo mgmt with subscription-manager + command: subscription-manager config --rhsm.manage_repos=1 + - name: Remove subscriptions + rhsm_repository: + name: '*' + state: absent + - name: Unregister system + redhat_subscription: + state: absent + - name: clean local subscription data + command: subscription-manager clean + when: ansible_distribution == "RedHat" + +- name: Remove yum package caches + yum: + autoremove: yes + lock_timeout: 60 + +- name: Remove yum package lists + command: /usr/bin/yum -y clean all + +- name: Reset network interface IDs + shell: sed -i '/^\(HWADDR\|UUID\)=/d' /etc/sysconfig/network-scripts/ifcfg-* + +- name: Remove the kickstart log + file: + state: absent + path: /root/anaconda-ks.cfg diff --git a/ansible/roles/sysprep/tasks/rpm_repos.yml b/ansible/roles/sysprep/tasks/rpm_repos.yml new file mode 100644 index 0000000..edbac04 --- /dev/null +++ b/ansible/roles/sysprep/tasks/rpm_repos.yml @@ -0,0 +1,33 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Remove extra repos + file: + path: "/etc/yum.repos.d/{{ item | basename }}" + state: absent + loop: "{{ extra_repos.split() }}" + when: remove_extra_repos and extra_repos != "" + +- name: Find disabled repo files + find: + depth: 1 + paths: /etc/yum.repos.d + patterns: '*.repo.disabled' + register: repo_files + when: disable_public_repos|default(false)|bool and reenable_public_repos|default(true)|bool + +- name: Enable repos + command: "mv {{ item.path }} {{ item.path | regex_replace('.disabled') }}" + loop: "{{ repo_files.files }}" + when: disable_public_repos|default(false)|bool and reenable_public_repos|default(true)|bool diff --git a/ansible/windows/OWNERS b/ansible/windows/OWNERS new file mode 100644 index 0000000..d047699 --- /dev/null +++ b/ansible/windows/OWNERS @@ -0,0 +1,4 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - image-builder-windows-maintainers diff --git a/ansible/windows/ansible_winrm.ps1 b/ansible/windows/ansible_winrm.ps1 new file mode 100644 index 0000000..04ba099 --- /dev/null +++ b/ansible/windows/ansible_winrm.ps1 @@ -0,0 +1,48 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is from packer documentation: +# https://www.packer.io/docs/provisioners/ansible.html#winrm-communicator +# https://www.packer.io/docs/builders/amazon/ebs#connecting-to-windows-instances-using-winrm + +Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force -ErrorAction Ignore + +# Don't set this before Set-ExecutionPolicy as it throws an error +$ErrorActionPreference = "stop" + +# Remove HTTP listener +Remove-Item -Path WSMan:\Localhost\listener\listener* -Recurse + +# Create a self-signed certificate to let ssl work +$Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "packer" +New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert.Thumbprint -Force + +# WinRM +write-output "Setting up WinRM" +write-host "(host) setting up WinRM" + +cmd.exe /c winrm quickconfig -q +cmd.exe /c winrm set "winrm/config" '@{MaxTimeoutms="1800000"}' +cmd.exe /c winrm set "winrm/config/winrs" '@{MaxMemoryPerShellMB="1024"}' +cmd.exe /c winrm set "winrm/config/service" '@{AllowUnencrypted="true"}' +cmd.exe /c winrm set "winrm/config/client" '@{AllowUnencrypted="true"}' +cmd.exe /c winrm set "winrm/config/service/auth" '@{Basic="true"}' +cmd.exe /c winrm set "winrm/config/client/auth" '@{Basic="true"}' +cmd.exe /c winrm set "winrm/config/service/auth" '@{CredSSP="true"}' +cmd.exe /c winrm set "winrm/config/listener?Address=*+Transport=HTTPS" "@{Port=`"5986`";Hostname=`"packer`";CertificateThumbprint=`"$($Cert.Thumbprint)`"}" +cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes +cmd.exe /c netsh firewall add portopening TCP 5986 "Port 5986" +cmd.exe /c net stop winrm +cmd.exe /c sc config winrm start= auto +cmd.exe /c net start winrm diff --git a/ansible/windows/example.vars.yml b/ansible/windows/example.vars.yml new file mode 100644 index 0000000..2edbe5d --- /dev/null +++ b/ansible/windows/example.vars.yml @@ -0,0 +1,38 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +kubernetes_base_url: https://dl.k8s.io/release/v1.19.2/bin/windows/amd64 +cloudbase_init_url: https://github.com/cloudbase/cloudbase-init/releases/download/1.1.2/CloudbaseInitSetup_1_1_2_x64.msi +wins_url: https://github.com/rancher/wins/releases/download/v0.0.4/wins.exe +nssm_url: https://azurek8scishared.blob.core.windows.net/nssm/nssm.exe +gmsa_keyvault_url: https://kubernetesartifacts.azureedge.net/ccgakvplugin/v1.1.4/binaries/windows-gmsa-ccgakvplugin-v1.1.4.zip + +runtime: docker-ee +docker_ee_version: "19.03.12" +kubernetes_install_path: 'c:\k' +windows_service_manager: 'nssm' +pause_image: "registry.k8s.io/pause:3.9" +load_additional_components: true +additional_registry_images: true +additional_registry_images_list: "docker.io/sigwindowstools/flannel:0.12.0, docker.io/sigwindowstools/kube-proxy:v1.19.2" +prepull: false +distribution_version: 2019 + +cloudbase_metadata_services: "cloudbaseinit.metadata.services.azureservice.AzureService, cloudbaseinit.metadata.services.ovfservice.OvfService" +cloudbase_plugins: "cloudbaseinit.plugins.common.ephemeraldisk.EphemeralDiskPlugin, cloudbaseinit.plugins.common.userdata.UserDataPlugin, cloudbaseinit.plugins.common.localscripts.LocalScriptsPlugin" +cloudbase_metadata_services_unattend: "cloudbaseinit.metadata.services.azureservice.AzureService, cloudbaseinit.metadata.services.ovfservice.OvfService" +cloudbase_plugins_unattend: "cloudbaseinit.plugins.common.mtu.MTUPlugin" + +debug_tools: true +additional_debug_files: "https://raw.githubusercontent.com/kubernetes-sigs/sig-windows-tools/master/hack/DebugWindowsNode.ps1" diff --git a/ansible/windows/node_windows.yml b/ansible/windows/node_windows.yml new file mode 100644 index 0000000..4d57969 --- /dev/null +++ b/ansible/windows/node_windows.yml @@ -0,0 +1,105 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +- hosts: all + vars: + node_custom_roles_pre: "" + node_custom_roles_post: "" + custom_role_names: "" + + tasks: + - name: Check if cloudbase-init url is set + set_fact: + install_cloudbase_init: '{{ true if (cloudbase_init_url is defined) and (cloudbase_init_url|length > 0) else false }}' + - name: Check if wins url is set + set_fact: + use_wins: '{{ true if (wins_url is defined) and (wins_url|length > 0) else false }}' + + # https://docs.ansible.com/ansible/latest/user_guide/windows_performance.html + - name: Optimise powershell + win_shell: | + function Optimize-PowershellAssemblies { + # NGEN powershell assembly, improves startup time of powershell by 10x + $old_path = $env:path + try { + $env:path = [Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory() + [AppDomain]::CurrentDomain.GetAssemblies() | % { + if (! $_.location) {continue} + $Name = Split-Path $_.location -leaf + if ($Name.startswith("Microsoft.PowerShell.")) { + Write-Progress -Activity "Native Image Installation" -Status "$name" + ngen install $_.location | % {"`t$_"} + } + } + } finally { + $env:path = $old_path + } + } + Optimize-PowershellAssemblies + become: yes + become_method: runas + become_user: SYSTEM + + - name: Get Install Drive + win_shell: $env:SYSTEMDRIVE + register: systemdrive + + - name: Get Program Files Directory + win_shell: $env:ProgramFiles + register: programfiles + + - name: Get All Users profile path + win_shell: $env:ALLUSERSPROFILE.Replace("\", "\\") + register: alluserprofile + + - name: Get TEMP Directory + win_shell: $env:TEMP + register: tempdir + + - include_role: + name: "{{ role }}" + loop: "{{ node_custom_roles_pre.split() }}" + loop_control: + loop_var: role + when: node_custom_roles_pre != "" + - include_role: + name: systemprep + - include_role: + name: cloudbase-init + when: install_cloudbase_init + - include_role: + name: providers + - include_role: + name: runtimes + - include_role: + name: kubernetes + - include_role: + name: gmsa + - include_role: + name: load_additional_components + when: load_additional_components | bool + - include_role: + name: debug + - include_role: + name: "{{ role }}" + loop: "{{ custom_role_names.split() + node_custom_roles_post.split() }}" + loop_control: + loop_var: role + when: custom_role_names != "" or node_custom_roles_post != "" + + environment: + HTTP_PROXY: "{{ http_proxy | default('') }}" + HTTPS_PROXY: "{{ https_proxy | default('') }}" + NO_PROXY: "{{ no_proxy | default('') }}" diff --git a/ansible/windows/roles/cloudbase-init/tasks/main.yml b/ansible/windows/roles/cloudbase-init/tasks/main.yml new file mode 100644 index 0000000..0224756 --- /dev/null +++ b/ansible/windows/roles/cloudbase-init/tasks/main.yml @@ -0,0 +1,53 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Download Cloudbase-init + win_get_url: + url: "{{ cloudbase_init_url }}" + dest: '{{ tempdir.stdout | trim }}\CloudbaseInitSetup.msi' + register: installer + retries: 5 + delay: 3 + until: installer is not failed + +- name: Ensure log directory + win_file: + path: '{{ systemdrive.stdout | trim }}\logs' + state: directory + +- name: Install Cloudbase-init + win_package: + path: '{{ installer.dest }}' + log_path: '{{ systemdrive.stdout | trim }}\logs\cloudbase-install-log-{{lookup("pipe", "date +%Y%m%dT%H%M%S")}}.log' + +# configuration modified from https://github.com/cloudbase/windows-openstack-imaging-tools/tree/master/Examples/config/azure +- name: Set up cloudbase-init unattend configuration + win_template: + src: templates/cloudbase-init-unattend.conf + dest: '{{ programfiles.stdout | trim }}\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init-unattend.conf' + +# configuration modified from https://github.com/cloudbase/windows-openstack-imaging-tools/tree/master/Examples/config/azure +- name: Set up cloudbase-init configuration + win_template: + src: templates/cloudbase-init.conf + dest: '{{ programfiles.stdout | trim }}\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init.conf' + +- name: Configure set up complete + win_shell: | + # If this file already exists then the following command fails + Remove-Item -Force {{ systemdrive.stdout | trim }}\Windows\Setup\Scripts\SetupComplete.cmd + & "{{ programfiles.stdout | trim }}\Cloudbase Solutions\Cloudbase-Init\bin\SetSetupComplete.cmd" + become: yes + become_method: runas + become_user: System diff --git a/ansible/windows/roles/cloudbase-init/templates/cloudbase-init-unattend.conf b/ansible/windows/roles/cloudbase-init/templates/cloudbase-init-unattend.conf new file mode 100644 index 0000000..4301dd6 --- /dev/null +++ b/ansible/windows/roles/cloudbase-init/templates/cloudbase-init-unattend.conf @@ -0,0 +1,28 @@ +[DEFAULT] +# This configuration with SetUserPasswordPlugin and CreateUserPlugin will create a user capi +# and generate a 123 charater random password. SSH can be configred on the machine to enable access. +username=capi +groups=Administrators +inject_user_password=false +user_password_length=123 +first_logon_behaviour=no + +config_drive_raw_hhd=true +config_drive_cdrom=true +config_drive_vfat=true +bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe +mtools_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\ +verbose=true +debug=true +logdir=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\ +logfile=cloudbase-init-unattend.log +default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN +logging_serial_port_settings={{ cloudbase_logging_serial_port }} +mtu_use_dhcp_config=true +ntp_use_dhcp_config=true +local_scripts_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\LocalScripts\ +metadata_services={{ cloudbase_metadata_services_unattend }} +plugins={{ cloudbase_plugins_unattend }} +allow_reboot=false +stop_service_on_exit=false +check_latest_version=false diff --git a/ansible/windows/roles/cloudbase-init/templates/cloudbase-init.conf b/ansible/windows/roles/cloudbase-init/templates/cloudbase-init.conf new file mode 100644 index 0000000..6732db7 --- /dev/null +++ b/ansible/windows/roles/cloudbase-init/templates/cloudbase-init.conf @@ -0,0 +1,36 @@ +[DEFAULT] +# This configuration with SetUserPasswordPlugin and CreateUserPlugin will create a user capi +# and generate a 123 charater random password. SSH can be configred on the machine to enable access. +username=capi +groups=Administrators +inject_user_password=false +user_password_length=123 +first_logon_behaviour=no +rename_admin_user=true + +config_drive_raw_hhd=true +config_drive_cdrom=true +config_drive_vfat=true +bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe +mtools_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\ +verbose=true +debug=true +logdir=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\ +logfile=cloudbase-init.log +default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN +logging_serial_port_settings={{ cloudbase_logging_serial_port }} +mtu_use_dhcp_config=true +ntp_use_dhcp_config=true +local_scripts_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\LocalScripts\ + +san_policy=OnlineAll +trim_enabled=True + +metadata_report_provisioning_started=True +metadata_report_provisioning_completed=True +ephemeral_disk_volume_label="Temporary Storage" +netbios_host_name_compatibility={{ netbios_host_name_compatibility }} + +metadata_services={{ cloudbase_metadata_services }} +plugins=cloudbaseinit.plugins.common.userdata.UserDataPlugin, + {{ cloudbase_plugins }} diff --git a/ansible/windows/roles/debug/defaults/main.yml b/ansible/windows/roles/debug/defaults/main.yml new file mode 100644 index 0000000..cdda26d --- /dev/null +++ b/ansible/windows/roles/debug/defaults/main.yml @@ -0,0 +1,27 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +debug_files: +- "https://github.com/microsoft/SDN/raw/master/Kubernetes/windows/debug/collectlogs.ps1" +- "https://github.com/microsoft/SDN/raw/master/Kubernetes/windows/debug/dumpVfpPolicies.ps1" +- "https://github.com/microsoft/SDN/raw/master/Kubernetes/windows/debug/portReservationTest.ps1" +- "https://github.com/microsoft/SDN/raw/master/Kubernetes/windows/debug/starthnstrace.cmd" +- "https://github.com/microsoft/SDN/raw/master/Kubernetes/windows/debug/startpacketcapture.cmd" +- "https://github.com/microsoft/SDN/raw/master/Kubernetes/windows/debug/stoppacketcapture.cmd" +- "https://github.com/Microsoft/SDN/raw/master/Kubernetes/windows/debug/VFP.psm1" +- "https://github.com/microsoft/SDN/raw/master/Kubernetes/windows/helper.psm1" +- "https://github.com/Microsoft/SDN/raw/master/Kubernetes/windows/hns.psm1" +- "https://raw.githubusercontent.com/kubernetes-sigs/sig-windows-tools/master/hack/DebugWindowsNode.ps1" + +additional_debug_files_list: "{{ additional_debug_files.split(',') if (additional_debug_files is defined) and (additional_debug_files|length > 0) else [] }}" diff --git a/ansible/windows/roles/debug/tasks/main.yml b/ansible/windows/roles/debug/tasks/main.yml new file mode 100644 index 0000000..134c265 --- /dev/null +++ b/ansible/windows/roles/debug/tasks/main.yml @@ -0,0 +1,33 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Add debug tools directory + win_file: + path: '{{ kubernetes_install_path }}\debug' + state: directory + when: (debug_tools | default(true) | bool) or (additional_debug_files_list|length > 0) + +- name: Get debug files + win_get_url: + url: '{{ item }}' + dest: '{{ kubernetes_install_path }}\debug\' + loop: '{{ debug_files }}' + when: debug_tools | default(true)|bool + +- name: Get additional debug files + win_get_url: + url: '{{ item }}' + dest: '{{ kubernetes_install_path }}\debug\' + loop: "{{ additional_debug_files_list }}" + when: additional_debug_files_list|length > 0 \ No newline at end of file diff --git a/ansible/windows/roles/gmsa/defaults/main.yml b/ansible/windows/roles/gmsa/defaults/main.yml new file mode 100644 index 0000000..8e2393d --- /dev/null +++ b/ansible/windows/roles/gmsa/defaults/main.yml @@ -0,0 +1,16 @@ +# Copyright 2022 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- + +gmsa_keyvault: '{{ true if (gmsa_keyvault_url is defined) and (gmsa_keyvault_url | length > 0) else false }}' diff --git a/ansible/windows/roles/gmsa/files/install-gmsa-keyvault-plugin.ps1 b/ansible/windows/roles/gmsa/files/install-gmsa-keyvault-plugin.ps1 new file mode 100644 index 0000000..a670b07 --- /dev/null +++ b/ansible/windows/roles/gmsa/files/install-gmsa-keyvault-plugin.ps1 @@ -0,0 +1,134 @@ +# Copyright 2022 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# script modified from https://github.com/Azure/AgentBaker/blob/8d5323f3b1a622d558e624e5a6b0963229f80b2a/staging/cse/windows/configfunc.ps1 under MIT +$ErrorActionPreference = 'Stop' + +function Enable-Privilege { + param($Privilege) + $Definition = @' + using System; + using System.Runtime.InteropServices; + public class AdjPriv { + [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] + internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, + ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr rele); + [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] + internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok); + [DllImport("advapi32.dll", SetLastError = true)] + internal static extern bool LookupPrivilegeValue(string host, string name, + ref long pluid); + [StructLayout(LayoutKind.Sequential, Pack = 1)] + internal struct TokPriv1Luid { + public int Count; + public long Luid; + public int Attr; + } + internal const int SE_PRIVILEGE_ENABLED = 0x00000002; + internal const int TOKEN_QUERY = 0x00000008; + internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; + public static bool EnablePrivilege(long processHandle, string privilege) { + bool retVal; + TokPriv1Luid tp; + IntPtr hproc = new IntPtr(processHandle); + IntPtr htok = IntPtr.Zero; + retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + ref htok); + tp.Count = 1; + tp.Luid = 0; + tp.Attr = SE_PRIVILEGE_ENABLED; + retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid); + retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, + IntPtr.Zero); + return retVal; + } + } +'@ + $ProcessHandle = (Get-Process -id $pid).Handle + $type = Add-Type $definition -PassThru + $type[0]::EnablePrivilege($processHandle, $Privilege) +} + +function Aquire-Privilege { + param($Privilege) + + write-output "Acquiring the $Privilege privilege" + $enablePrivilegeResponse=$false + for($i = 0; $i -lt 10; $i++) { + write-output "Retry $i : Trying to enable the $Privilege privilege" + $enablePrivilegeResponse = Enable-Privilege -Privilege "$Privilege" -ErrorAction 'Continue' + if ($enablePrivilegeResponse) { + break + } + Start-Sleep 1 + } + if(!$enablePrivilegeResponse) { + write-output "Failed to enable the $Privilege privilege." + exit 1 + } +} + +# Enable the PowerShell privilege to set the registry permissions. +Aquire-Privilege -Privilege "SeTakeOwnershipPrivilege" + +# Set the registry permissions. +write-output "Setting GMSA plugin registry permissions" +try { + $ccgKeyPath = "System\CurrentControlSet\Control\CCG\COMClasses" + $owner = [System.Security.Principal.NTAccount]"BUILTIN\Administrators" + + $key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey( + $ccgKeyPath, + [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, + [System.Security.AccessControl.RegistryRights]::TakeOwnership) + $acl = $key.GetAccessControl() + $originalOwner = $acl.owner + $acl.SetOwner($owner) + $key.SetAccessControl($acl) + + $key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey( + $ccgKeyPath, + [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, + [System.Security.AccessControl.RegistryRights]::ChangePermissions) + $acl = $key.GetAccessControl() + $rule = New-Object System.Security.AccessControl.RegistryAccessRule( + $owner, + [System.Security.AccessControl.RegistryRights]::FullControl, + [System.Security.AccessControl.AccessControlType]::Allow) + $acl.SetAccessRule($rule) + $key.SetAccessControl($acl) +} catch { + write-output "Failed to set GMSA plugin registry permissions. $_" + exit 1 +} + +# Set the appropriate registry values. +try { + write-output "Setting the appropriate GMSA plugin registry values" + reg.exe import "registerplugin.reg" +} catch { + write-output "Failed to set GMSA plugin registry values. $_" + exit 1 +} + +write-output "Restore original access to registry key" +$acl = $key.GetAccessControl() +$acl.RemoveAccessRule($rule) +$acl.SetOwner([System.Security.Principal.NTAccount]$originalowner) +Aquire-Privilege -Privilege "SeRestorePrivilege" +$key.SetAccessControl($acl) +$key.close() + + +write-output "Successfully installed the GMSA plugin" diff --git a/ansible/windows/roles/gmsa/tasks/gmsa_keyvault.yml b/ansible/windows/roles/gmsa/tasks/gmsa_keyvault.yml new file mode 100644 index 0000000..cc12d9a --- /dev/null +++ b/ansible/windows/roles/gmsa/tasks/gmsa_keyvault.yml @@ -0,0 +1,64 @@ +# Copyright 2022 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Download gMSA Key Vault plugin + win_get_url: + url: '{{ gmsa_keyvault_url }}' + dest: '{{ tempdir.stdout | trim }}\windows-gmsa-ccgakvplugin.zip' + async: 1800 + poll: 60 + retries: 5 + delay: 3 + register: gmsadownload + until: gmsadownload is not failed + +- name: Unzip gMSA Key Vault Archive + win_unzip: + src: '{{ gmsadownload.dest }}' + dest: '{{ kubernetes_install_path }}' + recurse: no + delete_archive: yes + +- name: Copy gMSA Key Vault plugin to System32 + win_shell: | + Move-Item -Force -Path {{ kubernetes_install_path }}\CCGAKVPlugin.dll -Destination {{ systemdrive.stdout | trim }}\Windows\System32\ + +# This is done via a script because Ansible doesn't have the ability to take ownership of registry keys +# The script enables the privilege for the process running and modifies the reg keys. Once process exits it no longer has privileges +# See https://groups.google.com/g/ansible-project/c/5Bt7jgq6ZFA/m/_XJtVzmhBwAJ +- name: Copy gMSA Key Vault installer file + win_copy: + src: install-gmsa-keyvault-plugin.ps1 + dest: '{{ kubernetes_install_path }}' + +- name: Register gMSA Key Vault plugin + win_shell: | + {{ kubernetes_install_path }}\install-gmsa-keyvault-plugin.ps1 + +- name: Install registry CCG logging manifest + win_shell: | + wevtutil.exe um {{ kubernetes_install_path }}\CCGEvents.man + wevtutil.exe im {{ kubernetes_install_path }}\CCGEvents.man + +- name: Install registry Key Vault plugin logging manifest + win_shell: | + wevtutil.exe um {{ kubernetes_install_path }}\CCGAKVPluginEvents.man + wevtutil.exe im {{ kubernetes_install_path }}\CCGAKVPluginEvents.man + +- name: Clean up gMSA install files + win_shell: | + Remove-Item {{ kubernetes_install_path }}\CCGEvents.man + Remove-Item {{ kubernetes_install_path }}\CCGAKVPluginEvents.man + Remove-Item {{ kubernetes_install_path }}\registerplugin.reg + Remove-Item {{ kubernetes_install_path }}\install-gmsa-keyvault-plugin.ps1 diff --git a/ansible/windows/roles/gmsa/tasks/main.yml b/ansible/windows/roles/gmsa/tasks/main.yml new file mode 100644 index 0000000..2cfd9f5 --- /dev/null +++ b/ansible/windows/roles/gmsa/tasks/main.yml @@ -0,0 +1,17 @@ +# Copyright 2022 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- + +- import_tasks: gmsa_keyvault.yml + when: gmsa_keyvault | bool diff --git a/ansible/windows/roles/kubernetes/defaults/main.yml b/ansible/windows/roles/kubernetes/defaults/main.yml new file mode 100644 index 0000000..949647b --- /dev/null +++ b/ansible/windows/roles/kubernetes/defaults/main.yml @@ -0,0 +1,18 @@ +# Copyright 2018 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +kubernetes_bins: +- kubeadm +- kubectl +- kubelet diff --git a/ansible/windows/roles/kubernetes/tasks/kubelet.yml b/ansible/windows/roles/kubernetes/tasks/kubelet.yml new file mode 100644 index 0000000..531463e --- /dev/null +++ b/ansible/windows/roles/kubernetes/tasks/kubelet.yml @@ -0,0 +1,58 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Create kubelet directory structure + win_file: + path: "{{ item }}" + state: directory + loop: + - '{{ systemdrive.stdout | trim }}\var\log\kubelet' + - '{{ systemdrive.stdout | trim }}\etc\kubernetes' + - '{{ systemdrive.stdout | trim }}\etc\kubernetes\manifests' + - '{{ systemdrive.stdout | trim }}\etc\kubernetes\pki' + +# this is required in 1.22 and below due to invalid absolute path handling +# https://github.com/kubernetes-sigs/image-builder/issues/853 +- name: Symlink kubelet pki folder + win_shell: New-Item -path $env:SystemDrive\var\lib\kubelet\etc\kubernetes\pki -type SymbolicLink -value $env:SystemDrive\etc\kubernetes\pki\ -Force + when: kubernetes_semver is version('v1.23.0', '<') + +- import_tasks: nssm.yml + when: windows_service_manager == "nssm" + +- import_tasks: sc.yml + when: windows_service_manager == "windows_service" + +# Dependency selection: https://www.reddit.com/r/ansible/comments/imfdgn/setting_a_variable_conditionally/g41anaf/?utm_source=reddit&utm_medium=web2x&context=3 +- name: Ensure kubelet is installed + win_service: + name: kubelet + dependencies: [ "{{ runtime_service }}" ] + start_mode: auto + vars: + dependencies: + containerd: containerd + docker-ee: docker + default: docker + runtime_service: "{{ dependencies[runtime] | default(dependencies['docker']) }}" + +- name: Add firewall rule for kubelet + win_firewall_rule: + name: kubelet + localport: 10250 + action: allow + direction: in + protocol: tcp + state: present + enabled: yes diff --git a/ansible/windows/roles/kubernetes/tasks/main.yml b/ansible/windows/roles/kubernetes/tasks/main.yml new file mode 100644 index 0000000..d64f117 --- /dev/null +++ b/ansible/windows/roles/kubernetes/tasks/main.yml @@ -0,0 +1,31 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Create kubernetes directory structure + win_file: + path: '{{ kubernetes_install_path }}' + state: directory + +- import_tasks: url.yml + +- name: Add kubernetes folder to path + win_path: + elements: + - '{{ kubernetes_install_path }}' + scope: Machine + +- import_tasks: kubelet.yml + +- import_tasks: wins.yml + when: use_wins diff --git a/ansible/windows/roles/kubernetes/tasks/nssm.yml b/ansible/windows/roles/kubernetes/tasks/nssm.yml new file mode 100644 index 0000000..3947b79 --- /dev/null +++ b/ansible/windows/roles/kubernetes/tasks/nssm.yml @@ -0,0 +1,39 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Download nssm + win_get_url: + url: '{{ nssm_url }}' + dest: '{{ kubernetes_install_path }}\' + retries: 5 + delay: 3 + register: nssm_download + until: nssm_download is not failed + +- name: Create kubelet start file for nssm + win_template: + src: templates/StartKubelet.ps1 + dest: '{{ kubernetes_install_path }}\StartKubelet.ps1' + +- name: Install kubelet via nssm + win_nssm: + name: kubelet + start_mode: auto + state: present + application: '%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe' + arguments: '-ExecutionPolicy Bypass -NoProfile {{ kubernetes_install_path }}\StartKubelet.ps1' + app_rotate_bytes: 10485760 + stderr_file: '{{ systemdrive.stdout | trim }}\var\log\kubelet\kubelet.err.log' + stdout_file: '{{ systemdrive.stdout | trim }}\var\log\kubelet\kubelet.log' + app_rotate_online: 1 diff --git a/ansible/windows/roles/kubernetes/tasks/sc.yml b/ansible/windows/roles/kubernetes/tasks/sc.yml new file mode 100644 index 0000000..0e6cf51 --- /dev/null +++ b/ansible/windows/roles/kubernetes/tasks/sc.yml @@ -0,0 +1,27 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +# Install kubelet as a windows service +# Requires --windows-service flag: https://github.com/kubernetes/kubernetes/blob/7f23a743e8c23ac6489340bbb34fa6f1d392db9d/cmd/kubelet/app/options/osflags_windows.go#L26 +# Does not support kubeadm KUBELET_KUBEADM_ARGS which is used by Cluster API to pass extra user args +- name: Set dockershim args + set_fact: + additional_kubelet_args: "--image-pull-progress-deadline=20m --network-plugin=cni" + when: runtime == "docker-ee" and kubernetes_semver is version('v1.24.0', '<') + +- name: Install kubelet as service + win_service: + name: kubelet + start_mode: manual + path: '{{ kubernetes_install_path }}\kubelet.exe --windows-service --cert-dir={{ systemdrive.stdout | trim }}/var/lib/kubelet/pki --config={{ systemdrive.stdout | trim }}/var/lib/kubelet/config.yaml --bootstrap-kubeconfig={{ systemdrive.stdout | trim }}/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig={{ systemdrive.stdout | trim }}/etc/kubernetes/kubelet.conf --hostname-override=$(hostname) --pod-infra-container-image=`"{{ pause_image }}`" --enable-debugging-handlers --cgroups-per-qos=false --enforce-node-allocatable=`"`" --resolv-conf=`"`" --log-dir={{ systemdrive.stdout | trim }}/var/log/kubelet --logtostderr=false {{ additional_kubelet_args if additional_kubelet_args is defined }}' diff --git a/ansible/windows/roles/kubernetes/tasks/url.yml b/ansible/windows/roles/kubernetes/tasks/url.yml new file mode 100644 index 0000000..7a90966 --- /dev/null +++ b/ansible/windows/roles/kubernetes/tasks/url.yml @@ -0,0 +1,24 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Download kubernetes binaries + win_get_url: + url: "{{ kubernetes_base_url }}/{{ item }}.exe" + dest: '{{ kubernetes_install_path }}\' + loop: "{{ kubernetes_bins }}" + retries: 5 + delay: 3 + register: kubernetes_download + until: kubernetes_download is not failed + \ No newline at end of file diff --git a/ansible/windows/roles/kubernetes/tasks/wins.yml b/ansible/windows/roles/kubernetes/tasks/wins.yml new file mode 100644 index 0000000..e3f4164 --- /dev/null +++ b/ansible/windows/roles/kubernetes/tasks/wins.yml @@ -0,0 +1,29 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Get wins + win_get_url: + url: '{{ wins_url }}' + dest: '{{ kubernetes_install_path }}' + retries: 5 + delay: 3 + register: wins_download + until: wins_download is not failed + +- name: Register wins.exe + win_command: wins.exe srv app run --register + +- name: Ensure that wins service is running + win_service: + name: rancher-wins diff --git a/ansible/windows/roles/kubernetes/templates/StartKubelet.ps1 b/ansible/windows/roles/kubernetes/templates/StartKubelet.ps1 new file mode 100644 index 0000000..a84bdf2 --- /dev/null +++ b/ansible/windows/roles/kubernetes/templates/StartKubelet.ps1 @@ -0,0 +1,43 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# From https://github.com/kubernetes-sigs/sig-windows-tools/blob/master/kubeadm/scripts/PrepareNode.ps1 +$FileContent = Get-Content -Path "/var/lib/kubelet/kubeadm-flags.env" +$kubeAdmArgs = $FileContent.TrimStart('KUBELET_KUBEADM_ARGS=').Trim('"') + +$args = "--cert-dir=$env:SYSTEMDRIVE/var/lib/kubelet/pki", + "--config=$env:SYSTEMDRIVE/var/lib/kubelet/config.yaml", + "--bootstrap-kubeconfig=$env:SYSTEMDRIVE/etc/kubernetes/bootstrap-kubelet.conf", + "--kubeconfig=$env:SYSTEMDRIVE/etc/kubernetes/kubelet.conf", + "--hostname-override=$(hostname)", + "--pod-infra-container-image=`"{{ pause_image }}`"", + "--enable-debugging-handlers", + "--cgroups-per-qos=false", + "--enforce-node-allocatable=`"`"", + "--resolv-conf=`"`"" + +{% if runtime == "docker-ee" and kubernetes_semver is version('v1.24.0', '<') %} +{% raw %} +$netId = docker network ls -f name=host --format "{{ .ID }}" +{% endraw %} +if ($netId.Length -lt 1) { + docker network create -d nat host +} + +$args += "--image-pull-progress-deadline=20m", + "--network-plugin=cni" +{% endif %} + +$kubeletCommandLine = "{{ kubernetes_install_path }}\kubelet.exe " + ($args -join " ") + " $kubeAdmArgs" +Invoke-Expression $kubeletCommandLine diff --git a/ansible/windows/roles/load_additional_components/defaults/main.yml b/ansible/windows/roles/load_additional_components/defaults/main.yml new file mode 100644 index 0000000..44aa745 --- /dev/null +++ b/ansible/windows/roles/load_additional_components/defaults/main.yml @@ -0,0 +1,22 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- + +additional_registry_images: "" +additional_registry_images_list: "" +additional_url_images: "" +additional_url_images_list: "" +additional_executables: "" +additional_executables_list: "" +additional_executables_destination_path: "" \ No newline at end of file diff --git a/ansible/windows/roles/load_additional_components/tasks/executables.yml b/ansible/windows/roles/load_additional_components/tasks/executables.yml new file mode 100644 index 0000000..54be847 --- /dev/null +++ b/ansible/windows/roles/load_additional_components/tasks/executables.yml @@ -0,0 +1,31 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Create temporary download dir + win_file: + path: "{{ additional_executables_destination_path }}/" + state: directory + +- name: Download additional executables + win_get_url: + url: "{{ item }}" + dest: "{{ additional_executables_destination_path }}/" + loop: "{{ additional_executables_list.split(',') }}" + async: 1800 + poll: 60 + retries: 5 + delay: 3 + register: download + until: download is not failed + \ No newline at end of file diff --git a/ansible/windows/roles/load_additional_components/tasks/main.yml b/ansible/windows/roles/load_additional_components/tasks/main.yml new file mode 100644 index 0000000..8b3921e --- /dev/null +++ b/ansible/windows/roles/load_additional_components/tasks/main.yml @@ -0,0 +1,22 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- import_tasks: executables.yml + when: additional_executables | bool + +- import_tasks: registry.yml + when: additional_registry_images | bool + +- import_tasks: url.yml + when: additional_url_images | bool diff --git a/ansible/windows/roles/load_additional_components/tasks/registry.yml b/ansible/windows/roles/load_additional_components/tasks/registry.yml new file mode 100644 index 0000000..381d551 --- /dev/null +++ b/ansible/windows/roles/load_additional_components/tasks/registry.yml @@ -0,0 +1,39 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Pull containerd additional images + win_shell: | + #refresh the path to ensure ansible sees update + $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ctr.exe -n k8s.io images pull {{ item }} + loop: "{{ additional_registry_images_list.split(',') }}" + async: 1800 + poll: 60 + retries: 5 + delay: 3 + register: pull + until: pull is not failed + when: runtime == "containerd" + +- name: Pre-pull docker additional images + win_shell: docker pull {{ item }} + loop: "{{ additional_registry_images_list.split(',') }}" + async: 1800 + poll: 60 + retries: 5 + delay: 3 + register: pull + until: pull is not failed + when: runtime == "docker-ee" + \ No newline at end of file diff --git a/ansible/windows/roles/load_additional_components/tasks/url.yml b/ansible/windows/roles/load_additional_components/tasks/url.yml new file mode 100644 index 0000000..a1d241c --- /dev/null +++ b/ansible/windows/roles/load_additional_components/tasks/url.yml @@ -0,0 +1,83 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Create temporary download dir + win_file: + path: '{{ tempdir.stdout | trim }}\images' + state: directory + when: runtime == "containerd" + +- name: Download additional images from url + win_get_url: + url: "{{ item }}" + dest: '{{ tempdir.stdout | trim }}\images\' + register: images + loop: "{{ additional_url_images_list.split(',') }}" + async: 1800 + poll: 60 + retries: 5 + delay: 3 + when: runtime == "containerd" + +- name: Load additional images to containerd + win_shell: | + Function DeGZip-File{ + Param( + $infile, + $outfile = ($infile -replace '\.gz$','') + ) + $input = New-Object System.IO.FileStream $inFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read) + $output = New-Object System.IO.FileStream $outFile, ([IO.FileMode]::Create), ([IO.FileAccess]::Write), ([IO.FileShare]::None) + $gzipStream = New-Object System.IO.Compression.GzipStream $input, ([IO.Compression.CompressionMode]::Decompress) + $buffer = New-Object byte[](1024) + while($true){ + $read = $gzipstream.Read($buffer, 0, 1024) + if ($read -le 0){break} + $output.Write($buffer, 0, $read) + } + $gzipStream.Close() + $output.Close() + $input.Close() + } + + $file = "{{ item.dest }}" + $ext = $file.substring($file.length - 3, 3) + + if ($ext -eq ".gz") { + DeGZip-File $file + $file = ($file -replace '\.gz$','') + } + #refresh the path to ensure ansible sees update + $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ctr.exe -n k8s.io images import --no-unpack $file + loop: "{{ images.results }}" + when: runtime == "containerd" + +- name: Load additional docker images + win_shell: | + docker import {{ item }} + loop: "{{ additional_url_images_list.split(',') }}" + async: 1800 + poll: 60 + retries: 5 + delay: 3 + register: import + until: import is not failed + when: runtime == "docker" + +- name: Remove downloaded files + win_file: + state: absent + path: '{{ tempdir.stdout | trim }}\images' + when: runtime == "containerd" \ No newline at end of file diff --git a/ansible/windows/roles/providers/defaults/main.yml b/ansible/windows/roles/providers/defaults/main.yml new file mode 100644 index 0000000..20548e6 --- /dev/null +++ b/ansible/windows/roles/providers/defaults/main.yml @@ -0,0 +1,15 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +packer_builder_type: "" diff --git a/ansible/windows/roles/providers/tasks/azure.yml b/ansible/windows/roles/providers/tasks/azure.yml new file mode 100644 index 0000000..1197a5c --- /dev/null +++ b/ansible/windows/roles/providers/tasks/azure.yml @@ -0,0 +1,48 @@ +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- + +- name: Create Azure wireserver access group + ansible.windows.win_group: + name: WireServerAccess + description: Controls access to the Azure WireServer + +# AzureGuestAgent and Cloudbase-init need access to wireserver otherwise VM doesn't boot +# So we give the users access via the firewall security filters +# https://docs.microsoft.com/en-us/powershell/module/netsecurity/set-netfirewallsecurityfilter +# +# Permissions set on the Firewall rule: +# S-1-1-0 is Everyone. We mark this as Allow (A) to ensure the Block is enforced for all users other than on the exception list. +# S-1-5-18 is LocalSystem used by AzureGuestAgent. We mark this as Deny (D) to add to Block exception list. +# We also add the newly created group WireServerAccess to the block exception list and add Cloudbase-init user later. +# +# View the details of the SDDL string used with ConvertFrom-SddlString and see well known sids: https://docs.microsoft.com/en-us/windows/win32/secauthz/well-known-sids +- name: Block traffic to 168.63.129.16 port 80 for cve-2021-27075 + win_shell: | + $wsg = Get-LocalGroup -n "WireServerAccess" + $r = New-NetFirewallRule -DisplayName 'Block-Outbound-168.63.129.16-port-80-for-cve-2021-27075' -Direction Outbound -RemoteAddress '168.63.129.16' -RemotePort '80' -Protocol TCP -Action Block + $r | Get-NetFirewallSecurityFilter | Set-NetFirewallSecurityFilter -LocalUser "O:LSD:(D;;CC;;;S-1-5-18)(D;;CC;;;$($wsg.SID.Value))(A;;CC;;;S-1-1-0)" + become: yes + become_method: runas + become_user: SYSTEM + +- name: Add users to WireServerAccessGroup + ansible.windows.win_group_membership: + name: WireServerAccess + members: + - cloudbase-init + +- name: Add additional users + ansible.windows.win_group_membership: + name: WireServerAccess + members: "{{ users }}" + vars: + users: "{{ wire_server_users.split(',') if (wire_server_users is defined) and (wire_server_users|length > 0) else [] }}" diff --git a/ansible/windows/roles/providers/tasks/main.yml b/ansible/windows/roles/providers/tasks/main.yml new file mode 100644 index 0000000..f9a7a61 --- /dev/null +++ b/ansible/windows/roles/providers/tasks/main.yml @@ -0,0 +1,14 @@ +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- + +- include_tasks: azure.yml + when: packer_builder_type.startswith('azure') diff --git a/ansible/windows/roles/runtimes/defaults/main.yml b/ansible/windows/roles/runtimes/defaults/main.yml new file mode 100644 index 0000000..d218ed3 --- /dev/null +++ b/ansible/windows/roles/runtimes/defaults/main.yml @@ -0,0 +1,28 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +pause_image: mcr.microsoft.com/oss/kubernetes/pause:3.9 +containerd_additional_settings: "" +containerd_config_file: "config.toml" + +prepull: false +prepull_images: + 2019: + - mcr.microsoft.com/windows/servercore:ltsc2019 + - mcr.microsoft.com/windows/nanoserver:1809 + - "{{ pause_image }}" + 2004: + - mcr.microsoft.com/windows/servercore:2004 + - mcr.microsoft.com/windows/nanoserver:2004 + - "{{ pause_image }}" \ No newline at end of file diff --git a/ansible/windows/roles/runtimes/tasks/containerd.yml b/ansible/windows/roles/runtimes/tasks/containerd.yml new file mode 100644 index 0000000..7485d3f --- /dev/null +++ b/ansible/windows/roles/runtimes/tasks/containerd.yml @@ -0,0 +1,111 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- name: Download containerd + win_get_url: + url: '{{ containerd_url }}' + dest: '{{ tempdir.stdout | trim }}\containerd.tar.gz' + checksum: '{{ containerd_sha256 }}' + checksum_algorithm: "sha256" + url_timeout: 300 + register: containerd + retries: 5 + delay: 3 + until: containerd is not failed + +- name: Create containerd directory structure + win_file: + path: "{{ item }}" + state: directory + loop: + - '{{ programfiles.stdout | trim }}\containerd' + - '{{ alluserprofile.stdout | trim }}\containerd\state' + - '{{ alluserprofile.stdout | trim }}\containerd\root' + - '{{ systemdrive.stdout | trim }}/opt/cni/bin' + - '{{ systemdrive.stdout | trim }}/etc/cni/net.d' + +- name: Check if containerd exists + win_stat: + path: '{{ programfiles.stdout | trim }}\containerd\containerd.exe' + register: containerd_file + +- name: Unpack containerd binaries + win_command: cmd /c tar -zxvf {{ containerd.dest }} -C "{{ programfiles.stdout | trim }}\containerd" --strip-components 1 + when: not containerd_file.stat.exists + +- name: Add containerd to path + win_path: + elements: + - '{{ programfiles.stdout | trim }}\containerd' + scope: machine + +- name: Copy containerd config file {{ containerd_config_file }} + win_template: + dest: '{{ programfiles.stdout | trim }}\containerd\config.toml' + src: "{{ containerd_config_file }}" + vars: + allusersprofile: "{{ alluserprofile.stdout | trim }}" + plugin_bin_dir: "{{ systemdrive.stdout | trim }}/opt/cni/bin" + plugin_conf_dir: "{{ systemdrive.stdout | trim }}/etc/cni/net.d" + # programfiles is C:\Program Files, but should be C:\\Program Files + # otherwise task Register Containerd fails with "invalid escape sequence: \P" + containerd_conf_dir: '{{ programfiles.stdout | trim | regex_replace("\\", "\\\\") }}\\\\containerd' + +- name: Check if a Containerd service is installed + win_service: + name: containerd + register: containerd_service + +- name: Register Containerd + win_shell: | + #refresh the path to ensure ansible sees update + $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + containerd.exe --register-service + when: containerd_service.exists == false + +# Enables DNS resolution of SMB shares +# https://github.com/kubernetes-sigs/windows-gmsa/issues/30#issuecomment-802240945 +- name: Apply SMB Resolution Fix for containerd + win_regedit: + path: HKLM:\SYSTEM\CurrentControlSet\Services\hns\State + state: present + name: EnableCompartmentNamespace + data: 1 + type: dword + +- name: Create Windows Defender Exclusions + win_shell: | + Add-MpPreference -ExclusionProcess "{{ programfiles.stdout | trim }}\containerd\containerd.exe" + Add-MpPreference -ExclusionProcess "{{ programfiles.stdout | trim }}\containerd\ctr.exe" + +- name: Ensure Containerd Service is running + win_service: + name: containerd + start_mode: auto + state: started + +- name: Pre-pull containerd images + win_shell: | + #refresh the path to ensure ansible sees update + $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ctr.exe -n k8s.io images pull {{ item }} + loop: "{{ images }}" + async: 1800 + poll: 60 + retries: 5 + register: pull + until: pull is not failed + when: (prepull | bool) + vars: + images: "{{ prepull_images[distribution_version] | default([]) }}" diff --git a/ansible/windows/roles/runtimes/tasks/docker_ee.yml b/ansible/windows/roles/runtimes/tasks/docker_ee.yml new file mode 100644 index 0000000..3392237 --- /dev/null +++ b/ansible/windows/roles/runtimes/tasks/docker_ee.yml @@ -0,0 +1,45 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- + +# Requires license. If you running on Azure License is currently provided with Windows Server images. +- name: Install docker via OneGet + win_shell: | + Install-PackageProvider -Name DockerMsftProvider -Force -ForceBootstrap | Out-Null + $package = Find-Package -Name Docker -ProviderName DockerMsftProvider -RequiredVersion {{ docker_ee_version }} + $package | Install-Package -Force | Out-Null + +- name: Start Docker Service + win_service: + name: docker + start_mode: auto + state: started + +- name: Set up Docker Network + win_shell: | + $exists=docker network ls -f name=host -q + if (-not $exists) { docker network create -d nat host } + +- name: Pre-pull docker images + win_command: docker pull {{ item }} + loop: "{{ images }}" + async: 1800 + poll: 60 + retries: 5 + register: pull + until: pull is not failed + when: (prepull | bool) + vars: + images: "{{ prepull_images[distribution_version] | default([]) }}" + \ No newline at end of file diff --git a/ansible/windows/roles/runtimes/tasks/main.yml b/ansible/windows/roles/runtimes/tasks/main.yml new file mode 100644 index 0000000..71da864 --- /dev/null +++ b/ansible/windows/roles/runtimes/tasks/main.yml @@ -0,0 +1,19 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +- import_tasks: containerd.yml + when: runtime == "containerd" + +- import_tasks: docker_ee.yml + when: runtime == "docker-ee" diff --git a/ansible/windows/roles/runtimes/templates/config.toml b/ansible/windows/roles/runtimes/templates/config.toml new file mode 100644 index 0000000..8bf07df --- /dev/null +++ b/ansible/windows/roles/runtimes/templates/config.toml @@ -0,0 +1,37 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +root = "{{ allusersprofile }}\\containerd\\root" +state = "{{ allusersprofile }}\\containerd\\state" +version = 2 + +{% if 'imports' not in containerd_additional_settings | b64decode %} +imports = ["{{ containerd_conf_dir }}\\conf.d\\*.toml"] +{% endif %} + +[grpc] + address = "\\\\.\\pipe\\containerd-containerd" + +[plugins] + [plugins."io.containerd.grpc.v1.cri"] + sandbox_image = "{{ pause_image }}" + [plugins."io.containerd.grpc.v1.cri".cni] + bin_dir = "{{ plugin_bin_dir }}" + conf_dir = "{{ plugin_conf_dir }}" +{% if packer_builder_type.startswith('azure') %} + [plugins."io.containerd.grpc.v1.cri".registry.headers] + X-Meta-Source-Client = ["azure/capz"] +{% endif %} + +{{containerd_additional_settings | b64decode}} diff --git a/ansible/windows/roles/systemprep/defaults/main.yml b/ansible/windows/roles/systemprep/defaults/main.yml new file mode 100644 index 0000000..d77195f --- /dev/null +++ b/ansible/windows/roles/systemprep/defaults/main.yml @@ -0,0 +1,17 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +windows_updates_kbs_numbers: "{{ windows_updates_kbs.split() if (windows_updates_kbs is defined) and (windows_updates_kbs|length > 0) else [] }}" +windows_updates_category_names: "{{ windows_updates_categories.split() if (windows_updates_categories is defined) and (windows_updates_categories|length > 0) else [] }}" +ssh_source_url: "{{ ssh_source_url if ssh_source_url is defined else ''}}" diff --git a/ansible/windows/roles/systemprep/tasks/main.yml b/ansible/windows/roles/systemprep/tasks/main.yml new file mode 100644 index 0000000..2a7a179 --- /dev/null +++ b/ansible/windows/roles/systemprep/tasks/main.yml @@ -0,0 +1,179 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +# This file was adapted from https://github.com/Azure/aks-engine/blob/master/vhd/packer/configure-windows-vhd.ps1 for ansible +- name: Remove Windows updates default registry settings + win_regedit: + path: HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\ + state: absent + delete_key: yes + +- name: Add Windows update registry path + win_regedit: + path: HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate + state: present + +- name: Add Windows automatic update registry path + win_regedit: + path: HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU + state: present + +# https://docs.microsoft.com/en-us/windows/deployment/update/waas-wu-settings#configuring-automatic-updates-by-editing-the-registry +- name: Disable Windows automatic updates in registry + win_regedit: + path: HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU + state: present + name: NoAutoUpdate + data: 1 + type: dword + +- name: Set Windows automatic updates to notify only in registry + win_regedit: + path: HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU + state: present + name: AUOptions + data: 2 + type: dword + +# Hyper-V messes with networking components on startup after the feature is enabled +# causing issues with communication over winrm and setting winrm to delayed start +# gives Hyper-V enough time to finish configuration before having packer continue. +- name: Set WinRm Service to delayed start + win_command: sc.exe config winrm start=delayed-auto + +# Best effort to update defender signatures +# This can fail if there is already a signature +# update running which means we will get them anyways +# Also at the time the VM is provisioned Defender will trigger any required updates +- name: Update Windows Defender signatures + win_shell: | + $service = Get-Service "Windefend" + $service.WaitForStatus("Running","00:5:00") + Update-MpSignature + ignore_errors: yes + +# Find KB Article numbers: +# - WS 2019 https://support.microsoft.com/en-us/help/4464619 +# - WS 2022 https://support.microsoft.com/topic/windows-server-2022-update-history-e1caa597-00c5-4ab9-9f3e-8212fe80b2ee +# Task to install specific updates by KB. All categories are specified as the module +# won't install the update unless the category matches. Setting windows_updates_kbs_numbers to [] +# will skip this task. +- name: Install Windows updates based on KB numbers + win_updates: + whitelist: "{{ windows_updates_kbs_numbers }}" + reboot: yes + category_names: + - Application + - Connectors + - CriticalUpdates + - DefinitionUpdates + - DeveloperKits + - Drivers + - FeaturePacks + - Guidance + - SecurityUpdates + - ServicePacks + - Tools + - UpdateRollups + - Updates + when: windows_updates_kbs_numbers|length > 0 + +# Task to install any outstanding updates that belong to specific categories. Setting +# windows_updates_category_names to [] will skip this task. +- name: Install Windows updates based on Categories + win_updates: + category_names: "{{ windows_updates_category_names }}" + reboot: yes + when: windows_updates_category_names|length > 0 + +- import_tasks: ssh-feature.yml + when: ssh_source_url == "" + +- import_tasks: ssh-archive.yml + when: ssh_source_url != "" + +- name: Set default SSH shell to Powershell + win_regedit: + path: HKLM:\SOFTWARE\OpenSSH + state: present + name: DefaultShell + data: '{{ systemdrive.stdout | trim }}\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' + type: string + +- name: Create SSH program data folder + win_shell: If (-Not (Test-Path -Path "$env:ProgramData\ssh")) { mkdir "$env:ProgramData\ssh" } + +- name: Enable ssh login without a password + win_shell: Add-Content -Path "$env:ProgramData\ssh\sshd_config" -Value "PasswordAuthentication no`nPubkeyAuthentication yes" + +- name: Set SSH service startup mode to auto and ensure it is started + win_service: + name: sshd + start_mode: auto + state: started + +# Apply HNS flags for fixes that need to be enabled via Registry +# these eventually get turned on automatically and can be removed in future releases +- name: Apply HNS control Flags 0x40 and 0x10 in 2022-11B patches + win_regedit: + path: HKLM:\SYSTEM\CurrentControlSet\Services\hns\State + state: present + name: HNSControlFlag + data: 0x50 + type: dword + when: distribution_version == "2019" + +- name: Apply WCIFS fix + win_regedit: + path: HKLM:\SYSTEM\CurrentControlSet\Services\wcifs + state: present + name: WcifsSOPCountDisabled + data: 0 + type: dword + when: distribution_version == "2019" + +- name: Expand dynamic port range to 34000-65535 to avoid port exhaustion + win_shell: netsh int ipv4 set dynamicportrange tcp 34000 31536 + +- name: Add required Windows Features + win_feature: + name: + - Containers + - Hyper-V-PowerShell + state: present + register: win_feature + +# Due to a limitation in some CNI plugins the Hyper-V role needs to be installed in order +# to use the VMSwitch Powershell Cmdlets. +# An issue has been logged to have the networking components to be split out but until +# that is complete, environments that do not support running a hypervisor require the +# below which skips the CPU check for Hypervisor support and still installs the VMSwitch Cmlets +# when disable_hypervisor is set to true +# https://github.com/microsoft/Windows-Containers/issues/80 + +- name: Add Hyper-V + win_shell: | + dism /online /enable-feature /featurename:Microsoft-Hyper-V /all /NoRestart + register: hyperv_installed + failed_when: hyperv_installed.rc != 1 and hyperv_installed.rc != 0 + +- name: Disable Hypervisor + win_shell: | + dism /online /disable-feature /featurename:Microsoft-Hyper-V-Online /NoRestart + when: (disable_hypervisor | default(false) | bool) + register: hypervisor_disabled + failed_when: hypervisor_disabled.rc != 1 and hypervisor_disabled.rc != 0 + +- name: Reboot + win_reboot: diff --git a/ansible/windows/roles/systemprep/tasks/ssh-archive.yml b/ansible/windows/roles/systemprep/tasks/ssh-archive.yml new file mode 100644 index 0000000..bb27d2f --- /dev/null +++ b/ansible/windows/roles/systemprep/tasks/ssh-archive.yml @@ -0,0 +1,73 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: Create OpenSSH directory structure + win_file: + path: "{{ item }}" + state: directory + loop: + - '{{ programfiles.stdout | trim }}\OpenSSH' + - '{{ alluserprofile.stdout | trim }}\ssh' + +# Win32-OpenSSH requires SYSTEM and Administrator groups having Write +# permissions on directory 'C:\Program Files\OpenSSH', authenticated +# users having only Read and Execute permissions on it, see: +# https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH +# +# "Make sure binary location has the Write permissions to just to SYSTEM, +# Administrator groups. Authenticated users should and only have Read and +# Execute." +# +# Folder 'C:\Program Files\OpenSSH' inherits users and permissions from its +# parent folder when it is created, by default, SYSTEM and Administrator +# already have Write permissions on it, the only exception is the inherited +# user BUILTIN\Users has ReadAndExecute permission but only authenticated +# users are allowed to have such permission, this prevent us from connecting +# to the sshd server, just remove it. +- name: Disable inheritance of OpenSSH directory + win_acl_inheritance: + path: '{{ programfiles.stdout | trim }}\OpenSSH' + state: absent + reorganize: yes +- name: Remove permission for Users + win_acl: + path: '{{ programfiles.stdout | trim }}\OpenSSH' + user: BUILTIN\Users + rights: ReadAndExecute,Synchronize + type: allow + state: absent + inherit: 'None' + propagation: 'None' + +- name: Download OpenSSH Archive + win_get_url: + url: '{{ ssh_source_url }}' + dest: '{{ tempdir.stdout | trim }}\OpenSSH.zip' + register: ssh + retries: 5 + delay: 3 + until: ssh is not failed + +- name: Unzip OpenSSH Archive + win_unzip: + src: '{{ ssh.dest }}' + dest: '{{ tempdir.stdout | trim }}' + recurse: no + delete_archive: yes + +- name: Install OpenSSH + win_shell: | + Get-ChildItem -Path "{{ tempdir.stdout | trim }}\OpenSSH-Win64\*" -Recurse | Move-Item -Destination "{{ programfiles.stdout | trim }}\OpenSSH" + Get-ChildItem -Path "{{ programfiles.stdout | trim }}\OpenSSH" | Unblock-File + & 'C:\Program Files\OpenSSH\install-sshd.ps1' diff --git a/ansible/windows/roles/systemprep/tasks/ssh-feature.yml b/ansible/windows/roles/systemprep/tasks/ssh-feature.yml new file mode 100644 index 0000000..8df8426 --- /dev/null +++ b/ansible/windows/roles/systemprep/tasks/ssh-feature.yml @@ -0,0 +1,21 @@ +# Copyright 2021 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Requires admin rights to install +# https://docs.ansible.com/ansible/latest/user_guide/become.html#become-and-windows +- name: Install OpenSSH + win_shell: Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 + become: yes + become_method: runas + become_user: SYSTEM diff --git a/azure_targets.sh b/azure_targets.sh new file mode 100644 index 0000000..ede51d3 --- /dev/null +++ b/azure_targets.sh @@ -0,0 +1,6 @@ +VHD_TARGETS="ubuntu-1804 ubuntu-2004 ubuntu-2204 centos-7 rhel-8 windows-2019 windows-2019-containerd windows-2022-containerd" +VHD_CI_TARGETS="ubuntu-2004 ubuntu-2204 centos-7 windows-2019-containerd windows-2022-containerd" +SIG_TARGETS="ubuntu-1804 ubuntu-2004 ubuntu-2204 centos-7 rhel-8 windows-2019 windows-2019-containerd windows-2022-containerd flatcar" +SIG_CI_TARGETS="ubuntu-2004 ubuntu-2204 centos-7 windows-2019-containerd windows-2022-containerd flatcar" +SIG_GEN2_TARGETS="ubuntu-1804 ubuntu-2004 ubuntu-2204 centos-7 flatcar" +SIG_GEN2_CI_TARGETS="ubuntu-2004 ubuntu-2204 centos-7 flatcar" diff --git a/cloudinit/.gitignore b/cloudinit/.gitignore new file mode 100644 index 0000000..5131f95 --- /dev/null +++ b/cloudinit/.gitignore @@ -0,0 +1,3 @@ +/*.iso +/*.tar.gz +/.cidata-* \ No newline at end of file diff --git a/cloudinit/Makefile b/cloudinit/Makefile new file mode 100644 index 0000000..5a243ea --- /dev/null +++ b/cloudinit/Makefile @@ -0,0 +1,31 @@ +all: build + +CONFIG_DIR ?= .cidata-$(shell date +%s) +CONFIG_DIR ?= $(abspath $(CONFIG_DIR)) + +ifneq (,$(strip $(KUBERNETES_VERSION))) +ISO ?= cidata-$(KUBERNETES_VERSION).iso +endif +ISO ?= cidata.iso +ISO := $(abspath $(ISO)) + +$(ISO): + @rm -f $@ + @mkdir -p $(CONFIG_DIR) && cp user-data meta-data $(CONFIG_DIR)/ +ifneq (,$(strip $(KUBERNETES_VERSION))) + sed 's/kubernetesVersion: v1.13.6/kubernetesVersion: $(KUBERNETES_VERSION)/' >$(CONFIG_DIR)/user-data /dev/null))) + cd $(CONFIG_DIR) && genisoimage -output $@ -volid cidata -joliet -rock user-data meta-data +else + hdiutil makehybrid -o $@ -hfs -joliet -iso -default-volume-name cidata $(CONFIG_DIR) +endif + @rm -fr $(CONFIG_DIR) +.PHONY: $(ISO) + +build: $(ISO) + +clean: + rm -fr .cidata-* *.iso *.tar.gz +.PHONY: clean diff --git a/cloudinit/README.md b/cloudinit/README.md new file mode 100644 index 0000000..27fb37b --- /dev/null +++ b/cloudinit/README.md @@ -0,0 +1,7 @@ +# Cloud-init Test Data + +The files in this directory: + +* **Are** example data used for testing +* Are **not** included in any of the images +* Should **not** be used in production systems diff --git a/cloudinit/ca.crt b/cloudinit/ca.crt new file mode 100644 index 0000000..7184ffc --- /dev/null +++ b/cloudinit/ca.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICyzCCAbOgAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl +cm5ldGVzMB4XDTE5MDUyMTE0MzkwN1oXDTI5MDUxODE0MzkwN1owFTETMBEGA1UE +AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPrB +vAWE8PxPLuWT264DwTpINrtiERzO0XGHUwfXW2QltBQKv7c2JfUufZBqZqzD4KzV +6IbUGoOl4Gmf5IEp4nbNFF3xHcbbNRPcosE9e6MXJpKddy+JP1h3JRuXJgI/T5ng +XCLqVDlVoH7PPJ1Sl2PN61HoNF+AOwh4qVBgVgQna+HGy2zqqz4N9YwGMoCcMwHL +0vBTvp/CxfyDdliWiaC8XnyEKb6CtUc0v5iNC5tk7DD6MVheqLYUBL3pDct4AQVy +Ur0nJm1mQUihFnveUitiRzZ64LVuTne8kvupfQrPAPoDyT80yxp8BLx9Diz9dCp+ +JtjilQL9/tYN403bKS0CAwEAAaMmMCQwDgYDVR0PAQH/BAQDAgKkMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDQYJKoZIhvcNAQELBQADggEBACOu+VKnB+55sQk627pxEsVu +7KMRSFInjzFjksisjiIOXeaUKoQHZZcso32U67p61LPaTZeDFzKEYS+dXFrfyab5 +xgUU2h1CFSX9zPRlp/OALt+5KW76nSwPkEl9OxMvW0MglShAZUm2J9EbFIdKzLZX +2TyzfVlxXuLWdToDjE2xFxvyJKz8wj7il9S/oaNerxQwxPXNoevlmPijOKZP3v/K +oatSeOqvUds0IudEMBEauupqKFfz5Xwpui268wNzodxyPrBK/wBH0qFxtnwEcfYD +P05LwTpP+xvqxqNNyIFRwFZw54hKIqVfKVqNib/iYZq4JzDW5pWrQa3xoA2IoGM= +-----END CERTIFICATE----- diff --git a/cloudinit/ca.key b/cloudinit/ca.key new file mode 100644 index 0000000..1c75d62 --- /dev/null +++ b/cloudinit/ca.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA+sG8BYTw/E8u5ZPbrgPBOkg2u2IRHM7RcYdTB9dbZCW0FAq/ +tzYl9S59kGpmrMPgrNXohtQag6XgaZ/kgSnids0UXfEdxts1E9yiwT17oxcmkp13 +L4k/WHclG5cmAj9PmeBcIupUOVWgfs88nVKXY83rUeg0X4A7CHipUGBWBCdr4cbL +bOqrPg31jAYygJwzAcvS8FO+n8LF/IN2WJaJoLxefIQpvoK1RzS/mI0Lm2TsMPox +WF6othQEvekNy3gBBXJSvScmbWZBSKEWe95SK2JHNnrgtW5Od7yS+6l9Cs8A+gPJ +PzTLGnwEvH0OLP10Kn4m2OKVAv3+1g3jTdspLQIDAQABAoIBAAnGocjpTOfZQm/K +2uam2NKn3BJkGVyxJ3MwnmkQ2UxHOAUMAjtnTgWIAXcu3r/fhxPV5xHSlRIK1nvn +suXiNyUAi8m5y7pj82bJ1EKKXhaWoXdX0jy1MhYF1xmDRAUUaMsL9yuZTR1LHE21 +UJyliqdmcMUps1kBy8thwOAUUWYp+4ZUKSVh9vPaOQbsPaTEWgQziz5rY/D7tABz +cqLfmEFfSKDBmldvWvLga8xIMoLAQHjvTj6m04TWjndppazdwGokv6VLphcr8xXu +2VUBBnXUaS9ed0GPo8I7OuF0J3fTynkvNE+WjJ+gCj352V02OaDB3i5xc0WV3mUI +5mX/JpUCgYEA/ZFfzOyq5EIaGqIvNWvkv5L5zuoeP7HTK5odlyYdSBk7qlJU9BW2 +LY6QS+FClAc1ZQxiegfk7yt+Q1f1KRlwOjqOsQ5uM/fkMhK5D01I9jRHT62v46Uo +5vOhAk+8vTof/BUXP4mAImlYfGbxC9Pd/uza3Nqd7MtV8mcG8u5skmcCgYEA/Sl1 +LKMBhazHx/Y8uw0aKlW3HmEfhE11RAAPmDn3Fr/CO1MkLaPRzVWDBO3l5DI30l8H +apGYd78UePW43og0vHueN5IjHalOIdvWRFDqLbB68/MJDBcYSMTV0VRZq3owV3U8 +8gjILQhxZd2A2nbSbGzhaqA4qYQxHkc4SsJ4c0sCgYEA9NPeuhBxWH9ykPCzwFLy +xP52cRCgMEPUby8ZDw3gC/NBJszj9eDYy9fw/zL6g88KAQ0aMFVa+Ir4GLHeptZH +BBHyIIacZVUeYjKtuFaY8g+8IvTC9XxMp+HoPkEbLWHn7A+5KMHslE0/AK6sYw0o +NbIgCEqVXUNfMvPDQ+BtuFUCgYEAhwvmhbkuxrA0omaoXt/OZWb0GDCXL2xicbPW +nc3OEUSZyCvB0NbixDYpfiepyuE/BenLev3P55D2ys/JnmvqNeF7tQkv0lLOayFq +W2cOhPDvpdKvsNNhEPBvXwswCllUEFNp/3LP1bX7R+uxINjhxxUN6mMt1r+9s/kp +/jdfKaECgYEA1SDLH7H6ANHEiel+oKXKHDf7WD+ZYphfaekwTYd4SyJJDPMJ5AXF +Mu7gYKsAVl2Eb7BgmE/yIkTSsxqvIDWllPQjnVfClXEGfcrWCuLuQjqxQUFne+Li +GzvsaINFnePtiea3zt2BK9FUSp3ceIFuZATcSbODq8HOJzutSreXbts= +-----END RSA PRIVATE KEY----- diff --git a/cloudinit/id_rsa.capi b/cloudinit/id_rsa.capi new file mode 100644 index 0000000..0919a94 --- /dev/null +++ b/cloudinit/id_rsa.capi @@ -0,0 +1,27 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn +NhAAAAAwEAAQAAAQEAxSCrM09uuR2LocFidwsKMwilyN8veG0KKHEH9fxEau15Fiee1t65 +G6TF7TNJdSCn4Y55EcxZFw2uVoEWBbwKLIevC3ipmIaCWDip8r8f52AU/2mFnS7v3nYL/E +/BmChtTIlOkXTb7BrFyACoZJwbXLJk3Edp4hMDpl0OTPz96DLMFpPuFiHFsiVOgVgEGyv2 +pVZ+ZCEUBWrOO5Oj5JtU4O0yr/jDl+iT87/IDqsb6nFxSqBHE7YQtibCr5kcADrS6wR4eQ +TMzilfRvgp5oM5jP6eqlNZ33m7wzbgbc04VET9JU3CRpn/oOVrWyfL3VHfjABWRqb6AEZd +b9bOFG5HnQAAA8BPyNvFT8jbxQAAAAdzc2gtcnNhAAABAQDFIKszT265HYuhwWJ3CwozCK +XI3y94bQoocQf1/ERq7XkWJ57W3rkbpMXtM0l1IKfhjnkRzFkXDa5WgRYFvAosh68LeKmY +hoJYOKnyvx/nYBT/aYWdLu/edgv8T8GYKG1MiU6RdNvsGsXIAKhknBtcsmTcR2niEwOmXQ +5M/P3oMswWk+4WIcWyJU6BWAQbK/alVn5kIRQFas47k6Pkm1Tg7TKv+MOX6JPzv8gOqxvq +cXFKoEcTthC2JsKvmRwAOtLrBHh5BMzOKV9G+CnmgzmM/p6qU1nfebvDNuBtzThURP0lTc +JGmf+g5WtbJ8vdUd+MAFZGpvoARl1v1s4UbkedAAAAAwEAAQAAAQAR4DeGLKLWyJYb8gRy +1R50qEkYYRzV59Vu+2kEZn7xz10WpDskMwhIOHX2X5s+stpmetwBwC0oCQaRM52CoZ2ukh +NOj/+ZJEF3rJPEvo4vFihxTOlf6py36K6Hj9f3a1sWALGOQTGcRIVA8MZUcU+N5WN+Ej/I +z36aPIAKfTqtLp1CdaAuw/9l48+e71yE4ESiaXBhTGlaTzATqLcN2URhjYwsJZverxlEtE +qWQmQ+vwm0JT1hsU5OEm/K7rtg9h0DZh1fLZlkbOSDX01nOsNnx4eAtuq+TLOuCvcc7Fl9 +FT4oYbGlhad/xLtxbcXrukEMLI3x4cMMfTVxJIQ5PcThAAAAgDu0Jmj+bWT4HhCTmfL8jG +g14j3HxyDx7fXCF7VJvZfpffxhkmHJEJL5+450XWm5XVE/4yYPF0Gghyh0wHcdXlB8IMHl +D7u9eWBOGNCSxv0uZAVKnRRlRsxF6kZ4uN+T+BGfIHTOBwli2xYv7tAAyryShbcf1iMKUh +SY31U9BsokAAAAgQDttiLUC4wjwlqEwAWg7FAnmz7QQ7wX6SxVWhbWm5XTkX3NfF2n4Ukg +qLoZh63RT3akrVtrWj0jG/Ozu/csSSNz0lgh1NbkWe9/wwiJWyKZEpHv5TIn6FhBSp4Txk +jBD68gkV80ys3Uw0SwI7eIUkKkPgUkMZMlYkeglXiDxHVjlQAAAIEA1Es12D9jRRHmNJgk +XOI8XObwfXZL+QVY8n2afliO3T3zDAwzbILY1Fn9DdSc87cjnadZ5lL3GPamxBzrdBnBx+ +DBU4b5oeUHkCh+bvDxdrbc4hsiVqgcRGD2p7M2001tcjJUCcqSA5r6wDTYO+WvAoMcZurr +NoSRtzHmev+i0ekAAAAEY2FwaQECAwQFBgc= +-----END OPENSSH PRIVATE KEY----- diff --git a/cloudinit/id_rsa.capi.pub b/cloudinit/id_rsa.capi.pub new file mode 100644 index 0000000..cee89af --- /dev/null +++ b/cloudinit/id_rsa.capi.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFIKszT265HYuhwWJ3CwozCKXI3y94bQoocQf1/ERq7XkWJ57W3rkbpMXtM0l1IKfhjnkRzFkXDa5WgRYFvAosh68LeKmYhoJYOKnyvx/nYBT/aYWdLu/edgv8T8GYKG1MiU6RdNvsGsXIAKhknBtcsmTcR2niEwOmXQ5M/P3oMswWk+4WIcWyJU6BWAQbK/alVn5kIRQFas47k6Pkm1Tg7TKv+MOX6JPzv8gOqxvqcXFKoEcTthC2JsKvmRwAOtLrBHh5BMzOKV9G+CnmgzmM/p6qU1nfebvDNuBtzThURP0lTcJGmf+g5WtbJ8vdUd+MAFZGpvoARl1v1s4Ubked capi diff --git a/cloudinit/meta-data b/cloudinit/meta-data new file mode 100644 index 0000000..6289f80 --- /dev/null +++ b/cloudinit/meta-data @@ -0,0 +1,12 @@ +cleanup-guestinfo: +- userdata +instance-id: iid-capi +local-hostname: capi.vm +network: + version: 2 + ethernets: + nics: + match: + name: ens* + dhcp4: yes + dhcp6: yes diff --git a/cloudinit/user-data b/cloudinit/user-data new file mode 100644 index 0000000..0e5e9e8 --- /dev/null +++ b/cloudinit/user-data @@ -0,0 +1,263 @@ +## template: jinja +#cloud-config + +write_files: +- path: /etc/kubernetes/pki/ca.crt + owner: root:root + permissions: '0640' + content: | + -----BEGIN CERTIFICATE----- + MIICyzCCAbOgAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl + cm5ldGVzMB4XDTE5MTIwODA3MjcwM1oXDTI5MTIwNTA3MzIwM1owFTETMBEGA1UE + AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN7G + 25nzw1aZ4Jt1dsrS/KeYMT4bxtmStu/8hvAy3vYD+OgLieIJI3UvNQfkf7UXE8Ad + 9nfGM3FcFSrsaXZ7ojW3Qd9fmwwS59nq0RY8ueF4spD/sO4jWe3AcC5m9sLB/ua5 + L4uWBqcBIa2iTHGqzIYxQfPhfSMncA+YieNCdcMk08t34uXPUjXTGck1I4UrBs/H + NvSszihL9ysL/tJC4prd1lBUxXJ+44aANVMloOWfr7yljgTXxEFCjJxec+xh2P6O + bqG7+TZvp75odj9jkVTZ2ENNq8tZFQjL+nD2fyafcXWoD3GmVT/tm+PtqUsc6C3M + pZCsmtkYHOOc3yklrl0CAwEAAaMmMCQwDgYDVR0PAQH/BAQDAgKkMBIGA1UdEwEB + /wQIMAYBAf8CAQAwDQYJKoZIhvcNAQELBQADggEBABxtRM80A5yJvxkZ0ELdHRWJ + 0rN+4tdFxjsDk9kci2pjuTAnNza8iiQrq6GaV00GO2nxQW0SXMj/5NL9H/wCqMi1 + vvueeDh8rOPCQ/UyjSi9/W4Jujh/L5KmTob7Ltw3alXFeE3Q/jwLVEFn3CSg2n3s + 1NefiO1/kJCYrKgtBiy704C6jvPDvaHV/SVvGhG9u+4xvyQeyzy4EOaupMeUps/A + 8qblFkiDwo/87cZoTr9z9qhitJI743UIEcrcoexMw+XhH7f0SsKa0gZn25PW63VO + K9CPCsvRfOFctN/qdvQSD7NIy7eqExn+9KWlPRmZuy2fMawXLXyn1JIAJTq5eeQ= + -----END CERTIFICATE----- + +- path: /etc/kubernetes/pki/ca.key + owner: root:root + permissions: '0600' + content: | + -----BEGIN RSA PRIVATE KEY----- + MIIEowIBAAKCAQEA3sbbmfPDVpngm3V2ytL8p5gxPhvG2ZK27/yG8DLe9gP46AuJ + 4gkjdS81B+R/tRcTwB32d8YzcVwVKuxpdnuiNbdB31+bDBLn2erRFjy54XiykP+w + 7iNZ7cBwLmb2wsH+5rkvi5YGpwEhraJMcarMhjFB8+F9IydwD5iJ40J1wyTTy3fi + 5c9SNdMZyTUjhSsGz8c29KzOKEv3Kwv+0kLimt3WUFTFcn7jhoA1UyWg5Z+vvKWO + BNfEQUKMnF5z7GHY/o5uobv5Nm+nvmh2P2ORVNnYQ02ry1kVCMv6cPZ/Jp9xdagP + caZVP+2b4+2pSxzoLcylkKya2Rgc45zfKSWuXQIDAQABAoIBAG+LBf1pjg7YcRul + jtszFQodK9q7Ma9SxIIY4L932Sc5CfG1hU5F4RkVj+npwP+9FEiHOBb0iGFkB708 + LfoDIU7f+P2M8ybyeGAmMJZ/xVpdgpsTS1WRIb/nMMQrDbaqR6TiaCnt7lrEOEam + Erx/FnTCSRGBf5SQdI16hN/jMO+Jm7yrKNfikkgoT5YF/bhZAuOEtdHFF9WiLLUY + KV64N9CvRTqJBA/ayvoT+35LVtFEKoYAosiSuT+qJVPHye8hL9HAQKiUWnfwW43m + hkzKDzq7kKilUy+T31UGWy6uvkJTAOPrSE6JxcChwG0bI0Ux5x5hwyM08M8uztC0 + ny1CggECgYEA9Zc2uxVVUeISQM1Go1pLQNUjwgfUcpN4DxXIyenh18U4OcFGKvVO + qeGELb0WXM/grKkK1t/Q+JNctBVX2sQT3y9GzjgD0JIhaGxwXJjd0zTpZbryef/J + eUmiBPoRPx8lRDQiQ2pZ7sU6QHZZHhuB4aH4TiuOplSjSCGlGS2RuEECgYEA6DgZ + +t6KHjOPO1Prua2HW0fsfAFXKsznvEZ3yRVdsvdrTa/KWdKvyiNQtgLSg7GtAfeq + b+w0M7e7hcDrj3H1Q8rRFjG6QcquzaJPEf6lWroTdypFChgGA2AgvF1WlWqoAlsY + QvDsSHCv8omPXEvKjNb/kNKKeXxse8Lsjj/YDx0CgYEArYdqCajaP2BQ627gQZ4U + XDv95ySnLUob4/TNijXy+QYGY3C4RrRMH+cUAUmBGpVbuEQ9P3Sn8GwXbbtC93Xi + YKnECwQzVdVbO7CbeCIfYxQY8mO03xUoY8XucDvNod888sMvjpj/8KF1NoUpFQf0 + rtxGWd2XDtnxAY+cW30CYMECgYBmBefcIRN7a1mdTiR9gjC6uOG8JXafdkDFpgwQ + i1OMQkmhav8y8W6MF3HpVVoZw+DnwWDfJV5V7n3zqKuVbRK9gwjTgGt9ZkfgTlQA + 6ujI8IGG1Epawe06ZGxddYCJyr8fsdf56RFWTjPvEeKrQR0vPXIwtV9jOngK87us + T35kPQKBgCc9VNuyDysSwkesHOozhqIBJW/6xDoodXd2QX6Ar+AXnzBkMbIkTJwA + 36y1hxWSj6vB2eJUhh/t8E9inU9fIj+Ak6Q3iAEvxeZZG3+x703Xd5e2YQSkiyDP + ojNzyST6biuKzV8VQKOg4XZju69eK3POH7yJ04u6DpA0Z68E5YuV + -----END RSA PRIVATE KEY----- + +- path: /etc/kubernetes/pki/etcd/ca.crt + owner: root:root + permissions: '0640' + content: | + -----BEGIN CERTIFICATE----- + MIICyzCCAbOgAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl + cm5ldGVzMB4XDTE5MTIwODA3MjcwNFoXDTI5MTIwNTA3MzIwNFowFTETMBEGA1UE + AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALFE + LSohMu0YznIKMmHq6/NCZXJLWbM2AHUJntnym/i1ynaJO5kNOTxy1DxdlM2GXXrN + tuCeu2s2EgeAa7odDmC1tXCnPbtmKx4UuNol/1ft9KbMu+nJ7tFdR1b4M8uquOUJ + dL2kyF7VLdl2J79TFKaHQs9yqhIQwdksBNBDG1NAE2fZDy3NxZA/WCx64kCWM7PT + Ea7SwKM6lJsLvFQBoJLXcG2DtC5lJN42a1+v/K8impTweJ5niJ1G6vvtr0n7X2ep + sezSTjKE/sEBhduWrI/FZnVI/OOS2vIKE+9NZm8nXwDl0LIOLMAbsxxBLUlE5Hih + PaaYQ2JfE5Ou0q+J9uMCAwEAAaMmMCQwDgYDVR0PAQH/BAQDAgKkMBIGA1UdEwEB + /wQIMAYBAf8CAQAwDQYJKoZIhvcNAQELBQADggEBAHSdUQ/LCAeEqyVDY7W8XUnt + y4vX/QHob3hVi8CdjkBP5RssotXAN9WBVB0myfo6fulcAQbQsbP5UCn1eJLnnYlX + GAaKbqVdzxz0vyIWgFRDYqWSPWXvFMJRQ1PHOJgh2xlI1QXI6Eu2SLcyl5oULZV4 + J9du4VoESAAHsZ5gwGuXtgepbAknNfdlal1L1ZI40aa6zkpy09gW/WwFFSt97Ps7 + c/NNZozZY5YNV+2riIDpINLw6qN6O8xKbCXZNA9D2yjoIjok3bX9MSvjkF/3voVu + 4lNx5D8KDzbyfSa9FSB5RkYAxwqYldzbnXVWtMXnsCPEhntEFzwfgfHzyterH38= + -----END CERTIFICATE----- + +- path: /etc/kubernetes/pki/etcd/ca.key + owner: root:root + permissions: '0600' + content: | + -----BEGIN RSA PRIVATE KEY----- + MIIEowIBAAKCAQEAsUQtKiEy7RjOcgoyYerr80JlcktZszYAdQme2fKb+LXKdok7 + mQ05PHLUPF2UzYZdes224J67azYSB4Bruh0OYLW1cKc9u2YrHhS42iX/V+30psy7 + 6cnu0V1HVvgzy6q45Ql0vaTIXtUt2XYnv1MUpodCz3KqEhDB2SwE0EMbU0ATZ9kP + Lc3FkD9YLHriQJYzs9MRrtLAozqUmwu8VAGgktdwbYO0LmUk3jZrX6/8ryKalPB4 + nmeInUbq++2vSftfZ6mx7NJOMoT+wQGF25asj8VmdUj845La8goT701mbydfAOXQ + sg4swBuzHEEtSUTkeKE9pphDYl8Tk67Sr4n24wIDAQABAoIBAFCrNeJ2OTask0ZS + XZsxzS5miMP6hleHu62HM0L7pP8Ju5k12mlMGz/nAa5258Cf5Op9szuFAMVJVesU + BfIsRt670lXxxaYCWJzX0Ud1Az6Ai1Vc1icOPiAI0u5BBVEp3/pa00V6N7TwTm0n + 1+65YCxoYX8GL18JQS4TWh1sbIL1Y70ioHha7gBQKJ4oph+B/Rd9VjZB/p3jutUx + T/DpcRbuYseOFXzUmYdtdELXeWc0OCpWTcHdC6xSfFlOoEqSDjXvNrFZ9xg6XO5J + +hAHqNytg5mmUAYW1JF+uMrXrr9rkEdZBT4jdYlnDqSRE14jsIWlpOURDquxOqku + g8zckAECgYEAyozhfeZMOW+rWJ/cWfZscsOHBM8WgjcfwEnqv1ryVGEu6Ksu3HY4 + buvp6ibxhnub6g167CXc2cagnXzYtxFrNcy7dhB+Tq1BGKR5O8qHT8V0Uyp1jybA + F3eqiO7HtdyhMMND+CbYf5d2IWZZyZsXiLj3fOvdhgBcYD/6ZzioLzMCgYEA4AtB + efmJdV6r0Y4efuFw7KsgQkSb7WSrGQwUlWZwPehS4n0+EduFg7bojxch7WxEf1/I + BR8tub7Et7IT7QR90jBgqo0T7PYCEbYEpZX9S3LG6O4snbMmlhWs6fVkyIu0vbwt + 0tn3tHb1kZxceLMyueIVD76pRADGfdAOIMqn2ZECgYEAjfVnJMH/slGdmaOQ4Exh + fZ2kR66Ma/8OdcpYiHzJUnI6Wj9/vGvu6W7WppFcvZBsmgGQoWl3+/nGIBqcGNJQ + fYhb6kds/t9WvFqpzUoIw9Pzz0X21rml78yi7Q3NUpyrLG3ueUFggyw4UvhU/YOB + XwWkDx2QSJaAJ8UvTqDa3xkCgYAQ8+kVcLNdBTfdGHLoSOjBj8VWHljqIqbrs0VP + dLvjg1PaPX3X3hOBPvLj+O0hSQL53GaHNK/CEVRTTg9B7QgUQoLeBOTQFmFbs7kw + SmQrNFkmwPbxS+AMlUFLRr1Ei4W2oamZ/dJHfoTgasN4gp7BAAF1+ohWU/SxCnA3 + PP5scQKBgANe++ZusilLjNG8CET1POf9zt7ZPogWRNeTb6GCqwmjh6/JTjAy9FdV + pAclkp/91usp8RmHnwJP7KzXCCq3qiJhytQl9lgiW3QecnKp5q0t9d5ObZU0vLQH + SJawb/BO0jqgG1R22DgSDqCsggOkqdG8Btm2i/rpuM4mnukUOtTQ + -----END RSA PRIVATE KEY----- + +- path: /etc/kubernetes/pki/front-proxy-ca.crt + owner: root:root + permissions: '0640' + content: | + -----BEGIN CERTIFICATE----- + MIICyzCCAbOgAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl + cm5ldGVzMB4XDTE5MTIwODA3MjcwM1oXDTI5MTIwNTA3MzIwM1owFTETMBEGA1UE + AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIm + mphoOFDsh6krI6sVGbBmq4K72+Dme7jCP8IMhvLDx5lSB0l4+HPowVd+cYScciEF + uENl4rZB9sWzkrdl/cukvqLd9Vkm57VQWzkDYKYj4Uvukda+9xu/hLv2FItwCzkm + wAeO5yNJKc/ut9qFEMUU45Lv+4929CDfEQaHLIPM7tUFTEKrqS8iyxnrO7DJ9ylC + IJULV3UaYAKsrYl5dU3zzjJOyio0O0BrDfZO7/mI2HYWtA3Y0AjNYWtHNOQ4qVZx + W2CGLgRmgq/9wMVnZtUIqj0ePuiS4VCXdZ5LNH6bOQT9ouO5P8v97/SnxG+dLfTd + PxrkXHd0uyLYujChaSMCAwEAAaMmMCQwDgYDVR0PAQH/BAQDAgKkMBIGA1UdEwEB + /wQIMAYBAf8CAQAwDQYJKoZIhvcNAQELBQADggEBAILC3rTdBQsDRox+rQnSkg0d + FLRyS5F3icVgE7C5iWLGKzM3kgYtyMAck4tCcEVMR1Omja0zOoRnvvfXKNzP8qf6 + XNXgQEloNd2QFAC5jQrGAZ365Ntop74VL8jigJTyKk7jdgPwuxIC5WLmVRfMspvj + ZoMK5GhbMhM6/IgkFq3tVQBoKnOYw+yeNKcRTraRuvZiEOcWT/9re75kYfOscBBZ + 3cFdvcnSA+qxlrn2PUY2Pfsrm6faTFZJ3ESkeDBLLIq81SsJiXuuK7tzRignP3UN + JL4aJZygxHqkLPFaTXZNYdJQeEOC5Kr6w+Rh/FeYRWVDyTo2+FDRC5v4WbjZqBc= + -----END CERTIFICATE----- + +- path: /etc/kubernetes/pki/front-proxy-ca.key + owner: root:root + permissions: '0600' + content: | + -----BEGIN RSA PRIVATE KEY----- + MIIEpQIBAAKCAQEAwiaamGg4UOyHqSsjqxUZsGargrvb4OZ7uMI/wgyG8sPHmVIH + SXj4c+jBV35xhJxyIQW4Q2XitkH2xbOSt2X9y6S+ot31WSbntVBbOQNgpiPhS+6R + 1r73G7+Eu/YUi3ALOSbAB47nI0kpz+632oUQxRTjku/7j3b0IN8RBocsg8zu1QVM + QqupLyLLGes7sMn3KUIglQtXdRpgAqytiXl1TfPOMk7KKjQ7QGsN9k7v+YjYdha0 + DdjQCM1ha0c05DipVnFbYIYuBGaCr/3AxWdm1QiqPR4+6JLhUJd1nks0fps5BP2i + 47k/y/3v9KfEb50t9N0/GuRcd3S7Iti6MKFpIwIDAQABAoIBAHV3remwhQJRWfM8 + qqQEbDqSpArBZtO4H/s1bCYYNj4DvmxBeS83Bfv7Q5+QXVaC4XqhX09IAdeMKaaM + c6SLDPd9gepAqQV7yI2nRMpGBOAArXunqI1plVEwmzquNNf4vpGhpGXuTGLJDYdF + Q+/uuqrDbL2mfWnb6vFIhaCRgJltAk/wpwfHkPlWdhJOUR2ofozCf4ebzQLZPYMv + NtRp+SsASuAzhVAxRAx2LSgyqjRaJUxi9Hczk0deWyxhZCUicBUfHVaL7F5nco6A + AIenh+ytnagFdYyxSLqiBvEKnR7RcwLAP9mgzyKLlnV/WC19tAZTYgOJc14NLp7w + jbQXmUECgYEAz7VcMyZvwSWMHY9XIab7iNHXCxb+uqVX0kfHf5maRyH3GCjbQ1SS + y36GJa3zwPOoPTs6Eohi68MXT/o/VPFK8DfSfWbegncKC39hl3MrMRqQlqrdlhCZ + TjYCke7YNg4X6kOKSIhr7WiHTeBqT6m3RtUjNtc5Xq7a/MGQ0y0ll0kCgYEA70pN + w0rHdURKrgBPinqmWYtlh5+0AQu8dOjo/Q2keH0rpfHo1qJ0jTzvM3FkiuM+hSIr + /BMVMCbq6jI4tLO+qadKOUfRb4VHfWAPKjoxKN3Jick9MFuPJFejoAfc4w5c0StC + Uih5jfhgcXhTKfQcsWiOXE4G7yuIBgrtsVHnoQsCgYEAzYMYctO5B1ZrSGQnRfi+ + MCXPq/1YlLw8JKc40Rvd9ju5DIKAUCJCDG5ntKhk4akz8UHEt8mSdstVKaDlQNpt + 1zikX8eEqXm2yqGCoiMlvTQXk7wD+xL5XNU7vcCg1Psk1nl1PUcd4ozmMzu0dJXr + 7X29lellrjU8H5I2BXxKEWECgYEAvRX/CuItaMnVJVgTgn7Wso2HZjtZlzX57nwZ + l9VO8PMgKZpV/j0TUoQjFIh3BZT6U2OkVCWUKZ+nI/cZfhlHAXKzIT5SDgjIbBcb + BKhFLmDLn/iIRI0lOHeUUaHE9xrjV1oSpy9alkf9lcyaEt3WSo4vaFsz+YxxiSzb + lLH/Ee8CgYEAzgWSlyV6f+Szs3794uaH+QHtjrAsIGbWnRR8pJw74mqwbzMtEVma + PlwA2dPh5ZHwXzUNHXDMeKflDg+tEZJr7MV60zlKCP5rUHHhtzixkNoyW1b5BxOp + WSmL3tHGg+NxwlifTGFm8a8WmSzZeS4uAwSGQUegvO7H8BClt+XrZk4= + -----END RSA PRIVATE KEY----- + +- path: /etc/kubernetes/pki/sa.pub + owner: root:root + permissions: '0640' + content: | + -----BEGIN PUBLIC KEY----- + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9sXSwCqczBP5YDJEzv/S + eHB1QinTswKE3NS4hxZ4iPO6q7cwkPd2yCtPNlbwZL+O30VIIKt8HoTwoX2njgfv + 0qHCBEvXK4Z3eVSH5I43IlH5p2l9BlyQHf2l2L+5bAkAxF3LXLBGPVsyQwIVzgKz + oFpx+otC5VI4G2u640Q4R1uG7steEaYVU0NgrBsuKfWpzcK10PjZ6Wr1RD+H4Z3N + UMZSuNQlwsZpL/32IZoOJmzDLwmc1gBeQSWsX8HHNvTiw3rvfR1pP5x4GUcY/m0y + lvH1T2Keo5+aV2YO9DeZzyFl/FRLGFfZ7MyxoRkaPBH4CQJMqYILFbVmGJZdLBrN + xwIDAQAB + -----END PUBLIC KEY----- + +- path: /etc/kubernetes/pki/sa.key + owner: root:root + permissions: '0600' + content: | + -----BEGIN RSA PRIVATE KEY----- + MIIEpAIBAAKCAQEA9sXSwCqczBP5YDJEzv/SeHB1QinTswKE3NS4hxZ4iPO6q7cw + kPd2yCtPNlbwZL+O30VIIKt8HoTwoX2njgfv0qHCBEvXK4Z3eVSH5I43IlH5p2l9 + BlyQHf2l2L+5bAkAxF3LXLBGPVsyQwIVzgKzoFpx+otC5VI4G2u640Q4R1uG7ste + EaYVU0NgrBsuKfWpzcK10PjZ6Wr1RD+H4Z3NUMZSuNQlwsZpL/32IZoOJmzDLwmc + 1gBeQSWsX8HHNvTiw3rvfR1pP5x4GUcY/m0ylvH1T2Keo5+aV2YO9DeZzyFl/FRL + GFfZ7MyxoRkaPBH4CQJMqYILFbVmGJZdLBrNxwIDAQABAoIBAQDkWy+pUEWEvD8a + e6oc+7LibP61WUtj7cLRL7AKogqsgQ6O9JhmrfknRpyopk8SjAlEJzKVuNrEyzR5 + 3HN/BW0yNyn5G81jo61Pg5+1Kr1ubvldqEpf5qwedKhSKSkHBlXFYR5dCWoWQRwD + 0hwnZWyfyNKMjO48k5cEGO76fBiwPfsmucRVuLMzbJH8ivvk/olopUnTwKP68Jhd + kfoJ5wGdhaTN3ec8HjOgMx2cNhpOwPf9lO9xAWxiFQatUpMlO3h227LA3qZRnzeJ + wQ/Hho9A+4eq5+eXEPFRCBD/cHIdMppPwDsp9vn+WxtAJncS39aT2lNZbs96y56v + 5mYGSVEBAoGBAP8IhnYedYEp6iWe9u7azbS1SdtfZ3kpiupAyQct5MQcEFwPY9XL + 6XqR/qyJWU48grX6QTILyRf9KNee9y0TKukPVj0STjtqlGXrBbkA9L14WZI7vdEc + kywxFNmrCRu5eiwEmsM1N/GelfqrIy44a59vzkExq1ugSS5maYVQqQoHAoGBAPe1 + SEL8pjyyhbDnLigo/pROd4rv0pJRG6Qf9o8sQm4iDDXHk0Jn2bvGbvCDU0l88T3M + bAki8TjCgAGmA+HO9xfTLVOmApr3ZOqBbX9CKCIDnCQi86LfS4tX/sAw/Ol3JuL3 + hRL3klYefhA5ziT6aPAoiyppIZddmhq5PKXTDi5BAoGAWOteBl0EVy6IBunv6sO7 + KSB0Sdpvt1z2pEpGTQyBUKcARTjQdECOfT/d7cZNruuGH3DLvmlBie2oidVRFRQz + x+KjDNQPFsRITWiuLBzbOBx4DnZp7jjqT2QlgucRW+tFX4eTdjBd+w5x+F4m+/yL + +aD/5tcsidvO6DCo5eSDq40CgYEA8L0Jbrj2ovTpg4UaUcONr/sWqTvszXDwSTEb + QghEw55peXbuAlLFxH3U4gDv1/MKzgG3WaXRBFXbbD65dSLc+BWv7qTf0VXwiQyi + q1RThsM1Y9VoLXmQhOtPVeAGXKwFaf4fIdDkMrhN0l0roLqRdB4jKmOkVuSMWb5/ + V7XoCUECgYBC2C/PIfGMjcJqAT6+oxKTqtZJxNX/sw0wj5ZyAhqc77beQEkEhopX + VxncpOw3yesIFtZgBZBZMgMkE0Alzxwxxz8v0PUv1MaPpeZGNvuIZ95hRbgaraHI + rKEN7grrzL7sI/DvruWG+JjCKchlD80wlNmDMQmfWetvsyCQm18r9A== + -----END RSA PRIVATE KEY----- + +- path: /tmp/kubeadm.yaml + owner: root:root + permissions: '0640' + content: | + --- + apiServer: + extraArgs: + cloud-provider: external + apiVersion: kubeadm.k8s.io/v1beta2 + certificatesDir: "" + clusterName: sakc4 + controlPlaneEndpoint: "" + controllerManager: + extraArgs: + cloud-provider: external + dns: + type: "" + etcd: {} + imageRepository: registry.k8s.io + kind: ClusterConfiguration + kubernetesVersion: 1.17.11 + networking: + dnsDomain: cluster.local + podSubnet: 100.96.0.0/11 + serviceSubnet: 100.64.0.0/13 + scheduler: {} + + --- + apiVersion: kubeadm.k8s.io/v1beta2 + kind: InitConfiguration + localAPIEndpoint: + advertiseAddress: "" + bindPort: 0 + nodeRegistration: + criSocket: /var/run/containerd/containerd.sock + kubeletExtraArgs: + cloud-provider: external + name: '{{ ds.meta_data.hostname }}' + +runcmd: + - "hostname \"{{ ds.meta_data.hostname }}\"" + - "echo \"::1 ipv6-localhost ipv6-loopback\" >/etc/hosts" + - "echo \"127.0.0.1 localhost {{ ds.meta_data.hostname }}\" >>/etc/hosts" + - "echo \"{{ ds.meta_data.hostname }}\" >/etc/hostname" + - 'kubeadm init --config /tmp/kubeadm.yaml' + +users: + - name: capv + sudo: ALL=(ALL) NOPASSWD:ALL + ssh_authorized_keys: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFIKszT265HYuhwWJ3CwozCKXI3y94bQoocQf1/ERq7XkWJ57W3rkbpMXtM0l1IKfhjnkRzFkXDa5WgRYFvAosh68LeKmYhoJYOKnyvx/nYBT/aYWdLu/edgv8T8GYKG1MiU6RdNvsGsXIAKhknBtcsmTcR2niEwOmXQ5M/P3oMswWk+4WIcWyJU6BWAQbK/alVn5kIRQFas47k6Pkm1Tg7TKv+MOX6JPzv8gOqxvqcXFKoEcTthC2JsKvmRwAOtLrBHh5BMzOKV9G+CnmgzmM/p6qU1nfebvDNuBtzThURP0lTcJGmf+g5WtbJ8vdUd+MAFZGpvoARl1v1s4Ubked capi diff --git a/hack/boxes-flatcar.sh b/hack/boxes-flatcar.sh new file mode 100755 index 0000000..66e217e --- /dev/null +++ b/hack/boxes-flatcar.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +export VAGRANT_VAGRANTFILE=${VAGRANT_VAGRANTFILE:-/tmp/Vagrantfile.builder-flatcar} + +fetch_vagrantfile() { + curl -sSL -o ${VAGRANT_VAGRANTFILE} \ + https://raw.githubusercontent.com/flatcar/flatcar-packer-qemu/builder-ignition/Vagrantfile.builder-flatcar +} + +list_boxes() { + vagrant box list \ + | grep -E '^flatcar-(alpha|beta|stable|edge)-[0-9.]+' \ + | sed 's/flatcar-\(alpha\|beta\|stable\|edge\)-\([0-9.]\+\).*/\1 \2/' +} + +fetch_vagrantfile + +list_boxes | while read -r channel release; do + export FLATCAR_CHANNEL="$channel" + export FLATCAR_VERSION="$release" + + echo "##############################################" + echo "Image:" + virsh vol-info --pool default "flatcar-${channel}-${release}_vagrant_box_image_0.img" + echo "Env:" + echo " export FLATCAR_CHANNEL='$channel'" + echo " export FLATCAR_VERSION='$release'" + echo " export VAGRANT_VAGRANTFILE='$VAGRANT_VAGRANTFILE'" + + # shellcheck disable=SC2016 + vagrant status | grep -v 'Run `vagrant up`' + + [ "$1" = "cleanup" ] && { + echo "#### Cleaning up vagrant VM" + + img_name="flatcar-${channel}-${release}_vagrant_box_image_0.img" + box_name="packer_flatcar-${channel}-${release}_libvirt.box" + vagrant_name="flatcar-$channel-$release" + + vagrant halt + vagrant destroy -f + vagrant box remove "$vagrant_name" + virsh vol-delete --pool=default "$img_name" + + rm -f "$box_name" + } +done diff --git a/hack/convert-cloudstack-image.sh b/hack/convert-cloudstack-image.sh new file mode 100755 index 0000000..0bf150d --- /dev/null +++ b/hack/convert-cloudstack-image.sh @@ -0,0 +1,136 @@ +#!/usr/bin/env bash + +# Copyright 2022 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +function xen_server_export() { + echo "Creating XenServer Export for $1" + qemu-img convert -f qcow2 -O raw "$1" "$1".raw + vhd-util convert -s 0 -t 1 -i "$1".raw -o "$1".vhd + faketime '2010-01-01' vhd-util convert -s 1 -t 2 -i "$1".vhd -o "$1-xen.vhd" + rm -f *.bak + echo "Created .vhd file, now zipping" + bzip2 "$1-xen.vhd" + chmod +r "$1-xen.vhd.bz2" + echo "$1 exported for XenServer: $1-xen.vhd.bz2" +} + +function vmware_export() { + echo "Creating VMware Export for $1" + qemu-img convert -f qcow2 -O vmdk -o adapter_type=lsilogic,subformat=streamOptimized,compat6 "$1" "$1-vmware.vmdk" + CDIR=$PWD + chmod 666 $1-vmware.vmdk + stage_vmx $1-vmware $1-vmware.vmdk + ovftool $1-vmware.vmx $1-vmware.ova + rm -f $1-vmware*.vmx $1-vmware*.vmdk + cd $CDIR + chmod +r "$1-vmware.ova" + echo "$1 exported for VMware: $1-vmware.ova" +} + +function stage_vmx() { + cat << VMXFILE > "${1}.vmx" +.encoding = "UTF-8" +displayname = "${1}" +annotation = "${1}" +guestos = "otherlinux-64" +virtualHW.version = "11" +config.version = "8" +numvcpus = "2" +cpuid.coresPerSocket = "2" +memsize = "2048" +pciBridge0.present = "TRUE" +pciBridge4.present = "TRUE" +pciBridge4.virtualDev = "pcieRootPort" +pciBridge4.functions = "8" +pciBridge5.present = "TRUE" +pciBridge5.virtualDev = "pcieRootPort" +pciBridge5.functions = "8" +pciBridge6.present = "TRUE" +pciBridge6.virtualDev = "pcieRootPort" +pciBridge6.functions = "8" +pciBridge7.present = "TRUE" +pciBridge7.virtualDev = "pcieRootPort" +pciBridge7.functions = "8" +vmci0.present = "TRUE" +floppy0.present = "FALSE" +ide0:0.clientDevice = "FALSE" +ide0:0.present = "TRUE" +ide0:0.deviceType = "atapi-cdrom" +ide0:0.autodetect = "TRUE" +ide0:0.startConnected = "FALSE" +mks.enable3d = "false" +svga.autodetect = "false" +svga.vramSize = "134217728" +scsi0:0.present = "TRUE" +scsi0:0.deviceType = "disk" +scsi0:0.fileName = "$2" +scsi0:0.mode = "persistent" +scsi0:0.writeThrough = "false" +scsi0.virtualDev = "lsilogic" +scsi0.present = "TRUE" +vmci0.unrestricted = "false" +vcpu.hotadd = "false" +vcpu.hotremove = "false" +firmware = "bios" +mem.hotadd = "false" +VMXFILE +} + +usage() { + echo "Converts a qcow2 image to any of the following formats" + echo " - x : XenServer [vhd]" + echo " - v : VMware [ova]" + echo "Usage: $0 QCOW2_IMAGE FORMAT" 1>&2 +} + +if [ "$1" = "-h" ]; then + usage + exit +fi + +FILE=$1 +if [ -z $FILE ]; then + usage + echo "File not specified. Exiting" + exit 1 +fi + +FORMAT=$2 +if [ -z $FILE ]; then + usage + echo "Format not specified. Exiting" + exit 1 +fi + +if [ ! -f $FILE ]; then + echo "File '$FILE' not found" + exit 1 +fi + +case $FORMAT in + v) + vmware_export $FILE + ;; + x) + xen_server_export $FILE + ;; + all) + vmware_export $FILE + xen_server_export $FILE + ;; + *) + echo "Unknown format. Supported options are [x, v]" + exit 1 +esac diff --git a/hack/ensure-ansible-windows.sh b/hack/ensure-ansible-windows.sh new file mode 100755 index 0000000..4f0241a --- /dev/null +++ b/hack/ensure-ansible-windows.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +# Copyright 2020 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +source hack/utils.sh + +_version="0.4.2" + +if [[ ${HOSTOS} == "darwin" ]]; then + echo "IMPORTANT: Winrm connection plugin for Ansible on MacOS causes connection issues." + echo "See https://docs.ansible.com/ansible/latest/user_guide/windows_winrm.html#what-is-winrm for more details." + echo "To fix the issue provide the enviroment variable 'no_proxy=*'" + echo "Example call to build Windows images on MacOS: 'no_proxy=* make build-'" +fi + +# Change directories to the parent directory of the one in which this +# script is located. +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +# Disable pip's version check and root user warning +export PIP_DISABLE_PIP_VERSION_CHECK=1 PIP_ROOT_USER_ACTION=ignore + +if pip3 show pywinrm >/dev/null 2>&1; then exit 0; fi + +ensure_py3 +pip3 install --user "pywinrm==${_version}" +if ! pip3 show pywinrm ; then exit 1; fi diff --git a/hack/ensure-ansible.sh b/hack/ensure-ansible.sh new file mode 100755 index 0000000..70f5b7a --- /dev/null +++ b/hack/ensure-ansible.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +# Copyright 2020 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +source hack/utils.sh + +_version="2.11.5" + +# Change directories to the parent directory of the one in which this +# script is located. +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +# Disable pip's version check and root user warning +export PIP_DISABLE_PIP_VERSION_CHECK=1 PIP_ROOT_USER_ACTION=ignore + +if ! command -v ansible >/dev/null 2>&1; then + ensure_py3 + pip3 install --user "ansible-core==${_version}" + ensure_py3_bin ansible + ensure_py3_bin ansible-playbook +fi + +ansible-galaxy collection install \ + community.general \ + ansible.posix \ + 'ansible.windows:>=1.7.0' \ + community.windows diff --git a/hack/ensure-azure-cli.sh b/hack/ensure-azure-cli.sh new file mode 100755 index 0000000..2d2a200 --- /dev/null +++ b/hack/ensure-azure-cli.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +# Copyright 2020 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +source hack/utils.sh + +# Change directories to the parent directory of the one in which this +# script is located. +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +if command -v az >/dev/null 2>&1; then exit 0; fi + +# Disable pip's version check and root user warning +export PIP_DISABLE_PIP_VERSION_CHECK=1 PIP_ROOT_USER_ACTION=ignore + +ensure_py3 +pip install -U pip setuptools +pip3 install --user azure-cli +ensure_py3_bin az azure-cli diff --git a/hack/ensure-boskosctl.sh b/hack/ensure-boskosctl.sh new file mode 100755 index 0000000..8492355 --- /dev/null +++ b/hack/ensure-boskosctl.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +if [[ -z "$(command -v boskosctl)" ]]; then + echo "installing boskosctl" + GO111MODULE=on go get sigs.k8s.io/boskos/cmd/boskosctl@master + echo "'boskosctl' has been installed to $GOPATH/bin, make sure this directory is in your \$PATH" +fi + +echo "testing boskosctl" +boskosctl --help diff --git a/hack/ensure-ct.sh b/hack/ensure-ct.sh new file mode 100755 index 0000000..b58474a --- /dev/null +++ b/hack/ensure-ct.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Copyright 2022 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +_version="v0.9.3" + +# Change directories to the parent directory of the one in which this +# script is located. +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +source hack/utils.sh + +if command -v ct >/dev/null 2>&1; then exit 0; fi + +mkdir -p .local/bin && cd .local/bin + +if [[ ${HOSTOS} == "linux" ]]; then + _binfile="ct-${_version}-x86_64-unknown-linux-gnu" +elif [[ ${HOSTOS} == "darwin" ]]; then + _binfile="ct-${_version}-x86_64-apple-darwin" +fi +_bin_url="https://github.com/flatcar/container-linux-config-transpiler/releases/download/${_version}/${_binfile}" +curl -SsL "${_bin_url}" -o ct +chmod 0755 ct +echo "'ct' has been installed to $(pwd), make sure this directory is in your \$PATH" diff --git a/hack/ensure-go.sh b/hack/ensure-go.sh new file mode 100755 index 0000000..823a4a7 --- /dev/null +++ b/hack/ensure-go.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash + +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +# Ensure the go tool exists and is a viable version. +verify_go_version() { + if [[ -z "$(command -v go)" ]]; then + if [[ "${INSTALL_GO:-"true"}" == "true" ]]; then + curl -sSL https://golang.org/dl/go${GO_VERSION:-"1.16.3"}.linux-amd64.tar.gz | tar -C /usr/local -xzf - + export PATH=/usr/local/go/bin:$PATH + export PATH=$(go env GOPATH)/bin:$PATH + else + cat <&2 + return 1 + ;; +esac + +# Check if current binary is latest +if [ -f "${_binfile}" ]; then + current_shasum=$(get_shasum "${_binfile}") + if [ "$current_shasum" != "$_sha256" ]; then + echo "Wrong version of binary present." + else + echo "Right version of binary present" + # Check if binary is executable. + # If not, delete it and proceed. If it is executable, exit 0 + { [ -x "${_binfile}" ] && exit 0; } || rm -f "${_binfile}" + fi +fi + +# download binary, verify shasum, make it executable and clean up trash files. +_bin_dir="$(dirname "${_tarfile}")" +mkdir -p "${_bin_dir}" && cd "${_bin_dir}" +curl -SsL "${_bin_url}" -o "${_tarfile}" +tar -C "${_bin_dir}" -xzf "${_tarfile}" +rm "${_tarfile}" +printf "%s *${_binfile}" "${_sha256}" >"${_binfile}.sha256" +if ! checksum_sha256 "${_binfile}.sha256"; then + _exit_code="${?}" + rm -f "${_binfile}.sha256" + exit "${_exit_code}" +fi +rm -f "${_binfile}.sha256" +chmod 0755 "${_binfile}" diff --git a/hack/ensure-jq.sh b/hack/ensure-jq.sh new file mode 100755 index 0000000..650466c --- /dev/null +++ b/hack/ensure-jq.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Copyright 2020 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +_version="1.6" # earlier versions don't follow the same OS/ARCH patterns + +# Change directories to the parent directory of the one in which this +# script is located. +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +source hack/utils.sh + +if command -v jq >/dev/null 2>&1; then exit 0; fi + +mkdir -p .local/bin && cd .local/bin + +if [[ ${HOSTOS} == "linux" ]]; then + _binfile="jq-linux64" +elif [[ ${HOSTOS} == "darwin" ]]; then + _binfile="jq-osx-amd64" +fi +_bin_url="https://github.com/stedolan/jq/releases/download/jq-${_version}/${_binfile}" +curl -SsL "${_bin_url}" -o jq +chmod 0755 jq +echo "'jq' has been installed to $(pwd), make sure this directory is in your \$PATH" diff --git a/hack/ensure-ovftool.sh b/hack/ensure-ovftool.sh new file mode 100755 index 0000000..f2b1611 --- /dev/null +++ b/hack/ensure-ovftool.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +[[ -z ${IB_OVFTOOL:-} ]] && exit 0 + +source hack/utils.sh + +if command -v ovftool >/dev/null 2>&1; then exit 0; fi + +echo "ovftool must be present to build OVAs. If already installed" >&2 +echo "make sure to add it to the PATH env var. If not installed, please" >&2 +echo "install latest from https://code.vmware.com/tool/ovf." >&2 +exit 1 diff --git a/hack/ensure-packer.sh b/hack/ensure-packer.sh new file mode 100755 index 0000000..00f3bab --- /dev/null +++ b/hack/ensure-packer.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +_version="1.8.5" + +# Change directories to the parent directory of the one in which this +# script is located. +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +source hack/utils.sh + +if command -v packer >/dev/null 2>&1; then exit 0; fi + +mkdir -p .local/bin && cd .local/bin + +SED="sed" +if command -v gsed >/dev/null; then + SED="gsed" +fi +if ! (${SED} --version 2>&1 | grep -q GNU); then + echo "!!! GNU sed is required. If on OS X, use 'brew install gnu-sed'." >&2 + exit 1 +fi + +_chkfile="packer_${_version}_SHA256SUMS" +_chk_url="https://releases.hashicorp.com/packer/${_version}/${_chkfile}" +_zipfile="packer_${_version}_${HOSTOS}_${HOSTARCH}.zip" +_zip_url="https://releases.hashicorp.com/packer/${_version}/${_zipfile}" +curl -SsLO "${_chk_url}" +curl -SsLO "${_zip_url}" +${SED} -i -n "/${HOSTOS}_${HOSTARCH}/p" "${_chkfile}" +checksum_sha256 "${_chkfile}" +unzip -o "${_zipfile}" +rm -f "${_chkfile}" "${_zipfile}" +echo "'packer' has been installed to $(pwd), make sure this directory is in your \$PATH" diff --git a/hack/ensure-powervs.sh b/hack/ensure-powervs.sh new file mode 100755 index 0000000..77cbae5 --- /dev/null +++ b/hack/ensure-powervs.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +# Copyright 2022 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +source hack/utils.sh + +SED="sed" +if command -v gsed >/dev/null; then + SED="gsed" +fi +if ! (${SED} --version 2>&1 | grep -q GNU); then + echo "!!! GNU sed is required. If on OS X, use 'brew install gnu-sed'." >&2 + exit 1 +fi + +_version="0.1.6" +_chkfile="packer-plugin-powervs_v${_version}_SHA256SUMS" +_chk_url="https://github.com/ppc64le-cloud/packer-plugin-powervs/releases/download/v${_version}/${_chkfile}" +_bin_url="https://github.com/ppc64le-cloud/packer-plugin-powervs/releases/download/v${_version}/packer-plugin-powervs_v${_version}_x5.0_${HOSTOS}_${HOSTARCH}.zip" +_zipfile="${HOME}/.packer.d/plugins/packer-plugin-powervs_v${_version}_x5.0_${HOSTOS}_${HOSTARCH}.zip" +_binfile="${HOME}/.packer.d/plugins/packer-plugin-powervs_v${_version}_x5.0_${HOSTOS}_${HOSTARCH}" +_powervs_bin="${HOME}/.packer.d/plugins/packer-plugin-powervs" + +_bin_dir="$(dirname "${_zipfile}")" +mkdir -p "${_bin_dir}" && cd "${_bin_dir}" +curl -SsLO "${_chk_url}" +curl -SsLO "${_bin_url}" +${SED} -i -n "/${HOSTOS}_${HOSTARCH}/p" "${_chkfile}" +checksum_sha256 "${_chkfile}" +rm -f "${_chkfile}" +unzip -o "${_zipfile}" +rm "${_zipfile}" +chmod 0755 "${_binfile}" +mv "${_binfile}" "${_powervs_bin}" diff --git a/hack/ensure-vhdutil.sh b/hack/ensure-vhdutil.sh new file mode 100755 index 0000000..df03c35 --- /dev/null +++ b/hack/ensure-vhdutil.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +# Copyright 2022 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +if ! command -v faketime >/dev/null 2>&1; then + echo "faketime must be present to convert to vhd" >&2 + exit 0 +fi + +if ! command -v vhd-util >/dev/null 2>&1; then + wget http://packages.shapeblue.com.s3-eu-west-1.amazonaws.com/systemvmtemplate/vhd-util + chmod +x vhd-util + wget http://packages.shapeblue.com.s3-eu-west-1.amazonaws.com/systemvmtemplate/libvhd.so.1.0 + echo "'vhd-util' and 'libvhd.so.1.0' has been installed to $(pwd), make sure this directory is in your \$PATH" +fi diff --git a/hack/generate-goss-specs.py b/hack/generate-goss-specs.py new file mode 100755 index 0000000..defcf03 --- /dev/null +++ b/hack/generate-goss-specs.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 + +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import itertools +import json +import os +import subprocess +import sys + +root_path = os.path.abspath(os.path.join(sys.argv[0], '..', '..')) + +# Define what OS's are supported on which providers +builds = {'amazon': ['amazon linux', 'centos', 'flatcar', 'ubuntu', 'windows'], + 'azure': ['centos', 'ubuntu', 'windows'], + 'ova': ['centos', 'photon', 'rhel', 'ubuntu', 'windows'], + 'oci':['ubuntu', 'oracle linux']} + +def generate_goss(provider, system, versions, runtime, dryrun=False, save=False): + cmd = ['goss', '-g', 'packer/goss/goss.yaml', '--vars', 'packer/goss/goss-vars.yaml'] + vars = {'OS': system, 'PROVIDER': provider, + 'OS_VERSION': versions['os'], + 'containerd_version': versions['containerd'], + 'docker_ee_version': versions['docker'], + 'distribution_version': versions['os'], + 'kubernetes_version': versions['k8s'], + 'kubernetes_deb_version': versions['k8s_deb'], + 'kubernetes_rpm_version': versions['k8s_rpm'], + 'kubernetes_source_type': 'pkg', + 'kubernetes_cni_version': versions['cni'], + 'kubernetes_cni_deb_version': versions['cni_deb'], + 'kubernetes_cni_rpm_version': versions['cni_rpm'], + 'kubernetes_cni_source_type': 'pkg', + 'runtime': runtime, + 'pause_image': versions['pause']} + + if system == "windows" and versions.get('ssh_url') is not None: + vars['ssh_source_url'] = versions['ssh_url'] + + # Build command + cmd.extend(['--vars-inline', json.dumps(vars), 'render']) + print('\nGenerating os: %s, provider: %s, runtime: %s' % (system, provider, runtime)) + print(cmd) + + # Run command with output going to file + if not dryrun: + if save: + out_dir = os.path.join(root_path, 'packer', 'goss') + out_filename = '%s-%s-%s-goss-spec.yaml' % (provider, + system.replace(' ', '-'), versions['k8s']) + out_filename = os.path.join(out_dir, out_filename) + with open(out_filename, 'w') as f: + subprocess.run(cmd, cwd=root_path, stdout=f, check=True) + else: + subprocess.run(cmd, cwd=root_path, check=True) + + +def read_json_file(filename): + j = None + with open(filename, 'r') as f: + j = json.load(f) + return j + + +def main(): + parser = argparse.ArgumentParser( + description='Generates GOSS specs. By default, generates all ' + 'possible specs to stdout.', + usage='%(prog)s [-h] [--provider {amazon,azure,ova}] ' + '[--os {al2,centos,flatcar,photon,rhel,ubuntu,windows}]') + parser.add_argument('--provider', + choices=['amazon', 'azure', 'ova','oci'], + action='append', + default=None, + help='One provider. Can be used multiple times') + parser.add_argument('--os', + choices=['al2', 'centos', 'flatcar', 'photon', 'rhel', 'ubuntu', 'windows'], + action='append', + default=None, + help='One OS. Can be used multiple times') + parser.add_argument('--dry-run', + action='store_true', + help='Do not run GOSS, just print GOSS commands') + parser.add_argument('--write', + action='store_true', + help='Write GOSS specs to file') + args = parser.parse_args() + + versions = {} + # Load JSON files with Version info + cni = read_json_file(os.path.join(root_path, 'packer', 'config', 'cni.json')) + versions['cni'] = cni['kubernetes_cni_semver'].lstrip('v') + versions['cni_deb'] = cni['kubernetes_cni_deb_version'] + versions['cni_rpm'] = cni['kubernetes_cni_rpm_version'].split('-')[0] + + k8s = read_json_file(os.path.join(root_path, 'packer', 'config', 'kubernetes.json')) + versions['k8s'] = k8s['kubernetes_semver'].lstrip('v') + versions['k8s_deb'] = k8s['kubernetes_deb_version'] + versions['k8s_rpm'] = k8s['kubernetes_rpm_version'].split('-')[0] + + containerd = read_json_file(os.path.join(root_path, 'packer', 'config', 'containerd.json')) + versions['containerd'] = containerd['containerd_version'] + + docker = read_json_file(os.path.join(root_path, 'packer', 'config', 'windows', 'docker.json')) + versions['docker'] = docker['docker_ee_version'] + + wincommon = read_json_file(os.path.join(root_path, 'packer', 'config', 'windows', 'common.json')) + versions['ssh_url'] = wincommon['ssh_source_url'] + + common = read_json_file(os.path.join(root_path, 'packer', 'config', 'common.json')) + versions['pause'] = common['pause_image'] + + providers = builds.keys() + if args.provider is not None: + providers = args.provider + + # Generate a unique list of all possible OS's if a choice wasn't made + oss = args.os + if args.os is None: + oss = [] + for x in list(builds.values()): + for o in x: + oss.append(o) + oss = list(set(oss)) + oss = [sub.replace('al2', 'amazon linux') for sub in oss] + # Generate spec for each valid permutation + for provider, system in itertools.product(providers, oss): + if system in builds[provider]: + if system == 'windows': + runtimes = ["docker-ee","containerd"] + os_versions = ["2019", "2004"] + elif system == 'rhel': + runtimes = ["containerd"] + os_versions = ["7", "8"] + elif system == 'photon': + runtimes = ["containerd"] + os_versions = ["3", "4"] + else: + runtimes = ["containerd"] + os_versions = [""] + for runtime in runtimes: + for version in os_versions: + versions["os"] = version + generate_goss(provider, system, versions, runtime, args.dry_run, args.write) + + +if __name__ == '__main__': + main() diff --git a/hack/image-build-flatcar.sh b/hack/image-build-flatcar.sh new file mode 100755 index 0000000..a598960 --- /dev/null +++ b/hack/image-build-flatcar.sh @@ -0,0 +1,145 @@ +#!/bin/sh -e + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +export VAGRANT_VAGRANTFILE=${VAGRANT_VAGRANTFILE:-/tmp/Vagrantfile.builder-flatcar} +export VAGRANT_SSH_PRIVATE_KEY=${VAGRANT_SSH_PRIVATE_KEY:-/tmp/vagrant-insecure-key} +export VAGRANT_SSH_PUBLIC_KEY=${VAGRANT_SSH_PUBLIC_KEY:-/tmp/vagrant-insecure-key.pub} + +usage() { + echo "Usage: $0 [] []" + echo " is one of: edge alpha beta stable (defaults to" + echo " stable)" + echo " release version to use (defaults to the latest" + echo " release available for )" +} +# -- + +check_for_release() { + channel="$1" + release="$2" + curl -L -s \ + "https://www.flatcar.org/releases-json/releases-$channel.json" \ + | jq -r 'to_entries[] | "\(.key)"' \ + | grep -q "$release" +} +# -- + +fetch_vagrant_ssh_keys() { + curl -sSL -o ${VAGRANT_SSH_PRIVATE_KEY} \ + https://raw.githubusercontent.com/hashicorp/vagrant/master/keys/vagrant + curl -sSL -o ${VAGRANT_SSH_PUBLIC_KEY} \ + https://raw.githubusercontent.com/hashicorp/vagrant/master/keys/vagrant.pub +} +# -- + +fetch_vagrantfile() { + curl -sSL -o ${VAGRANT_VAGRANTFILE} \ + https://raw.githubusercontent.com/flatcar/flatcar-packer-qemu/builder-ignition/Vagrantfile.builder-flatcar +} +# -- + +run_vagrant() { + echo "#### Fetching a test Vagrantfile remotely." + + fetch_vagrantfile + + echo "#### Importing $channel box to vagrant and setting up kubeadm." + + vagrant_name="flatcar-${channel}-${release}" + img_name="flatcar-${channel}-${release}_vagrant_box_image_0.img" + box_name="packer_flatcar_libvirt.box" + + export VAGRANT_VAGRANTFILE="${VAGRANT_VAGRANTFILE:-hack/Vagrantfile.flatcar}" + export VAGRANT_DEFAULT_PROVIDER="libvirt" + + echo "#### Cleaning up previous vagrant VMs" + vagrant halt || true + vagrant destroy -f || true + vagrant box remove "$vagrant_name" || true + virsh vol-delete --pool=default "$img_name" || true + + echo "#### creating and starting VM." + vagrant box add --name="$vagrant_name" "./$box_name" + vagrant up + vagrant ssh -c 'sudo systemctl stop locksmithd' + vagrant ssh -c 'sudo systemctl restart containerd' + + echo "#### Setting up kubeadm" + # shellcheck disable=SC1004 + vagrant ssh -c 'sudo kubeadm init --ignore-preflight-errors=NumCPU \ + --config=/etc/kubeadm.yml' + # shellcheck disable=SC2016 + vagrant ssh -c 'mkdir -p $HOME/.kube + sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config + sudo chown $(id -u):$(id -g) $HOME/.kube/config' + echo + vagrant ssh -c 'kubectl cluster-info' + echo + + echo "------------------------------------------------------------------" + echo "All done." + echo "You can access kubectl via 'vagrant ssh -c 'kubectl '" + echo "e.g." + echo " vagrant ssh -c 'kubectl get pods --all-namespaces'" + echo + echo " Please run:" + echo " export FLATCAR_CHANNEL='$channel'" + echo " export FLATCAR_VERSION='$release'" + echo " export VAGRANT_VAGRANTFILE='$VAGRANT_VAGRANTFILE'" + echo "before using vagrant commands." +} + +CAPI_PROVIDER=${CAPI_PROVIDER:-qemu} + +channel="$1" +case $channel in + edge);; + alpha);; + beta);; + stable);; + "") channel="stable";; + *) echo "Unknown channel '$channel'." + usage + exit 1;; +esac + +release="$2" +if [ -n "$release" ] ; then + check_for_release "$channel" "$release" || { + echo "Unknown release '$release' for channel '$channel'." + usage + exit 1; } +else + release="$(\ + "$(dirname "$0")"/image-grok-latest-flatcar-version.sh "$channel")" +fi + + +echo "#### Building for channel $channel, release $release." + +# set packer /vagrant env vars +FLATCAR_CHANNEL="$channel" +FLATCAR_VERSION="$release" +export FLATCAR_CHANNEL FLATCAR_VERSION + +rm -rf ./output/flatcar-"${channel}-${release}"-kube-* + +if [[ ${CAPI_PROVIDER} = "qemu" ]]; then + FLATCAR_MAKE_OPTS+="FLATCAR_CHANNEL=$channel FLATCAR_VERSION=$release " + FLATCAR_MAKE_OPTS+="SSH_PRIVATE_KEY_FILE=${VAGRANT_SSH_PRIVATE_KEY} " + FLATCAR_MAKE_OPTS+="SSH_PUBLIC_KEY_FILE=${VAGRANT_SSH_PUBLIC_KEY} " + + fetch_vagrant_ssh_keys + make ${FLATCAR_MAKE_OPTS} build-qemu-flatcar + run_vagrant +elif [[ ${CAPI_PROVIDER} = "aws" ]] || [[ ${CAPI_PROVIDER} = "ami" ]]; then + make ${FLATCAR_MAKE_OPTS} build-ami-flatcar +else + echo "Unknown CAPI_PROVIDER=${CAPI_PROVIDER}. exit." + exit 1 +fi + +exit 0 + +# vim:set sts=4 sw=4 et: diff --git a/hack/image-build-ova.py b/hack/image-build-ova.py new file mode 100755 index 0000000..162d6c0 --- /dev/null +++ b/hack/image-build-ova.py @@ -0,0 +1,272 @@ +#!/usr/bin/env python3 + +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################################################################ +# usage: image-build-ova.py [FLAGS] ARGS +# This program builds an OVA file from a VMDK and manifest file generated as a +# result of a Packer build. +################################################################################ + +import argparse +import hashlib +import io +import json +import os +import subprocess +from string import Template +import tarfile + + +def main(): + parser = argparse.ArgumentParser( + description="Builds an OVA using the artifacts from a Packer build") + parser.add_argument('--stream_vmdk', + dest='stream_vmdk', + action='store_true', + help='Compress vmdk file') + parser.add_argument('--vmx', + dest='vmx_version', + default='15', + help='The virtual hardware version') + parser.add_argument('--eula_file', + nargs='?', + metavar='EULA', + default='./ovf_eula.txt', + help='Text file containing EULA') + parser.add_argument('--ovf_template', + nargs='?', + metavar='OVF_TEMPLATE', + default='./ovf_template.xml', + help='XML template to build OVF') + parser.add_argument('--vmdk_file', + nargs='?', + metavar='FILE', + default=None, + help='Use FILE as VMDK instead of reading from manifest. ' + 'Must be in BUILD_DIR') + parser.add_argument(dest='build_dir', + nargs='?', + metavar='BUILD_DIR', + default='.', + help='The Packer build directory') + args = parser.parse_args() + + # Read in the EULA + eula = "" + with io.open(args.eula_file, 'r', encoding='utf-8') as f: + eula = f.read() + + # Read in the OVF template + ovf_template = "" + with io.open(args.ovf_template, 'r', encoding='utf-8') as f: + ovf_template = f.read() + + # Change the working directory if one is specified. + os.chdir(args.build_dir) + print("image-build-ova: cd %s" % args.build_dir) + + # Load the packer manifest JSON + data = None + with open('packer-manifest.json', 'r') as f: + data = json.load(f) + + # Get the first build. + build = data['builds'][0] + build_data = build['custom_data'] + + print("image-build-ova: loaded %s-kube-%s" % (build_data['build_name'], + build_data['kubernetes_semver'])) + + if args.vmdk_file is None: + # Get a list of the VMDK files from the packer manifest. + vmdk_files = get_vmdk_files(build['files']) + else: + vmdk_files = [{"name": args.vmdk_file, "size": os.path.getsize(args.vmdk_file)}] + + # Create stream-optimized versions of the VMDK files. + if args.stream_vmdk is True: + stream_optimize_vmdk_files(vmdk_files) + else: + for f in vmdk_files: + f['stream_name'] = f['name'] + f['stream_size'] = os.path.getsize(f['name']) + + # TODO(akutz) Support multiple VMDK files in the OVF/OVA + vmdk = vmdk_files[0] + + OS_id_map = {"vmware-photon-64": {"id": "36", "version": "", "type": "vmwarePhoton64Guest"}, + "centos7-64": {"id": "107", "version": "7", "type": "centos7-64"}, + "centos8-64": {"id": "107", "version": "8", "type": "centos8-64"}, + "rhel7-64": {"id": "80", "version": "7", "type": "rhel7_64guest"}, + "rhel8-64": {"id": "80", "version": "8", "type": "rhel8_64guest"}, + "ubuntu-64": {"id": "94", "version": "", "type": "ubuntu64Guest"}, + "flatcar-64": {"id": "100", "version": "", "type": "linux-64"}, + "Windows2019Server-64": {"id": "112", "version": "", "type": "windows9srv-64"}, + "Windows2004Server-64": {"id": "112", "version": "", "type": "windows9srv-64"}} + + # Create the OVF file. + data = { + 'BUILD_DATE': build_data['build_date'], + 'ARTIFACT_ID': build['artifact_id'], + 'BUILD_TIMESTAMP': build_data['build_timestamp'], + 'EULA': eula, + 'OS_NAME': build_data['os_name'], + 'OS_ID': OS_id_map[build_data['guest_os_type']]['id'], + 'OS_TYPE': OS_id_map[build_data['guest_os_type']]['type'], + 'OS_VERSION': OS_id_map[build_data['guest_os_type']]['version'], + 'IB_VERSION': build_data['ib_version'], + 'DISK_NAME': vmdk['stream_name'], + 'DISK_SIZE': build_data['disk_size'], + 'POPULATED_DISK_SIZE': vmdk['size'], + 'STREAM_DISK_SIZE': vmdk['stream_size'], + 'VMX_VERSION': args.vmx_version, + 'DISTRO_NAME': build_data['distro_name'], + 'DISTRO_VERSION': build_data['distro_version'], + 'DISTRO_ARCH': build_data['distro_arch'], + 'NESTEDHV': "false", + 'FIRMWARE': build_data['firmware'] + } + + capv_url = "https://github.com/kubernetes-sigs/cluster-api-provider-vsphere" + + data['CNI_VERSION'] = build_data['kubernetes_cni_semver'] + data['CONTAINERD_VERSION'] = build_data['containerd_version'] + data['KUBERNETES_SEMVER'] = build_data['kubernetes_semver'] + data['KUBERNETES_SOURCE_TYPE'] = build_data['kubernetes_source_type'] + data['PRODUCT'] = "%s and Kubernetes %s" % ( + build_data['os_name'], build_data['kubernetes_semver']) + data['ANNOTATION'] = "Cluster API vSphere image - %s - %s" % (data['PRODUCT'], capv_url) + data['WAKEONLANENABLED'] = "false" + data['TYPED_VERSION'] = build_data['kubernetes_typed_version'] + + data['PROPERTIES'] = Template(''' + + + + + + + \n''').substitute(data) + + # Check if OVF_CUSTOM_PROPERTIES environment Variable is set. + # If so, load the json file & add the properties to the OVF + + if os.environ.get("OVF_CUSTOM_PROPERTIES"): + with open(os.environ.get("OVF_CUSTOM_PROPERTIES"), 'r') as f: + custom_properties = json.loads(f.read()) + if custom_properties: + for k, v in custom_properties.items(): + data['PROPERTIES'] = data['PROPERTIES'] + \ + f''' \n''' + + if "windows" in OS_id_map[build_data['guest_os_type']]['type']: + if build_data['disable_hypervisor'] != "true": + data['NESTEDHV'] = "true" + + ovf = "%s-%s.ovf" % (build_data['build_name'], data['TYPED_VERSION']) + mf = "%s-%s.mf" % (build_data['build_name'], data['TYPED_VERSION']) + ova = "%s-%s.ova" % (build_data['build_name'], data['TYPED_VERSION']) + + # Create OVF + create_ovf(ovf, data, ovf_template) + + if os.environ.get("IB_OVFTOOL"): + # Create the OVA. + create_ova(ova, ovf, ovftool_args=os.environ.get("IB_OVFTOOL_ARGS", "")) + + else: + # Create the OVA manifest. + create_ova_manifest(mf, [ovf, vmdk['stream_name']]) + + # Create the OVA + create_ova(ova, ovf, ova_files=[mf, vmdk['stream_name']]) + + +def sha256(path): + m = hashlib.sha256() + with open(path, 'rb') as f: + while True: + data = f.read(65536) + if not data: + break + m.update(data) + return m.hexdigest() + + +def create_ova(ova_path, ovf_path, ovftool_args=None, ova_files=None): + if ova_files is None: + cmd = f"ovftool {ovftool_args} {ovf_path} {ova_path}" + + print("image-build-ova: creating OVA from %s using ovftool" % + ovf_path) + subprocess.run(cmd.split(), check=True) + else: + infile_paths = [ovf_path] + infile_paths.extend(ova_files) + print("image-build-ova: creating OVA using tar") + with open(ova_path, 'wb') as f: + with tarfile.open(fileobj=f, mode='w|') as tar: + for infile_path in infile_paths: + tar.add(infile_path) + + chksum_path = "%s.sha256" % ova_path + print("image-build-ova: create ova checksum %s" % chksum_path) + with open(chksum_path, 'w') as f: + f.write(sha256(ova_path)) + + +def create_ovf(path, data, ovf_template): + print("image-build-ova: create ovf %s" % path) + with io.open(path, 'w', encoding='utf-8') as f: + f.write(Template(ovf_template).substitute(data)) + + +def create_ova_manifest(path, infile_paths): + print("image-build-ova: create ova manifest %s" % path) + with open(path, 'w') as f: + for i in infile_paths: + f.write('SHA256(%s)= %s\n' % (i, sha256(i))) + + +def get_vmdk_files(inlist): + outlist = [] + for f in inlist: + if f['name'].endswith('.vmdk'): + outlist.append(f) + return outlist + + +def stream_optimize_vmdk_files(inlist): + for f in inlist: + infile = f['name'] + outfile = infile.replace('.vmdk', '.ova.vmdk', 1) + if os.path.isfile(outfile): + os.remove(outfile) + args = [ + 'vmware-vdiskmanager', + '-r', infile, + '-t', '5', + outfile + ] + print("image-build-ova: stream optimize %s --> %s (1-2 minutes)" % + (infile, outfile)) + subprocess.check_call(args) + f['stream_name'] = outfile + f['stream_size'] = os.path.getsize(outfile) + + +if __name__ == "__main__": + main() diff --git a/hack/image-govc-cloudinit.sh b/hack/image-govc-cloudinit.sh new file mode 100755 index 0000000..c5973ad --- /dev/null +++ b/hack/image-govc-cloudinit.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################################################################ +# usage: image-govc-cloudinit.sh VM +# This program updates a remote VM with the cloud-init data to ready it for +# testing. This program requires a configured govc. +################################################################################ + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +if [ "${#}" -lt "1" ]; then + echo "usage: ${0} VM" 1>&2 + exit 1 +fi + +if ! command -v govc >/dev/null 2>&1; then + echo "govc binary must be in \$PATH" 1>&2 + exit 1 +fi + +export GOVC_VM="${1-}" + +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +# If the VM has a "new" snapshot then revert to it and delete all other +# snapshots. +snapshots="$(govc snapshot.tree 2>/dev/null)" || true +if [[ ${snapshots} = *new* ]]; then + echo "image-govc-cloudinit: reverting to snapshot 'new'" + govc snapshot.revert new + for s in ${snapshots}; do + if [ "${s}" != "new" ] && [ "${s}" != "." ] ; then + echo "image-govc-cloudinit: removing snapshot '${s}'" + govc snapshot.remove "${s}" + fi + done +else + echo "image-govc-cloudinit: creating snapshot 'new'" + govc snapshot.create new +fi + +echo "image-govc-cloudinit: initializing cloud-init data" +govc vm.change \ + -e "guestinfo.userdata.encoding=base64" \ + -e "guestinfo.metadata.encoding=base64" \ + -e "guestinfo.userdata='$(base64 -w0 = 200 and r.status_code <= 299: + return url + except: + pass + # The URL wasn't valid, so add '.txt' to the end and let's see if the + # URL points to a valid build. + url = f'{url}.txt' + + # Do an HTTP GET on the txt file to get the actual Kubernetes version. + version = requests.get(url).text + version = version.strip() + + if buildID.startswith('ci/'): + version = f'ci/{version}' + url = f'{KUBE_SRC}/{version}' + + return url + + def __read_version_from_kube_tarball(self, url): + url = f'{url}/kubernetes.tar.gz' + r = requests.get(url) + if not r.status_code == 200: + raise Exception(f'HTTP GET {url} failed: {r.status_code}') + b = BytesIO(r.content) + t = tarfile.open(fileobj=b, mode='r') + v = t.extractfile('kubernetes/version') + return v.read().strip().decode('utf-8') + + +if __name__ == '__main__': + import argparse + import textwrap + parser = argparse.ArgumentParser( + formatter_class=argparse.RawTextHelpFormatter, + description='Generates new Kubernetes image config', + epilog=textwrap.dedent(r''' + THE VERSION STRING + ==================================================================== + The version string not only determines what version of Kubernetes + will be installed, but also *how* Kubernetes is installed. + + PLACEHOLDERS + ==================================================================== + The following placeholders are used in the examples below: + + BASE_URI https://dl.k8s.io + K8S_TGZ kubernetes.tar.gz + + PACKAGE MANAGER INSTALLATION + ==================================================================== + If the version string matches the pattern "^\d+\.\d+.\d+\-\d+$", + ex. 1.14.0-0, then Kubernetes is installed using the system's + package manager, such as yum or apt. + + MANUAL INSTALLATION + ==================================================================== + If the string does not match the above pattern then the following + logic is used to resolve the string VALUE to a valid Kubernetes + version along with the URLs for the Kubernetes artifiacts required + for installation: + + 1. If the VALUE begins with "http:" or "https:" then the value is + treated as a URL and the Kubernetes version is obtained by reading + the "kuberentes/version" file from the URL "VALUE/K8S_TGZ". + + 2. If the VALUE matches a semantic version then the value is + treated as a release build and "BASE_URI/release/SEMVER" + is processed like the URL in step one. + + 3. If the VALUE begins with "ci/" then: + + a. If VALUE does not end with ".txt" then a HEAD request is used + to check the existence of "BASE_URI/VALUE/K8S_TGZ": + + i. If the HEAD request is successful then the URL is processed + like the one in step one. + ii. If the HEAD request fails then ".txt" is added to the end + of the URL and is processed by step 3b. + + b. If VALUE *does* end with ".txt" then a GET request is used to + read "BASE_URI/VALUE" in order to get the dereferenced + version string. Then "BASE_URI/ci/DEREF" is processed + like the URL in step one. + + 4. If the VALUE begins with "release/" then the VALUE is processed + like step three, without the "ci/" prefix + + The resolved URL is used to install Kuberentes from the set of + pre-built container images and binaries. + ''')) + parser.add_argument('version', + nargs=1, + help='A Kubernetes version string') + + args = parser.parse_args() + resolver = KubeVersionResolver() + result = resolver.Resolve(args.version[0]) + + data = json.dumps(result, indent=2) + print(data) diff --git a/hack/image-post-create-config.sh b/hack/image-post-create-config.sh new file mode 100755 index 0000000..9582b66 --- /dev/null +++ b/hack/image-post-create-config.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################################################################ +# usage: image-post-create-config.sh BUILD_DIR +# This program runs after a new image is created and: +# 1. Creates a snapshot of the image named "new" +# 2. Modifies the image to use 2 vCPU +# 3. Creates a snapshot of the image named "2cpu" +# 4. Attaches the ISO build/images/cloudinit/cidata.iso +################################################################################ + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +if [ "${#}" -ne "1" ]; then + echo "usage: ${0} BUILD_DIR" 1>&2 + exit 1 +fi + +VM_RUN="${VM_RUN:-$(command -v vmrun 2>/dev/null)}" +if [ ! -e "${VM_RUN}" ] || [ ! -x "${VM_RUN}" ]; then + echo "vmrun must be in \$PATH or specified by \$VM_RUN" 1>&2 + exit 1 +fi +VM_RUN_DIR="$(dirname "${VM_RUN}")" +export PATH="${VM_RUN_DIR}:${PATH}" + +# Get the path of the VMX file. +VMX_FILE=$(/bin/ls "${1-}"/*.vmx) + +create_snapshot() { + snapshots="$(vmrun listSnapshots "${VMX_FILE}" 2>/dev/null)" + if [[ ${snapshots} = *${1-}* ]]; then + echo "image-post-create-config: skip snapshot '${1-}'; already exists" + else + echo "image-post-create-config: create snapshot '${1-}'" + vmrun snapshot "${VMX_FILE}" "${1-}" + fi +} + +create_snapshot new + +if grep -q 'numvcpus = "2"' "${VMX_FILE}"; then + echo "image-post-create-config: skipping cpu update; already 2" +else + echo "image-post-create-config: update cpu count to 2" + sed -i.bak -e 's/numvcpus = "1"/numvcpus = "2"/' -e 's/cpuid.corespersocket = "1"/cpuid.corespersocket = "2"/' "${VMX_FILE}" + create_snapshot 2cpu +fi + +if grep -q 'guestinfo.userdata' "${VMX_FILE}"; then + echo "image-post-create-config: skipping cloud-init data; already exists" +else + echo "image-post-create-config: insert cloud-init data" + CIDATA_DIR="$(dirname "${BASH_SOURCE[0]}")/../cloudinit" + cat <>"${VMX_FILE}" +guestinfo.userdata = "$({ base64 -w0 || base64; } 2>/dev/null <"${CIDATA_DIR}/user-data")" +guestinfo.userdata.encoding = "base64" +guestinfo.metadata = "$({ base64 -w0 || base64; } 2>/dev/null <"${CIDATA_DIR}/meta-data")" +guestinfo.metadata.encoding = "base64" +EOF + create_snapshot cloudinit +fi diff --git a/hack/image-ssh.sh b/hack/image-ssh.sh new file mode 100755 index 0000000..7a8e442 --- /dev/null +++ b/hack/image-ssh.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################################################################ +# usage: image-ssh.sh BUILD_DIR [SSH_USER] +# This program uses SSH to connect to an image running locally in VMware +# Workstation or VMware Fusion. +################################################################################ + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +if [ "${#}" -lt "1" ]; then + echo "usage: ${0} BUILD_DIR [SSH_USER]" 1>&2 + exit 1 +fi + +VM_RUN="${VM_RUN:-$(command -v vmrun 2>/dev/null)}" +if [ ! -e "${VM_RUN}" ] || [ ! -x "${VM_RUN}" ]; then + echo "vmrun must be in \$PATH or specified by \$VM_RUN" 1>&2 + exit 1 +fi +VM_RUN_DIR="$(dirname "${VM_RUN}")" +export PATH="${VM_RUN_DIR}:${PATH}" + +# Get the path of the VMX file. +VMX_FILE=$(/bin/ls "${1-}"/*.vmx) + +# Get the SSH user. +SSH_USER="${SSH_USER:-${2-}}" +if [ -z "${SSH_USER}" ]; then + SSH_USER=builder +fi +if [ -z "${SSH_USER}" ]; then + echo "SSH_USER is required" 1>&2 + exit 1 +fi + +# Get the VM's IP address. +IP_ADDR="$(vmrun getGuestIPAddress "${VMX_FILE}")" + +# SSH into the VM with the provided user. +SSH_KEY="$(dirname "${BASH_SOURCE[0]}")/../cloudinit/id_rsa.capi" +echo "image-ssh: ssh -i ${SSH_KEY} ${SSH_USER}@${IP_ADDR}" +exec ssh -o UserKnownHostsFile=/dev/null -i "${SSH_KEY}" "${SSH_USER}"@"${IP_ADDR}" diff --git a/hack/image-upload.py b/hack/image-upload.py new file mode 100755 index 0000000..bf856c5 --- /dev/null +++ b/hack/image-upload.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python + +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################################################################ +# usage: image-upload.py [FLAGS] ARGS +# This program uploads an OVA created from a Packer build +################################################################################ + +import argparse +import atexit +import hashlib +import json +import os +import re +import requests +import subprocess +import string +import sys + + +def main(): + parser = argparse.ArgumentParser( + description="Uploads an OVA created from a Packer build") + parser.add_argument(dest='build_dir', + nargs='?', + metavar='BUILD_DIR', + default='.', + help='The Packer build directory') + parser.add_argument('--key-file', + dest='key_file', + required=True, + nargs='?', + metavar='KEY_FILE', + help='The GCS key file') + args = parser.parse_args() + + # Get the absolute path to the GCS key file. + key_file = os.path.abspath(args.key_file) + + # Change the working directory if one is specified. + os.chdir(args.build_dir) + print("image-upload-ova: cd %s" % args.build_dir) + + # Load the packer manifest JSON + data = None + with open('packer-manifest.json', 'r') as f: + data = json.load(f) + + # Get the first build. + build = data['builds'][0] + build_data = build['custom_data'] + + version = build_data['kubernetes_semver'] + build_name = "%s-kube-%s" % (build_data['build_name'], version) + print("image-upload-ova: loaded %s" % build_name) + + # Get the OVA and its checksum. + ova = "%s.ova" % build_name + ova_sum = "%s.sha256" % ova + + # Determine whether or not this is a release or CI image. + upload_dir = 'ci' + if re.match(r'^v?\d+\.\d+\.\d+(-\d+)?$', version): + upload_dir = 'release' + + # Get the path to the GCS OVA and its checksum. + gcs_ova = "gs://capv-images/%s/%s/%s" % ( + upload_dir, version, ova) + gcs_ova_sum = "%s.sha256" % gcs_ova + + # Get the URL of the OVA and its checksum. + url_ova = string.replace(gcs_ova, "gs://", "http://storage.googleapis.com/") + url_ova_sum = "%s.sha256" % url_ova + + # Compare the remote checksum with the local checksum. + lcl_ova_sum_val = get_local_checksum(ova_sum) + print("image-upload-ova: local sha256 %s" % lcl_ova_sum_val) + rem_ova_sum_val = get_remote_checksum(url_ova_sum) + print("image-upload-ova: remote sha256 %s" % rem_ova_sum_val) + if lcl_ova_sum_val == rem_ova_sum_val: + print("image-upload-ova: skipping upload") + print("image-upload-ova: download from %s" % url_ova) + return + + # Activate the GCS service account. + activate_service_account(key_file) + atexit.register(deactivate_service_account) + + # Upload the OVA and its checksum. + print("image-upload-ova: upload %s" % gcs_ova) + subprocess.check_call(['gsutil', 'cp', ova, gcs_ova]) + print("image-upload-ova: upload %s" % gcs_ova_sum) + subprocess.check_call(['gsutil', 'cp', ova_sum, gcs_ova_sum]) + + print("image-upload-ova: download from %s" % url_ova) + + +def activate_service_account(path): + args = [ + "gcloud", "auth", + "activate-service-account", + "--key-file", path, + ] + subprocess.check_call(args) + + +def deactivate_service_account(): + subprocess.call(["gcloud", "auth", "revoke"]) + + +def get_remote_checksum(url): + r = requests.get(url) + if r.status_code >= 200 and r.status_code <= 299: + return r.text.strip() + return None + + +def get_local_checksum(path): + with open(path, 'r') as f: + return f.readline().strip() + + +if __name__ == "__main__": + main() diff --git a/hack/ovf_eula.txt b/hack/ovf_eula.txt new file mode 100644 index 0000000..f93d5c2 --- /dev/null +++ b/hack/ovf_eula.txt @@ -0,0 +1,273 @@ +VMWARE END USER LICENSE AGREEMENT + + + +PLEASE NOTE THAT THE TERMS OF THIS END USER LICENSE AGREEMENT SHALL GOVERN YOUR USE OF THE SOFTWARE, REGARDLESS OF ANY TERMS THAT MAY APPEAR DURING THE INSTALLATION OF THE SOFTWARE. + +IMPORTANT-READ CAREFULLY: BY DOWNLOADING, INSTALLING, OR USING THE SOFTWARE, YOU (THE INDIVIDUAL OR LEGAL ENTITY) AGREE TO BE BOUND BY THE TERMS OF THIS END USER LICENSE AGREEMENT ("EULA"). IF YOU DO NOT AGREE TO THE TERMS OF THIS EULA, YOU MUST NOT DOWNLOAD, INSTALL, OR USE THE SOFTWARE, AND YOU MUST DELETE OR RETURN THE UNUSED SOFTWARE TO THE VENDOR FROM WHICH YOU ACQUIRED IT WITHIN THIRTY (30) DAYS AND REQUEST A REFUND OF THE LICENSE FEE, IF ANY, THAT YOU PAID FOR THE SOFTWARE. + +EVALUATION LICENSE. If You are licensing the Software for evaluation purposes, Your use of the Software is only permitted in a non-production environment and for the period limited by the License Key. Notwithstanding any other provision in this EULA, an Evaluation License of the Software is provided "AS-IS" without indemnification, support or warranty of any kind, expressed or implied. + + + +1. DEFINITIONS. + + + +1.1. "Affiliate" means, with respect to a party at a given time, an entity that then is directly or indirectly controlled by, is under common control with, or controls that party, and here "control" means an ownership, voting or similar interest representing fifty percent (50%) or more of the total interests then outstanding of that entity. + + + +1.2. "Documentation" means that documentation that is generally provided to You by VMware with the Software, as revised by VMware from time to time, and which may include end user manuals, operation instructions, installation guides, release notes, and on-line help files regarding the use of the Software. + + + +1.3. "Guest Operating Systems" means instances of third-party operating systems licensed by You, installed in a Virtual Machine and run using the Software. + + + +1.4. "Intellectual Property Rights" means all worldwide intellectual property rights, including without limitation, copyrights, trademarks, service marks, trade secrets, know how, inventions, patents, patent applications, moral rights and all other proprietary rights, whether registered or unregistered. + + + +1.5. "License" means a license granted under Section 2.1 (General License Grant). + + + +1.6. "License Key" means a serial number that enables You to activate and use the Software. + + + +1.7. "License Term" means the duration of a License as specified in the Order. + + + +1.8. "License Type" means the type of License applicable to the Software, as more fully described in the Order. + + + +1.9. "Open Source Software" or "OSS" means software components embedded in the Software and provided under separate license terms, which can be found either in the open_source_licenses.txt file (or similar file) provided within the Software or at www.vmware.com/download/open_source.html. + + + +1.10. "Order" means a purchase order, enterprise license agreement, or other ordering document issued by You to VMware or a VMware authorized reseller that references and incorporates this EULA and is accepted by VMware as set forth in Section 4 (Order). + + + +1.11. "Product Guide" means the current version of the VMware Product Guide at the time of Your Order, copies of which are found at www.vmware.com/download/eula. + + + +1.12. "Support Services Terms" means VMware's then-current support policies, copies of which are posted at www.vmware.com/support/policies. + + + +1.13. "Software" means the VMware Tools and the VMware computer programs listed on VMware's commercial price list to which You acquire a license under an Order, together with any software code relating to the foregoing that is provided to You pursuant to a support and subscription service contract and that is not subject to a separate license agreement. + + + +1.14. "Territory" means the country or countries in which You have been invoiced; provided, however, that if You have been invoiced within any of the European Economic Area member states, You may deploy the corresponding Software throughout the European Economic Area. + + + +1.15. "Third Party Agent" means a third party delivering information technology services to You pursuant to a written contract with You. + + + +1.16. "Virtual Machine" means a software container that can run its own operating system and execute applications like a physical machine. + + + +1.17. "VMware" means VMware, Inc., a Delaware corporation, if You are purchasing Licenses or services for use in the United States and VMware International Unlimited Company , a company organized and existing under the laws of Ireland, for all other purchases. + + + +1.18. "VMware Tools" means the suite of utilities and drivers, Licensed by VMware under the "VMware Tools" name, that can be installed in a Guest Operating System to enhance the performance and functionality of a Guest Operating System when running in a Virtual Machine. + + + +2. LICENSE GRANT. + + + +2.1. General License Grant. VMware grants to You a non-exclusive, non-transferable (except as set forth in Section 12.1 (Transfers; Assignment)) license to use the Software and the Documentation during the period of the license and within the Territory, solely for Your internal business operations, and subject to the provisions of the Product Guide. Unless otherwise indicated in the Order, licenses granted to You will be perpetual, will be for use of object code only, and will commence on either delivery of the physical media or the date You are notified of availability for electronic download. + + + +2.2. Third Party Agents. Under the License granted to You in Section 2.1 (General License Grant) above, You may permit Your Third Party Agents to access, use and/or operate the Software on Your behalf for the sole purpose of delivering services to You, provided that You will be fully responsible for Your Third Party Agents' compliance with terms and conditions of this EULA and any breach of this EULA by a Third Party Agent shall be deemed to be a breach by You. + + + +2.3. Copying Permitted. You may copy the Software and Documentation as necessary to install and run the quantity of copies licensed, but otherwise for archival purposes only. + + + +2.4. Benchmarking. You may use the Software to conduct internal performance testing and benchmarking studies. You may only publish or otherwise distribute the results of such studies to third parties as follows: (a) if with respect to VMware's Workstation or Fusion products, only if You provide a copy of Your study to benchmark@vmware.com prior to distribution; (b) if with respect to any other Software, only if VMware has reviewed and approved of the methodology, assumptions and other parameters of the study (please contact VMware at benchmark@vmware.com to request such review and approval) prior to such publication and distribution. + + + +2.5. VMware Tools. You may distribute the VMware Tools to third parties solely when installed in a Guest Operating System within a Virtual Machine. You are liable for compliance by those third parties with the terms and conditions of this EULA. + + + +2.6. Open Source Software. Notwithstanding anything herein to the contrary, Open Source Software is licensed to You under such OSS's own applicable license terms, which can be found in the open_source_licenses.txt file, the Documentation or as applicable, the corresponding source files for the Software available at www.vmware.com/download/open_source.html. These OSS license terms are consistent with the license granted in Section 2 (License Grant), and may contain additional rights benefiting You. The OSS license terms shall take precedence over this EULA to the extent that this EULA imposes greater restrictions on You than the applicable OSS license terms. To the extent the license for any Open Source Software requires VMware to make available to You the corresponding source code and/or modifications (the "Source Files"), You may obtain a copy of the applicable Source Files from VMware's website at www.vmware.com/download/open_source.html or by sending a written request, with Your name and address to: VMware, Inc., 3401 Hillview Avenue, Palo Alto, CA 94304, United States of America. All requests should clearly specify: Open Source Files Request, Attention: General Counsel. This offer to obtain a copy of the Source Files is valid for three years from the date You acquired this Software. + + + +3. RESTRICTIONS; OWNERSHIP. + + + +3.1. License Restrictions. Without VMware's prior written consent, You must not, and must not allow any third party to: (a) use Software in an application services provider, service bureau, or similar capacity for third parties, except that You may use the Software to deliver hosted services to Your Affiliates; (b) disclose to any third party the results of any benchmarking testing or comparative or competitive analyses of VMware's Software done by or on behalf of You, except as specified in Section 2.4 (Benchmarking); (c) make available Software in any form to anyone other than Your employees or contractors reasonably acceptable to VMware and require access to use Software on behalf of You in a matter permitted by this EULA, except as specified in Section 2.2 (Third Party Agents); (d) transfer or sublicense Software or Documentation to an Affiliate or any third party, except as expressly permitted in Section 12.1 (Transfers; Assignment); (e) use Software in conflict with the terms and restrictions of the Software's licensing model and other requirements specified in Product Guide and/or VMware quote; (f) except to the extent permitted by applicable mandatory law, modify, translate, enhance, or create derivative works from the Software, or reverse engineer, decompile, or otherwise attempt to derive source code from the Software, except as specified in Section 3.2 (Decompilation); (g) remove any copyright or other proprietary notices on or in any copies of Software; or (h) violate or circumvent any technological restrictions within the Software or specified in this EULA, such as via software or services. + + + +3.2. Decompilation. Notwithstanding the foregoing, decompiling the Software is permitted to the extent the laws of the Territory give You the express right to do so to obtain information necessary to render the Software interoperable with other software; provided, however, You must first request such information from VMware, provide all reasonably requested information to allow VMware to assess Your claim, and VMware may, in its discretion, either provide such interoperability information to You, impose reasonable conditions, including a reasonable fee, on such use of the Software, or offer to provide alternatives to ensure that VMware's proprietary rights in the Software are protected and to reduce any adverse impact on VMware's proprietary rights. + + + +3.3. Ownership. The Software and Documentation, all copies and portions thereof, and all improvements, enhancements, modifications and derivative works thereof, and all Intellectual Property Rights therein, are and shall remain the sole and exclusive property of VMware and its licensors. Your rights to use the Software and Documentation shall be limited to those expressly granted in this EULA and any applicable Order. No other rights with respect to the Software or any related Intellectual Property Rights are implied. You are not authorized to use (and shall not permit any third party to use) the Software, Documentation or any portion thereof except as expressly authorized by this EULA or the applicable Order. VMware reserves all rights not expressly granted to You. VMware does not transfer any ownership rights in any Software. + + + +3.4. Guest Operating Systems. Certain Software allows Guest Operating Systems and application programs to run on a computer system. You acknowledge that You are responsible for obtaining and complying with any licenses necessary to operate any such third-party software. + + + +4. ORDER. Your Order is subject to this EULA. No Orders are binding on VMware until accepted by VMware. Orders for Software are deemed to be accepted upon VMware's delivery of the Software included in such Order. Orders issued to VMware do not have to be signed to be valid and enforceable. + + + +5. RECORDS AND AUDIT. During the License Term for Software and for two (2) years after its expiration or termination, You will maintain accurate records of Your use of the Software sufficient to show compliance with the terms of this EULA. During this period, VMware will have the right to audit Your use of the Software to confirm compliance with the terms of this EULA. That audit is subject to reasonable notice by VMware and will not unreasonably interfere with Your business activities. VMware may conduct no more than one (1) audit in any twelve (12) month period, and only during normal business hours. You will reasonably cooperate with VMware and any third party auditor and will, without prejudice to other rights of VMware, address any non-compliance identified by the audit by promptly paying additional fees. You will promptly reimburse VMware for all reasonable costs of the audit if the audit reveals either underpayment of more than five (5%) percent of the Software fees payable by You for the period audited, or that You have materially failed to maintain accurate records of Software use. + + + +6. SUPPORT AND SUBSCRIPTION SERVICES. Except as expressly specified in the Product Guide, VMware does not provide any support or subscription services for the Software under this EULA. You have no rights to any updates, upgrades or extensions or enhancements to the Software developed by VMware unless you separately purchase VMware support or subscription services. These support or subscription services are subject to the Support Services Terms. + + + +7. WARRANTIES. + + + +7.1. Software Warranty, Duration and Remedy. VMware warrants to You that the Software will, for a period of ninety (90) days following notice of availability for electronic download or delivery ("Warranty Period"), substantially conform to the applicable Documentation, provided that the Software: (a) has been properly installed and used at all times in accordance with the applicable Documentation; and (b) has not been modified or added to by persons other than VMware or its authorized representative. VMware will, at its own expense and as its sole obligation and Your exclusive remedy for any breach of this warranty, either replace that Software or correct any reproducible error in that Software reported to VMware by You in writing during the Warranty Period. If VMware determines that it is unable to correct the error or replace the Software, VMware will refund to You the amount paid by You for that Software, in which case the License for that Software will terminate. + + + +7.2. Software Disclaimer of Warranty. OTHER THAN THE WARRANTY ABOVE, AND TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, VMWARE AND ITS SUPPLIERS MAKE NO OTHER EXPRESS WARRANTIES UNDER THIS EULA, AND DISCLAIM ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT, AND ANY WARRANTY ARISING BY STATUTE, OPERATION OF LAW, COURSE OF DEALING OR PERFORMANCE, OR USAGE OF TRADE. VMWARE AND ITS LICENSORS DO NOT WARRANT THAT THE SOFTWARE WILL OPERATE UNINTERRUPTED OR THAT IT WILL BE FREE FROM DEFECTS OR THAT IT WILL MEET YOUR REQUIREMENTS. + + + +8. INTELLECTUAL PROPERTY INDEMNIFICATION. + + + +8.1. Defense and Indemnification. Subject to the remainder of this Section 8 (Intellectual Property Indemnification), VMware shall defend You against any third party claim that the Software infringes any patent, trademark or copyright of such third party, or misappropriates a trade secret (but only to the extent that the misappropriation is not a result of Your actions) under the laws of: (a) the United States and Canada; (b) the European Economic Area; (c) Australia; (d) New Zealand; (e) Japan; or (f) the People's Republic of China, to the extent that such countries are part of the Territory for the License ("Infringement Claim") and indemnify You from the resulting costs and damages finally awarded against You to such third party by a court of competent jurisdiction or agreed to in settlement. The foregoing obligations are applicable only if You: (i) promptly notify VMware in writing of the Infringement Claim; (ii) allow VMware sole control over the defense for the claim, any settlement negotiations and any related action challenging the validity of the allegedly infringed patent, trademark, or copyright; and (iii) reasonably cooperate in response to VMware requests for assistance. You may not settle or compromise any Infringement Claim without the prior written consent of VMware. + + + +8.2. Remedies. If the alleged infringing Software become, or in VMware's opinion be likely to become, the subject of an Infringement Claim, VMware will, at VMware's option and expense, do one of the following: (a) procure the rights necessary for You to make continued use of the affected Software; (b) replace or modify the affected Software to make it non-infringing; or (c) terminate the License to the affected Software and discontinue the related support services, and, upon Your certified deletion of the affected Software, refund: (i) the fees paid by You for the License to the affected Software, less straight-line depreciation over a three (3) year useful life beginning on the date such Software was delivered; and (ii) any pre-paid service fee attributable to related support services to be delivered after the date such service is stopped. Nothing in this Section 8.2 (Remedies) shall limit VMware's obligation under Section 8.1 (Defense and Indemnification) to defend and indemnify You, provided that You replace the allegedly infringing Software upon VMware's making alternate Software available to You and/or You discontinue using the allegedly infringing Software upon receiving VMware's notice terminating the affected License. + + + +8.3. Exclusions. Notwithstanding the foregoing, VMware will have no obligation under this Section 8 (Intellectual Property Indemnification) or otherwise with respect to any claim based on: (a) a combination of Software with non-VMware products (other than non-VMware products that are listed on the Order and used in an unmodified form); (b) use for a purpose or in a manner for which the Software was not designed; (c) use of any older version of the Software when use of a newer VMware version would have avoided the infringement; (d) any modification to the Software made without VMware's express written approval; (e) any claim that relates to open source software or freeware technology or any derivatives or other adaptations thereof that is not embedded by VMware into Software listed on VMware's commercial price list; or (f) any Software provided on a no charge, beta or evaluation basis. THIS SECTION 8 (INTELLECTUAL PROPERTY INDEMNIFICATION) STATES YOUR SOLE AND EXCLUSIVE REMEDY AND VMWARE'S ENTIRE LIABILITY FOR ANY INFRINGEMENT CLAIMS OR ACTIONS. + + + +9. LIMITATION OF LIABILITY. + + + +9.1. Limitation of Liability. TO THE MAXIMUM EXTENT MANDATED BY LAW, IN NO EVENT WILL VMWARE AND ITS LICENSORS BE LIABLE FOR ANY LOST PROFITS OR BUSINESS OPPORTUNITIES, LOSS OF USE, LOSS OF REVENUE, LOSS OF GOODWILL, BUSINESS INTERRUPTION, LOSS OF DATA, OR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES UNDER ANY THEORY OF LIABILITY, WHETHER BASED IN CONTRACT, TORT, NEGLIGENCE, PRODUCT LIABILITY, OR OTHERWISE. BECAUSE SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE PRECEDING LIMITATION MAY NOT APPLY TO YOU. VMWARE'S AND ITS LICENSORS' LIABILITY UNDER THIS EULA WILL NOT, IN ANY EVENT, REGARDLESS OF WHETHER THE CLAIM IS BASED IN CONTRACT, TORT, STRICT LIABILITY, OR OTHERWISE, EXCEED THE GREATER OF THE LICENSE FEES YOU PAID FOR THE SOFTWARE GIVING RISE TO THE CLAIM OR $5000. THE FOREGOING LIMITATIONS SHALL APPLY REGARDLESS OF WHETHER VMWARE OR ITS LICENSORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES AND REGARDLESS OF WHETHER ANY REMEDY FAILS OF ITS ESSENTIAL PURPOSE. + + + +9.2. Further Limitations. VMware's licensors shall have no liability of any kind under this EULA and VMware's liability with respect to any third party software embedded in the Software shall be subject to Section 9.1 (Limitation of Liability). You may not bring a claim under this EULA more than eighteen (18) months after the cause of action arises. + + + +10. TERMINATION. + + + +10.1. EULA Term. The term of this EULA begins on the notice of availability for electronic download or delivery of the Software and continues until this EULA is terminated in accordance with this Section 10. + + + +10.2. Termination for Breach. VMware may terminate this EULA effective immediately upon written notice to You if: (a) You fail to pay any portion of the fees under an applicable Order within ten (10) days after receiving written notice from VMware that payment is past due; or (b) You breach any other provision of this EULA and fail to cure within thirty (30) days after receipt of VMware's written notice thereof. + + + +10.3. Termination for Insolvency. VMware may terminate this EULA effective immediately upon written notice to You if You: (a) terminate or suspend your business; (b) become insolvent, admit in writing Your inability to pay Your debts as they mature, make an assignment for the benefit of creditors; or become subject to control of a trustee, receiver or similar authority; or (c) become subject to any bankruptcy or insolvency proceeding. + + + +10.4. Effect of Termination. Upon VMware's termination of this EULA: (a) all Licensed rights to all Software granted to You under this EULA will immediately cease; and (b) You must cease all use of all Software, and return or certify destruction of all Software and License Keys (including copies) to VMware, and return, or if requested by VMware, destroy, any related VMware Confidential Information in Your possession or control and certify in writing to VMware that You have fully complied with these requirements. Any provision will survive any termination or expiration if by its nature and context it is intended to survive, including Sections 1 (Definitions), 2.6 (Open Source Software), 3 (Restrictions; Ownership), 5 (Records and Audit), 7.2 (Software Disclaimer of Warranty), 9 (Limitation of Liability), 10 (Termination), 11 (Confidential Information) and 12 (General). + + + +11. CONFIDENTIAL INFORMATION. + + + +11.1. Definition. "Confidential Information" means information or materials provided by one party ("Discloser") to the other party ("Recipient") which are in tangible form and labelled "confidential" or the like, or, information which a reasonable person knew or should have known to be confidential. The following information shall be considered Confidential Information whether or not marked or identified as such: (a) License Keys; (b) information regarding VMware's pricing, product roadmaps or strategic marketing plans; and (c) non-public materials relating to the Software. + + + +11.2. Protection. Recipient may use Confidential Information of Discloser; (a) to exercise its rights and perform its obligations under this EULA; or (b) in connection with the parties' ongoing business relationship. Recipient will not use any Confidential Information of Discloser for any purpose not expressly permitted by this EULA, and will disclose the Confidential Information of Discloser only to the employees or contractors of Recipient who have a need to know such Confidential Information for purposes of this EULA and who are under a duty of confidentiality no less restrictive than Recipient's duty hereunder. Recipient will protect Confidential Information from unauthorized use, access, or disclosure in the same manner as Recipient protects its own confidential or proprietary information of a similar nature but with no less than reasonable care. + + + +11.3. Exceptions. Recipient's obligations under Section 11.2 (Protection) with respect to any Confidential Information will terminate if Recipient can show by written records that such information: (a) was already known to Recipient at the time of disclosure by Discloser; (b) was disclosed to Recipient by a third party who had the right to make such disclosure without any confidentiality restrictions; (c) is, or through no fault of Recipient has become, generally available to the public; or (d) was independently developed by Recipient without access to, or use of, Discloser's Information. In addition, Recipient will be allowed to disclose Confidential Information to the extent that such disclosure is required by law or by the order of a court of similar judicial or administrative body, provided that Recipient notifies Discloser of such required disclosure promptly and in writing and cooperates with Discloser, at Discloser's request and expense, in any lawful action to contest or limit the scope of such required disclosure. + + + +11.4. Data Privacy. You agree that VMware may process technical and related information about Your use of the Software which may include internet protocol address, hardware identification, operating system, application software, peripheral hardware, and non-personally identifiable Software usage statistics to facilitate the provisioning of updates, support, invoicing or online services and may transfer such information to other companies in the VMware worldwide group of companies from time to time. To the extent that this information constitutes personal data, VMware shall be the controller of such personal data. To the extent that it acts as a controller, each party shall comply at all times with its obligations under applicable data protection legislation. + + + +12. GENERAL. + + + +12.1. Transfers; Assignment. Except to the extent transfer may not legally be restricted or as permitted by VMware's transfer and assignment policies, in all cases following the process set forth at www.vmware.com/support/policies/licensingpolicies.html, You will not assign this EULA, any Order, or any right or obligation herein or delegate any performance without VMware's prior written consent, which consent will not be unreasonably withheld. Any other attempted assignment or transfer by You will be void. VMware may use its Affiliates or other sufficiently qualified subcontractors to provide services to You, provided that VMware remains responsible to You for the performance of the services. + + + +12.2. Notices. Any notice delivered by VMware to You under this EULA will be delivered via mail, email or fax. + + + +12.3. Waiver. Failure to enforce a provision of this EULA will not constitute a waiver. + + + +12.4. Severability. If any part of this EULA is held unenforceable, the validity of all remaining parts will not be affected. + + + +12.5. Compliance with Laws; Export Control; Government Regulations. Each party shall comply with all laws applicable to the actions contemplated by this EULA. You acknowledge that the Software is of United States origin, is provided subject to the U.S. Export Administration Regulations, may be subject to the export control laws of the applicable territory, and that diversion contrary to applicable export control laws is prohibited. You represent that (1) you are not, and are not acting on behalf of, (a) any person who is a citizen, national, or resident of, or who is controlled by the government of any country to which the United States has prohibited export transactions; or (b) any person or entity listed on the U.S. Treasury Department list of Specially Designated Nationals and Blocked Persons, or the U.S. Commerce Department Denied Persons List or Entity List; and (2) you will not permit the Software to be used for, any purposes prohibited by law, including, any prohibited development, design, manufacture or production of missiles or nuclear, chemical or biological weapons. The Software and accompanying documentation are deemed to be "commercial computer software" and "commercial computer software documentation", respectively, pursuant to DFARS Section 227.7202 and FAR Section 12.212(b), as applicable. Any use, modification, reproduction, release, performing, displaying or disclosing of the Software and documentation by or for the U.S. Government shall be governed solely by the terms and conditions of this EULA. + + + +12.6. Construction. The headings of sections of this EULA are for convenience and are not to be used in interpreting this EULA. As used in this EULA, the word ‘including' means "including but not limited to". + + + +12.7. Governing Law. This EULA is governed by the laws of the State of California, United States of America (excluding its conflict of law rules), and the federal laws of the United States. To the extent permitted by law, the state and federal courts located in Santa Clara County, California will be the exclusive jurisdiction for disputes arising out of or in connection with this EULA. The U.N. Convention on Contracts for the International Sale of Goods does not apply. + + + +12.8. Third Party Rights. Other than as expressly set out in this EULA, this EULA does not create any rights for any person who is not a party to it, and no person who is not a party to this EULA may enforce any of its terms or rely on any exclusion or limitation contained in it. + + + +12.9. Order of Precedence. In the event of conflict or inconsistency among the Product Guide, this EULA and the Order, the following order of precedence shall apply unless otherwise set forth in an enterprise license agreement: (a) the Product Guide, (b) this EULA and (c) the Order. With respect to any inconsistency between this EULA and an Order, the terms of this EULA shall supersede and control over any conflicting or additional terms and conditions of any purchase order, acknowledgement or confirmation or other document issued by You. + + + +12.10. Entire Agreement. This EULA, including accepted Orders and any amendments hereto, and the Product Guide contain the entire agreement of the parties with respect to the subject matter of this EULA and supersede all previous or contemporaneous communications, representations, proposals, commitments, understandings and agreements, whether written or oral, between the parties regarding the subject matter hereof. This EULA may be amended only in writing signed by authorized representatives of both parties. + + + +12.11. Contact Information. Please direct legal notices or other correspondence to VMware, Inc., 3401 Hillview Avenue, Palo Alto, California 94304, United States of America, Attention: Legal Department. diff --git a/hack/ovf_template.xml b/hack/ovf_template.xml new file mode 100644 index 0000000..316427e --- /dev/null +++ b/hack/ovf_template.xml @@ -0,0 +1,170 @@ + + + + + + + Virtual disk information + + + + The list of logical networks + + Please select a network + + + + A virtual machine + ${ARTIFACT_ID} + + A human-readable annotation + ${ANNOTATION} + + + The operating system installed + + + Virtual hardware requirements + + Virtual Hardware Family + 0 + ${ARTIFACT_ID} + vmx-${VMX_VERSION} + + + hertz * 10^6 + Number of Virtual CPUs + 2 virtual CPU(s) + 1 + 3 + 2 + 2 + + + byte * 2^20 + Memory Size + 2048MB of memory + 2 + 4 + 2048 + + + 0 + SCSI Controller + SCSI controller 0 + 3 + VirtualSCSI + 6 + + + + 1 + IDE Controller + IDE 1 + 4 + 5 + + + 0 + IDE Controller + IDE 0 + 5 + 5 + + + false + Video card + 6 + 24 + + + + + + + + false + VMCI device + 7 + vmware.vmci + 1 + + + + + 0 + Hard disk 1 + ovf:/disk/vmdisk1 + 8 + 3 + 17 + + + + 7 + true + nic0 + VmxNet3 ethernet adapter + Network adapter 1 + 9 + VmxNet3 + 10 + + + + + + 0 + false + CD/DVD drive 1 + 10 + 5 + vmware.cdrom.remotepassthrough + 15 + + + + + + + + + + + + + + + + + + + + + + + + + Virtual hardware device boot order + + + An end-user license agreement + +${EULA} + + + + Information about the installed software + ${PRODUCT} + VMware Inc. + ${TYPED_VERSION} + ${TYPED_VERSION} + https://vmware.com + Cluster API Provider (CAPI) + + + + ${PROPERTIES} + + + diff --git a/hack/utils.sh b/hack/utils.sh new file mode 100755 index 0000000..cfea5db --- /dev/null +++ b/hack/utils.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env bash + +# Copyright 2020 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +case "${OSTYPE}" in +linux*) + HOSTOS=linux + ;; +darwin*) + HOSTOS=darwin + ;; +*) + echo "unsupported HOSTOS=${OSTYPE}" 1>&2 + exit 1 + ;; +esac + +_hostarch=$(uname -m) +case "${_hostarch}" in +*64*) + HOSTARCH=amd64 + ;; +*386*) + HOSTARCH=386 + ;; +*686*) + HOSTARCH=386 + ;; +*) + echo "unsupported HOSTARCH=${_hostarch}" 1>&2 + exit 1 + ;; +esac + +checksum_sha256() { + if command -v shasum >/dev/null 2>&1; then + shasum -a 256 -c "${1}" + elif command -v sha256sum >/dev/null 2>&1; then + sha256sum -c "${1}" + else + echo "missing shasum tool" 1>&2 + return 1 + fi +} + +get_shasum() { + local present_shasum='' + if command -v shasum >/dev/null 2>&1; then + present_shasum=$(shasum -a 256 "${1}"| awk -F' ' '{print $1}') + elif command -v sha256sum >/dev/null 2>&1; then + present_shasum=$(sha256sum "${1}" | awk -F' ' '{print $1}') + else + echo "missing shasum tool" 1>&2 + return 1 + fi + echo "$present_shasum" +} + +ensure_py3_bin() { + # If given executable is not available, the user Python bin dir is not in path + # This function assumes the executable to be checked was installed with + # pip3 install --user ... + if ! command -v "${1}" >/dev/null 2>&1; then + echo "User's Python3 binary directory must be in \$PATH" 1>&2 + echo "Location of package is:" 1>&2 + pip3 show --disable-pip-version-check ${2:-$1} | grep "Location" + echo "\$PATH is currently: $PATH" 1>&2 + exit 1 + fi +} + +ensure_py3() { + if ! command -v python3 >/dev/null 2>&1; then + echo "python3 binary must be in \$PATH" 1>&2 + exit 1 + fi + if ! command -v pip3 >/dev/null 2>&1; then + curl -SsL https://bootstrap.pypa.io/get-pip.py -o get-pip.py + python3 get-pip.py --user + rm -f get-pip.py + ensure_py3_bin pip3 + fi +} diff --git a/hack/windows-ova-unattend.py b/hack/windows-ova-unattend.py new file mode 100755 index 0000000..4c75aa5 --- /dev/null +++ b/hack/windows-ova-unattend.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 + +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import xml.etree.ElementTree as ET +import os +import argparse +import json + +def set_xmlstring(root, location, key, value): + setting = root.find(location) + setting.find(key).text = value + return setting + +def main(): + parser = argparse.ArgumentParser( + description="Updates select variables in autounattend.xml") + parser.add_argument(dest='build_dir', + nargs='?', + metavar='BUILD_DIR', + default='.', + help='The Packer build directory') + parser.add_argument('--var-file', + dest='var_file', + nargs='?', + metavar='VARIABLES_FILE', + required=False, + default='./packer_cache/unattend.json', + help='The file that containers the unattend variables') + parser.add_argument('--unattend-file', + dest='unattend_file', + required=False, + nargs='?', + metavar='UNATTEND_FILE', + help='The Unattend file') + args = parser.parse_args() + + print("windows-ova-unattend: cd %s" % args.build_dir) + + # Load the packer manifest JSON + data = None + with open(args.var_file, 'r') as f: + data = json.load(f) + + modified=0 + os.chdir(args.build_dir) + unattend=ET.parse(args.unattend_file) + ET.register_namespace('', "urn:schemas-microsoft-com:unattend") + ET.register_namespace('wcm', "http://schemas.microsoft.com/WMIConfig/2002/State") + ET.register_namespace('xsi', "http://www.w3.org/2001/XMLSchema-instance") + + root = unattend.getroot() + + if data["unattend_timezone"] != "": + modified=1 + setting = set_xmlstring(root, ".//*[@pass='oobeSystem']/*[@name='Microsoft-Windows-Shell-Setup']",'{urn:schemas-microsoft-com:unattend}TimeZone', data["unattend_timezone"]) + print("windows-ova-unattend: Setting Timezone to %s" % data["unattend_timezone"]) + + if modified == 1: + print("windows-ova-unattend: Updating %s ..." % args.unattend_file) + unattend.write(args.unattend_file) + + if modified == 0: + print("windows-ova-unattend: skipping...") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/kubevirt-Dockerfile b/kubevirt-Dockerfile new file mode 100644 index 0000000..4d6ec14 --- /dev/null +++ b/kubevirt-Dockerfile @@ -0,0 +1,5 @@ +FROM registry.access.redhat.com/ubi8/ubi:latest AS builder +ADD --chown=107:107 /disk/image.qcow2 + +FROM scratch +COPY --from=builder /disk/* /disk/ diff --git a/packer/.gitignore b/packer/.gitignore new file mode 100644 index 0000000..4cab851 --- /dev/null +++ b/packer/.gitignore @@ -0,0 +1,3 @@ +/packer_cache/ +/output-*/ +/output/ \ No newline at end of file diff --git a/packer/ami/OWNERS b/packer/ami/OWNERS new file mode 100644 index 0000000..f131739 --- /dev/null +++ b/packer/ami/OWNERS @@ -0,0 +1,4 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - cluster-api-aws-maintainers diff --git a/packer/ami/amazon-2.json b/packer/ami/amazon-2.json new file mode 100644 index 0000000..1fb106e --- /dev/null +++ b/packer/ami/amazon-2.json @@ -0,0 +1,11 @@ +{ + "ami_filter_name": "amzn2-ami-hvm-2*", + "ami_filter_owners": "amazon", + "build_name": "amazon-2", + "distribution": "Amazon Linux", + "distribution_release": "Amazon Linux 2", + "distribution_version": "2", + "root_device_name": "/dev/xvda", + "source_ami": "", + "ssh_username": "ec2-user" +} diff --git a/packer/ami/centos-7.json b/packer/ami/centos-7.json new file mode 100644 index 0000000..ff952ad --- /dev/null +++ b/packer/ami/centos-7.json @@ -0,0 +1,11 @@ +{ + "ami_filter_name": "CentOS Linux 7 x86_64 HVM EBS ENA*", + "ami_filter_owners": "461800378586", + "build_name": "centos-7", + "distribution": "CentOS", + "distribution_release": "Core", + "distribution_version": "7", + "root_device_name": "/dev/sda1", + "source_ami": "", + "ssh_username": "centos" +} diff --git a/packer/ami/flatcar.json b/packer/ami/flatcar.json new file mode 100644 index 0000000..cb73125 --- /dev/null +++ b/packer/ami/flatcar.json @@ -0,0 +1,17 @@ +{ + "ami_filter_name": "Flatcar*{{env `FLATCAR_CHANNEL`}}*", + "ami_filter_owners": "075585003325", + "ansible_extra_vars": "ansible_python_interpreter=/opt/bin/python", + "build_name": "flatcar-{{env `FLATCAR_CHANNEL`}}", + "crictl_source_type": "http", + "distribution": "flatcar", + "kubernetes_cni_source_type": "http", + "kubernetes_source_type": "http", + "python_path": "/opt/bin/builder-env/site-packages", + "root_device_name": "/dev/xvda", + "ssh_username": "core", + "systemd_prefix": "/etc/systemd", + "sysusr_prefix": "/opt", + "sysusrlocal_prefix": "/opt", + "user_data": "" +} diff --git a/packer/ami/packer-windows.json b/packer/ami/packer-windows.json new file mode 100644 index 0000000..f0373dc --- /dev/null +++ b/packer/ami/packer-windows.json @@ -0,0 +1,208 @@ +{ + "builders": [ + { + "access_key": "{{user `aws_access_key`}}", + "ami_description": "{{user `ami_description`}}", + "ami_groups": "{{user `ami_groups`}}", + "ami_name": "capa-ami-{{user `build_name`}}-{{user `kubernetes_semver` | clean_resource_name}}-{{user `build_timestamp`}}", + "ami_product_codes": "", + "ami_regions": "{{user `ami_regions`}}", + "ami_users": "{{user `ami_users`}}", + "associate_public_ip_address": true, + "communicator": "winrm", + "disable_stop_instance": true, + "encrypt_boot": "{{user `encrypted`}}", + "iam_instance_profile": "{{user `iam_instance_profile`}}", + "instance_type": "{{user `builder_instance_type`}}", + "kms_key_id": "{{user `kms_key_id`}}", + "launch_block_device_mappings": [ + { + "delete_on_termination": true, + "device_name": "{{ user `root_device_name` }}", + "throughput": "{{ user `throughput` }}", + "volume_size": "{{ user `volume_size` }}", + "volume_type": "{{ user `volume_type` }}" + } + ], + "name": "{{user `build_name`}}", + "profile": "{{ user `aws_profile`}}", + "region": "{{ user `aws_region` }}", + "secret_key": "{{user `aws_secret_key`}}", + "security_group_ids": "{{user `aws_security_group_ids`}}", + "skip_create_ami": "{{ user `skip_create_ami`}}", + "skip_profile_validation": "{{user `skip_profile_validation`}}", + "snapshot_groups": "{{user `snapshot_groups`}}", + "snapshot_users": "{{user `snapshot_users`}}", + "source_ami": "{{user `source_ami`}}", + "source_ami_filter": { + "filters": { + "architecture": "x86_64", + "name": "{{user `ami_filter_name`}}", + "root-device-type": "ebs", + "virtualization-type": "hvm" + }, + "most_recent": true, + "owners": "{{user `ami_filter_owners`}}" + }, + "ssh_keypair_name": "{{user `ssh_keypair_name`}}", + "ssh_private_key_file": "{{user `ssh_private_key_file`}}", + "subnet_id": "{{ user `subnet_id` }}", + "tags": { + "build_date": "{{isotime}}", + "build_timestamp": "{{user `build_timestamp`}}", + "containerd_version": "{{user `containerd_version`}}", + "distribution": "{{user `distribution`}}", + "distribution_version": "{{user `distribution_version`}}", + "image_builder_version": "{{user `ib_version`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}", + "source_ami": "{{user `source_ami`}}" + }, + "temporary_security_group_source_cidrs": "{{ user `temporary_security_group_source_cidrs` }}", + "token": "{{ user `aws_session_token` }}", + "type": "amazon-ebs", + "user_data_file": "packer/ami/scripts/winrm_bootstrap.txt", + "vpc_id": "{{ user `vpc_id` }}", + "winrm_insecure": true, + "winrm_timeout": "6m", + "winrm_use_ssl": true, + "winrm_username": "Administrator" + } + ], + "post-processors": [ + { + "custom_data": { + "containerd_version": "{{user `containerd_version`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}" + }, + "output": "{{user `manifest_output`}}", + "type": "manifest" + } + ], + "provisioners": [ + { + "extra_arguments": [ + "-e", + "ansible_winrm_server_cert_validation=ignore", + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}" + ], + "playbook_file": "ansible/windows/node_windows.yml", + "type": "ansible", + "use_proxy": false, + "user": "Administrator" + }, + { + "restart_timeout": "10m", + "type": "windows-restart" + }, + { + "arch": "{{user `goss_arch`}}", + "download_path": "{{user `goss_download_path`}}", + "format": "{{user `goss_format`}}", + "format_options": "{{user `goss_format_options`}}", + "goss_file": "{{user `goss_entry_file`}}", + "inspect": "{{user `goss_inspect_mode`}}", + "remote_folder": "{{user `goss_remote_folder`}}", + "remote_path": "{{user `goss_remote_path`}}", + "skip_install": "{{user `goss_skip_install`}}", + "target_os": "Windows", + "tests": [ + "{{user `goss_tests_dir`}}" + ], + "type": "goss", + "url": "{{user `goss_url`}}", + "use_sudo": false, + "vars_env": { + "GOSS_MAX_CONCURRENT": "1", + "GOSS_USE_ALPHA": "1" + }, + "vars_file": "{{user `goss_vars_file`}}", + "vars_inline": { + "OS": "{{user `distribution` | lower}}", + "PROVIDER": "amazon", + "containerd_version": "{{user `containerd_version`}}", + "distribution_version": "{{user `distribution_version`}}", + "docker_ee_version": "{{user `docker_ee_version`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}", + "pause_image": "{{user `pause_image`}}", + "runtime": "{{user `runtime`}}", + "ssh_source_url": "{{user `ssh_source_url`}}" + }, + "version": "{{user `goss_version`}}" + }, + { + "inline": [ + "rm -Force -Recurse C:\\var\\log\\kubelet\\*" + ], + "type": "powershell" + }, + { + "elevated_password": "{{.WinRMPassword}}", + "elevated_user": "Administrator", + "script": "packer/ami/scripts/sysprep_prerequisites.ps1", + "type": "powershell" + }, + { + "inline": [ + "C:/ProgramData/Amazon/EC2-Windows/Launch/Scripts/SysprepInstance.ps1" + ], + "type": "powershell" + } + ], + "variables": { + "additional_debug_files": null, + "ami_description": "Cluster API base image designed for {{user `kubernetes_semver`}}", + "ami_groups": "all", + "ami_regions": "ap-south-1,eu-west-3,eu-west-2,eu-west-1,ap-northeast-2,ap-northeast-1,sa-east-1,ca-central-1,ap-southeast-1,ap-southeast-2,eu-central-1,us-east-1,us-east-2,us-west-1,us-west-2", + "ami_users": "", + "ansible_common_vars": "", + "ansible_extra_vars": "", + "ansible_user_vars": "", + "aws_access_key": "", + "aws_profile": "", + "aws_region": "us-east-1", + "aws_secret_key": "", + "aws_security_group_ids": "", + "aws_session_token": "", + "build_name": null, + "build_timestamp": "{{timestamp}}", + "builder_instance_type": "t3.large", + "cloudbase_init_url": "https://github.com/cloudbase/cloudbase-init/releases/download/{{user `cloudbase_init_version`}}/CloudbaseInitSetup_{{user `cloudbase_init_version` | replace_all `.` `_` }}_x64.msi", + "cloudbase_metadata_services": "cloudbaseinit.metadata.services.ec2service.EC2Service", + "cloudbase_metadata_services_unattend": "cloudbaseinit.metadata.services.base.EmptyMetadataService", + "cloudbase_plugins": "cloudbaseinit.plugins.windows.createuser.CreateUserPlugin, cloudbaseinit.plugins.common.setuserpassword.SetUserPasswordPlugin, cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin, cloudbaseinit.plugins.common.ephemeraldisk.EphemeralDiskPlugin, cloudbaseinit.plugins.common.mtu.MTUPlugin, cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin, cloudbaseinit.plugins.common.sshpublickeys.SetUserSSHPublicKeysPlugin", + "cloudbase_plugins_unattend": "cloudbaseinit.plugins.common.mtu.MTUPlugin", + "containerd_sha256": null, + "containerd_url": "", + "containerd_version": null, + "encrypted": "false", + "iam_instance_profile": "", + "ib_version": "{{env `IB_VERSION`}}", + "kms_key_id": "", + "kubernetes_base_url": "https://kubernetesreleases.blob.core.windows.net/kubernetes/{{user `kubernetes_semver`}}/binaries/node/windows/{{user `kubernetes_goarch`}}", + "manifest_output": "manifest.json", + "nssm_url": null, + "prepull": null, + "skip_create_ami": "false", + "skip_profile_validation": "false", + "snapshot_groups": "all", + "snapshot_users": "", + "ssh_keypair_name": "", + "ssh_private_key_file": "", + "subnet_id": "", + "temporary_security_group_source_cidrs": "", + "throughput": "125", + "volume_size": "40", + "volume_type": "gp3", + "vpc_id": "", + "windows_service_manager": null, + "windows_updates_kbs": null, + "wins_url": "https://github.com/rancher/wins/releases/download/v{{user `wins_version`}}/wins.exe" + } +} diff --git a/packer/ami/packer.json b/packer/ami/packer.json new file mode 100644 index 0000000..7b957a8 --- /dev/null +++ b/packer/ami/packer.json @@ -0,0 +1,210 @@ +{ + "builders": [ + { + "access_key": "{{user `aws_access_key`}}", + "ami_description": "{{user `ami_description`}}", + "ami_groups": "{{user `ami_groups`}}", + "ami_name": "capa-ami-{{user `build_name`}}-{{user `kubernetes_semver` | clean_resource_name}}-{{user `build_timestamp`}}", + "ami_product_codes": "", + "ami_regions": "{{user `ami_regions`}}", + "ami_users": "{{user `ami_users`}}", + "encrypt_boot": "{{user `encrypted`}}", + "iam_instance_profile": "{{user `iam_instance_profile`}}", + "instance_type": "{{user `builder_instance_type`}}", + "kms_key_id": "{{user `kms_key_id`}}", + "launch_block_device_mappings": [ + { + "delete_on_termination": true, + "device_name": "{{ user `root_device_name` }}", + "iops": "{{ user `iops`}}", + "throughput": "{{ user `throughput` }}", + "volume_size": "{{ user `volume_size` }}", + "volume_type": "{{ user `volume_type` }}" + } + ], + "name": "{{user `build_name`}}", + "profile": "{{ user `aws_profile`}}", + "region": "{{ user `aws_region` }}", + "secret_key": "{{user `aws_secret_key`}}", + "security_group_ids": "{{user `aws_security_group_ids`}}", + "skip_create_ami": "{{ user `skip_create_ami`}}", + "skip_profile_validation": "{{user `skip_profile_validation`}}", + "snapshot_groups": "{{user `snapshot_groups`}}", + "snapshot_users": "{{user `snapshot_users`}}", + "source_ami": "{{user `source_ami`}}", + "source_ami_filter": { + "filters": { + "architecture": "x86_64", + "name": "{{user `ami_filter_name`}}", + "root-device-type": "ebs", + "virtualization-type": "hvm" + }, + "most_recent": true, + "owners": "{{user `ami_filter_owners`}}" + }, + "ssh_keypair_name": "{{user `ssh_keypair_name`}}", + "ssh_private_key_file": "{{user `ssh_private_key_file`}}", + "ssh_username": "{{user `ssh_username`}}", + "subnet_id": "{{ user `subnet_id` }}", + "tags": { + "build_date": "{{isotime}}", + "build_timestamp": "{{user `build_timestamp`}}", + "containerd_version": "{{user `containerd_version`}}", + "distribution": "{{user `distribution`}}", + "distribution_release": "{{user `distribution_release`}}", + "distribution_version": "{{user `distribution_version`}}", + "image_builder_version": "{{user `ib_version`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}", + "source_ami": "{{user `source_ami`}}" + }, + "temporary_security_group_source_cidrs": "{{ user `temporary_security_group_source_cidrs` }}", + "token": "{{ user `aws_session_token` }}", + "type": "amazon-ebs", + "user_data": "{{ user `user_data` }}", + "vpc_id": "{{ user `vpc_id` }}" + } + ], + "post-processors": [ + { + "custom_data": { + "containerd_version": "{{user `containerd_version`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}" + }, + "output": "{{user `manifest_output`}}", + "type": "manifest" + } + ], + "provisioners": [ + { + "environment_vars": [ + "BUILD_NAME={{user `build_name`}}" + ], + "inline": [ + "if [ $BUILD_NAME != \"ubuntu-1804\" ]; then exit 0; fi", + "while [ ! -f /var/lib/cloud/instance/boot-finished ]; do echo 'Waiting for cloud-init...'; sleep 1; done", + "sudo apt-get -qq update && sudo DEBIAN_FRONTEND=noninteractive apt-get -qqy install python python-pip" + ], + "type": "shell" + }, + { + "execute_command": "BUILD_NAME={{user `build_name`}}; if [[ \"${BUILD_NAME}\" == *\"flatcar\"* ]]; then sudo {{.Vars}} -S -E bash '{{.Path}}'; fi", + "script": "./packer/files/flatcar/scripts/bootstrap-flatcar.sh", + "type": "shell" + }, + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} {{user `ansible_common_ssh_args`}}'" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}", + "--scp-extra-args", + "{{user `ansible_scp_extra_args`}}" + ], + "playbook_file": "./ansible/node.yml", + "type": "ansible" + }, + { + "arch": "{{user `goss_arch`}}", + "download_path": "{{user `goss_download_path`}}", + "format": "{{user `goss_format`}}", + "format_options": "{{user `goss_format_options`}}", + "goss_file": "{{user `goss_entry_file`}}", + "inspect": "{{user `goss_inspect_mode`}}", + "remote_folder": "{{user `goss_remote_folder`}}", + "remote_path": "{{user `goss_remote_path`}}", + "skip_install": "{{user `goss_skip_install`}}", + "tests": [ + "{{user `goss_tests_dir`}}" + ], + "type": "goss", + "url": "{{user `goss_url`}}", + "use_sudo": true, + "vars_file": "{{user `goss_vars_file`}}", + "vars_inline": { + "ARCH": "amd64", + "OS": "{{user `distribution` | lower}}", + "OS_VERSION": "{{user `distribution_version` | lower}}", + "PROVIDER": "amazon", + "containerd_version": "{{user `containerd_version`}}", + "kubernetes_cni_deb_version": "{{ user `kubernetes_cni_deb_version` }}", + "kubernetes_cni_rpm_version": "{{ split (user `kubernetes_cni_rpm_version`) \"-\" 0 }}", + "kubernetes_cni_source_type": "{{user `kubernetes_cni_source_type`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver` | replace \"v\" \"\" 1}}", + "kubernetes_deb_version": "{{ user `kubernetes_deb_version` }}", + "kubernetes_rpm_version": "{{ split (user `kubernetes_rpm_version`) \"-\" 0 }}", + "kubernetes_source_type": "{{user `kubernetes_source_type`}}", + "kubernetes_version": "{{user `kubernetes_semver` | replace \"v\" \"\" 1}}" + }, + "version": "{{user `goss_version`}}" + } + ], + "variables": { + "amazon_ssm_agent_rpm": "https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm", + "ami_description": "Cluster API base image designed for {{user `kubernetes_semver`}}", + "ami_groups": "all", + "ami_regions": "ap-south-1,eu-west-3,eu-west-2,eu-west-1,ap-northeast-2,ap-northeast-1,sa-east-1,ca-central-1,ap-southeast-1,ap-southeast-2,eu-central-1,us-east-1,us-east-2,us-west-1,us-west-2", + "ami_users": "", + "ansible_common_vars": "", + "ansible_extra_vars": "", + "ansible_scp_extra_args": "", + "ansible_user_vars": "", + "aws_access_key": "", + "aws_profile": "", + "aws_region": "us-east-1", + "aws_secret_key": "", + "aws_security_group_ids": "", + "aws_session_token": "", + "build_timestamp": "{{timestamp}}", + "builder_instance_type": "t3.small", + "containerd_sha256": null, + "containerd_url": "https://github.com/containerd/containerd/releases/download/v{{user `containerd_version`}}/cri-containerd-cni-{{user `containerd_version`}}-linux-amd64.tar.gz", + "containerd_version": null, + "crictl_url": "https://github.com/kubernetes-sigs/cri-tools/releases/download/v{{user `crictl_version`}}/crictl-v{{user `crictl_version`}}-linux-amd64.tar.gz", + "crictl_version": null, + "encrypted": "false", + "existing_ansible_ssh_args": "{{env `ANSIBLE_SSH_ARGS`}}", + "iam_instance_profile": "", + "ib_version": "{{env `IB_VERSION`}}", + "iops": "3000", + "kms_key_id": "", + "kubernetes_cni_deb_version": null, + "kubernetes_cni_http_source": null, + "kubernetes_cni_rpm_version": null, + "kubernetes_cni_semver": null, + "kubernetes_cni_source_type": null, + "kubernetes_container_registry": null, + "kubernetes_deb_gpg_key": null, + "kubernetes_deb_repo": null, + "kubernetes_deb_version": null, + "kubernetes_http_source": null, + "kubernetes_load_additional_imgs": null, + "kubernetes_rpm_gpg_check": null, + "kubernetes_rpm_gpg_key": null, + "kubernetes_rpm_repo": null, + "kubernetes_rpm_version": null, + "kubernetes_semver": null, + "kubernetes_source_type": null, + "manifest_output": "manifest.json", + "python_path": "", + "skip_create_ami": "false", + "skip_profile_validation": "false", + "snapshot_groups": "all", + "snapshot_users": "", + "ssh_keypair_name": "", + "ssh_private_key_file": "", + "subnet_id": "", + "temporary_security_group_source_cidrs": "", + "throughput": "125", + "user_data": "#cloud-config\nrepo_upgrade: none", + "volume_size": "8", + "volume_type": "gp3", + "vpc_id": "" + } +} diff --git a/packer/ami/rhel-8.json b/packer/ami/rhel-8.json new file mode 100644 index 0000000..cf86b63 --- /dev/null +++ b/packer/ami/rhel-8.json @@ -0,0 +1,15 @@ +{ + "ami_filter_name": "RHEL-8.6.0_HVM-*", + "ami_filter_owners": "309956199498", + "build_name": "rhel-8", + "builder_instance_type": "m5.large", + "distribution": "rhel", + "distribution_release": "Enterprise", + "distribution_version": "8", + "epel_rpm_gpg_key": "https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8", + "redhat_epel_rpm": "https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm", + "root_device_name": "/dev/sda1", + "source_ami": "", + "ssh_username": "ec2-user", + "volume_size": "10" +} diff --git a/packer/ami/rockylinux-8.json b/packer/ami/rockylinux-8.json new file mode 100644 index 0000000..fc1fd16 --- /dev/null +++ b/packer/ami/rockylinux-8.json @@ -0,0 +1,14 @@ +{ + "ami_filter_name": "Rocky-8-ec2-8.5-*", + "ami_filter_owners": "679593333241", + "build_name": "rockylinux-8", + "distribution": "rockylinux", + "distribution_release": "Core", + "distribution_version": "8", + "epel_rpm_gpg_key": "https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8", + "redhat_epel_rpm": "https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm", + "root_device_name": "/dev/sda1", + "source_ami": "", + "ssh_username": "rocky", + "volume_size": "10" +} diff --git a/packer/ami/scripts/sysprep_prerequisites.ps1 b/packer/ami/scripts/sysprep_prerequisites.ps1 new file mode 100644 index 0000000..0321e63 --- /dev/null +++ b/packer/ami/scripts/sysprep_prerequisites.ps1 @@ -0,0 +1,29 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Write-Output 'Removing default unattend.xml file...' +if( Test-Path $Env:SystemRoot\system32\Sysprep\unattend.xml ) { + Remove-Item $Env:SystemRoot\system32\Sysprep\unattend.xml -Force +} + +# Schedule InitializeInstance to run on next boot +& $Env:ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 -Schedule + +$unattendedXml = "$ENV:ProgramFiles\Cloudbase Solutions\Cloudbase-Init\conf\Unattend.xml" +$FileExists = Test-Path $unattendedXml +If ($FileExists -eq $True) { + # Use the Cloudbase-init provided unattend file during install + Write-Output "Using cloudbase-init unattend file for sysprep: $unattendedXml" + Copy-Item -Force 'C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\Unattend.xml' $Env:ProgramData\Amazon\EC2-Windows\Launch\Sysprep\Unattend.xml +} diff --git a/packer/ami/scripts/winrm_bootstrap.txt b/packer/ami/scripts/winrm_bootstrap.txt new file mode 100644 index 0000000..1da0612 --- /dev/null +++ b/packer/ami/scripts/winrm_bootstrap.txt @@ -0,0 +1,47 @@ + + +# MAKE SURE IN YOUR PACKER CONFIG TO SET: +# +# +# "winrm_username": "Administrator", +# "winrm_insecure": true, +# "winrm_use_ssl": true, +# +# + + +write-output "Running User Data Script" +write-host "(host) Running User Data Script" + +Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force -ErrorAction Ignore + +# Don't set this before Set-ExecutionPolicy as it throws an error +$ErrorActionPreference = "stop" + +# Remove HTTP listener +Remove-Item -Path WSMan:\Localhost\listener\listener* -Recurse + +# Create a self-signed certificate to let ssl work +$Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "packer" +New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert.Thumbprint -Force + +# WinRM +write-output "Setting up WinRM" +write-host "(host) setting up WinRM" + +cmd.exe /c winrm quickconfig -q +cmd.exe /c winrm set "winrm/config" '@{MaxTimeoutms="1800000"}' +cmd.exe /c winrm set "winrm/config/winrs" '@{MaxMemoryPerShellMB="1024"}' +cmd.exe /c winrm set "winrm/config/service" '@{AllowUnencrypted="true"}' +cmd.exe /c winrm set "winrm/config/client" '@{AllowUnencrypted="true"}' +cmd.exe /c winrm set "winrm/config/service/auth" '@{Basic="true"}' +cmd.exe /c winrm set "winrm/config/client/auth" '@{Basic="true"}' +cmd.exe /c winrm set "winrm/config/service/auth" '@{CredSSP="true"}' +cmd.exe /c winrm set "winrm/config/listener?Address=*+Transport=HTTPS" "@{Port=`"5986`";Hostname=`"packer`";CertificateThumbprint=`"$($Cert.Thumbprint)`"}" +cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes +cmd.exe /c netsh firewall add portopening TCP 5986 "Port 5986" +cmd.exe /c net stop winrm +cmd.exe /c sc config winrm start= auto +cmd.exe /c net start winrm + + \ No newline at end of file diff --git a/packer/ami/ubuntu-1804.json b/packer/ami/ubuntu-1804.json new file mode 100644 index 0000000..08d013b --- /dev/null +++ b/packer/ami/ubuntu-1804.json @@ -0,0 +1,11 @@ +{ + "ami_filter_name": "ubuntu/images/*ubuntu-bionic-18.04-amd64-server-*", + "ami_filter_owners": "099720109477", + "build_name": "ubuntu-18.04", + "distribution": "Ubuntu", + "distribution_release": "bionic", + "distribution_version": "18.04", + "root_device_name": "/dev/sda1", + "source_ami": "", + "ssh_username": "ubuntu" +} diff --git a/packer/ami/ubuntu-2004.json b/packer/ami/ubuntu-2004.json new file mode 100644 index 0000000..707fd1b --- /dev/null +++ b/packer/ami/ubuntu-2004.json @@ -0,0 +1,11 @@ +{ + "ami_filter_name": "ubuntu/images/*ubuntu-focal-20.04-amd64-server-*", + "ami_filter_owners": "099720109477", + "build_name": "ubuntu-20.04", + "distribution": "Ubuntu", + "distribution_release": "focal", + "distribution_version": "20.04", + "root_device_name": "/dev/sda1", + "source_ami": "", + "ssh_username": "ubuntu" +} diff --git a/packer/ami/ubuntu-2204.json b/packer/ami/ubuntu-2204.json new file mode 100644 index 0000000..785ddba --- /dev/null +++ b/packer/ami/ubuntu-2204.json @@ -0,0 +1,11 @@ +{ + "ami_filter_name": "ubuntu/images/*ubuntu-jammy-22.04-amd64-server-*", + "ami_filter_owners": "099720109477", + "build_name": "ubuntu-22.04", + "distribution": "Ubuntu", + "distribution_release": "jammy", + "distribution_version": "22.04", + "root_device_name": "/dev/sda1", + "source_ami": "", + "ssh_username": "ubuntu" +} diff --git a/packer/ami/windows-2004.json b/packer/ami/windows-2004.json new file mode 100644 index 0000000..0d8c80f --- /dev/null +++ b/packer/ami/windows-2004.json @@ -0,0 +1,10 @@ +{ + "ami_filter_name": "Windows_Server-2004-English-Core-ContainersLatest-*", + "ami_filter_owners": "amazon", + "build_name": "windows-2004", + "distribution": "windows", + "distribution_version": "2004", + "root_device_name": "/dev/sda1", + "source_ami": "", + "windows_updates_kbs": "KB4588962 KB2267602" +} diff --git a/packer/ami/windows-2019.json b/packer/ami/windows-2019.json new file mode 100644 index 0000000..e647114 --- /dev/null +++ b/packer/ami/windows-2019.json @@ -0,0 +1,10 @@ +{ + "ami_filter_name": "Windows_Server-2019-English-Full-HyperV-*", + "ami_filter_owners": "amazon", + "build_name": "windows-2019", + "distribution": "windows", + "distribution_version": "2019", + "root_device_name": "/dev/sda1", + "source_ami": "", + "windows_updates_kbs": "KB4588962 KB2267602" +} diff --git a/packer/azure/.pipelines/build-vhd.yaml b/packer/azure/.pipelines/build-vhd.yaml new file mode 100644 index 0000000..009477d --- /dev/null +++ b/packer/azure/.pipelines/build-vhd.yaml @@ -0,0 +1,50 @@ +# Required pipeline variables: +# - BUILD_POOL - Azure DevOps build pool to use +# - CONTAINER_IMAGE - Dev container image URL to use. Should have Azure CLI, Packer and Ansible. +# - AZURE_TENANT_ID - tenant ID +# - AZURE_CLIENT_ID - Service principal ID +# - AZURE_CLIENT_SECRET - Service principal secret +# - AZURE_SUBSCRIPTION_ID - Subscription ID used by the pipeline +# - KUBERNETES_VERSION - version of Kubernetes to build the image with, e.g. `1.16.2` +# - OS - target of build e.g. `Ubuntu/Windows` +# - OS_VERSION - target of build e.g. `18.04/2004/2019` + +jobs: +- job: build_vhd + container: $[ variables['CONTAINER_IMAGE'] ] + timeoutInMinutes: 120 + strategy: + maxParallel: 0 + pool: + name: $(BUILD_POOL) + steps: + - template: k8s-config.yaml + - script: | + set -o pipefail + make deps-azure + os=$(echo "${OS}" | tr '[:upper:]' '[:lower:]') + version=$(echo "${OS_VERSION}" | tr '[:upper:]' '[:lower:]' | tr -d .) + export RESOURCE_GROUP_NAME="cluster-api-images" + + # timestamp is in RFC-3339 format to match kubetest + export TIMESTAMP="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" + export JOB_NAME="${JOB_NAME:-"image-builder-vhd"}" + export TAGS="creationTimestamp=${TIMESTAMP} jobName=${JOB_NAME}" + printf "${TAGS}" | tee packer/azure/tags.out + make build-azure-vhd-$os-$version | tee packer/azure/packer.out + displayName: Building VHD + workingDirectory: '$(system.defaultWorkingDirectory)/images/capi' + env: + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET) + - template: generate-sas.yaml + - template: vhd-publishing-info.yaml + - task: PublishPipelineArtifact@1 + inputs: + artifact: 'publishing-info' + path: '$(system.defaultWorkingDirectory)/images/capi/packer/azure/vhd-publishing-info.json' + condition: eq(variables.CLEANUP, 'False') + - template: delete-storage-account.yaml + - script: | + chown -R $USER:$USER . + displayName: cleanup - chown all files in work directory + condition: always() diff --git a/packer/azure/.pipelines/create-disk-version.yaml b/packer/azure/.pipelines/create-disk-version.yaml new file mode 100644 index 0000000..9317ce1 --- /dev/null +++ b/packer/azure/.pipelines/create-disk-version.yaml @@ -0,0 +1,38 @@ +# Required pipeline variables: +# - BUILD_POOL - Azure DevOps build pool to use +# - CONTAINER_IMAGE - Dev container image URL to use. Should have Azure CLI, Packer and Ansible. +# - AZURE_TENANT_ID - tenant ID +# - AZURE_CLIENT_ID - Service principal ID +# - AZURE_CLIENT_SECRET - Service principal secret +# - OS - target of build e.g. `Ubuntu/Windows` +# - OS_VERSION - target of build e.g. `18.04/2004/2019` + +jobs: +- job: create_disk_version + container: $[ variables['CONTAINER_IMAGE'] ] + timeoutInMinutes: 120 + strategy: + maxParallel: 0 + pool: + name: $(BUILD_POOL) + steps: + - task: DownloadPipelineArtifact@2 + inputs: + source: current + artifact: publishing-info + path: $(system.defaultWorkingDirectory)/images/capi/packer/azure/vhd/ + - task: DownloadPipelineArtifact@2 + inputs: + source: current + artifact: sku-info + path: $(system.defaultWorkingDirectory)/images/capi/packer/azure/sku/ + - script: | + ./scripts/new-disk-version.sh + displayName: Create a new marketplace SKU + workingDirectory: '$(system.defaultWorkingDirectory)/images/capi/packer/azure' + env: + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET) + - task: PublishPipelineArtifact@1 + inputs: + artifact: 'version_info' + path: '$(system.defaultWorkingDirectory)/images/capi/packer/azure/version.json' diff --git a/packer/azure/.pipelines/create-sku.yaml b/packer/azure/.pipelines/create-sku.yaml new file mode 100644 index 0000000..149a091 --- /dev/null +++ b/packer/azure/.pipelines/create-sku.yaml @@ -0,0 +1,34 @@ +# Required pipeline variables: +# - BUILD_POOL - Azure DevOps build pool to use +# - CONTAINER_IMAGE - Dev container image URL to use. Should have Azure CLI, Packer and Ansible. +# - AZURE_CLIENT_ID - Service principal ID +# - AZURE_CLIENT_SECRET - Service principal secret +# - AZURE_TENANT_ID - tenant ID +# - KUBERNETES_VERSION - version of Kubernetes to create the sku for, e.g. `1.16.2` +# - OFFER - the name of the offer to create the sku for +# - OS - target of build e.g. `Ubuntu/Windows` +# - OS_VERSION - target of build e.g. `18.04/2004/2019/2022-containerd` +# - PUBLISHER - the name of the publisher to create the sku for +# - SKU_TEMPLATE_FILE - the base template file to use for the sku +# - VM_GENERATION - VM generation to use, e.g. `gen2` + +jobs: +- job: create_sku + container: $[ variables['CONTAINER_IMAGE'] ] + timeoutInMinutes: 120 + strategy: + maxParallel: 0 + pool: + name: $(BUILD_POOL) + steps: + - script: | + ./scripts/new-sku.sh + displayName: Create a new marketplace SKU + workingDirectory: '$(system.defaultWorkingDirectory)/images/capi/packer/azure' + env: + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET) + - task: PublishPipelineArtifact@1 + inputs: + artifact: 'sku-info' + path: '$(system.defaultWorkingDirectory)/images/capi/packer/azure/sku-publishing-info.json' + \ No newline at end of file diff --git a/packer/azure/.pipelines/delete-storage-account.yaml b/packer/azure/.pipelines/delete-storage-account.yaml new file mode 100644 index 0000000..eacda22 --- /dev/null +++ b/packer/azure/.pipelines/delete-storage-account.yaml @@ -0,0 +1,13 @@ +steps: +- script: | + set -o pipefail + RESOURCE_GROUP_NAME=$(jq -r '.builds[-1].custom_data.resource_group_name' manifest.json | cut -d ":" -f2) + STORAGE_ACCOUNT_NAME=$(jq -r '.builds[-1].custom_data.storage_account_name' manifest.json | cut -d ":" -f2) + az login --service-principal -u ${AZURE_CLIENT_ID} -p ${AZURE_CLIENT_SECRET} --tenant ${AZURE_TENANT_ID} + az account set -s ${AZURE_SUBSCRIPTION_ID} + az storage account delete -n ${STORAGE_ACCOUNT_NAME} -g ${RESOURCE_GROUP_NAME} --yes + displayName: cleanup - delete storage account + workingDirectory: '$(system.defaultWorkingDirectory)/images/capi' + condition: eq(variables.CLEANUP, 'True') + env: + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET) diff --git a/packer/azure/.pipelines/generate-sas.yaml b/packer/azure/.pipelines/generate-sas.yaml new file mode 100644 index 0000000..0cddefd --- /dev/null +++ b/packer/azure/.pipelines/generate-sas.yaml @@ -0,0 +1,21 @@ +steps: +- script: | + set -o pipefail + RESOURCE_GROUP_NAME=$(jq -r '.builds[-1].custom_data.resource_group_name' manifest.json | cut -d ":" -f2) + STORAGE_ACCOUNT_NAME=$(jq -r '.builds[-1].custom_data.storage_account_name' manifest.json | cut -d ":" -f2) + OS_DISK_URI=$(cat packer/azure/packer.out | grep "OSDiskUri:" -m 1 | cut -d " " -f 2) + printf "${STORAGE_ACCOUNT_NAME}" | tee packer/azure/storage-account-name.out + printf "${OS_DISK_URI}" | tee packer/azure/vhd-base-url.out + printf "${OS_DISK_URI}?" | tee packer/azure/vhd-url.out + printf "${RESOURCE_GROUP_NAME}" | tee packer/azure/resource-group-name.out + az login --service-principal -u ${AZURE_CLIENT_ID} -p ${AZURE_CLIENT_SECRET} --tenant ${AZURE_TENANT_ID} + az account set -s ${AZURE_SUBSCRIPTION_ID} + ACCOUNT_KEY=$(az storage account keys list -g ${RESOURCE_GROUP_NAME} --subscription ${AZURE_SUBSCRIPTION_ID} --account-name ${STORAGE_ACCOUNT_NAME} --query '[0].value') + start_date=$(date +"%Y-%m-%dT00:00Z" -d "-1 day") + expiry_date=$(date +"%Y-%m-%dT00:00Z" -d "+1 year") + az storage container generate-sas --name system --permissions lr --account-name ${STORAGE_ACCOUNT_NAME} --account-key ${ACCOUNT_KEY} --start $start_date --expiry $expiry_date | tr -d '\"' | tee -a packer/azure/vhd-url.out + displayName: Getting OS VHD URL + workingDirectory: '$(system.defaultWorkingDirectory)/images/capi' + condition: eq(variables.CLEANUP, 'False') + env: + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET) diff --git a/packer/azure/.pipelines/k8s-config.yaml b/packer/azure/.pipelines/k8s-config.yaml new file mode 100644 index 0000000..1a154ef --- /dev/null +++ b/packer/azure/.pipelines/k8s-config.yaml @@ -0,0 +1,15 @@ +steps: +- script: | + KUBERNETES_RELEASE=$(echo ${KUBERNETES_VERSION} | cut -d "." -f -2) + sed -i "s/.*kubernetes_series.*/ \"kubernetes_series\": \"v${KUBERNETES_RELEASE}\",/g" kubernetes.json + sed -i "s/.*kubernetes_semver.*/ \"kubernetes_semver\": \"v${KUBERNETES_VERSION}\",/g" kubernetes.json + if [[ "${KUBERNETES_VERSION:-}" == "1.16.11" || "${KUBERNETES_VERSION:-}" == "1.17.7" || "${KUBERNETES_VERSION:-}" == "1.18.4" ]]; then + sed -i "s/.*kubernetes_rpm_version.*/ \"kubernetes_rpm_version\": \"${KUBERNETES_VERSION}-1\",/g" kubernetes.json + sed -i "s/.*kubernetes_deb_version.*/ \"kubernetes_deb_version\": \"${KUBERNETES_VERSION}-01\",/g" kubernetes.json + else + sed -i "s/.*kubernetes_rpm_version.*/ \"kubernetes_rpm_version\": \"${KUBERNETES_VERSION}-0\",/g" kubernetes.json + sed -i "s/.*kubernetes_deb_version.*/ \"kubernetes_deb_version\": \"${KUBERNETES_VERSION}-00\",/g" kubernetes.json + fi + cat kubernetes.json + displayName: Write configuration files + workingDirectory: '$(system.defaultWorkingDirectory)/images/capi/packer/config' diff --git a/packer/azure/.pipelines/smoke-test.yaml b/packer/azure/.pipelines/smoke-test.yaml new file mode 100644 index 0000000..a321034 --- /dev/null +++ b/packer/azure/.pipelines/smoke-test.yaml @@ -0,0 +1,59 @@ +# Required pipeline variables: +# - BUILD_POOL - Azure DevOps build pool to use +# - CONTAINER_IMAGE - Dev container image URL to use. Should have Azure CLI, Packer and Ansible. +# - AZURE_TENANT_ID_VHD - tenant ID to build the vhd +# - AZURE_CLIENT_ID_VHD - Service principal ID to build the vhd +# - AZURE_CLIENT_SECRET_VHD - Service principal secret to build the vhd +# - AZURE_SUBSCRIPTION_ID_VHD - Subscription ID to build the vhd +# - KUBERNETES_VERSION - version of Kubernetes to create the sku for, e.g. `1.21.3` +# - CLEANUP - whether or not to clean up resources created in the run + +trigger: none + +schedules: + - cron: "0 1 * * *" + displayName: "nightly build" + always: true + branches: + include: + - master + +stages: + - stage: vhd + jobs: + - job: + container: $[ variables['CONTAINER_IMAGE'] ] + timeoutInMinutes: 120 + pool: + name: $(BUILD_POOL) + steps: + - template: k8s-config.yaml + - script: | + set -o pipefail + make deps-azure + os=$(echo "$OS" | tr '[:upper:]' '[:lower:]') + version=$(echo "$OS_VERSION" | tr '[:upper:]' '[:lower:]' | tr -d .) + make build-azure-vhd-$os-$version | tee packer/azure/packer.out + displayName: Building VHD + workingDirectory: '$(system.defaultWorkingDirectory)/images/capi' + env: + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET) + - template: delete-storage-account.yaml + - script: | + chown -R $USER:$USER . + displayName: cleanup - chown all files in work directory + condition: always() + strategy: + maxParallel: 0 + matrix: + Windows: + OS: Windows + OS_VERSION: 2019 + Linux: + OS: Ubuntu + OS_VERSION: 2004 + variables: + AZURE_TENANT_ID: $(AZURE_TENANT_ID_VHD) + AZURE_CLIENT_ID: $(AZURE_CLIENT_ID_VHD) + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET_VHD) + AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID_VHD) diff --git a/packer/azure/.pipelines/stages.yaml b/packer/azure/.pipelines/stages.yaml new file mode 100644 index 0000000..e83ec1c --- /dev/null +++ b/packer/azure/.pipelines/stages.yaml @@ -0,0 +1,57 @@ +# Required pipeline variables: +# - BUILD_POOL - Azure DevOps build pool to use +# - CONTAINER_IMAGE - Dev container image URL to use. Should have Azure CLI, Packer and Ansible. +# - AZURE_TENANT_ID_VHD - tenant ID to build the vhd +# - AZURE_CLIENT_ID_VHD - Service principal ID to build the vhd +# - AZURE_CLIENT_SECRET_VHD - Service principal secret to build the vhd +# - AZURE_SUBSCRIPTION_ID_VHD - Subscription ID to build the vhd +# - AZURE_TENANT_ID_SKU - tenant ID to PUT the SKU +# - AZURE_CLIENT_ID_SKU - Service principal ID to PUT the SKU +# - AZURE_CLIENT_SECRET_SKU - Service principal secret to PUT the SKU +# - KUBERNETES_VERSION - version of Kubernetes to create the sku for, e.g. `1.16.2` +# - PUBLISHER - the name of the publisher to create the sku for +# - OFFER - the name of the offer to create the sku for +# - SKU_TEMPLATE_FILE - the base template file to use for the sku +# - OS - target of build e.g. `Ubuntu/Windows` +# - OS_VERSION - target of build e.g. `18.04/2004/2019` + +trigger: none +pr: none + +stages: + - stage: vhd + jobs: + - template: build-vhd.yaml + variables: + AZURE_TENANT_ID: $(AZURE_TENANT_ID_VHD) + AZURE_CLIENT_ID: $(AZURE_CLIENT_ID_VHD) + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET_VHD) + AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID_VHD) + + - stage: test + condition: and(succeeded(), eq(variables.CLEANUP, 'False')) + jobs: + - template: test-vhd.yaml + variables: + AZURE_TENANT_ID: $(AZURE_TENANT_ID_VHD) + AZURE_CLIENT_ID: $(AZURE_CLIENT_ID_VHD) + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET_VHD) + AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID_VHD) + + - stage: sku + condition: and(succeeded(), eq(variables.CLEANUP, 'False')) + jobs: + - template: create-sku.yaml + variables: + AZURE_TENANT_ID: $(AZURE_TENANT_ID_SKU) + AZURE_CLIENT_ID: $(AZURE_CLIENT_ID_SKU) + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET_SKU) + + - stage: disk_version + condition: and(succeeded(), eq(variables.CLEANUP, 'False')) + jobs: + - template: create-disk-version.yaml + variables: + AZURE_TENANT_ID: $(AZURE_TENANT_ID_SKU) + AZURE_CLIENT_ID: $(AZURE_CLIENT_ID_SKU) + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET_SKU) diff --git a/packer/azure/.pipelines/test-vhd.yaml b/packer/azure/.pipelines/test-vhd.yaml new file mode 100644 index 0000000..8c0a282 --- /dev/null +++ b/packer/azure/.pipelines/test-vhd.yaml @@ -0,0 +1,143 @@ +# Required pipeline variables: +# - BUILD_POOL - Azure DevOps build pool to use +# - CONTAINER_IMAGE - Dev container image URL to use. Should have Azure CLI, Packer, and Ansible. +# - AZ_CAPI_EXTENSION_URL - URL to the Azure CAPI extension build. +# - AZURE_TENANT_ID - tenant ID +# - AZURE_CLIENT_ID - Service principal ID +# - AZURE_CLIENT_SECRET - Service principal secret +# - AZURE_SUBSCRIPTION_ID - Subscription ID used by the pipeline +# - KUBERNETES_VERSION - version of Kubernetes to build the image with, e.g. `1.16.2` +# - OS - target of build e.g. `Ubuntu/Windows` +# - OS_VERSION - target of build e.g. `18.04/2004/2019` + +jobs: +- job: test_vhd + container: $[ variables['CONTAINER_IMAGE'] ] + timeoutInMinutes: 120 + strategy: + maxParallel: 0 + pool: + name: $(BUILD_POOL) + steps: + - task: DownloadPipelineArtifact@2 + inputs: + source: current + artifact: publishing-info + path: $(system.defaultWorkingDirectory)/images/capi/packer/azure/vhd/ + - script: | + set -x + set -e -o pipefail + + VHD_RESOURCE_ID=$(jq -r .vhd_base_url $(system.defaultWorkingDirectory)/images/capi/packer/azure/vhd/vhd-publishing-info.json) + STORAGE_ACCOUNT_NAME=$(jq -r .storage_account_name $(system.defaultWorkingDirectory)/images/capi/packer/azure/vhd/vhd-publishing-info.json) + TAGS=$(jq -r .tags $(system.defaultWorkingDirectory)/images/capi/packer/azure/vhd/vhd-publishing-info.json) + + echo "##vso[task.setvariable variable=VHD_RESOURCE_ID]$VHD_RESOURCE_ID" + echo "##vso[task.setvariable variable=STORAGE_ACCOUNT_NAME]$STORAGE_ACCOUNT_NAME" + echo "##vso[task.setvariable variable=TAGS;]$TAGS" + displayName: Import variables from build vhd job + env: + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET) + - script: | + set -x + set -e -o pipefail + + RANDOM=$(bash -c 'echo $RANDOM') + RESOURCE_GROUP="capi-testvmimage-${RANDOM}" + echo "${RESOURCE_GROUP}" is the group + + # Azure CLI login + az login -u $AZURE_CLIENT_ID -p $AZURE_CLIENT_SECRET --service-principal --tenant $AZURE_TENANT_ID + + # Find the VHD blob location from its storage account + AZURE_LOCATION=$(az storage account show --name "${STORAGE_ACCOUNT_NAME}" --query '[location]' -o tsv) + + # Create the resource group + az group create --name "${RESOURCE_GROUP}" --location "${AZURE_LOCATION}" --tags "${TAGS}" + + # Create a managed image from the VHD blob + OS_TYPE="Linux" + if [ "$OS" == "Windows" ]; then + OS_TYPE="Windows" + fi + az image create -n testvmimage -g "${RESOURCE_GROUP}" --os-type "${OS_TYPE}" --source "${VHD_RESOURCE_ID}" + + # Pass the managed image resource ID on to the next step + IMAGE_ID=$(az image show -g "${RESOURCE_GROUP}" -n testvmimage --query '[id]' --output tsv) + echo "##vso[task.setvariable variable=RESOURCE_GROUP;]$RESOURCE_GROUP" + echo "##vso[task.setvariable variable=MANAGED_IMAGE_ID;]$IMAGE_ID" + echo "##vso[task.setvariable variable=AZURE_LOCATION;]$AZURE_LOCATION" + displayName: promote VHD blob to managed image + env: + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET) + - template: k8s-config.yaml + - script: | + set -x + set -e -o pipefail + + export PATH=${PATH}:.local/bin + ./packer/azure/scripts/ensure-kustomize.sh + + # Generate cluster template with kustomize + if [ "$OS" == "Windows" ]; then + kustomize build --load-restrictor LoadRestrictionsNone $(system.defaultWorkingDirectory)/images/capi/packer/azure/scripts/test-templates/windows/ > $(system.defaultWorkingDirectory)/images/capi/packer/azure/scripts/test-templates/cluster-template.yaml + else + kustomize build --load-restrictor LoadRestrictionsNone $(system.defaultWorkingDirectory)/images/capi/packer/azure/scripts/test-templates/linux/ > $(system.defaultWorkingDirectory)/images/capi/packer/azure/scripts/test-templates/cluster-template.yaml + fi + TEST_TEMPLATE=$(system.defaultWorkingDirectory)/images/capi/packer/azure/scripts/test-templates/cluster-template.yaml + echo "##vso[task.setvariable variable=TEST_TEMPLATE;]$TEST_TEMPLATE" + displayName: generate cluster template + workingDirectory: '$(system.defaultWorkingDirectory)/images/capi' + env: + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET) + - script: | + set -x + set -e -o pipefail + + os=$(echo "$OS" | tr '[:upper:]' '[:lower:]') + + # Set up the Azure CLI Cluster API extension + # https://github.com/Azure/azure-capi-cli-extension/releases/download/az-capi-nightly/capi-0.0.vnext-py2.py3-none-any.whl + az extension add --yes --source "${AZ_CAPI_EXTENSION_URL}" + + # Install required binaries + mkdir ~/test-binaries + export PATH=${PATH}:~/test-binaries + az capi install -a -ip ~/test-binaries + + echo "##vso[task.setvariable variable=PATH;]$PATH" + displayName: Install and configure az capi extension + env: + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET) + - script: | + params=() + if [ "$OS" == "Windows" ]; then + params+=(--windows) + fi + + # Create a cluster + az capi create \ + --yes \ + --debug \ + --name testvm \ + --kubernetes-version="${KUBERNETES_VERSION}" \ + --location="${AZURE_LOCATION}" \ + --resource-group="${RESOURCE_GROUP}" \ + --management-cluster-resource-group-name="${RESOURCE_GROUP}" \ + --control-plane-machine-count=1 \ + --node-machine-count=1 \ + --template="${TEST_TEMPLATE}" \ + --tags="${TAGS}" \ + --wait-for-nodes=2 \ + "${params[@]}" + displayName: Create a cluster + env: + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET) + - script: | + set -x + set -e -o pipefail + + # Clean up the test resource group + az group delete -n "${RESOURCE_GROUP}" --yes --no-wait + displayName: Clean up test resource group + condition: always() diff --git a/packer/azure/.pipelines/vhd-publishing-info.yaml b/packer/azure/.pipelines/vhd-publishing-info.yaml new file mode 100644 index 0000000..d0928c3 --- /dev/null +++ b/packer/azure/.pipelines/vhd-publishing-info.yaml @@ -0,0 +1,19 @@ +steps: +- script: | + VHD_BASE_URL="$(cat packer/azure/vhd-base-url.out)" + VHD_URL="$(cat packer/azure/vhd-url.out)" + STORAGE_ACCOUNT_NAME="$(cat packer/azure/storage-account-name.out)" + RESOURCE_GROUP_NAME="$(cat packer/azure/resource-group-name.out)" + TAGS="$(cat packer/azure/tags.out)" + cat < packer/azure/vhd-publishing-info.json + { + "vhd_base_url": "${VHD_BASE_URL}", + "vhd_url": "${VHD_URL}", + "storage_account_name": "${STORAGE_ACCOUNT_NAME}", + "resource_group_name": "${RESOURCE_GROUP_NAME}", + "tags": "${TAGS}" + } + EOF + displayName: Generating publishing info for VHD + workingDirectory: '$(system.defaultWorkingDirectory)/images/capi' + condition: eq(variables.CLEANUP, 'False') diff --git a/packer/azure/OWNERS b/packer/azure/OWNERS new file mode 100644 index 0000000..6c303be --- /dev/null +++ b/packer/azure/OWNERS @@ -0,0 +1,8 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - cluster-api-azure-maintainers + +reviewers: + - cluster-api-azure-maintainers + - image-builder-azure-reviewers diff --git a/packer/azure/azure-config.json b/packer/azure/azure-config.json new file mode 100644 index 0000000..c914195 --- /dev/null +++ b/packer/azure/azure-config.json @@ -0,0 +1,8 @@ +{ + "azure_location": "{{env `AZURE_LOCATION`}}", + "client_id": "{{env `AZURE_CLIENT_ID`}}", + "client_secret": "{{env `AZURE_CLIENT_SECRET`}}", + "containerd_wasm_shims_runtimes": "spin,slight", + "subscription_id": "{{env `AZURE_SUBSCRIPTION_ID`}}", + "vm_size": "Standard_B2ms" +} diff --git a/packer/azure/azure-sig-gen2.json b/packer/azure/azure-sig-gen2.json new file mode 100644 index 0000000..74bada0 --- /dev/null +++ b/packer/azure/azure-sig-gen2.json @@ -0,0 +1,7 @@ +{ + "image_name": "capi-{{user `distribution`}}-{{user `distribution_version`}}-gen2", + "replication_regions": "{{env `AZURE_LOCATION`}}", + "resource_group_name": "{{env `RESOURCE_GROUP_NAME`}}", + "shared_image_gallery_name": "{{env `GALLERY_NAME`}}", + "sig_image_version": "0.3.{{user `build_timestamp`}}" +} diff --git a/packer/azure/azure-sig.json b/packer/azure/azure-sig.json new file mode 100644 index 0000000..5eeaae9 --- /dev/null +++ b/packer/azure/azure-sig.json @@ -0,0 +1,7 @@ +{ + "image_name": "capi-{{user `distribution`}}-{{user `distribution_version`}}", + "replication_regions": "{{env `AZURE_LOCATION`}}", + "resource_group_name": "{{env `RESOURCE_GROUP_NAME`}}", + "shared_image_gallery_name": "{{env `GALLERY_NAME`}}", + "sig_image_version": "0.3.{{user `build_timestamp`}}" +} diff --git a/packer/azure/azure-vhd.json b/packer/azure/azure-vhd.json new file mode 100644 index 0000000..20296cb --- /dev/null +++ b/packer/azure/azure-vhd.json @@ -0,0 +1,5 @@ +{ + "capture_container_name": "cluster-api-vhds", + "resource_group_name": "{{env `RESOURCE_GROUP_NAME`}}", + "storage_account_name": "{{env `STORAGE_ACCOUNT_NAME`}}" +} diff --git a/packer/azure/centos-7-gen2.json b/packer/azure/centos-7-gen2.json new file mode 100644 index 0000000..39791c9 --- /dev/null +++ b/packer/azure/centos-7-gen2.json @@ -0,0 +1,9 @@ +{ + "build_name": "centos-7-gen2", + "distribution": "centos", + "distribution_release": "centos-7", + "distribution_version": "7", + "image_offer": "CentOS", + "image_publisher": "OpenLogic", + "image_sku": "7_7-gen2" +} diff --git a/packer/azure/centos-7.json b/packer/azure/centos-7.json new file mode 100644 index 0000000..5d02cea --- /dev/null +++ b/packer/azure/centos-7.json @@ -0,0 +1,9 @@ +{ + "build_name": "centos-7", + "distribution": "centos", + "distribution_release": "centos-7", + "distribution_version": "7", + "image_offer": "CentOS", + "image_publisher": "OpenLogic", + "image_sku": "7.7" +} diff --git a/packer/azure/flatcar-gen2.json b/packer/azure/flatcar-gen2.json new file mode 100644 index 0000000..6141216 --- /dev/null +++ b/packer/azure/flatcar-gen2.json @@ -0,0 +1,23 @@ +{ + "ansible_extra_vars": "ansible_python_interpreter=/opt/pypy/bin/pypy", + "build_name": "flatcar-gen2", + "crictl_source_type": "http", + "distribution": "flatcar", + "distribution_release": "{{env `FLATCAR_CHANNEL`}}", + "distribution_version": "{{env `FLATCAR_CHANNEL`}}-{{env `FLATCAR_VERSION`}}", + "image_offer": "flatcar-container-linux-free", + "image_publisher": "kinvolk", + "image_sku": "{{env `FLATCAR_CHANNEL`}}-gen2", + "image_version": "{{env `FLATCAR_VERSION` }}", + "kubernetes_cni_source_type": "http", + "kubernetes_source_type": "http", + "plan_image_offer": "{{user `image_offer`}}", + "plan_image_publisher": "{{user `image_publisher`}}", + "plan_image_sku": "{{user `image_sku`}}", + "python_path": "/opt/pypy/site-packages", + "root_device_name": "/dev/sda", + "ssh_username": "core", + "systemd_prefix": "/etc/systemd", + "sysusr_prefix": "/opt", + "sysusrlocal_prefix": "/opt" +} diff --git a/packer/azure/flatcar.json b/packer/azure/flatcar.json new file mode 100644 index 0000000..4b75526 --- /dev/null +++ b/packer/azure/flatcar.json @@ -0,0 +1,23 @@ +{ + "ansible_extra_vars": "ansible_python_interpreter=/opt/pypy/bin/pypy", + "build_name": "flatcar", + "crictl_source_type": "http", + "distribution": "flatcar", + "distribution_release": "{{env `FLATCAR_CHANNEL`}}", + "distribution_version": "{{env `FLATCAR_CHANNEL`}}-{{env `FLATCAR_VERSION`}}", + "image_offer": "flatcar-container-linux-free", + "image_publisher": "kinvolk", + "image_sku": "{{env `FLATCAR_CHANNEL`}}", + "image_version": "{{env `FLATCAR_VERSION` }}", + "kubernetes_cni_source_type": "http", + "kubernetes_source_type": "http", + "plan_image_offer": "{{user `image_offer`}}", + "plan_image_publisher": "{{user `image_publisher`}}", + "plan_image_sku": "{{user `image_sku`}}", + "python_path": "/opt/pypy/site-packages", + "root_device_name": "/dev/sda", + "ssh_username": "core", + "systemd_prefix": "/etc/systemd", + "sysusr_prefix": "/opt", + "sysusrlocal_prefix": "/opt" +} diff --git a/packer/azure/packer-windows.json b/packer/azure/packer-windows.json new file mode 100644 index 0000000..ae5d815 --- /dev/null +++ b/packer/azure/packer-windows.json @@ -0,0 +1,244 @@ +{ + "builders": [ + { + "azure_tags": { + "build_date": "{{isotime}}", + "build_timestamp": "{{user `build_timestamp`}}", + "creationTimestamp": "{{isotime \"2006-01-02T15:04:05Z\"}}", + "image_builder_version": "{{user `ib_version`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}", + "os_version": "{{user `image_sku`}}" + }, + "capture_container_name": "{{user `capture_container_name`}}", + "capture_name_prefix": "capi-{{user `build_timestamp`}}", + "client_id": "{{user `client_id`}}", + "client_secret": "{{user `client_secret`}}", + "communicator": "winrm", + "image_offer": "{{user `image_offer` }}", + "image_publisher": "{{user `image_publisher` }}", + "image_sku": "{{user `image_sku`}}", + "image_version": "{{user `image_version`}}", + "location": "{{user `azure_location`}}", + "name": "vhd-{{user `build_name`}}", + "os_disk_size_gb": "{{user `os_disk_size_gb`}}", + "os_type": "Windows", + "private_virtual_network_with_public_ip": "{{user `private_virtual_network_with_public_ip`}}", + "resource_group_name": "{{user `resource_group_name`}}", + "storage_account": "{{user `storage_account_name`}}", + "subscription_id": "{{user `subscription_id`}}", + "type": "azure-arm", + "virtual_network_name": "{{user `virtual_network_name`}}", + "virtual_network_resource_group_name": "{{user `virtual_network_resource_group_name`}}", + "virtual_network_subnet_name": "{{user `virtual_network_subnet_name`}}", + "vm_size": "{{user `vm_size`}}", + "winrm_insecure": true, + "winrm_timeout": "10m", + "winrm_use_ssl": true, + "winrm_username": "packer" + }, + { + "azure_tags": { + "build_date": "{{isotime}}", + "build_timestamp": "{{user `build_timestamp`}}", + "creationTimestamp": "{{isotime \"2006-01-02T15:04:05Z\"}}", + "image_builder_version": "{{user `ib_version`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}", + "os_version": "{{user `image_sku`}}" + }, + "client_id": "{{user `client_id`}}", + "client_secret": "{{user `client_secret`}}", + "communicator": "winrm", + "image_offer": "{{user `image_offer` }}", + "image_publisher": "{{user `image_publisher` }}", + "image_sku": "{{user `image_sku`}}", + "image_version": "{{user `image_version`}}", + "location": "{{user `azure_location`}}", + "managed_image_name": "{{user `image_name`}}-{{user `runtime`}}-{{user `build_timestamp`}}", + "managed_image_resource_group_name": "{{user `resource_group_name`}}", + "managed_image_storage_account_type": "{{user `storage_account_type`}}", + "name": "sig-{{user `build_name`}}", + "os_disk_size_gb": "{{user `os_disk_size_gb`}}", + "os_type": "Windows", + "private_virtual_network_with_public_ip": "{{user `private_virtual_network_with_public_ip`}}", + "shared_gallery_image_version_exclude_from_latest": "{{ user `exclude_from_latest` }}", + "shared_image_gallery": { + "community_gallery_image_id": "{{ user `community_gallery_image_id` }}", + "direct_shared_gallery_image_id": "{{ user `direct_shared_gallery_image_id` }}", + "gallery_name": "{{user `source_sig_name`}}", + "image_name": "{{user `source_sig_image_name`}}", + "image_version": "{{user `source_sig_image_version`}}", + "resource_group": "{{user `source_sig_resource_group_name`}}", + "subscription": "{{user `source_sig_subscription_id`}}" + }, + "shared_image_gallery_destination": { + "gallery_name": "{{user `shared_image_gallery_name`}}", + "image_name": "{{user `image_name`}}-{{user `runtime`}}", + "image_version": "{{user `sig_image_version`}}", + "replication_regions": "{{user `replication_regions`}}", + "resource_group": "{{user `resource_group_name`}}", + "storage_account_type": "{{user `storage_account_type`}}" + }, + "subscription_id": "{{user `subscription_id`}}", + "type": "azure-arm", + "virtual_network_name": "{{user `virtual_network_name`}}", + "virtual_network_resource_group_name": "{{user `virtual_network_resource_group_name`}}", + "virtual_network_subnet_name": "{{user `virtual_network_subnet_name`}}", + "vm_size": "{{user `vm_size`}}", + "winrm_insecure": true, + "winrm_timeout": "10m", + "winrm_use_ssl": true, + "winrm_username": "packer" + } + ], + "post-processors": [ + { + "custom_data": { + "build_date": "{{isotime}}", + "build_name": "{{user `build_name`}}", + "build_timestamp": "{{user `build_timestamp`}}", + "build_type": "node", + "containerd_version": "{{user `containerd_version`}}", + "kubernetes_cni_semver": "{{user `kubernetes_cni_semver`}}", + "kubernetes_semver": "{{user `kubernetes_semver`}}", + "kubernetes_source_type": "{{user `kubernetes_source_type`}}", + "os_name": "{{user `distro_name`}}", + "resource_group_name": "{{user `resource_group_name`}}", + "storage_account_name": "{{user `storage_account_name`}}" + }, + "output": "{{user `manifest_output`}}", + "strip_path": true, + "type": "manifest" + } + ], + "provisioners": [ + { + "elevated_password": "{{.WinRMPassword}}", + "elevated_user": "packer", + "script": "ansible/windows/ansible_winrm.ps1", + "type": "powershell" + }, + { + "extra_arguments": [ + "-e", + "ansible_winrm_server_cert_validation=ignore ansible_winrm_operation_timeout_sec=120 ansible_winrm_read_timeout_sec=150", + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `azure_extra_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}", + "--extra-vars", + "gmsa_keyvault_url={{user `gmsa_keyvault_url`}}" + ], + "max_retries": 5, + "pause_before": "15s", + "playbook_file": "ansible/windows/node_windows.yml", + "type": "ansible", + "use_proxy": false, + "user": "packer" + }, + { + "restart_timeout": "10m", + "type": "windows-restart" + }, + { + "arch": "{{user `goss_arch`}}", + "download_path": "{{user `goss_download_path`}}", + "format": "{{user `goss_format`}}", + "format_options": "{{user `goss_format_options`}}", + "goss_file": "{{user `goss_entry_file`}}", + "inspect": "{{user `goss_inspect_mode`}}", + "remote_folder": "{{user `goss_remote_folder`}}", + "remote_path": "{{user `goss_remote_path`}}", + "skip_install": "{{user `goss_skip_install`}}", + "target_os": "Windows", + "tests": [ + "{{user `goss_tests_dir`}}" + ], + "type": "goss", + "url": "{{user `goss_url`}}", + "use_sudo": false, + "vars_env": { + "GOSS_MAX_CONCURRENT": "1", + "GOSS_USE_ALPHA": "1" + }, + "vars_file": "{{user `goss_vars_file`}}", + "vars_inline": { + "OS": "{{user `distribution` | lower}}", + "PROVIDER": "azure", + "containerd_version": "{{user `containerd_version`}}", + "distribution_version": "{{user `distribution_version`}}", + "docker_ee_version": "{{user `docker_ee_version`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}", + "pause_image": "{{user `pause_image`}}", + "runtime": "{{user `runtime`}}", + "ssh_source_url": "{{user `ssh_source_url`}}" + }, + "version": "{{user `goss_version`}}" + }, + { + "inline": [ + "rm -Force -Recurse C:\\var\\log\\kubelet\\*" + ], + "type": "powershell" + }, + { + "elevated_password": "{{.WinRMPassword}}", + "elevated_user": "packer", + "script": "packer/azure/scripts/sysprep.ps1", + "type": "powershell" + } + ], + "variables": { + "additional_debug_files": null, + "ansible_common_vars": "", + "ansible_extra_vars": "", + "ansible_user_vars": "", + "azure_extra_vars": "wire_server_users={{user `wire_server_users`}}", + "azure_location": null, + "build_name": null, + "build_timestamp": "{{timestamp}}", + "client_id": null, + "client_secret": null, + "cloudbase_init_url": "https://github.com/cloudbase/cloudbase-init/releases/download/{{user `cloudbase_init_version`}}/CloudbaseInitSetup_{{user `cloudbase_init_version` | replace_all `.` `_` }}_x64.msi", + "cloudbase_logging_serial_port": "COM2,115200,N,8", + "cloudbase_metadata_services": "cloudbaseinit.metadata.services.azureservice.AzureService", + "cloudbase_metadata_services_unattend": "cloudbaseinit.metadata.services.base.EmptyMetadataService", + "cloudbase_plugins": "cloudbaseinit.plugins.windows.createuser.CreateUserPlugin, cloudbaseinit.plugins.common.setuserpassword.SetUserPasswordPlugin, cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin, cloudbaseinit.plugins.common.ephemeraldisk.EphemeralDiskPlugin, cloudbaseinit.plugins.windows.azureguestagent.AzureGuestAgentPlugin, cloudbaseinit.plugins.common.mtu.MTUPlugin, cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin", + "cloudbase_plugins_unattend": "cloudbaseinit.plugins.common.mtu.MTUPlugin", + "community_gallery_image_id": "", + "containerd_url": "", + "containerd_version": null, + "direct_shared_gallery_image_id": "", + "exclude_from_latest": "false", + "gmsa_keyvault_url": "https://kubernetesartifacts.azureedge.net/ccgakvplugin/v1.1.4/binaries/windows-gmsa-ccgakvplugin-v1.1.4.zip", + "ib_version": "{{env `IB_VERSION`}}", + "image_offer": "", + "image_publisher": "", + "image_sku": "", + "image_version": "latest", + "kubernetes_base_url": "https://kubernetesreleases.blob.core.windows.net/kubernetes/{{user `kubernetes_semver`}}/binaries/node/windows/{{user `kubernetes_goarch`}}", + "manifest_output": "manifest.json", + "nssm_url": null, + "os_disk_size_gb": "", + "prepull": null, + "private_virtual_network_with_public_ip": "", + "source_sig_image_name": "", + "source_sig_image_version": "", + "source_sig_name": "", + "source_sig_resource_group_name": "", + "source_sig_subscription_id": "", + "storage_account_type": "", + "subscription_id": null, + "virtual_network_name": "", + "virtual_network_resource_group_name": "", + "virtual_network_subnet_name": "", + "vm_size": "", + "windows_service_manager": null, + "windows_updates_kbs": null, + "wins_url": "https://github.com/rancher/wins/releases/download/v{{user `wins_version`}}/wins.exe", + "wire_server_users": "" + } +} diff --git a/packer/azure/packer.json b/packer/azure/packer.json new file mode 100644 index 0000000..0447350 --- /dev/null +++ b/packer/azure/packer.json @@ -0,0 +1,276 @@ +{ + "builders": [ + { + "azure_tags": { + "build_date": "{{isotime}}", + "build_timestamp": "{{user `build_timestamp`}}", + "creationTimestamp": "{{isotime \"2006-01-02T15:04:05Z\"}}", + "distribution": "{{user `distribution`}}", + "distribution_release": "{{user `distribution_release`}}", + "distribution_version": "{{user `distribution_version`}}", + "image_builder_version": "{{user `ib_version`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}" + }, + "capture_container_name": "{{user `capture_container_name`}}", + "capture_name_prefix": "capi-{{user `build_timestamp`}}", + "client_id": "{{user `client_id`}}", + "client_secret": "{{user `client_secret`}}", + "image_offer": "{{user `image_offer` }}", + "image_publisher": "{{user `image_publisher` }}", + "image_sku": "{{user `image_sku`}}", + "image_version": "{{user `image_version`}}", + "location": "{{user `azure_location`}}", + "name": "vhd-{{user `build_name`}}", + "os_disk_size_gb": "{{user `os_disk_size_gb`}}", + "os_type": "Linux", + "private_virtual_network_with_public_ip": "{{user `private_virtual_network_with_public_ip`}}", + "resource_group_name": "{{user `resource_group_name`}}", + "ssh_username": "packer", + "storage_account": "{{user `storage_account_name`}}", + "subscription_id": "{{user `subscription_id`}}", + "type": "azure-arm", + "virtual_network_name": "{{user `virtual_network_name`}}", + "virtual_network_resource_group_name": "{{user `virtual_network_resource_group_name`}}", + "virtual_network_subnet_name": "{{user `virtual_network_subnet_name`}}", + "vm_size": "{{user `vm_size`}}" + }, + { + "azure_tags": { + "build_date": "{{isotime}}", + "build_timestamp": "{{user `build_timestamp`}}", + "creationTimestamp": "{{isotime \"2006-01-02T15:04:05Z\"}}", + "distribution": "{{user `distribution`}}", + "distribution_release": "{{user `distribution_release`}}", + "distribution_version": "{{user `distribution_version`}}", + "image_builder_version": "{{user `ib_version`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}" + }, + "client_id": "{{user `client_id`}}", + "client_secret": "{{user `client_secret`}}", + "image_offer": "{{user `image_offer` }}", + "image_publisher": "{{user `image_publisher` }}", + "image_sku": "{{user `image_sku`}}", + "image_version": "{{user `image_version`}}", + "location": "{{user `azure_location`}}", + "managed_image_name": "{{user `image_name`}}-{{user `build_timestamp`}}", + "managed_image_resource_group_name": "{{user `resource_group_name`}}", + "managed_image_storage_account_type": "{{user `storage_account_type`}}", + "name": "sig-{{user `build_name`}}", + "os_disk_size_gb": "{{user `os_disk_size_gb`}}", + "os_type": "Linux", + "plan_info": { + "plan_name": "{{user `plan_image_sku`}}", + "plan_product": "{{user `plan_image_offer`}}", + "plan_publisher": "{{user `plan_image_publisher`}}" + }, + "private_virtual_network_with_public_ip": "{{user `private_virtual_network_with_public_ip`}}", + "shared_gallery_image_version_exclude_from_latest": "{{ user `exclude_from_latest` }}", + "shared_image_gallery": { + "community_gallery_image_id": "{{ user `community_gallery_image_id` }}", + "direct_shared_gallery_image_id": "{{ user `direct_shared_gallery_image_id` }}", + "gallery_name": "{{user `source_sig_name`}}", + "image_name": "{{user `source_sig_image_name`}}", + "image_version": "{{user `source_sig_image_version`}}", + "resource_group": "{{user `source_sig_resource_group_name`}}", + "subscription": "{{user `source_sig_subscription_id`}}" + }, + "shared_image_gallery_destination": { + "gallery_name": "{{user `shared_image_gallery_name`}}", + "image_name": "{{user `image_name`}}", + "image_version": "{{user `sig_image_version`}}", + "replication_regions": "{{user `replication_regions`}}", + "resource_group": "{{user `resource_group_name`}}", + "storage_account_type": "{{user `storage_account_type`}}" + }, + "ssh_username": "packer", + "subscription_id": "{{user `subscription_id`}}", + "type": "azure-arm", + "virtual_network_name": "{{user `virtual_network_name`}}", + "virtual_network_resource_group_name": "{{user `virtual_network_resource_group_name`}}", + "virtual_network_subnet_name": "{{user `virtual_network_subnet_name`}}", + "vm_size": "{{user `vm_size`}}" + } + ], + "post-processors": [ + { + "custom_data": { + "build_date": "{{isotime}}", + "build_name": "{{user `build_name`}}", + "build_timestamp": "{{user `build_timestamp`}}", + "build_type": "node", + "containerd_version": "{{user `containerd_version`}}", + "kubernetes_cni_semver": "{{user `kubernetes_cni_semver`}}", + "kubernetes_semver": "{{user `kubernetes_semver`}}", + "kubernetes_source_type": "{{user `kubernetes_source_type`}}", + "os_name": "{{user `distro_name`}}", + "resource_group_name": "{{user `resource_group_name`}}", + "storage_account_name": "{{user `storage_account_name`}}" + }, + "output": "{{user `manifest_output`}}", + "strip_path": true, + "type": "manifest" + } + ], + "provisioners": [ + { + "environment_vars": [ + "BUILD_NAME={{user `build_name`}}" + ], + "inline": [ + "if [ $BUILD_NAME != \"ubuntu-1804\" ] && [ $BUILD_NAME != \"ubuntu-1804-gen2\" ]; then exit 0; fi", + "while [ ! -f /var/lib/cloud/instance/boot-finished ]; do echo 'Waiting for cloud-init...'; sleep 1; done", + "sudo apt-get -qq update && sudo DEBIAN_FRONTEND=noninteractive apt-get -qqy install python python-pip" + ], + "type": "shell" + }, + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} {{user `ansible_common_ssh_args`}}'" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}", + "--scp-extra-args", + "{{user `ansible_scp_extra_args`}}" + ], + "playbook_file": "./ansible/python.yml", + "type": "ansible", + "user": "packer" + }, + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} {{user `ansible_common_ssh_args`}}'" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}", + "--scp-extra-args", + "{{user `ansible_scp_extra_args`}}" + ], + "playbook_file": "./ansible/node.yml", + "type": "ansible", + "user": "packer" + }, + { + "arch": "{{user `goss_arch`}}", + "download_path": "{{user `goss_download_path`}}", + "format": "{{user `goss_format`}}", + "format_options": "{{user `goss_format_options`}}", + "goss_file": "{{user `goss_entry_file`}}", + "inspect": "{{user `goss_inspect_mode`}}", + "remote_folder": "{{user `goss_remote_folder`}}", + "remote_path": "{{user `goss_remote_path`}}", + "skip_install": "{{user `goss_skip_install`}}", + "tests": [ + "{{user `goss_tests_dir`}}" + ], + "type": "goss", + "url": "{{user `goss_url`}}", + "use_sudo": true, + "vars_file": "{{user `goss_vars_file`}}", + "vars_inline": { + "ARCH": "amd64", + "OS": "{{user `distribution` | lower}}", + "OS_VERSION": "{{user `distribution_version` | lower}}", + "PROVIDER": "azure", + "containerd_version": "{{user `containerd_version`}}", + "containerd_wasm_shims_runtimes": "{{user `containerd_wasm_shims_runtimes` }}", + "kubernetes_cni_deb_version": "{{ user `kubernetes_cni_deb_version` }}", + "kubernetes_cni_rpm_version": "{{ split (user `kubernetes_cni_rpm_version`) \"-\" 0 }}", + "kubernetes_cni_source_type": "{{user `kubernetes_cni_source_type`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver` | replace \"v\" \"\" 1}}", + "kubernetes_deb_version": "{{ user `kubernetes_deb_version` }}", + "kubernetes_rpm_version": "{{ split (user `kubernetes_rpm_version`) \"-\" 0 }}", + "kubernetes_source_type": "{{user `kubernetes_source_type`}}", + "kubernetes_version": "{{user `kubernetes_semver` | replace \"v\" \"\" 1}}" + }, + "version": "{{user `goss_version`}}" + }, + { + "environment_vars": [ + "BUILD_NAME={{user `build_name`}}" + ], + "inline": [ + "if [[ $BUILD_NAME != \"flatcar\"* ]]; then exit 0; fi", + "sudo bash -c \"/usr/share/oem/python/bin/python /usr/share/oem/bin/waagent -force -deprovision+user && sync\"" + ], + "inline_shebang": "/bin/bash -x", + "remote_folder": "{{user `provisioner_remote_folder`}}", + "type": "shell" + } + ], + "variables": { + "ansible_common_vars": "", + "ansible_extra_vars": "", + "ansible_scp_extra_args": "", + "ansible_user_vars": "", + "azure_location": null, + "build_name": null, + "build_resource_group_name": "{{ env `BUILD_RESOURCE_GROUP_NAME` }}", + "build_timestamp": "{{timestamp}}", + "client_id": null, + "client_secret": null, + "community_gallery_image_id": "", + "containerd_sha256": null, + "containerd_url": "https://github.com/containerd/containerd/releases/download/v{{user `containerd_version`}}/cri-containerd-cni-{{user `containerd_version`}}-linux-amd64.tar.gz", + "containerd_version": null, + "containerd_wasm_shims_runtimes": null, + "crictl_url": "https://github.com/kubernetes-sigs/cri-tools/releases/download/v{{user `crictl_version`}}/crictl-v{{user `crictl_version`}}-linux-amd64.tar.gz", + "crictl_version": null, + "direct_shared_gallery_image_id": "", + "distribution": null, + "distribution_release": null, + "distribution_version": null, + "exclude_from_latest": "false", + "existing_ansible_ssh_args": "{{env `ANSIBLE_SSH_ARGS`}}", + "ib_version": "{{env `IB_VERSION`}}", + "image_offer": "", + "image_publisher": "", + "image_sku": "", + "image_version": "latest", + "kubernetes_cni_deb_version": null, + "kubernetes_cni_http_source": null, + "kubernetes_cni_rpm_version": null, + "kubernetes_cni_semver": null, + "kubernetes_cni_source_type": null, + "kubernetes_container_registry": null, + "kubernetes_deb_gpg_key": null, + "kubernetes_deb_repo": null, + "kubernetes_deb_version": null, + "kubernetes_http_source": null, + "kubernetes_load_additional_imgs": null, + "kubernetes_rpm_gpg_check": null, + "kubernetes_rpm_gpg_key": null, + "kubernetes_rpm_repo": null, + "kubernetes_rpm_version": null, + "kubernetes_semver": null, + "kubernetes_series": null, + "kubernetes_source_type": null, + "manifest_output": "manifest.json", + "os_disk_size_gb": "", + "plan_image_offer": "", + "plan_image_publisher": "", + "plan_image_sku": "", + "private_virtual_network_with_public_ip": "", + "provisioner_remote_folder": "/tmp", + "source_sig_image_name": "", + "source_sig_image_version": "", + "source_sig_name": "", + "source_sig_resource_group_name": "", + "source_sig_subscription_id": "", + "storage_account_type": "", + "subscription_id": null, + "virtual_network_name": "", + "virtual_network_resource_group_name": "", + "virtual_network_subnet_name": "", + "vm_size": "" + } +} diff --git a/packer/azure/rhel-8.json b/packer/azure/rhel-8.json new file mode 100644 index 0000000..6796dc4 --- /dev/null +++ b/packer/azure/rhel-8.json @@ -0,0 +1,11 @@ +{ + "build_name": "rhel-8", + "distribution": "rhel", + "distribution_release": "rhel-8", + "distribution_version": "8", + "epel_rpm_gpg_key": "https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8", + "image_offer": "RHEL", + "image_publisher": "RedHat", + "image_sku": "8_7", + "redhat_epel_rpm": "https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm" +} diff --git a/packer/azure/scripts/delete-unused-storage.sh b/packer/azure/scripts/delete-unused-storage.sh new file mode 100755 index 0000000..74ec66a --- /dev/null +++ b/packer/azure/scripts/delete-unused-storage.sh @@ -0,0 +1,156 @@ +#!/bin/bash +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script deletes unused Azure storage accounts created in the process of +# building CAPZ reference images. It also archives existing accounts into one +# main storage account to reduce the limited number of accounts in use. +# Usage: +# delete-unused-storage.sh +# +# The `pub` tool (https://github.com/devigned/pub) and the `az` CLI tool +# (https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) must be found +# in the PATH. +# +# In order to run this script, log in to the publishing account with the +# `az account set -s ` command. Then export these environment +# variables to enable access to the storage accounts: +# AZURE_CLIENT_ID +# AZURE_CLIENT_SECRET +# AZURE_SUBSCRIPTION_ID +# AZURE_TENANT_ID +# +# By default, the script will not modify any resources. Pass the environment variable +# DRYRUN=false to enable the script to archive and to delete the storage accounts. + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +RESOURCE_GROUP=${RESOURCE_GROUP:-cluster-api-images} +PUBLISHER=${PUBLISHER:-cncf-upstream} +OFFERS=${OFFERS:-capi capi-windows} +PREFIX=${PREFIX:-capi} +LONG_PREFIX=${LONG_PREFIX:-${PREFIX}[0-9]{10\}} +ARCHIVE_STORAGE_ACCOUNT=${ARCHIVE_STORAGE_ACCOUNT:-${PREFIX}archive} +DRYRUN=${DRYRUN:-true} +RED='\033[0;31m' +NC='\033[0m' + +if ${DRYRUN}; then + echo "DRYRUN: This script will not copy or delete any resources." + ECHO=echo +else + ECHO= +fi + +which pub &> /dev/null || (echo "Please install pub from https://github.com/devigned/pub/releases" && exit 1) + +# Get URLs in use by the marketplace offers +URLS="" +for name in ${OFFERS}; do + echo "Getting URLs for ${name}..." + offer=$(pub offers show -p "$PUBLISHER" -o "$name") + # Capture "label" as well as "osVhdUrl" so we can archive storage accounts with something readable. + urls=$(echo "${offer}" | jq -r '.definition["plans"][]."microsoft-azure-corevm.vmImagesPublicAzure"[] | [.label, .osVhdUrl] | @csv') + if [[ -z $URLS ]]; then + URLS=${urls} + else + URLS=${URLS}$'\n'${urls} + fi +done +NOW=$(date +%s) + +# ensure the existence of the archive storage account +if ! az storage account show -g "${RESOURCE_GROUP}" -n "${ARCHIVE_STORAGE_ACCOUNT}" &> /dev/null; then + echo "Creating archive storage account ${ARCHIVE_STORAGE_ACCOUNT}..." + $ECHO az storage account create -g "${RESOURCE_GROUP}" -n "${ARCHIVE_STORAGE_ACCOUNT}" --access-tier Cool --allow-blob-public-access false +fi + +IFS=$'\n' +archived=0 +deleted=0 +# For each storage account in the subscription, +for account in $(az storage account list -g "${RESOURCE_GROUP}" -o tsv --query "[?starts_with(name, '${PREFIX}')].[name,creationTime]"); do + IFS=$'\t' read -r storage_account creation_time <<< "$account" + created=$(date -d "${creation_time}" +%s 2>/dev/null || date -j -f "%F" "${creation_time}" +%s 2>/dev/null) + age=$(( (NOW - created) / 86400 )) + # if it's older than a month + if [[ $age -gt 30 ]]; then + # and it has the right naming pattern + if [[ ${storage_account} =~ ^${LONG_PREFIX} ]]; then + # but isn't referenced in the offer osVhdUrls + if [[ ! ${URLS} =~ ${storage_account} ]]; then + # delete it. + echo "Deleting unreferenced storage account ${storage_account} that is ${age} days old" + ${ECHO} az storage account delete -g "${RESOURCE_GROUP}" -n "${storage_account}" -y + deleted=$((deleted+1)) + else + # archive it. + for URL in ${URLS}; do + IFS=$',' read -r label url <<< "${URL}" + # container names are somewhat strict, so transform the label into a valid container name + # See https://github.com/MicrosoftDocs/azure-docs/blob/master/includes/storage-container-naming-rules-include.md + dest_label=${label//[ .]/-} + dest_label=${dest_label//[^a-zA-Z0-9-]/} + dest_label=$(echo "${dest_label}" | tr '[:upper:]' '[:lower:]') + if [[ ${url} =~ ${storage_account} ]]; then + echo "Archiving storage account ${storage_account} (${label}) that is ${age} days old" + # create a destination container + if [[ $(az storage container exists --account-name "${ARCHIVE_STORAGE_ACCOUNT}" -n "${dest_label}" -o tsv 2>/dev/null) != "True" ]]; then + ${ECHO} az storage container create --only-show-errors --public-access=container \ + -n ${dest_label} -g "${RESOURCE_GROUP}" --account-name "${ARCHIVE_STORAGE_ACCOUNT}" 2>/dev/null + fi + # for each source container + for container in $(az storage container list --only-show-errors --account-name ${storage_account} --query "[].name" -o tsv 2>/dev/null); do + # copy it to the destination container + ${ECHO} az storage blob copy start-batch \ + --account-name ${ARCHIVE_STORAGE_ACCOUNT} \ + --destination-container ${dest_label} \ + --destination-path ${container} \ + --source-container ${container} \ + --source-account-name ${storage_account} \ + --pattern '*capi-*' \ + 2>/dev/null + done + # poll the target container until all blobs have "succeeded" copy status + for target in $(az storage blob list --account-name ${ARCHIVE_STORAGE_ACCOUNT} -c ${dest_label} --query '[].name' -o tsv 2>/dev/null); do + while true; do + status=$(az storage blob show --account-name ${ARCHIVE_STORAGE_ACCOUNT} --container-name ${dest_label} --name $target -o tsv --query 'properties.copy.status' 2>/dev/null) + if [[ ${status} == "success" ]]; then + echo "Copied ${dest_label}/${target}" + break + else + echo "Copying ${dest_label}/${target} ..." + sleep 20 + fi + done + done + echo "Deleting source storage account ${storage_account}..." + ${ECHO} az storage account delete -g "${RESOURCE_GROUP}" -n "${storage_account}" -y + archived=$((archived+1)) + fi + done + echo -e "Pausing for 10 seconds. ${RED}Hit Ctrl-C to stop.${NC}" + sleep 10 + echo + fi + fi + fi +done + +echo "Deleted ${deleted} storage accounts." +echo "Archived ${archived} storage accounts." diff --git a/packer/azure/scripts/disable-windows-prepull.json b/packer/azure/scripts/disable-windows-prepull.json new file mode 100644 index 0000000..ab76d7a --- /dev/null +++ b/packer/azure/scripts/disable-windows-prepull.json @@ -0,0 +1,3 @@ +{ + "prepull": "false" +} diff --git a/packer/azure/scripts/ensure-kustomize.sh b/packer/azure/scripts/ensure-kustomize.sh new file mode 100755 index 0000000..e1c8404 --- /dev/null +++ b/packer/azure/scripts/ensure-kustomize.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +# Copyright 2022 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +# Change directories to the parent directory of the one in which this +# script is located. +CAPI_ROOT=$(dirname "${BASH_SOURCE[0]}")/../../.. +cd "${CAPI_ROOT}" || exit 1 + +source hack/utils.sh + +if command -v kustomize >/dev/null 2>&1; then exit 0; fi + +mkdir -p .local/bin && cd .local/bin + +KUSTOMIZE_VERSION=4.5.2 +_binfile="kustomize-v${KUSTOMIZE_VERSION}.tar.gz" + +echo "installing kustomize" +curl -sLo "${_binfile}" "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv${KUSTOMIZE_VERSION}/kustomize_v${KUSTOMIZE_VERSION}_${HOSTOS}_${HOSTARCH}.tar.gz" +tar -zvxf "${_binfile}" -C "./" +chmod +x "./kustomize" +rm "${_binfile}" +echo "'kustomize' has been installed to $(pwd), make sure this directory is in your \$PATH" diff --git a/packer/azure/scripts/init-sig.sh b/packer/azure/scripts/init-sig.sh new file mode 100755 index 0000000..087c44f --- /dev/null +++ b/packer/azure/scripts/init-sig.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +tracestate="$(shopt -po xtrace)" +set +o xtrace +az login --service-principal -u ${AZURE_CLIENT_ID} -p ${AZURE_CLIENT_SECRET} --tenant ${AZURE_TENANT_ID} >/dev/null 2>&1 +az account set -s ${AZURE_SUBSCRIPTION_ID} >/dev/null 2>&1 +eval "$tracestate" + +export RESOURCE_GROUP_NAME="${RESOURCE_GROUP_NAME:-cluster-api-images}" +export AZURE_LOCATION="${AZURE_LOCATION:-southcentralus}" +if ! az group show -n ${RESOURCE_GROUP_NAME} -o none 2>/dev/null; then + az group create -n ${RESOURCE_GROUP_NAME} -l ${AZURE_LOCATION} --tags ${TAGS:-} +fi +CREATE_TIME="$(date +%s)" +RANDOM_SUFFIX="$(head /dev/urandom | LC_ALL=C tr -dc a-z | head -c 4 ; echo '')" +export GALLERY_NAME="${GALLERY_NAME:-ClusterAPI${CREATE_TIME}${RANDOM_SUFFIX}}" + +# Hack to set only build_resource_group_name or location, a better solution is welcome +# https://developer.hashicorp.com/packer/plugins/builders/azure/arm#build_resource_group_name +PACKER_FILE_PATH=packer/azure/ +TMP_PACKER_FILE=$PACKER_FILE_PATH"packer.json.tmp" +PACKER_FILE=$PACKER_FILE_PATH"packer.json" +if [ ${BUILD_RESOURCE_GROUP_NAME} ]; then + if ! az group show -n ${BUILD_RESOURCE_GROUP_NAME} -o none 2>/dev/null; then + az group create -n ${BUILD_RESOURCE_GROUP_NAME} -l ${AZURE_LOCATION} --tags ${TAGS:-} + fi + jq '(.builders | map(if .name | contains("sig") then del(.location) + {"build_resource_group_name": "{{user `build_resource_group_name`}}"} else . end)) as $updated | .builders = $updated' $PACKER_FILE > $TMP_PACKER_FILE + mv $TMP_PACKER_FILE $PACKER_FILE +fi + +packer validate -syntax-only $PACKER_FILE || exit 1 + +az sig create --resource-group ${RESOURCE_GROUP_NAME} --gallery-name ${GALLERY_NAME} + +create_image_definition() { + az sig image-definition create \ + --resource-group ${RESOURCE_GROUP_NAME} \ + --gallery-name ${GALLERY_NAME} \ + --gallery-image-definition capi-${1} \ + --publisher capz \ + --offer capz-demo \ + --sku ${2} \ + --hyper-v-generation ${3} \ + --os-type ${4} +} + +SIG_TARGET=$1 + +case ${SIG_TARGET} in + ubuntu-1804) + create_image_definition ${SIG_TARGET} "18.04-LTS" "V1" "Linux" + ;; + ubuntu-2004) + create_image_definition ${SIG_TARGET} "20_04-lts" "V1" "Linux" + ;; + ubuntu-2204) + create_image_definition ${SIG_TARGET} "22_04-lts" "V1" "Linux" + ;; + centos-7) + create_image_definition "centos-7" "centos-7" "V1" "Linux" + ;; + rhel-8) + create_image_definition "rhel-8" "rhel-8" "V1" "Linux" + ;; + windows-2019) + create_image_definition "windows-2019-docker-ee" "win-2019-docker-ee" "V1" "Windows" + ;; + windows-2019-containerd) + create_image_definition ${SIG_TARGET} "win-2019-containerd" "V1" "Windows" + ;; + windows-2022-containerd) + create_image_definition ${SIG_TARGET} "win-2022-containerd" "V1" "Windows" + ;; + flatcar) + SKU="flatcar-${FLATCAR_CHANNEL}-${FLATCAR_VERSION}" + create_image_definition ${SKU} ${SKU} "V1" "Linux" + ;; + ubuntu-1804-gen2) + create_image_definition ${SIG_TARGET} "18.04-lts-gen2" "V2" "Linux" + ;; + ubuntu-2004-gen2) + create_image_definition ${SIG_TARGET} "20_04-lts-gen2" "V2" "Linux" + ;; + ubuntu-2204-gen2) + create_image_definition ${SIG_TARGET} "22_04-lts-gen2" "V2" "Linux" + ;; + centos-7-gen2) + create_image_definition "centos-7-gen2" "centos-7-gen2" "V2" "Linux" + ;; + flatcar-gen2) + SKU="flatcar-${FLATCAR_CHANNEL}-${FLATCAR_VERSION}-gen2" + create_image_definition "${SKU}" "${SKU}" "V2" "Linux" + ;; + *) + >&2 echo "Unsupported SIG target: '${SIG_TARGET}'" + exit 1 + ;; +esac diff --git a/packer/azure/scripts/init-vhd.sh b/packer/azure/scripts/init-vhd.sh new file mode 100755 index 0000000..e963f9e --- /dev/null +++ b/packer/azure/scripts/init-vhd.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +echo "Sign into Azure" +tracestate="$(shopt -po xtrace)" +set +o xtrace +az login --service-principal -u ${AZURE_CLIENT_ID} -p ${AZURE_CLIENT_SECRET} --tenant ${AZURE_TENANT_ID} >/dev/null 2>&1 +az account set -s ${AZURE_SUBSCRIPTION_ID} >/dev/null 2>&1 +eval "$tracestate" + +echo "Create storage account" +export RESOURCE_GROUP_NAME="${RESOURCE_GROUP_NAME:-cluster-api-images}" +export AZURE_LOCATION="${AZURE_LOCATION:-southcentralus}" +if ! az group show -n ${RESOURCE_GROUP_NAME} -o none 2>/dev/null; then + az group create -n ${RESOURCE_GROUP_NAME} -l ${AZURE_LOCATION} --tags ${TAGS:-} +fi +CREATE_TIME="$(date +%s)" +RANDOM_SUFFIX="$(head /dev/urandom | LC_ALL=C tr -dc a-z | head -c 4 ; echo '')" +get_random_region() { + local REGIONS=("canadacentral" "eastus" "eastus2" "northeurope" "uksouth" "westeurope" "westus2" "westus3") + echo "${REGIONS[${RANDOM} % ${#REGIONS[@]}]}" +} +RANDOMIZE_STORAGE_ACCOUNT="${RANDOMIZE_STORAGE_ACCOUNT:-"false"}" +if [ "$RANDOMIZE_STORAGE_ACCOUNT" == "true" ]; then + export AZURE_LOCATION="$(get_random_region)" +fi +export STORAGE_ACCOUNT_NAME="${STORAGE_ACCOUNT_NAME:-capi${CREATE_TIME}${RANDOM_SUFFIX}}" +az storage account check-name --name ${STORAGE_ACCOUNT_NAME} +az storage account create -n ${STORAGE_ACCOUNT_NAME} -g ${RESOURCE_GROUP_NAME} -l ${AZURE_LOCATION} --allow-blob-public-access false + +echo "done" diff --git a/packer/azure/scripts/new-disk-version.sh b/packer/azure/scripts/new-disk-version.sh new file mode 100755 index 0000000..d3f1e8c --- /dev/null +++ b/packer/azure/scripts/new-disk-version.sh @@ -0,0 +1,107 @@ +#!/bin/bash -e + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +echo "PWD: $PWD" + +OS=${OS:-"Ubuntu"} +OS_VERSION=${OS_VERSION:-"18.04"} +PUB_VERSION=${PUB_VERSION:-"v0.3.3"} + +required_env_vars=( + "AZURE_CLIENT_ID" + "AZURE_CLIENT_SECRET" + "AZURE_TENANT_ID" + "OS" + "OS_VERSION" + "PUB_VERSION" +) + +for v in "${required_env_vars[@]}" +do + if [ -z "${!v}" ]; then + echo "$v was not set!" + exit 1 + fi +done + +SKU_INFO="sku/sku-publishing-info.json" +VHD_INFO="vhd/vhd-publishing-info.json" + +required_files=( + "SKU_INFO" + "VHD_INFO" +) + +for f in "${required_files[@]}" +do + if [ ! -f "${!f}" ]; then + echo "could not find file: ${!f}" + exit 1 + fi +done + +echo "Getting pub..." +(set -x ; curl -fsSL https://github.com/devigned/pub/releases/download/${PUB_VERSION}/pub_${PUB_VERSION}_linux_amd64.tar.gz -o pub; tar -xzf pub) + +echo "SKU publishing info:" +cat $SKU_INFO +echo + +echo "VHD publishing info:" +cat $VHD_INFO +echo + + +# get Kubernetes version and split into major, minor, and patch +k8s_version=$(< $SKU_INFO jq -r ".k8s_version") +IFS='.' # set period (.) as delimiter +read -ra ADDR <<< "${k8s_version}" # str is read into an array as tokens separated by IFS +IFS=' ' # reset to default value after usage +major=${ADDR[0]} +minor=${ADDR[1]} +patch=${ADDR[2]} + +# generate image version +image_version=${major}${minor}.${patch}.$(date +"%Y%m%d") + +# generate media name +sku_id=$(< $SKU_INFO jq -r ".sku_id") +media_name="${sku_id}-${image_version}" + +# generate published date +published_date=$(date +"%m/%d/%Y") + +# get vhd url +vhd_url=$(< $VHD_INFO jq -r ".vhd_url") + +label="Kubernetes $k8s_version $OS $OS_VERSION" +description="Kubernetes $k8s_version $OS $OS_VERSION" + +# create version.json +cat < version.json +{ + "$image_version" : { + "mediaName": "$media_name", + "showInGui": false, + "publishedDate": "$published_date", + "label": "$label", + "description": "$description", + "osVHdUrl": "$vhd_url" + } +} +EOF + +echo "Version info:" +cat version.json + +publisher=$(< $SKU_INFO jq -r ".publisher") +offer=$(< $SKU_INFO jq -r ".offer") +sku=$(< $SKU_INFO jq -r ".sku_id") + +# TODO: Update pub versions put to take in version.json as a file +echo "Create new disk version" +set -x +./pub_linux_amd64 versions put corevm -p $publisher -o $offer -s $sku --version $image_version --vhd-uri $vhd_url --media-name $media_name --label "$label" --desc "$description" --published-date "$published_date" +set +x +echo -e "\nCreated disk version" diff --git a/packer/azure/scripts/new-sku.sh b/packer/azure/scripts/new-sku.sh new file mode 100755 index 0000000..9b9a13f --- /dev/null +++ b/packer/azure/scripts/new-sku.sh @@ -0,0 +1,80 @@ +#!/bin/bash -e + +OS=${OS:-"Ubuntu"} +OS_VERSION=${OS_VERSION:-"18.04"} +PUB_VERSION=${PUB_VERSION:-"v0.3.3"} +VM_GENERATION=${VM_GENERATION:-"gen1"} +[[ -n ${DEBUG:-} ]] && set -o xtrace + +required_env_vars=( + "AZURE_CLIENT_ID" + "AZURE_CLIENT_SECRET" + "AZURE_TENANT_ID" + "KUBERNETES_VERSION" + "OFFER" + "OS" + "OS_VERSION" + "PUB_VERSION" + "PUBLISHER" + "SKU_TEMPLATE_FILE" + "VM_GENERATION" +) + +for v in "${required_env_vars[@]}" +do + if [ -z "${!v}" ]; then + echo "$v was not set!" + exit 1 + fi +done + +if [ ! -f "$SKU_TEMPLATE_FILE" ]; then + echo "Could not find sku template file: ${SKU_TEMPLATE_FILE}!" + exit 1 +fi + +os=$(echo "$OS" | tr '[:upper:]' '[:lower:]') +version=$(echo "$OS_VERSION" | tr '[:upper:]' '[:lower:]' | tr -d .) +sku_id="${os}-${version}-${VM_GENERATION}" + +if [ "$OS" == "Ubuntu" ]; then + os_type="Ubuntu" + os_family="Linux" +elif [ "$OS" == "Windows" ]; then + os_type="Other" + os_family="Windows" +else + echo "Cannot configure unknown OS: ${OS}!" + exit 1 +fi + +< $SKU_TEMPLATE_FILE sed s/{{ID}}/"$sku_id"/ \ + | sed s/{{KUBERNETES_VERSION}}/"$KUBERNETES_VERSION/" \ + | sed s/{{OS}}/"$OS/" \ + | sed s/{{OS_VERSION}}/"$OS_VERSION/" \ + | sed s/{{OS_TYPE}}/"$os_type/" \ + | sed s/{{OS_FAMILY}}/"$os_family/" \ + > sku.json +cat sku.json + +echo +echo "Getting pub..." +(set -x ; curl -fsSL https://github.com/devigned/pub/releases/download/${PUB_VERSION}/pub_${PUB_VERSION}_linux_amd64.tar.gz -o pub; tar -xzf pub) + +echo "Creating new SKU" +set -x +./pub_linux_amd64 skus put -p $PUBLISHER -o "$OFFER" -f sku.json +set +x +echo -e "\nCreated sku" + +echo "Writing publishing info" +cat < sku-publishing-info.json +{ + "publisher" : "$PUBLISHER", + "offer" : "$OFFER", + "sku_id" : "$sku_id", + "k8s_version" : "$KUBERNETES_VERSION" +} +EOF + +cat sku-publishing-info.json diff --git a/packer/azure/scripts/parse-prow-creds.sh b/packer/azure/scripts/parse-prow-creds.sh new file mode 100755 index 0000000..6d2cfab --- /dev/null +++ b/packer/azure/scripts/parse-prow-creds.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# Copyright 2020 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail +set +o xtrace + +parse_cred() { + grep -E -o "\b$1[[:blank:]]*=[[:blank:]]*\"[^[:space:]\"]+\"" | cut -d '"' -f 2 +} + + +# for Prow we use the provided AZURE_CREDENTIALS file. +# the file is expected to be in toml format. +if [[ -n "${AZURE_CREDENTIALS:-}" ]]; then + export AZURE_SUBSCRIPTION_ID="$(cat ${AZURE_CREDENTIALS} | parse_cred SubscriptionID)" + export AZURE_TENANT_ID="$(cat ${AZURE_CREDENTIALS} | parse_cred TenantID)" + export AZURE_CLIENT_ID="$(cat ${AZURE_CREDENTIALS} | parse_cred ClientID)" + export AZURE_CLIENT_SECRET="$(cat ${AZURE_CREDENTIALS} | parse_cred ClientSecret)" +fi diff --git a/packer/azure/scripts/sysprep.ps1 b/packer/azure/scripts/sysprep.ps1 new file mode 100644 index 0000000..a540be4 --- /dev/null +++ b/packer/azure/scripts/sysprep.ps1 @@ -0,0 +1,46 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Modified from https://docs.microsoft.com/en-us/azure/virtual-machines/linux/image-builder-troubleshoot#sysprep-command-windows +# The Windows Azure Guest Agent is required for sysprep: https://www.packer.io/docs/builders/azure/arm#windows +Write-Output '>>> Waiting for GA Service (RdAgent) to start ...' +while ((Get-Service RdAgent).Status -ne 'Running') { Start-Sleep -s 5 } +Write-Output '>>> Waiting for GA Service (WindowsAzureTelemetryService) to start ...' +while ((Get-Service WindowsAzureTelemetryService) -and ((Get-Service WindowsAzureTelemetryService).Status -ne 'Running')) { Start-Sleep -s 5 } +Write-Output '>>> Waiting for GA Service (WindowsAzureGuestAgent) to start ...' +while ((Get-Service WindowsAzureGuestAgent).Status -ne 'Running') { Start-Sleep -s 5 } +Write-Output '>>> Sysprepping VM ...' +if( Test-Path $Env:SystemRoot\system32\Sysprep\unattend.xml ) { + Remove-Item $Env:SystemRoot\system32\Sysprep\unattend.xml -Force +} + +$unattendedXml = "$ENV:ProgramFiles\Cloudbase Solutions\Cloudbase-Init\conf\Unattend.xml" +$FileExists = Test-Path $unattendedXml +If ($FileExists -eq $True) { + # Use the Cloudbase-init provided unattend file during install + Write-Output "Using cloudbase-init unattend file for sysprep: $unattendedXml" + & $Env:SystemRoot\System32\Sysprep\Sysprep.exe /oobe /generalize /mode:vm /quit /quiet /unattend:$unattendedXml +}else { + & $Env:SystemRoot\System32\Sysprep\Sysprep.exe /oobe /generalize /mode:vm /quit /quiet +} + +# Wait for the image to be reset +while($true) { + $imageState = (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\State).ImageState + Write-Output $imageState + if ($imageState -eq 'IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE') { break } + Start-Sleep -s 5 +} + +Write-Output '>>> Sysprep complete ...' diff --git a/packer/azure/scripts/test-templates/linux/kustomization.yaml b/packer/azure/scripts/test-templates/linux/kustomization.yaml new file mode 100644 index 0000000..775b2d0 --- /dev/null +++ b/packer/azure/scripts/test-templates/linux/kustomization.yaml @@ -0,0 +1,7 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - https://github.com/kubernetes-sigs/cluster-api-provider-azure/releases/download/v1.6.0/cluster-template.yaml +patchesStrategicMerge: +- ../patches/azuremachinetemplate-controlplane.yaml +- ../patches/azuremachinetemplate-workload.yaml \ No newline at end of file diff --git a/packer/azure/scripts/test-templates/patches/azuremachinetemplate-controlplane.yaml b/packer/azure/scripts/test-templates/patches/azuremachinetemplate-controlplane.yaml new file mode 100644 index 0000000..53e8216 --- /dev/null +++ b/packer/azure/scripts/test-templates/patches/azuremachinetemplate-controlplane.yaml @@ -0,0 +1,11 @@ +apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 +kind: AzureMachineTemplate +metadata: + name: ${CLUSTER_NAME}-control-plane + namespace: default +spec: + template: + spec: + image: + id: ${MANAGED_IMAGE_ID} +--- \ No newline at end of file diff --git a/packer/azure/scripts/test-templates/patches/azuremachinetemplate-windows.yaml b/packer/azure/scripts/test-templates/patches/azuremachinetemplate-windows.yaml new file mode 100644 index 0000000..2abc884 --- /dev/null +++ b/packer/azure/scripts/test-templates/patches/azuremachinetemplate-windows.yaml @@ -0,0 +1,11 @@ +apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 +kind: AzureMachineTemplate +metadata: + name: ${CLUSTER_NAME}-md-win + namespace: default +spec: + template: + spec: + image: + id: ${MANAGED_IMAGE_ID} +--- \ No newline at end of file diff --git a/packer/azure/scripts/test-templates/patches/azuremachinetemplate-workload.yaml b/packer/azure/scripts/test-templates/patches/azuremachinetemplate-workload.yaml new file mode 100644 index 0000000..1bc33e3 --- /dev/null +++ b/packer/azure/scripts/test-templates/patches/azuremachinetemplate-workload.yaml @@ -0,0 +1,11 @@ +apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 +kind: AzureMachineTemplate +metadata: + name: ${CLUSTER_NAME}-md-0 + namespace: default +spec: + template: + spec: + image: + id: ${MANAGED_IMAGE_ID} +--- \ No newline at end of file diff --git a/packer/azure/scripts/test-templates/patches/kubeadmcontrolplane-windows.yaml b/packer/azure/scripts/test-templates/patches/kubeadmcontrolplane-windows.yaml new file mode 100644 index 0000000..8a040a4 --- /dev/null +++ b/packer/azure/scripts/test-templates/patches/kubeadmcontrolplane-windows.yaml @@ -0,0 +1,8 @@ +apiVersion: controlplane.cluster.x-k8s.io/v1beta1 +kind: KubeadmControlPlane +metadata: + name: ${CLUSTER_NAME}-control-plane + namespace: default +spec: + version: ${KUBERNETES_BOOTSTRAP_VERSION} +--- \ No newline at end of file diff --git a/packer/azure/scripts/test-templates/patches/machinedeployment-windows.yaml b/packer/azure/scripts/test-templates/patches/machinedeployment-windows.yaml new file mode 100644 index 0000000..1c66ce2 --- /dev/null +++ b/packer/azure/scripts/test-templates/patches/machinedeployment-windows.yaml @@ -0,0 +1,8 @@ +apiVersion: cluster.x-k8s.io/v1beta1 +kind: MachineDeployment +metadata: + name: ${CLUSTER_NAME}-md-0 + namespace: default +spec: + replicas: 0 +--- \ No newline at end of file diff --git a/packer/azure/scripts/test-templates/windows/kustomization.yaml b/packer/azure/scripts/test-templates/windows/kustomization.yaml new file mode 100644 index 0000000..f65b590 --- /dev/null +++ b/packer/azure/scripts/test-templates/windows/kustomization.yaml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - https://github.com/kubernetes-sigs/cluster-api-provider-azure/releases/download/v1.6.0/cluster-template-windows.yaml +patchesStrategicMerge: +- ../patches/azuremachinetemplate-windows.yaml +- ../patches/kubeadmcontrolplane-windows.yaml +- ../patches/machinedeployment-windows.yaml \ No newline at end of file diff --git a/packer/azure/sku-template.json b/packer/azure/sku-template.json new file mode 100644 index 0000000..242184a --- /dev/null +++ b/packer/azure/sku-template.json @@ -0,0 +1,41 @@ +{ + "microsoft-azure-corevm.cloudAvailability": [ + "PublicAzure", + "Mooncake", + "Fairfax" + ], + "microsoft-azure-corevm.defaultImageSizeGB": "30", + "microsoft-azure-corevm.deploymentModels": [ + "ARM" + ], + "microsoft-azure-corevm.freeTierEligible": true, + "microsoft-azure-corevm.generation": "1", + "microsoft-azure-corevm.hardened": false, + "microsoft-azure-corevm.hideSKUForSolutionTemplate": true, + "microsoft-azure-corevm.imageType": "VmImage", + "microsoft-azure-corevm.imageVisibility": true, + "microsoft-azure-corevm.isPremiumThirdParty": false, + "microsoft-azure-corevm.largeLogo": "https://capiofferlogos.blob.core.windows.net/logos/large216x216", + "microsoft-azure-corevm.mediumLogo": "https://capiofferlogos.blob.core.windows.net/logos/medium90x90", + "microsoft-azure-corevm.migratedOffer": false, + "microsoft-azure-corevm.operatingSystemFamily": "{{OS_FAMILY}}", + "microsoft-azure-corevm.osType": "{{OS_TYPE}}", + "microsoft-azure-corevm.privacyURL": "https://github.com/cncf/foundation/blob/master/copyright-notices.md", + "microsoft-azure-corevm.skuDescriptionFairfax": "Base Image for building Kubernetes cluster on Azure with Cluster API. This image is not intended for use outside of https://github.com/kubernetes-sigs/cluster-api-provider-azure.", + "microsoft-azure-corevm.skuDescriptionMooncake": "Base Image for building Kubernetes cluster on Azure with Cluster API. This image is not intended for use outside of https://github.com/kubernetes-sigs/cluster-api-provider-azure.", + "microsoft-azure-corevm.skuDescriptionPublicAzure": "Base Image for building Kubernetes cluster on Azure with Cluster API. This image is not intended for use outside of https://github.com/kubernetes-sigs/cluster-api-provider-azure.", + "microsoft-azure-corevm.skuLongSummary": "Cluster API Kubernetes {{OS}} {{OS_VERSION}} Base Image", + "microsoft-azure-corevm.skuSummary": "Cluster API Kubernetes {{OS}} {{OS_VERSION}} Base Image", + "microsoft-azure-corevm.skuTitle": "Kubernetes {{OS}} {{OS_VERSION}}", + "microsoft-azure-corevm.smallLogo": "https://capiofferlogos.blob.core.windows.net/logos/small48x48", + "microsoft-azure-corevm.supportsAADLogin": false, + "microsoft-azure-corevm.supportsBackup": false, + "microsoft-azure-corevm.supportsClientHub": false, + "microsoft-azure-corevm.supportsHub": false, + "microsoft-azure-corevm.supportsHubOnOffSwitch": false, + "microsoft-azure-corevm.supportsSriov": false, + "microsoft-azure-corevm.termsOfUseURL": "https://github.com/cncf/foundation/blob/master/copyright-notices.md", + "microsoft-azure-corevm.vmImagesPublicAzure": {}, + "microsoft-azure-corevm.wideLogo": "https://capiofferlogos.blob.core.windows.net/logos/wide255x115", + "planId": "{{ID}}" +} diff --git a/packer/azure/ubuntu-1804-gen2.json b/packer/azure/ubuntu-1804-gen2.json new file mode 100644 index 0000000..6f4ba3f --- /dev/null +++ b/packer/azure/ubuntu-1804-gen2.json @@ -0,0 +1,9 @@ +{ + "build_name": "ubuntu-1804-gen2", + "distribution": "ubuntu", + "distribution_release": "bionic", + "distribution_version": "1804", + "image_offer": "UbuntuServer", + "image_publisher": "Canonical", + "image_sku": "18_04-lts-gen2" +} diff --git a/packer/azure/ubuntu-1804.json b/packer/azure/ubuntu-1804.json new file mode 100644 index 0000000..92a3e2f --- /dev/null +++ b/packer/azure/ubuntu-1804.json @@ -0,0 +1,9 @@ +{ + "build_name": "ubuntu-1804", + "distribution": "ubuntu", + "distribution_release": "bionic", + "distribution_version": "1804", + "image_offer": "UbuntuServer", + "image_publisher": "Canonical", + "image_sku": "18.04-LTS" +} diff --git a/packer/azure/ubuntu-2004-gen2.json b/packer/azure/ubuntu-2004-gen2.json new file mode 100644 index 0000000..4f79e02 --- /dev/null +++ b/packer/azure/ubuntu-2004-gen2.json @@ -0,0 +1,9 @@ +{ + "build_name": "ubuntu-2004-gen2", + "distribution": "ubuntu", + "distribution_release": "focal", + "distribution_version": "2004", + "image_offer": "0001-com-ubuntu-server-focal", + "image_publisher": "Canonical", + "image_sku": "20_04-lts-gen2" +} diff --git a/packer/azure/ubuntu-2004.json b/packer/azure/ubuntu-2004.json new file mode 100644 index 0000000..00ee76f --- /dev/null +++ b/packer/azure/ubuntu-2004.json @@ -0,0 +1,9 @@ +{ + "build_name": "ubuntu-2004", + "distribution": "ubuntu", + "distribution_release": "focal", + "distribution_version": "2004", + "image_offer": "0001-com-ubuntu-server-focal", + "image_publisher": "Canonical", + "image_sku": "20_04-lts" +} diff --git a/packer/azure/ubuntu-2204-gen2.json b/packer/azure/ubuntu-2204-gen2.json new file mode 100644 index 0000000..78442cb --- /dev/null +++ b/packer/azure/ubuntu-2204-gen2.json @@ -0,0 +1,9 @@ +{ + "build_name": "ubuntu-2204-gen2", + "distribution": "ubuntu", + "distribution_release": "jammy", + "distribution_version": "2204", + "image_offer": "0001-com-ubuntu-server-jammy", + "image_publisher": "Canonical", + "image_sku": "22_04-lts-gen2" +} diff --git a/packer/azure/ubuntu-2204.json b/packer/azure/ubuntu-2204.json new file mode 100644 index 0000000..d32ba3e --- /dev/null +++ b/packer/azure/ubuntu-2204.json @@ -0,0 +1,9 @@ +{ + "build_name": "ubuntu-2204", + "distribution": "ubuntu", + "distribution_release": "jammy", + "distribution_version": "2204", + "image_offer": "0001-com-ubuntu-server-jammy", + "image_publisher": "Canonical", + "image_sku": "22_04-lts" +} diff --git a/packer/azure/windows-2004.json b/packer/azure/windows-2004.json new file mode 100644 index 0000000..039919c --- /dev/null +++ b/packer/azure/windows-2004.json @@ -0,0 +1,10 @@ +{ + "build_name": "windows-2004", + "distribution": "windows", + "distribution_version": "2004", + "image_offer": "WindowsServer", + "image_publisher": "MicrosoftWindowsServer", + "image_sku": "Datacenter-Core-2004-with-Containers-smalldisk", + "vm_size": "Standard_D4s_v3", + "windows_updates_kbs": "" +} diff --git a/packer/azure/windows-2019-containerd.json b/packer/azure/windows-2019-containerd.json new file mode 100644 index 0000000..bd01bc0 --- /dev/null +++ b/packer/azure/windows-2019-containerd.json @@ -0,0 +1,16 @@ +{ + "additional_registry_images": "false", + "additional_registry_images_list": "", + "build_name": "windows-2019-containerd", + "distribution": "windows", + "distribution_version": "2019", + "image_offer": "WindowsServer", + "image_publisher": "MicrosoftWindowsServer", + "image_sku": "2019-Datacenter-Core-smalldisk", + "image_version": "latest", + "load_additional_components": "false", + "runtime": "containerd", + "vm_size": "Standard_D4s_v3", + "windows_updates_kbs": "", + "wins_url": "" +} diff --git a/packer/azure/windows-2019.json b/packer/azure/windows-2019.json new file mode 100644 index 0000000..8b278ed --- /dev/null +++ b/packer/azure/windows-2019.json @@ -0,0 +1,14 @@ +{ + "additional_registry_images": "true", + "additional_registry_images_list": "docker.io/sigwindowstools/flannel:v0.13.0-nanoserver,docker.io/sigwindowstools/kube-proxy:{{user `kubernetes_semver`}}-nanoserver", + "build_name": "windows-2019", + "distribution": "windows", + "distribution_version": "2019", + "image_offer": "WindowsServer", + "image_publisher": "MicrosoftWindowsServer", + "image_sku": "2019-Datacenter-Core-smalldisk", + "image_version": "latest", + "load_additional_components": "true", + "vm_size": "Standard_D4s_v3", + "windows_updates_kbs": "" +} diff --git a/packer/azure/windows-2022-containerd.json b/packer/azure/windows-2022-containerd.json new file mode 100644 index 0000000..7638ad8 --- /dev/null +++ b/packer/azure/windows-2022-containerd.json @@ -0,0 +1,16 @@ +{ + "additional_registry_images": "false", + "additional_registry_images_list": "", + "build_name": "windows-2022-containerd", + "distribution": "windows", + "distribution_version": "2022", + "image_offer": "WindowsServer", + "image_publisher": "MicrosoftWindowsServer", + "image_sku": "2022-Datacenter-Core-smalldisk", + "image_version": "latest", + "load_additional_components": "false", + "runtime": "containerd", + "vm_size": "Standard_D4s_v3", + "windows_updates_kbs": "", + "wins_url": "" +} diff --git a/packer/config/additional_components.json b/packer/config/additional_components.json new file mode 100644 index 0000000..ea94621 --- /dev/null +++ b/packer/config/additional_components.json @@ -0,0 +1,10 @@ +{ + "additional_executables": "false", + "additional_executables_destination_path": "", + "additional_executables_list": "", + "additional_registry_images": "false", + "additional_registry_images_list": "", + "additional_url_images": "false", + "additional_url_images_list": "", + "load_additional_components": "false" +} diff --git a/packer/config/ansible-args.json b/packer/config/ansible-args.json new file mode 100644 index 0000000..b44429a --- /dev/null +++ b/packer/config/ansible-args.json @@ -0,0 +1,5 @@ +{ + "ansible_common_ssh_args": "-o IdentitiesOnly=yes -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedKeyTypes=+ssh-rsa", + "ansible_common_vars": "containerd_url={{user `containerd_url`}} containerd_sha256={{user `containerd_sha256`}} pause_image={{user `pause_image`}} containerd_additional_settings={{user `containerd_additional_settings`}} containerd_cri_socket={{user `containerd_cri_socket`}} containerd_version={{user `containerd_version`}} containerd_wasm_shims_url={{user `containerd_wasm_shims_url`}} containerd_wasm_shims_version={{user `containerd_wasm_shims_version`}} containerd_wasm_shims_sha256={{user `containerd_wasm_shims_sha256`}} containerd_wasm_shims_runtimes=\"{{user `containerd_wasm_shims_runtimes`}}\" crictl_url={{user `crictl_url`}} crictl_sha256={{user `crictl_sha256`}} crictl_source_type={{user `crictl_source_type`}} custom_role_names=\"{{user `custom_role_names`}}\" firstboot_custom_roles_pre=\"{{user `firstboot_custom_roles_pre`}}\" firstboot_custom_roles_post=\"{{user `firstboot_custom_roles_post`}}\" node_custom_roles_pre=\"{{user `node_custom_roles_pre`}}\" node_custom_roles_post=\"{{user `node_custom_roles_post`}}\" disable_public_repos={{user `disable_public_repos`}} extra_debs=\"{{user `extra_debs`}}\" extra_repos=\"{{user `extra_repos`}}\" extra_rpms=\"{{user `extra_rpms`}}\" http_proxy={{user `http_proxy`}} https_proxy={{user `https_proxy`}} kubeadm_template={{user `kubeadm_template`}} kubernetes_cni_http_source={{user `kubernetes_cni_http_source`}} kubernetes_cni_http_checksum={{user `kubernetes_cni_http_checksum`}} kubernetes_http_source={{user `kubernetes_http_source`}} kubernetes_container_registry={{user `kubernetes_container_registry`}} kubernetes_rpm_repo={{user `kubernetes_rpm_repo`}} kubernetes_rpm_gpg_key={{user `kubernetes_rpm_gpg_key`}} kubernetes_rpm_gpg_check={{user `kubernetes_rpm_gpg_check`}} kubernetes_deb_repo={{user `kubernetes_deb_repo`}} kubernetes_deb_gpg_key={{user `kubernetes_deb_gpg_key`}} kubernetes_cni_deb_version={{user `kubernetes_cni_deb_version`}} kubernetes_cni_rpm_version={{user `kubernetes_cni_rpm_version`}} kubernetes_cni_semver={{user `kubernetes_cni_semver`}} kubernetes_cni_source_type={{user `kubernetes_cni_source_type`}} kubernetes_semver={{user `kubernetes_semver`}} kubernetes_source_type={{user `kubernetes_source_type`}} kubernetes_load_additional_imgs={{user `kubernetes_load_additional_imgs`}} kubernetes_deb_version={{user `kubernetes_deb_version`}} kubernetes_rpm_version={{user `kubernetes_rpm_version`}} no_proxy={{user `no_proxy`}} pip_conf_file={{user `pip_conf_file`}} python_path={{user `python_path`}} redhat_epel_rpm={{user `redhat_epel_rpm`}} epel_rpm_gpg_key={{user `epel_rpm_gpg_key`}} reenable_public_repos={{user `reenable_public_repos`}} remove_extra_repos={{user `remove_extra_repos`}} systemd_prefix={{user `systemd_prefix`}} sysusr_prefix={{user `sysusr_prefix`}} sysusrlocal_prefix={{user `sysusrlocal_prefix`}} load_additional_components={{ user `load_additional_components`}} additional_registry_images={{ user `additional_registry_images`}} additional_registry_images_list={{ user `additional_registry_images_list`}} additional_url_images={{ user `additional_url_images`}} additional_url_images_list={{ user `additional_url_images_list`}} additional_executables={{ user `additional_executables`}} additional_executables_list={{ user `additional_executables_list`}} additional_executables_destination_path={{ user `additional_executables_destination_path`}} build_target={{ user `build_target`}} amazon_ssm_agent_rpm={{ user `amazon_ssm_agent_rpm` }}", + "ansible_scp_extra_args": "{{env `ANSIBLE_SCP_EXTRA_ARGS`}}" +} diff --git a/packer/config/cni.json b/packer/config/cni.json new file mode 100644 index 0000000..3ae265f --- /dev/null +++ b/packer/config/cni.json @@ -0,0 +1,9 @@ +{ + "kubernetes_cni_deb_version": "1.2.0-00", + "kubernetes_cni_http_checksum": "sha256:https://storage.googleapis.com/k8s-artifacts-cni/release/v1.2.0/cni-plugins-linux-{{user `kubernetes_cni_http_checksum_arch`}}-v1.2.0.tgz.sha256", + "kubernetes_cni_http_checksum_arch": "amd64", + "kubernetes_cni_http_source": "https://github.com/containernetworking/plugins/releases/download", + "kubernetes_cni_rpm_version": "1.2.0-0", + "kubernetes_cni_semver": "v1.2.0", + "kubernetes_cni_source_type": "pkg" +} diff --git a/packer/config/common.json b/packer/config/common.json new file mode 100644 index 0000000..a8166cc --- /dev/null +++ b/packer/config/common.json @@ -0,0 +1,19 @@ +{ + "build_target": "virt", + "disable_public_repos": "false", + "extra_debs": "", + "extra_repos": "", + "extra_rpms": "", + "firstboot_custom_roles_post": "", + "firstboot_custom_roles_pre": "", + "http_proxy": "", + "https_proxy": "", + "no_proxy": "", + "node_custom_roles_post": "", + "node_custom_roles_pre": "", + "pause_image": "registry.k8s.io/pause:3.9", + "pip_conf_file": "", + "redhat_epel_rpm": "https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm", + "reenable_public_repos": "true", + "remove_extra_repos": "false" +} diff --git a/packer/config/containerd.json b/packer/config/containerd.json new file mode 100644 index 0000000..4703f26 --- /dev/null +++ b/packer/config/containerd.json @@ -0,0 +1,7 @@ +{ + "containerd_additional_settings": null, + "containerd_cri_socket": "/var/run/containerd/containerd.sock", + "containerd_sha256": "152c8479fc0054db63ff0175fea014da227279b8d3dcab5f2f4b4876317ffe26", + "containerd_sha256_windows": "5b723eb58f7678a63928ec6eadc4a837d52a727e264f365a888d1ee97046bc7f", + "containerd_version": "1.6.15" +} diff --git a/packer/config/goss-args.json b/packer/config/goss-args.json new file mode 100644 index 0000000..fe140de --- /dev/null +++ b/packer/config/goss-args.json @@ -0,0 +1,15 @@ +{ + "goss_arch": "amd64", + "goss_download_path": "", + "goss_entry_file": "goss/goss.yaml", + "goss_format": "json", + "goss_format_options": "pretty", + "goss_inspect_mode": "true", + "goss_remote_folder": "", + "goss_remote_path": "", + "goss_skip_install": "false", + "goss_tests_dir": "packer/goss", + "goss_url": "", + "goss_vars_file": "packer/goss/goss-vars.yaml", + "goss_version": "0.3.16" +} diff --git a/packer/config/kubernetes.json b/packer/config/kubernetes.json new file mode 100644 index 0000000..7d0ec58 --- /dev/null +++ b/packer/config/kubernetes.json @@ -0,0 +1,25 @@ +{ + "crictl_arch": "amd64", + "crictl_sha256": "https://github.com/kubernetes-sigs/cri-tools/releases/download/v{{user `crictl_version`}}/crictl-v{{user `crictl_version`}}-linux-{{user `crictl_arch`}}.tar.gz.sha256", + "crictl_source_type": "pkg", + "crictl_url": "https://github.com/kubernetes-sigs/cri-tools/releases/download/v{{user `crictl_version`}}/crictl-v{{user `crictl_version`}}-linux-{{user `crictl_arch`}}.tar.gz", + "crictl_version": "1.26.0", + "kubeadm_template": "etc/kubeadm.yml", + "kubernetes_container_registry": "registry.k8s.io", + "kubernetes_deb_gpg_key": "https://packages.cloud.google.com/apt/doc/apt-key.gpg", + "kubernetes_deb_repo": "\"https://apt.kubernetes.io/ kubernetes-xenial\"", + "kubernetes_deb_version": "1.23.15-00", + "kubernetes_http_source": "https://dl.k8s.io/release", + "kubernetes_load_additional_imgs": "false", + "kubernetes_rpm_gpg_check": "True", + "kubernetes_rpm_gpg_key": "\"https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg\"", + "kubernetes_rpm_repo": "https://packages.cloud.google.com/yum/repos/kubernetes-el7-{{user `kubernetes_rpm_repo_arch`}}", + "kubernetes_rpm_repo_arch": "x86_64", + "kubernetes_rpm_version": "1.23.15-0", + "kubernetes_semver": "v1.23.15", + "kubernetes_series": "v1.23", + "kubernetes_source_type": "pkg", + "systemd_prefix": "/usr/lib/systemd", + "sysusr_prefix": "/usr", + "sysusrlocal_prefix": "/usr/local" +} diff --git a/packer/config/ppc64le/cni.json b/packer/config/ppc64le/cni.json new file mode 100644 index 0000000..7c874dc --- /dev/null +++ b/packer/config/ppc64le/cni.json @@ -0,0 +1,3 @@ +{ + "kubernetes_cni_http_checksum_arch": "ppc64le" +} diff --git a/packer/config/ppc64le/common.json b/packer/config/ppc64le/common.json new file mode 100644 index 0000000..d48a3d3 --- /dev/null +++ b/packer/config/ppc64le/common.json @@ -0,0 +1,3 @@ +{ + "build_target": "raw" +} diff --git a/packer/config/ppc64le/containerd.json b/packer/config/ppc64le/containerd.json new file mode 100644 index 0000000..d5e5f6b --- /dev/null +++ b/packer/config/ppc64le/containerd.json @@ -0,0 +1,5 @@ +{ + "containerd_sha256": "49e46a2b8a1fe8b0406e49d745c955b91360f1d024063e0dbe0d9b9873649631", + "containerd_url": "https://oplab9.parqtec.unicamp.br/pub/ppc64el/containerd-cri/containerd-cri-{{user `containerd_version`}}/cri-containerd-cni-{{user `containerd_version`}}-linux-ppc64le.tar.gz", + "containerd_version": "1.6.2" +} diff --git a/packer/config/ppc64le/kubernetes.json b/packer/config/ppc64le/kubernetes.json new file mode 100644 index 0000000..b1c2c04 --- /dev/null +++ b/packer/config/ppc64le/kubernetes.json @@ -0,0 +1,4 @@ +{ + "crictl_arch": "ppc64le", + "kubernetes_rpm_repo_arch": "ppc64le" +} diff --git a/packer/config/wasm-shims.json b/packer/config/wasm-shims.json new file mode 100644 index 0000000..8a020a6 --- /dev/null +++ b/packer/config/wasm-shims.json @@ -0,0 +1,6 @@ +{ + "containerd_wasm_shims_runtimes": "", + "containerd_wasm_shims_sha256": "da84b1c065a58f95a841d39e143cd7115d43e6faedcce7a8782f2942388260d7", + "containerd_wasm_shims_url": "https://github.com/deislabs/containerd-wasm-shims/releases/download/{{user `containerd_wasm_shims_version`}}/containerd-wasm-shims-v1-linux-x86_64.tar.gz", + "containerd_wasm_shims_version": "v0.3.3" +} diff --git a/packer/config/windows/OWNERS b/packer/config/windows/OWNERS new file mode 100644 index 0000000..d047699 --- /dev/null +++ b/packer/config/windows/OWNERS @@ -0,0 +1,4 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - image-builder-windows-maintainers diff --git a/packer/config/windows/ansible-args-windows.json b/packer/config/windows/ansible-args-windows.json new file mode 100644 index 0000000..1ea4a2a --- /dev/null +++ b/packer/config/windows/ansible-args-windows.json @@ -0,0 +1,3 @@ +{ + "ansible_common_vars": "runtime={{user `runtime`}} docker_ee_version={{user `docker_ee_version`}} containerd_url={{user `containerd_url`}} containerd_sha256={{user `containerd_sha256_windows`}} pause_image={{user `pause_image`}} additional_debug_files=\"{{user `additional_debug_files`}}\" containerd_additional_settings={{user `containerd_additional_settings`}} custom_role_names=\"{{user `custom_role_names`}}\" http_proxy={{user `http_proxy`}} https_proxy={{user `https_proxy`}} no_proxy={{user `no_proxy`}} kubernetes_base_url={{user `kubernetes_base_url`}} kubernetes_semver={{user `kubernetes_semver`}} kubernetes_install_path={{user `kubernetes_install_path`}} cloudbase_init_url=\"{{user `cloudbase_init_url`}}\" cloudbase_plugins=\"{{user `cloudbase_plugins`}}\" cloudbase_metadata_services=\"{{user `cloudbase_metadata_services`}}\" cloudbase_plugins_unattend=\"{{user `cloudbase_plugins_unattend`}}\" cloudbase_metadata_services_unattend=\"{{user `cloudbase_metadata_services_unattend`}}\" prepull={{user `prepull`}} wins_url={{user `wins_url`}} windows_updates_kbs=\"{{user `windows_updates_kbs`}}\" windows_updates_categories=\"{{user `windows_updates_categories`}}\" windows_service_manager={{user `windows_service_manager`}} nssm_url={{user `nssm_url`}} distribution_version={{user `distribution_version`}} netbios_host_name_compatibility={{user `netbios_host_name_compatibility`}} disable_hypervisor={{ user `disable_hypervisor` }} cloudbase_logging_serial_port={{ user `cloudbase_logging_serial_port` }} load_additional_components={{ user `load_additional_components`}} additional_registry_images={{ user `additional_registry_images`}} additional_registry_images_list={{ user `additional_registry_images_list`}} additional_url_images={{ user `additional_url_images`}} additional_url_images_list={{ user `additional_url_images_list`}} additional_executables={{ user `additional_executables`}} additional_executables_list={{ user `additional_executables_list`}} additional_executables_destination_path={{ user `additional_executables_destination_path`}} ssh_source_url={{user `ssh_source_url` }} debug_tools={{user `debug_tools`}}" +} diff --git a/packer/config/windows/cloudbase-init.json b/packer/config/windows/cloudbase-init.json new file mode 100644 index 0000000..bb3ac70 --- /dev/null +++ b/packer/config/windows/cloudbase-init.json @@ -0,0 +1,3 @@ +{ + "cloudbase_init_version": "1.1.2" +} diff --git a/packer/config/windows/common.json b/packer/config/windows/common.json new file mode 100644 index 0000000..fa985b2 --- /dev/null +++ b/packer/config/windows/common.json @@ -0,0 +1,17 @@ +{ + "additional_debug_files": "", + "debug_tools": "true", + "disable_hypervisor": "false", + "http_proxy": "", + "https_proxy": "", + "netbios_host_name_compatibility": "true", + "no_proxy": "", + "nssm_url": "https://upstreamartifacts.azureedge.net/nssm/nssm.exe", + "prepull": "true", + "runtime": "docker-ee", + "ssh_source_url": "", + "windows_service_manager": "nssm", + "windows_updates_categories": "", + "windows_updates_kbs": "", + "wins_version": "0.0.4" +} diff --git a/packer/config/windows/containerd.json b/packer/config/windows/containerd.json new file mode 100644 index 0000000..ad43316 --- /dev/null +++ b/packer/config/windows/containerd.json @@ -0,0 +1,4 @@ +{ + "containerd_additional_settings": null, + "containerd_url": "https://github.com/containerd/containerd/releases/download/v{{user `containerd_version`}}/containerd-{{user `containerd_version`}}-windows-amd64.tar.gz" +} diff --git a/packer/config/windows/docker.json b/packer/config/windows/docker.json new file mode 100644 index 0000000..194f84b --- /dev/null +++ b/packer/config/windows/docker.json @@ -0,0 +1,3 @@ +{ + "docker_ee_version": "19.03.12" +} diff --git a/packer/config/windows/kubernetes.json b/packer/config/windows/kubernetes.json new file mode 100644 index 0000000..738e669 --- /dev/null +++ b/packer/config/windows/kubernetes.json @@ -0,0 +1,4 @@ +{ + "kubernetes_goarch": "amd64", + "kubernetes_install_path": "c:\\k" +} diff --git a/packer/digitalocean/OWNERS b/packer/digitalocean/OWNERS new file mode 100644 index 0000000..f1f027f --- /dev/null +++ b/packer/digitalocean/OWNERS @@ -0,0 +1,6 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - cluster-api-digitalocean-maintainers +reviewers: + - cluster-api-digitalocean-maintainers diff --git a/packer/digitalocean/centos-7.json b/packer/digitalocean/centos-7.json new file mode 100644 index 0000000..7df49b1 --- /dev/null +++ b/packer/digitalocean/centos-7.json @@ -0,0 +1,5 @@ +{ + "build_name": "centos-7", + "snapshot_name_suffix": "on CentOS 7", + "source_image": "centos-7-x64" +} diff --git a/packer/digitalocean/packer.json b/packer/digitalocean/packer.json new file mode 100644 index 0000000..4306921 --- /dev/null +++ b/packer/digitalocean/packer.json @@ -0,0 +1,95 @@ +{ + "builders": [ + { + "api_token": "{{ user `access_token` }}", + "image": "{{ user `source_image` }}", + "name": "{{user `build_name`}}", + "region": "{{ user `region` }}", + "size": "{{ user `size` }}", + "snapshot_name": "Cluster API Kubernetes {{ user `kubernetes_semver` }} {{ user `snapshot_name_suffix` }}", + "snapshot_regions": [ + "nyc1" + ], + "ssh_username": "root", + "tags": [ + "cluster-api-{{ user `build_name` }}:{{ user `kubernetes_semver` | replace_all `.` `-` }}" + ], + "type": "digitalocean" + } + ], + "provisioners": [ + { + "environment_vars": [ + "BUILD_NAME={{user `build_name`}}" + ], + "inline": [ + "if [ $BUILD_NAME != \"ubuntu-1804\" ]; then exit 0; fi", + "while [ ! -f /var/lib/cloud/instance/boot-finished ]; do echo 'Waiting for cloud-init...'; sleep 1; done", + "sudo apt-get -qq update && sudo DEBIAN_FRONTEND=noninteractive apt-get -qqy install python python-pip" + ], + "type": "shell" + }, + { + "environment_vars": [ + "BUILD_NAME={{user `build_name`}}" + ], + "inline": [ + "if [ $BUILD_NAME != \"ubuntu-2004\" ]; then exit 0; fi", + "while [ ! -f /var/lib/cloud/instance/boot-finished ]; do echo 'Waiting for cloud-init...'; sleep 1; done", + "sudo apt-get -qq update" + ], + "type": "shell" + }, + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} {{user `ansible_common_ssh_args`}}'" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}", + "--scp-extra-args", + "{{user `ansible_scp_extra_args`}}" + ], + "playbook_file": "./ansible/node.yml", + "type": "ansible", + "user": "packer" + } + ], + "variables": { + "access_token": "{{env `DIGITALOCEAN_ACCESS_TOKEN`}}", + "ansible_common_vars": "", + "ansible_extra_vars": "", + "ansible_scp_extra_args": "", + "build_timestamp": "{{timestamp}}", + "containerd_sha256": null, + "containerd_url": "https://github.com/containerd/containerd/releases/download/v{{user `containerd_version`}}/cri-containerd-cni-{{user `containerd_version`}}-linux-amd64.tar.gz", + "containerd_version": null, + "crictl_url": "https://github.com/kubernetes-sigs/cri-tools/releases/download/v{{user `crictl_version`}}/crictl-v{{user `crictl_version`}}-linux-amd64.tar.gz", + "crictl_version": null, + "existing_ansible_ssh_args": "{{env `ANSIBLE_SSH_ARGS`}}", + "kubernetes_cni_deb_version": null, + "kubernetes_cni_http_source": null, + "kubernetes_cni_rpm_version": null, + "kubernetes_cni_semver": null, + "kubernetes_cni_source_type": null, + "kubernetes_container_registry": null, + "kubernetes_deb_gpg_key": null, + "kubernetes_deb_repo": null, + "kubernetes_deb_version": null, + "kubernetes_http_source": null, + "kubernetes_load_additional_imgs": null, + "kubernetes_rpm_gpg_check": null, + "kubernetes_rpm_gpg_key": null, + "kubernetes_rpm_repo": null, + "kubernetes_rpm_version": null, + "kubernetes_semver": null, + "kubernetes_series": null, + "kubernetes_source_type": null, + "region": "nyc1", + "size": "s-1vcpu-1gb" + } +} diff --git a/packer/digitalocean/ubuntu-1804.json b/packer/digitalocean/ubuntu-1804.json new file mode 100644 index 0000000..0b01b1d --- /dev/null +++ b/packer/digitalocean/ubuntu-1804.json @@ -0,0 +1,5 @@ +{ + "build_name": "ubuntu-1804", + "snapshot_name_suffix": "on Ubuntu 18.04", + "source_image": "ubuntu-18-04-x64" +} diff --git a/packer/digitalocean/ubuntu-2004.json b/packer/digitalocean/ubuntu-2004.json new file mode 100644 index 0000000..48060cd --- /dev/null +++ b/packer/digitalocean/ubuntu-2004.json @@ -0,0 +1,5 @@ +{ + "build_name": "ubuntu-2004", + "snapshot_name_suffix": "on Ubuntu 20.04", + "source_image": "ubuntu-20-04-x64" +} diff --git a/packer/files/flatcar/README.md b/packer/files/flatcar/README.md new file mode 100644 index 0000000..910fc25 --- /dev/null +++ b/packer/files/flatcar/README.md @@ -0,0 +1,42 @@ +# Flatcar-Related Build Files + +This directory contains files needed for building Flatcar Container Linux CAPI images. + +The following subdirectories exist: + +- `clc` - contains [Container Linux Config][1] files. +- `ignition` - contains [Ignition][2] files generated from the CLC files in the `clc` directory. +- `scripts` - contains scripts which are used by the various Flatcar builds. + +## Ignition Files + +Some Flatcar builds (e.g. QEMU) require Ignition files during OS installation. These files can be +consumed directly from the `ignition` directory. Ignition files are generated from CLC files by the +[Container Linux Config Transpiler][3]. + +### Adding New Files + +To add a new Ignition file, do the following: + +1. Place a CLC YAML file with the desired config in `clc`. +1. Add the name of the file without an extension to the `ignition_files` variable under the + `gen-ignition` target in the [Makefile](../../../Makefile). For example, for a CLC file named + `foo.yaml`, add `foo` to the Make target. +1. Run `make gen-ignition` under `images/capi`. A new Ignition file is generated under `ignition`. +1. Commit both the CLC file and the resulting Ignition file and open a PR to merge the changes. + +Once the changes are merged, the new Ignition file can be referenced in Flatcar builds and consumed +as a raw file directly from GitHub. + +### Changing Existing Files + +To change an existing Ignition file, do the following: + +1. Edit the relevant CLC YAML file in `clc`. +1. Run `make gen-ignition` under `images/capi`. The corresponding Ignition file is updated under + `ignition`. +1. Commit the changes and open a PR to merge them. + +[1]: https://flatcar.org/docs/latest/provisioning/cl-config/ +[2]: https://flatcar.org/docs/latest/provisioning/ignition/ +[3]: https://flatcar.org/docs/latest/provisioning/config-transpiler/ diff --git a/packer/files/flatcar/clc/bootstrap.yaml b/packer/files/flatcar/clc/bootstrap.yaml new file mode 100644 index 0000000..9727034 --- /dev/null +++ b/packer/files/flatcar/clc/bootstrap.yaml @@ -0,0 +1,26 @@ +# This file is used for initial provisioning of a Flatcar machine, before Packer provisioners (e.g. +# Ansible) are executed. +passwd: + users: + - name: builder + # "BUILDERPASSWORDHASH" gets overwritten by Packer on platforms where SSH password auth is used. + password_hash: BUILDERPASSWORDHASH + # "BUILDERSSHAUTHKEY" gets overwritten by Packer on platforms where SSH key auth is used. + # TODO: Once https://github.com/kubernetes-sigs/image-builder/pull/882 is merged we can remove + # the ssh_authorized_keys key altogether since the QEMU and raw targets would be using password + # auth and the rest of the targets have provider-specific authorization mechanisms, meaning SSH + # keys don't have to be specified in this CLC file. + ssh_authorized_keys: ["BUILDERSSHAUTHKEY"] + groups: + - wheel + - sudo + - docker +systemd: + units: + - name: docker.service + enable: true + # Mask update-engine and locksmithd to disable automatic updates during image creation. + - name: update-engine.service + mask: true + - name: locksmithd.service + mask: true diff --git a/packer/files/flatcar/ignition/bootstrap.json b/packer/files/flatcar/ignition/bootstrap.json new file mode 100644 index 0000000..bb2a848 --- /dev/null +++ b/packer/files/flatcar/ignition/bootstrap.json @@ -0,0 +1,44 @@ +{ + "ignition": { + "config": {}, + "security": { + "tls": {} + }, + "timeouts": {}, + "version": "2.3.0" + }, + "networkd": {}, + "passwd": { + "users": [ + { + "groups": [ + "wheel", + "sudo", + "docker" + ], + "name": "builder", + "passwordHash": "BUILDERPASSWORDHASH", + "sshAuthorizedKeys": [ + "BUILDERSSHAUTHKEY" + ] + } + ] + }, + "storage": {}, + "systemd": { + "units": [ + { + "enable": true, + "name": "docker.service" + }, + { + "mask": true, + "name": "update-engine.service" + }, + { + "mask": true, + "name": "locksmithd.service" + } + ] + } +} diff --git a/packer/files/flatcar/scripts/bootstrap-flatcar.sh b/packer/files/flatcar/scripts/bootstrap-flatcar.sh new file mode 100644 index 0000000..402cfd3 --- /dev/null +++ b/packer/files/flatcar/scripts/bootstrap-flatcar.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# +# This script installs PyPy as a Python interpreter on a Flatcar instance. + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +BINDIR="/opt/bin" +BUILDER_ENV="/opt/bin/builder-env" + +set -x + +mkdir -p ${BINDIR} + +cd ${BINDIR} + +if [[ -e ${BINDIR}/.bootstrapped ]]; then + exit 0 +fi + +PYPY_VERSION=7.2.0 +PYTHON3_VERSION=3.6 + +curl -sfL https://github.com/squeaky-pl/portable-pypy/releases/download/pypy-${PYPY_VERSION}/pypy-${PYPY_VERSION}-linux_x86_64-portable.tar.bz2 | tar -xjf - +mv -n pypy-${PYPY_VERSION}-linux_x86_64-portable pypy2 +ln -s ./pypy2/bin/pypy python2 +ln -s ./pypy2/bin/pypy python + +curl -sfL https://github.com/squeaky-pl/portable-pypy/releases/download/pypy${PYTHON3_VERSION}-${PYPY_VERSION}/pypy${PYTHON3_VERSION}-${PYPY_VERSION}-linux_x86_64-portable.tar.bz2 | tar -xjf - +mv -n pypy${PYTHON3_VERSION}-${PYPY_VERSION}-linux_x86_64-portable pypy3 +ln -s ./pypy3/bin/pypy3 python3 + +${BINDIR}/python --version + +${BINDIR}/pypy2/bin/virtualenv-pypy ${BUILDER_ENV} +chown -R core ${BUILDER_ENV} + +ln -s builder-env/bin/pip ${BINDIR}/pip +# need to have symlink pip3 required by ansible/roles/providers/tasks/aws.yml +ln -s builder-env/bin/pip ${BINDIR}/pip3 + +touch ${BINDIR}/.bootstrapped diff --git a/packer/gce/OWNERS b/packer/gce/OWNERS new file mode 100644 index 0000000..3ac3383 --- /dev/null +++ b/packer/gce/OWNERS @@ -0,0 +1,4 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - cluster-api-gcp-maintainers diff --git a/packer/gce/ci/nightly/README.md b/packer/gce/ci/nightly/README.md new file mode 100644 index 0000000..03a82fe --- /dev/null +++ b/packer/gce/ci/nightly/README.md @@ -0,0 +1,5 @@ +## Configs for nightly builds + +The configurations in the directory is being used for the nightly job to build the images for GCE. + +The script that runs is [ci-gce-nightly.sh](../../../../scripts/ci-gce-nightly.sh) diff --git a/packer/gce/ci/nightly/overwrite-1-23.json b/packer/gce/ci/nightly/overwrite-1-23.json new file mode 100644 index 0000000..7a04e6d --- /dev/null +++ b/packer/gce/ci/nightly/overwrite-1-23.json @@ -0,0 +1,8 @@ +{ + "build_timestamp": "nightly", + "kubernetes_deb_version": "1.23.15-00", + "kubernetes_rpm_version": "1.23.15-0", + "kubernetes_semver": "v1.23.15", + "kubernetes_series": "v1.23", + "service_account_email": "gcb-builder-cluster-api-gcp@k8s-staging-cluster-api-gcp.iam.gserviceaccount.com" +} diff --git a/packer/gce/ci/nightly/overwrite-1-24.json b/packer/gce/ci/nightly/overwrite-1-24.json new file mode 100644 index 0000000..13d9de7 --- /dev/null +++ b/packer/gce/ci/nightly/overwrite-1-24.json @@ -0,0 +1,8 @@ +{ + "build_timestamp": "nightly", + "kubernetes_deb_version": "1.24.9-00", + "kubernetes_rpm_version": "1.24.9-0", + "kubernetes_semver": "v1.24.9", + "kubernetes_series": "v1.24", + "service_account_email": "gcb-builder-cluster-api-gcp@k8s-staging-cluster-api-gcp.iam.gserviceaccount.com" +} diff --git a/packer/gce/ci/nightly/overwrite-1-25.json b/packer/gce/ci/nightly/overwrite-1-25.json new file mode 100644 index 0000000..64a5faa --- /dev/null +++ b/packer/gce/ci/nightly/overwrite-1-25.json @@ -0,0 +1,8 @@ +{ + "build_timestamp": "nightly", + "kubernetes_deb_version": "1.25.5-00", + "kubernetes_rpm_version": "1.25.5-0", + "kubernetes_semver": "v1.25.5", + "kubernetes_series": "v1.25", + "service_account_email": "gcb-builder-cluster-api-gcp@k8s-staging-cluster-api-gcp.iam.gserviceaccount.com" +} diff --git a/packer/gce/ci/nightly/overwrite-1-26.json b/packer/gce/ci/nightly/overwrite-1-26.json new file mode 100644 index 0000000..815ccfa --- /dev/null +++ b/packer/gce/ci/nightly/overwrite-1-26.json @@ -0,0 +1,8 @@ +{ + "build_timestamp": "nightly", + "kubernetes_deb_version": "1.26.0-00", + "kubernetes_rpm_version": "1.26.0-0", + "kubernetes_semver": "v1.26.0", + "kubernetes_series": "v1.26", + "service_account_email": "gcb-builder-cluster-api-gcp@k8s-staging-cluster-api-gcp.iam.gserviceaccount.com" +} diff --git a/packer/gce/packer.json b/packer/gce/packer.json new file mode 100644 index 0000000..3ab7dc3 --- /dev/null +++ b/packer/gce/packer.json @@ -0,0 +1,126 @@ +{ + "builders": [ + { + "disable_default_service_account": "{{ user `disable_default_service_account` }}", + "image_family": "{{user `image_family` | clean_resource_name}}", + "image_name": "{{user `image_name` | clean_resource_name}}", + "labels": { + "build_timestamp": "{{user `build_timestamp`}}", + "distribution": "ubuntu", + "distribution_release": "{{user `distribution_release`}}", + "distribution_version": "{{user `distribution_version`}}", + "kubernetes_version": "{{user `kubernetes_semver` | clean_resource_name}}" + }, + "machine_type": "{{ user `machine_type` }}", + "name": "{{user `build_name`}}", + "project_id": "{{ user `project_id` }}", + "service_account_email": "{{ user `service_account_email` }}", + "source_image_family": "{{ user `source_image_family` }}", + "ssh_username": "ubuntu", + "type": "googlecompute", + "use_internal_ip": "{{ user `use_internal_ip`}}", + "zone": "{{ user `zone` }}" + } + ], + "provisioners": [ + { + "environment_vars": [ + "BUILD_NAME={{user `build_name`}}" + ], + "inline": [ + "if [ $BUILD_NAME != \"ubuntu-1804\" ] || [ $BUILD_NAME != \"ubuntu-2004\" ]; then exit 0; fi", + "while [ ! -f /var/lib/cloud/instance/boot-finished ]; do echo 'Waiting for cloud-init...'; sleep 1; done", + "sudo apt-get -qq update && sudo DEBIAN_FRONTEND=noninteractive apt-get -qqy install python python-pip" + ], + "type": "shell" + }, + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} {{user `ansible_common_ssh_args`}}'" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--scp-extra-args", + "{{user `ansible_scp_extra_args`}}" + ], + "playbook_file": "./ansible/node.yml", + "type": "ansible" + }, + { + "arch": "{{user `goss_arch`}}", + "download_path": "{{user `goss_download_path`}}", + "format": "{{user `goss_format`}}", + "format_options": "{{user `goss_format_options`}}", + "goss_file": "{{user `goss_entry_file`}}", + "inspect": "{{user `goss_inspect_mode`}}", + "remote_folder": "{{user `goss_remote_folder`}}", + "remote_path": "{{user `goss_remote_path`}}", + "skip_install": "{{user `goss_skip_install`}}", + "tests": [ + "{{user `goss_tests_dir`}}" + ], + "type": "goss", + "url": "{{user `goss_url`}}", + "use_sudo": true, + "vars_file": "{{user `goss_vars_file`}}", + "vars_inline": { + "ARCH": "amd64", + "OS": "ubuntu", + "PROVIDER": "gcp", + "containerd_version": "{{user `containerd_version`}}", + "kubernetes_cni_deb_version": "{{ user `kubernetes_cni_deb_version` }}", + "kubernetes_cni_rpm_version": "{{ split (user `kubernetes_cni_rpm_version`) \"-\" 0 }}", + "kubernetes_cni_source_type": "{{user `kubernetes_cni_source_type`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver` | replace \"v\" \"\" 1}}", + "kubernetes_deb_version": "{{ user `kubernetes_deb_version` }}", + "kubernetes_rpm_version": "{{ split (user `kubernetes_rpm_version`) \"-\" 0 }}", + "kubernetes_source_type": "{{user `kubernetes_source_type`}}", + "kubernetes_version": "{{user `kubernetes_semver` | replace \"v\" \"\" 1}}" + }, + "version": "{{user `goss_version`}}" + } + ], + "variables": { + "ansible_common_vars": "", + "ansible_extra_vars": "", + "ansible_scp_extra_args": "", + "build_timestamp": "{{timestamp}}", + "containerd_sha256": null, + "containerd_url": "https://github.com/containerd/containerd/releases/download/v{{user `containerd_version`}}/cri-containerd-cni-{{user `containerd_version`}}-linux-amd64.tar.gz", + "containerd_version": null, + "crictl_url": "https://github.com/kubernetes-sigs/cri-tools/releases/download/v{{user `crictl_version`}}/crictl-v{{user `crictl_version`}}-linux-amd64.tar.gz", + "crictl_version": null, + "disable_default_service_account": "", + "encrypted": "false", + "existing_ansible_ssh_args": "{{env `ANSIBLE_SSH_ARGS`}}", + "image_family": "capi-{{user `build_name`}}-k8s-{{user `kubernetes_series`}}", + "image_name": "cluster-api-{{user `build_name`}}-{{user `kubernetes_semver`}}-{{user `build_timestamp`}}", + "kubernetes_cni_deb_version": null, + "kubernetes_cni_http_source": null, + "kubernetes_cni_rpm_version": null, + "kubernetes_cni_semver": null, + "kubernetes_cni_source_type": null, + "kubernetes_container_registry": null, + "kubernetes_deb_gpg_key": null, + "kubernetes_deb_repo": null, + "kubernetes_deb_version": null, + "kubernetes_http_source": null, + "kubernetes_load_additional_imgs": null, + "kubernetes_rpm_gpg_check": null, + "kubernetes_rpm_gpg_key": null, + "kubernetes_rpm_repo": null, + "kubernetes_rpm_version": null, + "kubernetes_semver": null, + "kubernetes_series": null, + "kubernetes_source_type": null, + "machine_type": "n1-standard-1", + "project_id": "{{env `GCP_PROJECT_ID`}}", + "service_account_email": "", + "source_image_family": "{{user `build_name`}}-lts", + "use_internal_ip": "false", + "zone": null + } +} diff --git a/packer/gce/ubuntu-1804.json b/packer/gce/ubuntu-1804.json new file mode 100644 index 0000000..c7ab95a --- /dev/null +++ b/packer/gce/ubuntu-1804.json @@ -0,0 +1,6 @@ +{ + "build_name": "ubuntu-1804", + "distribution_release": "bionic", + "distribution_version": "1804", + "zone": "us-central1-a" +} diff --git a/packer/gce/ubuntu-2004.json b/packer/gce/ubuntu-2004.json new file mode 100644 index 0000000..6e7b78c --- /dev/null +++ b/packer/gce/ubuntu-2004.json @@ -0,0 +1,6 @@ +{ + "build_name": "ubuntu-2004", + "distribution_release": "focal", + "distribution_version": "2004", + "zone": "us-central1-a" +} diff --git a/packer/gce/ubuntu-2204.json b/packer/gce/ubuntu-2204.json new file mode 100644 index 0000000..c7cd853 --- /dev/null +++ b/packer/gce/ubuntu-2204.json @@ -0,0 +1,6 @@ +{ + "build_name": "ubuntu-2204", + "distribution_release": "jammy", + "distribution_version": "2204", + "zone": "us-central1-a" +} diff --git a/packer/goss/goss-command.yaml b/packer/goss/goss-command.yaml new file mode 100644 index 0000000..6ae2150 --- /dev/null +++ b/packer/goss/goss-command.yaml @@ -0,0 +1,261 @@ +command: +{{ if ne .Vars.OS "windows" }} # Linux Only + containerd --version | awk -F' ' '{print substr($3,2); }': + exit-status: 0 + stdout: [] + stderr: [] + timeout: 0 + crictl ps: + exit-status: 0 + stdout: [] + stderr: [] + timeout: 0 +{{if ne .Vars.containerd_wasm_shims_runtimes ""}} + containerd-shim-slight-v1: + exit-status: 1 + stdout: [ ] + stderr: ["io.containerd.slight.v1: InvalidArgument(\"Shim namespace cannot be empty\")"] + timeout: 0 + containerd-shim-spin-v1: + exit-status: 1 + stdout: [ ] + stderr: ["io.containerd.spin.v1: InvalidArgument(\"Shim namespace cannot be empty\")"] + timeout: 0 + grep -E 'io\.containerd\.(slight|spin)\.v1' /etc/containerd/config.toml: + exit-status: 0 + stdout: [ ] + stderr: [ ] + timeout: 0 +{{end}} +{{if eq .Vars.kubernetes_source_type "pkg"}} +{{if eq .Vars.kubernetes_cni_source_type "pkg"}} + crictl images | grep -v 'IMAGE ID' | awk -F'[ /]' '{print $2}' | sed 's/-{{ .Vars.arch }}//g' | sort: + exit-status: 0 + stderr: [] + timeout: 0 + stdout: ["coredns", "etcd", "kube-apiserver", "kube-controller-manager", "kube-proxy", "kube-scheduler", "pause"] +{{end}} +{{end}} +{{if and (eq .Vars.kubernetes_source_type "http") (eq .Vars.kubernetes_cni_source_type "http") (not .Vars.kubernetes_load_additional_imgs)}} +# The second last pipe of awk is to take out arch from kube-apiserver-amd64 (i.e. amd64 or any other arch) + crictl images | grep -v 'IMAGE ID' | awk -F'[ /]' '{print $2}' | sed 's/-{{ .Vars.arch }}//g' | sort: + exit-status: 0 + stderr: [] + timeout: 0 + stdout: ["kube-apiserver", "kube-controller-manager", "kube-proxy", "kube-scheduler"] +{{end}} +{{if and (eq .Vars.kubernetes_source_type "http") (eq .Vars.kubernetes_cni_source_type "http") (.Vars.kubernetes_load_additional_imgs)}} +# The second last pipe of awk is to take out arch from kube-apiserver-amd64 (i.e. amd64 or any other arch) + crictl images | grep -v 'IMAGE ID' | awk -F'[ /]' '{print $2}' | sed 's/-{{ .Vars.arch }}//g' | sort: + exit-status: 0 + stderr: [] + timeout: 0 + stdout: ["coredns", "etcd", "kube-apiserver", "kube-controller-manager", "kube-proxy", "kube-scheduler", "pause"] +{{end}} +{{if eq .Vars.kubernetes_source_type "http"}} + kubectl version --short --client=true -o json | jq .clientVersion.gitVersion | tr -d '"' | awk '{print substr($1,2); }': + exit-status: 0 + stdout: [{{ .Vars.kubernetes_version }}] + stderr: [] + timeout: 0 + kubeadm version -o json | jq .clientVersion.gitVersion | tr -d '"' | awk '{print substr($1,2); }': + exit-status: 0 + stdout: [{{ .Vars.kubernetes_version }}] + stderr: [] + timeout: 0 + kubelet --version | awk -F' ' '{print $2}' | tr -d '"' | awk '{print substr($1,2); }': + exit-status: 0 + stdout: [{{ .Vars.kubernetes_version }}] + stderr: [] + timeout: 0 +{{end}} +{{if eq .Vars.kubernetes_cni_source_type "http"}} + /opt/cni/bin/host-device 2>&1 | awk -F' ' '{print substr($4,2); }': + exit-status: 0 + stdout: [{{ .Vars.kubernetes_cni_version }}] + stderr: [] + timeout: 0 +{{end}} +{{if eq .Vars.OS "photon"}} + cat /sys/kernel/mm/transparent_hugepage/enabled: + exit-status: 0 + stdout: ["always [madvise] never"] + stderr: [] + timeout: 0 +{{end}} +{{range $name, $vers := index .Vars .Vars.OS .Vars.PROVIDER "command"}} + {{ $name }}: + {{range $key, $val := $vers}} + {{$key}}: {{$val}} + {{end}} +{{end}} +{{end}} #End linux only + +{{ if eq .Vars.OS "windows" }} # Windows + automatic updates set to notify: + exit-status: 0 + exec: powershell -command "(Get-ItemPropertyValue 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU' -name AUOptions) -eq '2'" + stdout: + - "True" + timeout: 30000 + automatic updates set to notify with correct type: + exit-status: 0 + exec: powershell -command "(Get-ItemPropertyValue 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU' -name AUOptions).GetType().Name -eq 'Int32'" + stdout: + - "True" + timeout: 30000 + automatic updates are disabled: + exit-status: 0 + exec: powershell -command "(Get-ItemPropertyValue 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU' -name NoAutoUpdate) -eq '1'" + stdout: + - "True" + timeout: 30000 + automatic updates are disabled with correct type: + exit-status: 0 + exec: powershell -command "(Get-ItemPropertyValue 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU' -name NoAutoUpdate).GetType().Name -eq 'Int32'" + stdout: + - "True" + timeout: 30000 + kubectl version --client: + exit-status: 0 + stdout: + - {{.Vars.kubernetes_version}} + - "windows" + - {{.Vars.arch}} + timeout: 30000 + kubeadm version: + exit-status: 0 + stdout: + - {{.Vars.kubernetes_version}} + - "windows" + - {{.Vars.arch}} + timeout: 30000 + kubelet --version: + exit-status: 0 + stdout: + - {{.Vars.kubernetes_version}} + timeout: 10000 +{{ if eq .Vars.distribution_version "2019" }} + Windows build version is high enough: + exit-status: 0 + exec: powershell -command "(Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name UBR).UBR -ge 1817" + stdout: + - "True" + timeout: 30000 + Check HNS Control Flag: + exit-status: 0 + exec: powershell -command "(Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\hns\State" -Name HNSControlFlag).HNSControlFlag -eq 80" + stdout: + - True + timeout: 30000 + Check WCIFS Flag: + exit-status: 0 + exec: powershell -command "(Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Services\wcifs' -Name WcifsSOPCountDisabled).WcifsSOPCountDisabled -eq 0" + stdout: + - True + timeout: 30000 +{{end}} +{{ if eq .Vars.runtime "containerd" }} + Correct Containerd Version: + exec: "\"/Program Files/containerd/containerd.exe\" --version" + exit-status: 0 + stdout: + - "{{.Vars.containerd_version}}" + timeout: 30000 + Correct Containerd config: + exec: "\"/Program Files/containerd/containerd.exe\" config dump" + exit-status: 0 + stdout: + - "sandbox_image = \"{{.Vars.pause_image}}\"" + - "conf_dir = \"C:/etc/cni/net.d\"" + - "bin_dir = \"C:/opt/cni/bin\"" + - "root = \"C:\\\\ProgramData\\\\containerd\\\\root\"" + - "state = \"C:\\\\ProgramData\\\\containerd\\\\state\"" + timeout: 30000 + Check Windows Defender Exclusions are in place: + exit-status: 0 + exec: powershell -command "(Get-MpPreference | select ExclusionProcess)" + stdout: + - \Program Files\containerd\containerd.exe, + - \Program Files\containerd\ctr.exe + Check SMB CompartmentNamespace Flag: + exit-status: 0 + exec: powershell -command "(Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Services\hns\State' -Name EnableCompartmentNamespace).EnableCompartmentNamespace -eq 1" + stdout: + - True + timeout: 30000 + Windows Port Range is Expanded: + exit-status: 0 + exec: netsh int ipv4 show dynamicportrange tcp + stdout: + - "Start Port : 34000" + - "Number of Ports : 31536" + timeout: 30000 +{{end}} + +{{ if eq .Vars.runtime "docker-ee" }} + Correct Docker Version: + exec: "docker.exe version" + exit-status: 0 + stdout: + - "{{.Vars.docker_ee_version}}" + timeout: 30000 +{{end}} + +{{if eq .Vars.PROVIDER "azure"}} + Verify firewall rule to block 168.63.129.16:80 for cve-2021-27075: + exit-status: 0 + exec: powershell -command "(Get-NetFirewallRule -ErrorAction Stop -DisplayName 'Block-Outbound-168.63.129.16-port-80-for-cve-2021-27075').Enabled" + stdout: + - True + stderr: [] + timeout: 30000 + + # this could be moved to place for other providers if they want to install it + Key Vault gMSA binary is installed: + exec: powershell -command "Test-Path -Path C:\Windows\System32\CCGAKVPlugin.dll" + exit-status: 0 + stdout: + - "True" + timeout: 30000 + Key Vault gMSA binary COM is registered: + exec: powershell -command "(Get-Item 'HKLM:SYSTEM\CurrentControlSet\Control\CCG\COMClasses\{CCC2A336-D7F3-4818-A213-272B7924213E}') | Ft -autosize -wrap" + exit-status: 0 + stdout: + - "CCC2A336-D7F3-4818-A213-272B7924213E" + timeout: 30000 + Key Vault gMSA binary is registered: + exec: powershell -command "Get-ItemProperty -Path 'HKLM:SOFTWARE\CLASSES\CLSID\{CCC2A336-D7F3-4818-A213-272B7924213E}\InprocServer32\'" + exit-status: 0 + stdout: + - "C:\\Windows\\System32\\CCGAKVPlugin.dll" + timeout: 30000 + Key Vault gMSA CCG interface is registered: + exec: powershell -command "(Get-Item 'HKLM:SOFTWARE\Classes\Interface\{6ECDA518-2010-4437-8BC3-46E752B7B172}') | Ft -autosize -wrap" + exit-status: 0 + stdout: + - "ICcgDomainAuthCredentials" + timeout: 30000 +{{end}} + +{{ if ne .Vars.ssh_source_url "" }} + Check permission of OpenSSH directory for SYSTEM: + exec: powershell -command "((Get-Acl 'C:\Program Files\OpenSSH').Access | Where-Object{$_.IdentityReference -eq 'NT AUTHORITY\SYSTEM' -and $_.FileSystemRights -eq 'FullControl'}) -ne $null" + exit-status: 0 + stdout: + - True + timeout: 30000 + Check permission of OpenSSH directory for Administrators: + exec: powershell -command "((Get-Acl 'C:\Program Files\OpenSSH').Access | Where-Object{$_.IdentityReference -eq 'BUILTIN\Administrators' -and $_.FileSystemRights -eq 'FullControl'}) -ne $null" + exit-status: 0 + stdout: + - True + timeout: 30000 + Check permission of OpenSSH directory for Users: + exec: powershell -command "((Get-Acl 'C:\Program Files\OpenSSH').Access | Where-Object{$_.IdentityReference -eq 'BUILTIN\Users' -and $_.FileSystemRights -eq 'ReadAndExecute, Synchronize'}) -eq $null" + exit-status: 0 + stdout: + - True + timeout: 30000 +{{end}} +{{end}} #end windows diff --git a/packer/goss/goss-files.yaml b/packer/goss/goss-files.yaml new file mode 100644 index 0000000..278f403 --- /dev/null +++ b/packer/goss/goss-files.yaml @@ -0,0 +1,17 @@ +file: +{{range $name, $vers := index .Vars .Vars.OS "common-files"}} + {{ $name }}: + exists: {{ $vers.exists }} + filetype: {{ $vers.filetype }} + contains: {{ range $vers.contains}} + - {{.}} + {{end}} +{{end}} +{{range $name, $vers := index .Vars .Vars.OS .Vars.PROVIDER "files"}} + {{ $name }}: + exists: {{ $vers.exists }} + filetype: {{ $vers.filetype }} + contains: {{ range $vers.contains}} + - {{.}} + {{end}} +{{end}} \ No newline at end of file diff --git a/packer/goss/goss-kernel-params.yaml b/packer/goss/goss-kernel-params.yaml new file mode 100644 index 0000000..b3413ee --- /dev/null +++ b/packer/goss/goss-kernel-params.yaml @@ -0,0 +1,31 @@ +{{ if ne .Vars.OS "windows" }} +kernel-param: + net.bridge.bridge-nf-call-iptables: + value: "1" + net.ipv6.conf.all.forwarding: + value: "1" + net.ipv6.conf.all.disable_ipv6: + value: "0" + net.ipv4.ip_forward: + value: "1" + net.bridge.bridge-nf-call-ip6tables: + value: "1" + vm.overcommit_memory: + value: "1" + kernel.panic: + value: "10" + kernel.panic_on_oops: + value: "1" +{{range $name, $vers := index .Vars .Vars.OS "common-kernel-param"}} + {{ $name }}: + {{range $key, $val := $vers}} + {{$key}}: "{{$val}}" + {{end}} +{{end}} +{{range $name, $vers := index .Vars .Vars.OS .Vars.PROVIDER "kernel-param"}} + {{ $name }}: + {{range $key, $val := $vers}} + {{$key}}: "{{$val}}" + {{end}} +{{end}} +{{end}} \ No newline at end of file diff --git a/packer/goss/goss-package.yaml b/packer/goss/goss-package.yaml new file mode 100644 index 0000000..3b41225 --- /dev/null +++ b/packer/goss/goss-package.yaml @@ -0,0 +1,86 @@ +{{ if ne .Vars.OS "windows"}} +kubernetes_version: &kubernetes_version + versions: + or: + - contain-element: + match-regexp: "^\\Q{{ .Vars.kubernetes_deb_version }}\\E$" + - contain-element: + match-regexp: "^\\Q{{ .Vars.kubernetes_rpm_version }}\\E$" + +kubernetes_cni_version: &kubernetes_cni_version + versions: + or: + - contain-element: + match-regexp: "^\\Q{{ .Vars.kubernetes_cni_deb_version }}\\E$" + - contain-element: + match-regexp: "^\\Q{{ .Vars.kubernetes_cni_rpm_version }}\\E$" + +package: +# Flatcar uses Ignition instead of cloud-init +{{if ne .Vars.OS "flatcar"}} + cloud-init: + installed: true +{{end}} + ntp: + installed: false +{{if eq .Vars.kubernetes_source_type "pkg"}} + kubeadm: + installed: true + <<: *kubernetes_version + kubelet: + installed: true + <<: *kubernetes_version + kubectl: + installed: true + <<: *kubernetes_version +{{end}} +{{if eq .Vars.kubernetes_cni_source_type "pkg"}} + kubernetes-cni: + installed: true + <<: *kubernetes_cni_version +{{end}} +# Looping over common packages for an OS +{{range $name, $vers := index .Vars .Vars.OS "common-package"}} + {{$name}}: + installed: true + {{range $key, $val := $vers}} + {{$key}}: {{$val}} + {{end}} +{{end}} +# Looping over provider specific packages for an OS +{{range $name, $vers := index .Vars .Vars.OS .Vars.PROVIDER "package"}} + {{$name}}: + installed: true + {{range $key, $val := $vers}} + {{$key}}: {{$val}} + {{end}} +{{end}} + +# Iterate thru different OS Versions like RHEL7/8, Photon 3/4(future) etc. +{{$distro_version := .Vars.OS_VERSION}} +{{range $component := index .Vars .Vars.OS .Vars.PROVIDER "os_version"}} +{{if eq $distro_version (index $component "distro_version")}} + {{ range $name, $vers := index $component "package"}} + {{$name}}: + installed: true + {{range $key, $val := $vers}} + {{$key}}: {{$val}} + {{end}} + {{end}} +{{end}} +{{end}} +{{end}} + +{{ if eq .Vars.OS "windows"}} # Windows +# Workaround until windows features are added to goss +command: +{{range $name, $vers := index .Vars .Vars.OS "common-windows-features"}} + "Windows Feature - {{ $name }}": + exec: powershell -command "(Get-WindowsFeature {{ $name }} | select *)" + exit-status: 0 + stdout: {{range $vers.expected}} + - {{.}} + timeout: 60000 + {{end}} +{{end}} +{{end}} diff --git a/packer/goss/goss-service.yaml b/packer/goss/goss-service.yaml new file mode 100644 index 0000000..44e03ee --- /dev/null +++ b/packer/goss/goss-service.yaml @@ -0,0 +1,77 @@ +service: +{{ if ne .Vars.OS "windows"}} # Linux + containerd: + enabled: true + running: true + dockerd: + enabled: false + running: false + kubelet: + enabled: true + running: false + conntrackd: + enabled: false + running: false + auditd: + enabled: true + running: true + {{if ne .Vars.OS "flatcar"}} + # Flatcar uses systemd-timesyncd instead of chronyd. + chronyd: + enabled: true + running: true + {{end}} +{{range $name, $vers := index .Vars .Vars.OS "common-service"}} + {{ $name }}: + {{range $key, $val := $vers}} + {{$key}}: {{$val}} + {{end}} +{{end}} +{{range $name, $vers := index .Vars .Vars.OS .Vars.PROVIDER "service"}} + {{ $name }}: + {{range $key, $val := $vers}} + {{$key}}: {{$val}} + {{end}} +{{end}} +{{end}} + +{{ if eq .Vars.OS "windows"}} # Windows +# Workaround until windows services are added to goss +command: +{{range $name, $vers := index .Vars .Vars.OS "common-windows-service"}} + "Windows Service - {{ $name }}": + exec: powershell -command "(Get-Service {{ $name }} | select *)" + exit-status: 0 + stdout: {{range $vers.expected}} + - {{.}} + {{end}} +{{end}} +{{range $name, $vers := index .Vars .Vars.OS .Vars.PROVIDER "windows-service"}} + "Windows Service - {{ $name }}": + exec: powershell -command "(Get-Service {{ $name }} | select *)" + exit-status: 0 + stdout: {{range $vers.expected}} + - {{.}} + {{end}} +{{end}} + +{{ if eq .Vars.runtime "docker-ee" }} + + "Windows Service - docker": + exec: powershell -command "(Get-Service docker | select *)" + exit-status: 0 + stdout: + - Automatic + - Running +{{end}} + +{{ if eq .Vars.runtime "containerd"}} + "Windows Service - containerd": + exec: powershell -command "(Get-Service containerd | select *)" + exit-status: 0 + stdout: + - Automatic + - Running +{{end}} + +{{end}} diff --git a/packer/goss/goss-vars.yaml b/packer/goss/goss-vars.yaml new file mode 100644 index 0000000..42b7476 --- /dev/null +++ b/packer/goss/goss-vars.yaml @@ -0,0 +1,546 @@ +--- +common_rpms: &common_rpms + audit: + ca-certificates: + cloud-init: + cloud-utils-growpart: + conntrack-tools: + chrony: + curl: + jq: + python3-pip: + socat: + sysstat: + yum-utils: + +al2_rpms: &al2_rpms + ebtables: + python-netifaces: + python-requests: + +rh7_rpms: &rh7_rpms + ebtables: + python-netifaces: + python-requests: + +rh8_rpms: &rh8_rpms + nftables: + python3-netifaces: + python3-requests: + +common_debs: &common_debs + auditd: + apt-transport-https: + conntrack: + chrony: + curl: + ebtables: + jq: + gnupg: + libnetfilter-acct1: + libnetfilter-cttimeout1: + libnetfilter-log1: + python3-distutils: + python3-netifaces: + python3-pip: + socat: + +chrony_deb: &chrony_deb + chrony: + ntp: + skip: true + installed: false + +common_photon_rpms: &common_photon_rpms + audit: + apparmor-parser: + conntrack-tools: + chrony: + distrib-compat: + ebtables: + net-tools: + openssl-c_rehash: + python3-pip: + rng-tools: + socat: + tar: + unzip: + +photon_3_rpms: &photon_3_rpms + python-netifaces: + python-requests: + jq: + +photon_4_rpms: &photon_4_rpms + jq: + +arch: "amd64" +containerd_version: "" +containerd_wasm_shims_runtimes: "" +kubernetes_cni_source_type: "" +kubernetes_cni_version: "" +kubernetes_source_type: "" +kubernetes_version: "" +kubernetes_rpm_version: "" +kubernetes_deb_version: "" +kubernetes_cni_deb_version: "" +kubernetes_cni_rpm_version: "" +# When k8s and k8s cni source is http +kubernetes_load_additional_imgs: false + +#windows variables +kubernetes_install_path: "" +windows_service_manager: "" +distribution_version: "" +runtime: "" + +# OS Specific package/Command/Kernal Params etc... +# Structured in below format +# OS_NAME +# common-package: +# common-kernel-params: +# common-services: +# PROVIDER_NAME: +# package: +# command: +# service: +# ... +amazon linux: + common-package: *common_rpms + amazon: + service: + amazon-ssm-agent: + enabled: true + running: true + package: + awscli: + amazon-ssm-agent: + <<: *al2_rpms +centos: + common-package: *common_rpms + amazon: + package: + amazon-ssm-agent: + <<: *rh7_rpms + command: + pip3 list --format=columns | grep 'awscli' | awk -F' ' '{print $1}': + exit-status: 0 + stdout: ["awscli"] + stderr: [] + timeout: 0 + azure: + package: + open-vm-tools: + azure-cli: + ova: + package: + python2-pip: + open-vm-tools: + <<: *rh7_rpms + qemu: + package: + open-vm-tools: + cloud-init: + cloud-utils-growpart: + python2-pip: + <<: *rh7_rpms + raw: + package: + cloud-init: + cloud-utils-growpart: + python2-pip: +flatcar: + common-service: + containerd: + enabled: true + running: true + systemd-timesyncd: + enabled: true + running: true + amazon: + command: + azure: + command: + qemu: + command: + raw: + command: + ova: + command: + nutanix: + command: +photon: + common-service: + apparmor: + enabled: false + running: false + common-kernel-param: + net.ipv4.tcp_limit_output_bytes: + value: "524288" + common-package: + <<: *common_photon_rpms + audit: + ova: + command: + grep apparmor=0 /boot/photon.cfg: + exit-status: 0 + stdout: ["apparmor=0"] + stderr: [] + timeout: 0 + service: + networkd-dispatcher: + enabled: true + running: true + package: + open-vm-tools: + cloud-init: + cloud-utils: + python3-netifaces: + os_version: + - distro_version: "3" + package: + <<: *photon_3_rpms + - distro_version: "4" + package: + <<: *photon_4_rpms +rockylinux: + common-package: *common_rpms + amazon: + package: + amazon-ssm-agent: + <<: *rh8_rpms + command: + pip3 list --format=columns | grep 'awscli' | awk -F' ' '{print $1}': + exit-status: 0 + stdout: [ "awscli" ] + stderr: [ ] + timeout: 0 + service: + amazon-ssm-agent: + enabled: true + running: true + ova: + package: + open-vm-tools: + python2-pip: + <<: *rh8_rpms + qemu: + package: + open-vm-tools: + cloud-init: + cloud-utils: + python3-netifaces: + <<: *rh8_rpms + raw: + package: + cloud-init: + cloud-utils: + python3-netifaces: + <<: *rh8_rpms + nutanix: + package: + cloud-init: + python3-netifaces: + iscsi-initiator-utils: + nfs-utils: + lvm2: + xfsprogs: + <<: *rh8_rpms + service: + iscsid: + enabled: true + running: true +rhel: + common-package: *common_rpms + amazon: + package: + amazon-ssm-agent: + os_version: + - distro_version: "8" + package: + <<: *rh8_rpms + command: + pip3 list --format=columns | grep 'awscli' | awk -F' ' '{print $1}': + exit-status: 0 + stdout: [ "awscli" ] + stderr: [ ] + timeout: 0 + service: + amazon-ssm-agent: + enabled: true + running: true + azure: + package: + open-vm-tools: + azure-cli: + os_version: + - distro_version: "8" + package: + <<: *rh8_rpms + ova: + package: + python2-pip: + open-vm-tools: + os_version: + - distro_version: "7" + package: + <<: *rh7_rpms + - distro_version: "8" + package: + <<: *rh8_rpms + qemu: + package: + open-vm-tools: + cloud-init: + cloud-utils-growpart: + python2-pip: + <<: *rh7_rpms + raw: + package: + cloud-init: + cloud-utils-growpart: + python2-pip: + <<: *rh7_rpms +ubuntu: + common-kernel-param: + net.ipv4.conf.all.rp_filter: + value: "1" + common-package: + <<: *common_debs + common-service: + apt-daily.timer: + enabled: false + running: false + apt-daily-upgrade.timer: + enabled: false + running: false + azure: + command: + pip3 list --format=columns | grep 'azure-cli' | awk -F' ' '{print $1}': + exit-status: 0 + stdout: ["azure-cli"] + stderr: [] + timeout: 0 + iptables -C FORWARD -d 168.63.129.16/32 -p tcp -m tcp --dport 80 -m comment --comment "block traffic to 168.63.129.16 for cve-2021-27075" -j DROP: + exit-status: 0 + timeout: 0 + package: + open-vm-tools: + linux-cloud-tools-virtual: + linux-tools-virtual: + <<: *chrony_deb + service: + chrony: + enabled: true + running: true + amazon: + service: + snap.amazon-ssm-agent.amazon-ssm-agent.service: + enabled: true + running: true + package: + linux-cloud-tools-virtual: + linux-tools-virtual: + command: + snap list | grep 'amazon-ssm-agent' | awk -F' ' '{print $1}': + exit-status: 0 + stdout: ["amazon-ssm-agent"] + stderr: [] + timeout: 0 + pip3 list --format=columns | grep 'awscli' | awk -F' ' '{print $1}': + exit-status: 0 + stdout: ["awscli"] + stderr: [] + timeout: 0 + gcp: + package: + linux-cloud-tools-virtual: + linux-tools-virtual: + command: + find -L /bin -maxdepth 1 -type f -executable -printf "%f\n" | grep -Fx 'gcloud': + exit-status: 0 + stdout: ["gcloud"] + stderr: [] + timeout: 0 + oci: + service: + package: + command: + outscale: + package: + linux-cloud-tools-virtual: + linux-tools-virtual: + ova: + service: + networkd-dispatcher: + enabled: true + running: true + package: + linux-cloud-tools-virtual: + linux-tools-virtual: + open-vm-tools: + cloud-guest-utils: + cloud-initramfs-copymods: + cloud-initramfs-dyn-netconf: + qemu: + package: + linux-cloud-tools-virtual: + linux-tools-virtual: + open-vm-tools: + cloud-guest-utils: + cloud-initramfs-copymods: + cloud-initramfs-dyn-netconf: + raw: + package: + cloud-guest-utils: + cloud-initramfs-copymods: + cloud-initramfs-dyn-netconf: + linux-cloud-tools-generic: + linux-tools-generic: + nutanix: + package: + linux-cloud-tools-virtual: + linux-tools-virtual: + cloud-guest-utils: + cloud-initramfs-copymods: + cloud-initramfs-dyn-netconf: + open-iscsi: + xfsprogs: + mdadm: + nfs-common: + service: + iscsid: + enabled: true + running: true + +oracle linux: + common-kernel-param: + common-package: + <<: *common_rpms + common-service: + oci: + command: + service: + package: + <<: *rh8_rpms + +# Windows specific variables +windows: + common-windows-features: + Hyper-V-PowerShell: + expected: + - Installed + Containers: + expected: + - Installed + + common-files: + c:/etc/kubernetes/pki: + exists: true + filetype: directory + contains: + c:/etc/kubernetes: + exists: true + filetype: directory + contains: + c:/etc/kubernetes/manifests: + exists: true + filetype: directory + contains: + c:/var/log/kubelet: + exists: true + filetype: directory + contains: + + common-windows-service: + cloudbase-init: + expected: + - Manual + - Stopped + kubelet: + expected: + - Automatic + - "/RequiredServices.+:.+(containerd|docker)/" + sshd: + expected: + - Automatic + - Running + + azure: + windows-service: + + files: + 'c:/program files/Cloudbase Solutions/Cloudbase-init/conf/cloudbase-init.conf': + exists: true + filetype: file + contains: + - "COM2,115200,N,8" + - "metadata_services=cloudbaseinit.metadata.services.azureservice.AzureService" + - "cloudbaseinit.plugins.common.ephemeraldisk.EphemeralDiskPlugin" + - "cloudbaseinit.plugins.windows.azureguestagent.AzureGuestAgentPlugin" + - "cloudbaseinit.plugins.common.mtu.MTUPlugin" + - "cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin" + ova: + windows-service: + vmtools: + expected: + - Automatic + - Running + files: + 'c:/program files/Cloudbase Solutions/Cloudbase-init/conf/cloudbase-init.conf': + exists: true + filetype: file + contains: + - "!/logging_serial_port=COM1,115200,N,8/" + - "cloudbaseinit.metadata.services.vmwareguestinfoservice.VMwareGuestInfoService" + - "cloudbaseinit.plugins.common.ephemeraldisk.EphemeralDiskPlugin" + - "cloudbaseinit.plugins.common.mtu.MTUPlugin" + - "cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin" + - "cloudbaseinit.plugins.common.sshpublickeys.SetUserSSHPublicKeysPlugin" + - "cloudbaseinit.plugins.common.userdata.UserDataPlugin" + - "cloudbaseinit.plugins.common.localscripts.LocalScriptsPlugin" + - "cloudbaseinit.plugins.windows.createuser.CreateUserPlugin" + - "cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin" + 'c:/program files/Cloudbase Solutions/Cloudbase-init/conf/cloudbase-init-unattend.conf': + exists: true + filetype: file + contains: + - "metadata_services=cloudbaseinit.metadata.services.vmwareguestinfoservice.VMwareGuestInfoService" + amazon: + windows-service: + + files: + 'c:/program files/Cloudbase Solutions/Cloudbase-init/conf/cloudbase-init.conf': + exists: true + filetype: file + contains: + - "!/logging_serial_port=COM1,115200,N,8/" + - "metadata_services=cloudbaseinit.metadata.services.ec2service.EC2Service" + - "cloudbaseinit.plugins.common.ephemeraldisk.EphemeralDiskPlugin" + - "cloudbaseinit.plugins.common.mtu.MTUPlugin" + - "cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin" + - "cloudbaseinit.plugins.common.sshpublickeys.SetUserSSHPublicKeysPlugin" + + nutanix: + windows-service: + + files: + 'c:/program files/Cloudbase Solutions/Cloudbase-init/conf/cloudbase-init.conf': + exists: true + filetype: file + contains: + - "!/logging_serial_port=COM1,115200,N,8/" + - "cloudbaseinit.metadata.services.configdrive.ConfigDriveService" + - "cloudbaseinit.plugins.common.ephemeraldisk.EphemeralDiskPlugin" + - "cloudbaseinit.plugins.common.mtu.MTUPlugin" + - "cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin" + - "cloudbaseinit.plugins.common.sshpublickeys.SetUserSSHPublicKeysPlugin" + - "cloudbaseinit.plugins.common.userdata.UserDataPlugin" + - "cloudbaseinit.plugins.common.localscripts.LocalScriptsPlugin" + - "cloudbaseinit.plugins.windows.createuser.CreateUserPlugin" + - "cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin" + 'c:/program files/Cloudbase Solutions/Cloudbase-init/conf/cloudbase-init-unattend.conf': + exists: true + filetype: file + contains: + - "metadata_services=cloudbaseinit.metadata.services.base.EmptyMetadataService" \ No newline at end of file diff --git a/packer/goss/goss.yaml b/packer/goss/goss.yaml new file mode 100644 index 0000000..aff8aee --- /dev/null +++ b/packer/goss/goss.yaml @@ -0,0 +1,6 @@ +gossfile: + goss-command.yaml: {} + goss-kernel-params.yaml: {} + goss-service.yaml: {} + goss-package.yaml: {} + goss-files.yaml: {} diff --git a/packer/nutanix/OWNERS b/packer/nutanix/OWNERS new file mode 100644 index 0000000..b552638 --- /dev/null +++ b/packer/nutanix/OWNERS @@ -0,0 +1,7 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - cluster-api-nutanix-maintainers + +reviewers: + - cluster-api-nutanix-reviewers diff --git a/packer/nutanix/config.pkr.hcl b/packer/nutanix/config.pkr.hcl new file mode 100644 index 0000000..cf940f9 --- /dev/null +++ b/packer/nutanix/config.pkr.hcl @@ -0,0 +1,8 @@ +packer { + required_plugins { + nutanix = { + version = ">= 0.3.1" + source = "github.com/nutanix-cloud-native/nutanix" + } + } +} diff --git a/packer/nutanix/flatcar.json b/packer/nutanix/flatcar.json new file mode 100644 index 0000000..0f57bd1 --- /dev/null +++ b/packer/nutanix/flatcar.json @@ -0,0 +1,20 @@ +{ + "ansible_extra_vars": "ansible_python_interpreter=/opt/bin/python3", + "build_name": "flatcar-{{env `FLATCAR_CHANNEL`}}-{{env `FLATCAR_VERSION`}}", + "channel_name": "{{env `FLATCAR_CHANNEL`}}", + "crictl_source_type": "http", + "distribution": "flatcar", + "distribution_release": "Core", + "distribution_version": "{{env `FLATCAR_CHANNEL`}}", + "distro_name": "flatcar", + "guest_os_type": "Linux", + "image_url": "flatcar_production_openstack_image.img", + "kubernetes_cni_source_type": "http", + "kubernetes_source_type": "http", + "python_path": "/opt/bin/builder-env/site-packages", + "shutdown_command": "shutdown -P now", + "systemd_prefix": "/etc/systemd", + "sysusr_prefix": "/opt", + "sysusrlocal_prefix": "/opt", + "user_data": "ewogICAgImlnbml0aW9uIjogewogICAgICAgICJjb25maWciOiB7fSwKICAgICAgICAic2VjdXJpdHkiOiB7CiAgICAgICAgICAgICJ0bHMiOiB7fQogICAgICAgIH0sCiAgICAgICAgInRpbWVvdXRzIjoge30sCiAgICAgICAgInZlcnNpb24iOiAiMi4zLjAiCiAgICB9LAogICAgIm5ldHdvcmtkIjoge30sCiAgICAicGFzc3dkIjogewogICAgICAgICJ1c2VycyI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgImdyb3VwcyI6IFsKICAgICAgICAgICAgICAgICAgICAid2hlZWwiLAogICAgICAgICAgICAgICAgICAgICJzdWRvIiwKICAgICAgICAgICAgICAgICAgICAiZG9ja2VyIgogICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgICJuYW1lIjogImJ1aWxkZXIiLAogICAgICAgICAgICAgICAgInBhc3N3b3JkSGFzaCI6ICIkNSQydU9Kc3M1ekpOalFZJHpYSVc3VFNxcUROTXZEbXFseUVybWQveE5UaGNDT1ZwRjZFUTZvR2JmaDUiCiAgICAgICAgICAgIH0KICAgICAgICBdCiAgICB9LAogICAgInN0b3JhZ2UiOiB7fSwKICAgICJzeXN0ZW1kIjogewogICAgICAgICJ1bml0cyI6IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgIm5hbWUiOiAiZG9ja2VyLnNlcnZpY2UiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJuYW1lIjogImZsYXRjYXItb3BlbnN0YWNrLWhvc3RuYW1lLnNlcnZpY2UiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJtYXNrIjogdHJ1ZSwKICAgICAgICAgICAgICAgICJuYW1lIjogInVwZGF0ZS1lbmdpbmUuc2VydmljZSIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgIm1hc2siOiB0cnVlLAogICAgICAgICAgICAgICAgIm5hbWUiOiAibG9ja3NtaXRoZC5zZXJ2aWNlIgogICAgICAgICAgICB9CiAgICAgICAgXQogICAgfQp9" +} diff --git a/packer/nutanix/nutanix.json b/packer/nutanix/nutanix.json new file mode 100644 index 0000000..89e0712 --- /dev/null +++ b/packer/nutanix/nutanix.json @@ -0,0 +1,11 @@ +{ + "force_deregister": "true", + "nutanix_cluster_name": "", + "nutanix_endpoint": "", + "nutanix_insecure": "false", + "nutanix_password": "", + "nutanix_port": "9440", + "nutanix_subnet_name": "", + "nutanix_username": "admin", + "scp_extra_vars": "" +} diff --git a/packer/nutanix/packer-windows.json b/packer/nutanix/packer-windows.json new file mode 100644 index 0000000..6558260 --- /dev/null +++ b/packer/nutanix/packer-windows.json @@ -0,0 +1,149 @@ +{ + "builders": [ + { + "boot_type": "{{user `boot_type`}}", + "cd_files": [ + "./packer/nutanix/windows/{{user `build_name`}}/autounattend.xml", + "./packer/nutanix/windows/disable-network-discovery.cmd", + "./packer/nutanix/windows/sysprep.ps1" + ], + "cd_label": "OEMDRV", + "cluster_name": "{{user `nutanix_cluster_name`}}", + "communicator": "winrm", + "force_deregister": "{{user `force_deregister`}}", + "image_description": "kube image-builder packer", + "image_name": "{{user `image_name`}}", + "memory_mb": "{{user `memory`}}", + "nutanix_endpoint": "{{user `nutanix_endpoint`}}", + "nutanix_insecure": "{{user `nutanix_insecure`}}", + "nutanix_password": "{{user `nutanix_password`}}", + "nutanix_port": "{{user `nutanix_port`}}", + "nutanix_username": "{{user `nutanix_username`}}", + "os_type": "{{user `guest_os_type`}}", + "shutdown_command": "powershell F:/sysprep.ps1", + "shutdown_timeout": "1h", + "type": "nutanix", + "vm_disks": [ + { + "image_type": "ISO_IMAGE", + "source_image_name": "{{user `source_image_name`}}" + }, + { + "image_type": "ISO_IMAGE", + "source_image_name": "{{user `virtio_image_name`}}" + }, + { + "disk_size_gb": "{{user `disk_size_gb`}}", + "image_type": "DISK" + } + ], + "vm_name": "{{user `build_name`}}-kube-{{user `kubernetes_semver`}}", + "vm_nics": { + "subnet_name": "{{user `nutanix_subnet_name`}}" + }, + "winrm_insecure": true, + "winrm_password": "S3cr3t0!", + "winrm_port": 5986, + "winrm_timeout": "4h", + "winrm_use_ssl": true, + "winrm_username": "Administrator" + } + ], + "provisioners": [ + { + "extra_arguments": [ + "-e", + "ansible_winrm_server_cert_validation=ignore", + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}" + ], + "playbook_file": "ansible/windows/node_windows.yml", + "type": "ansible", + "use_proxy": false, + "user": "Administrator" + }, + { + "restart_timeout": "10m", + "type": "windows-restart" + }, + { + "arch": "{{user `goss_arch`}}", + "download_path": "{{user `goss_download_path`}}", + "format": "{{user `goss_format`}}", + "format_options": "{{user `goss_format_options`}}", + "goss_file": "{{user `goss_entry_file`}}", + "inspect": "{{user `goss_inspect_mode`}}", + "remote_folder": "{{user `goss_remote_folder`}}", + "remote_path": "{{user `goss_remote_path`}}", + "skip_install": "{{user `goss_skip_install`}}", + "target_os": "Windows", + "tests": [ + "{{user `goss_tests_dir`}}" + ], + "type": "goss", + "url": "{{user `goss_url`}}", + "use_sudo": false, + "vars_env": { + "GOSS_MAX_CONCURRENT": "1", + "GOSS_USE_ALPHA": "1" + }, + "vars_file": "{{user `goss_vars_file`}}", + "vars_inline": { + "OS": "{{user `distro_name` | lower}}", + "PROVIDER": "nutanix", + "containerd_version": "{{user `containerd_version`}}", + "distribution_version": "{{user `distro_version`}}", + "docker_ee_version": "{{user `docker_ee_version`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}", + "pause_image": "{{user `pause_image`}}", + "runtime": "{{user `runtime`}}", + "ssh_source_url": "{{user `ssh_source_url`}}" + }, + "version": "{{user `goss_version`}}" + }, + { + "inline": [ + "rm -Force -Recurse C:\\var\\log\\kubelet\\*" + ], + "type": "powershell" + } + ], + "variables": { + "ansible_common_vars": "", + "ansible_extra_vars": "", + "ansible_user_vars": "", + "build_timestamp": "{{timestamp}}", + "cloudbase_init_url": "https://github.com/cloudbase/cloudbase-init/releases/download/{{user `cloudbase_init_version`}}/CloudbaseInitSetup_{{user `cloudbase_init_version` | replace_all `.` `_` }}_x64.msi", + "cloudbase_metadata_services": "cloudbaseinit.metadata.services.configdrive.ConfigDriveService", + "cloudbase_metadata_services_unattend": "cloudbaseinit.metadata.services.base.EmptyMetadataService", + "cloudbase_plugins": "cloudbaseinit.plugins.windows.createuser.CreateUserPlugin, cloudbaseinit.plugins.common.setuserpassword.SetUserPasswordPlugin, cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin, cloudbaseinit.plugins.common.ephemeraldisk.EphemeralDiskPlugin, cloudbaseinit.plugins.common.mtu.MTUPlugin, cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin, cloudbaseinit.plugins.common.sshpublickeys.SetUserSSHPublicKeysPlugin, cloudbaseinit.plugins.common.userdata.UserDataPlugin, cloudbaseinit.plugins.common.localscripts.LocalScriptsPlugin, cloudbaseinit.plugins.windows.createuser.CreateUserPlugin, cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin", + "cloudbase_plugins_unattend": "cloudbaseinit.plugins.common.mtu.MTUPlugin", + "containerd_sha256": null, + "containerd_url": "", + "containerd_version": null, + "cpus": "2", + "crictl_url": "", + "crictl_version": null, + "disk_size_gb": "40", + "existing_ansible_ssh_args": "{{env `ANSIBLE_SSH_ARGS`}}", + "image_name": "{{user `build_name`}}-kube-{{user `kubernetes_semver`}}", + "kubernetes_base_url": "https://kubernetesreleases.blob.core.windows.net/kubernetes/{{user `kubernetes_semver`}}/binaries/node/windows/{{user `kubernetes_goarch`}}", + "kubernetes_container_registry": null, + "kubernetes_http_package_url": "", + "kubernetes_http_source": null, + "kubernetes_install_path": "c:\\k", + "kubernetes_load_additional_imgs": null, + "kubernetes_semver": null, + "kubernetes_series": null, + "kubernetes_source_type": null, + "kubernetes_typed_version": "kube-{{user `kubernetes_semver`}}", + "machine_id_mode": "444", + "memory": "4096", + "scp_extra_vars": "", + "wins_url": null + } +} diff --git a/packer/nutanix/packer.json b/packer/nutanix/packer.json new file mode 100644 index 0000000..a29194d --- /dev/null +++ b/packer/nutanix/packer.json @@ -0,0 +1,142 @@ +{ + "builders": [ + { + "boot_type": "{{user `boot_type`}}", + "cluster_name": "{{user `nutanix_cluster_name`}}", + "cpu": "{{user `cpus`}}", + "force_deregister": "{{user `force_deregister`}}", + "image_description": "kube image-builder packer", + "image_name": "{{user `image_name`}}", + "memory_mb": "{{user `memory`}}", + "nutanix_endpoint": "{{user `nutanix_endpoint`}}", + "nutanix_insecure": "{{user `nutanix_insecure`}}", + "nutanix_password": "{{user `nutanix_password`}}", + "nutanix_port": "{{user `nutanix_port`}}", + "nutanix_username": "{{user `nutanix_username`}}", + "os_type": "{{user `guest_os_type`}}", + "shutdown_command": "echo '{{user `ssh_password`}}' | sudo -S -E sh -c 'usermod -L {{user `ssh_username`}} && {{user `shutdown_command`}}'", + "ssh_handshake_attempts": "100", + "ssh_password": "{{user `ssh_password`}}", + "ssh_timeout": "20m", + "ssh_username": "{{user `ssh_username`}}", + "type": "nutanix", + "user_data": "{{user `user_data`}}", + "vm_disks": { + "disk_size_gb": "{{user `disk_size_gb`}}", + "image_type": "DISK_IMAGE", + "source_image_uri": "{{user `image_url`}}" + }, + "vm_name": "{{user `build_name`}}-kube-{{user `kubernetes_semver`}}", + "vm_nics": { + "subnet_name": "{{user `nutanix_subnet_name`}}" + } + } + ], + "post-processors": [ + { + "environment_vars": [ + "CUSTOM_POST_PROCESSOR={{user `custom_post_processor`}}" + ], + "inline": [ + "if [ \"$CUSTOM_POST_PROCESSOR\" != \"true\" ]; then exit 0; fi", + "{{user `custom_post_processor_command`}}" + ], + "name": "custom-post-processor", + "type": "shell-local" + } + ], + "provisioners": [ + { + "environment_vars": [ + "BUILD_NAME={{user `build_name`}}" + ], + "execute_command": "BUILD_NAME={{user `build_name`}}; if [[ \"${BUILD_NAME}\" == *\"flatcar\"* ]]; then sudo {{.Vars}} -S -E bash '{{.Path}}'; fi", + "script": "./packer/files/flatcar/scripts/bootstrap-flatcar.sh", + "type": "shell" + }, + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} -o IdentitiesOnly=yes'" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}", + "--scp-extra-args={{user `scp_extra_vars`}}" + ], + "playbook_file": "./ansible/node.yml", + "type": "ansible", + "user": "builder" + }, + { + "arch": "{{user `goss_arch`}}", + "format": "{{user `goss_format`}}", + "format_options": "{{user `goss_format_options`}}", + "goss_file": "{{user `goss_entry_file`}}", + "inspect": "{{user `goss_inspect_mode`}}", + "tests": [ + "{{user `goss_tests_dir`}}" + ], + "type": "goss", + "url": "{{user `goss_url`}}", + "use_sudo": true, + "vars_file": "{{user `goss_vars_file`}}", + "vars_inline": { + "ARCH": "amd64", + "OS": "{{user `distro_name` | lower}}", + "PROVIDER": "nutanix", + "containerd_version": "{{user `containerd_version`}}", + "kubernetes_cni_deb_version": "{{ user `kubernetes_cni_deb_version` }}", + "kubernetes_cni_rpm_version": "{{ split (user `kubernetes_cni_rpm_version`) \"-\" 0 }}", + "kubernetes_cni_source_type": "{{user `kubernetes_cni_source_type`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver` | replace \"v\" \"\" 1}}", + "kubernetes_deb_version": "{{ user `kubernetes_deb_version` }}", + "kubernetes_rpm_version": "{{ split (user `kubernetes_rpm_version`) \"-\" 0 }}", + "kubernetes_source_type": "{{user `kubernetes_source_type`}}", + "kubernetes_version": "{{user `kubernetes_semver` | replace \"v\" \"\" 1}}" + }, + "version": "{{user `goss_version`}}" + } + ], + "variables": { + "ansible_common_vars": "", + "ansible_extra_vars": "", + "ansible_user_vars": "", + "build_timestamp": "{{timestamp}}", + "containerd_sha256": null, + "containerd_url": "https://github.com/containerd/containerd/releases/download/v{{user `containerd_version`}}/cri-containerd-cni-{{user `containerd_version`}}-linux-amd64.tar.gz", + "containerd_version": null, + "cpus": "1", + "crictl_url": "https://github.com/kubernetes-sigs/cri-tools/releases/download/v{{user `crictl_version`}}/crictl-v{{user `crictl_version`}}-linux-amd64.tar.gz", + "crictl_version": null, + "disk_size_gb": "10", + "existing_ansible_ssh_args": "{{env `ANSIBLE_SSH_ARGS`}}", + "image_name": "{{user `build_name`}}-kube-{{user `kubernetes_semver`}}", + "kubernetes_cni_deb_version": null, + "kubernetes_cni_http_source": null, + "kubernetes_cni_semver": null, + "kubernetes_cni_source_type": null, + "kubernetes_container_registry": null, + "kubernetes_deb_gpg_key": null, + "kubernetes_deb_repo": null, + "kubernetes_deb_version": null, + "kubernetes_http_source": null, + "kubernetes_load_additional_imgs": null, + "kubernetes_rpm_gpg_check": null, + "kubernetes_rpm_gpg_key": null, + "kubernetes_rpm_repo": null, + "kubernetes_rpm_version": null, + "kubernetes_semver": null, + "kubernetes_series": null, + "kubernetes_source_type": null, + "machine_id_mode": "444", + "memory": "2048", + "python_path": "", + "scp_extra_vars": "", + "ssh_password": "builder", + "ssh_username": "builder" + } +} diff --git a/packer/nutanix/rockylinux-8.json b/packer/nutanix/rockylinux-8.json new file mode 100644 index 0000000..defaa83 --- /dev/null +++ b/packer/nutanix/rockylinux-8.json @@ -0,0 +1,15 @@ +{ + "boot_type": "uefi", + "build_name": "rockylinux-8", + "distribution": "rockylinux", + "distribution_release": "Core", + "distribution_version": "8", + "distro_name": "rockylinux", + "epel_rpm_gpg_key": "https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8", + "extra_rpms": "python3", + "guest_os_type": "Linux", + "image_url": "https://dl.rockylinux.org/pub/rocky/8/images/x86_64/Rocky-8-GenericCloud-Base-8.7-20221130.0.x86_64.qcow2", + "redhat_epel_rpm": "https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm", + "shutdown_command": "shutdown -P now", + "user_data": "I2Nsb3VkLWNvbmZpZwp1c2VyczoKICAtIG5hbWU6IGJ1aWxkZXIKICAgIHN1ZG86IFsnQUxMPShBTEwpIE5PUEFTU1dEOkFMTCddCmNocGFzc3dkOgogIGxpc3Q6IHwKICAgIGJ1aWxkZXI6YnVpbGRlcgogIGV4cGlyZTogRmFsc2UKc3NoX3B3YXV0aDogVHJ1ZQ==" +} diff --git a/packer/nutanix/rockylinux-9.json b/packer/nutanix/rockylinux-9.json new file mode 100644 index 0000000..dd727e7 --- /dev/null +++ b/packer/nutanix/rockylinux-9.json @@ -0,0 +1,14 @@ +{ + "boot_type": "uefi", + "build_name": "rockylinux-9", + "distribution": "rockylinux", + "distribution_release": "Core", + "distribution_version": "9", + "distro_name": "rockylinux", + "epel_rpm_gpg_key": "https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-9", + "guest_os_type": "Linux", + "image_url": "https://dl.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base-9.1-20221130.0.x86_64.qcow2", + "redhat_epel_rpm": "https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm", + "shutdown_command": "shutdown -P now", + "user_data": "I2Nsb3VkLWNvbmZpZwp1c2VyczoKICAtIG5hbWU6IGJ1aWxkZXIKICAgIHN1ZG86IFsnQUxMPShBTEwpIE5PUEFTU1dEOkFMTCddCmNocGFzc3dkOgogIGxpc3Q6IHwKICAgIGJ1aWxkZXI6YnVpbGRlcgogIGV4cGlyZTogRmFsc2UKc3NoX3B3YXV0aDogVHJ1ZQ==" +} diff --git a/packer/nutanix/ubuntu-2004.json b/packer/nutanix/ubuntu-2004.json new file mode 100644 index 0000000..7c55d68 --- /dev/null +++ b/packer/nutanix/ubuntu-2004.json @@ -0,0 +1,8 @@ +{ + "build_name": "ubuntu-2004", + "distro_name": "ubuntu", + "guest_os_type": "Linux", + "image_url": "https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img", + "shutdown_command": "shutdown -P now", + "user_data": "I2Nsb3VkLWNvbmZpZwp1c2VyczoKICAtIG5hbWU6IGJ1aWxkZXIKICAgIHN1ZG86IFsnQUxMPShBTEwpIE5PUEFTU1dEOkFMTCddCiAgICBzaGVsbDogL2Jpbi9iYXNoCmNocGFzc3dkOgogIGxpc3Q6IHwKICAgIGJ1aWxkZXI6YnVpbGRlcgogIGV4cGlyZTogRmFsc2UKc3NoX3B3YXV0aDogVHJ1ZQo=" +} diff --git a/packer/nutanix/ubuntu-2204.json b/packer/nutanix/ubuntu-2204.json new file mode 100644 index 0000000..39946a9 --- /dev/null +++ b/packer/nutanix/ubuntu-2204.json @@ -0,0 +1,8 @@ +{ + "build_name": "ubuntu-2204", + "distro_name": "ubuntu", + "guest_os_type": "Linux", + "image_url": "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img", + "shutdown_command": "shutdown -P now", + "user_data": "I2Nsb3VkLWNvbmZpZwp1c2VyczoKICAtIG5hbWU6IGJ1aWxkZXIKICAgIHN1ZG86IFsnQUxMPShBTEwpIE5PUEFTU1dEOkFMTCddCiAgICBzaGVsbDogL2Jpbi9iYXNoCmNocGFzc3dkOgogIGxpc3Q6IHwKICAgIGJ1aWxkZXI6YnVpbGRlcgogIGV4cGlyZTogRmFsc2UKc3NoX3B3YXV0aDogVHJ1ZQo=" +} diff --git a/packer/nutanix/windows-2022.json b/packer/nutanix/windows-2022.json new file mode 100644 index 0000000..5a64a5c --- /dev/null +++ b/packer/nutanix/windows-2022.json @@ -0,0 +1,11 @@ +{ + "build_name": "windows-2022", + "distro_name": "windows", + "distro_version": "2022", + "guest_os_type": "Windows", + "runtime": "containerd", + "shutdown_command": "shutdown /s /t 10 /f /d p:4:1 /c \"Packer Shutdown\"", + "source_image_name": "en-us_windows_server_2022_x64_dvd_620d7eac", + "virtio_image_name": "Nutanix-VirtIO-1.2.1", + "wins_url": "" +} diff --git a/packer/nutanix/windows/disable-network-discovery.cmd b/packer/nutanix/windows/disable-network-discovery.cmd new file mode 100644 index 0000000..d2c47db --- /dev/null +++ b/packer/nutanix/windows/disable-network-discovery.cmd @@ -0,0 +1,2 @@ +reg ADD HKLM\SYSTEM\CurrentControlSet\Control\Network\NewNetworkWindowOff /f +netsh advfirewall firewall set rule group="Network Discovery" new enable=No \ No newline at end of file diff --git a/packer/nutanix/windows/sysprep.ps1 b/packer/nutanix/windows/sysprep.ps1 new file mode 100644 index 0000000..571c759 --- /dev/null +++ b/packer/nutanix/windows/sysprep.ps1 @@ -0,0 +1,31 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Write-Output '>>> Sysprepping VM ...' + +Write-Output 'Removing default unattend.xml file...' +if( Test-Path $Env:SystemRoot\system32\Sysprep\unattend.xml ) { + Remove-Item $Env:SystemRoot\system32\Sysprep\unattend.xml -Force +} + +$unattendedXml = "$ENV:ProgramFiles\Cloudbase Solutions\Cloudbase-Init\conf\Unattend.xml" +$FileExists = Test-Path $unattendedXml + +If ($FileExists -eq $True) { + # Use the Cloudbase-init provided unattend file during install + Write-Output "Using cloudbase-init unattend file for sysprep: $unattendedXml" + & $Env:SystemRoot\System32\Sysprep\Sysprep.exe /oobe /generalize /mode:vm /shutdown /quiet /unattend:$unattendedXml +}else { + & $Env:SystemRoot\System32\Sysprep\Sysprep.exe /oobe /generalize /mode:vm /shutdown /quiet +} diff --git a/packer/nutanix/windows/windows-2022/autounattend.xml b/packer/nutanix/windows/windows-2022/autounattend.xml new file mode 100644 index 0000000..77d5e6d --- /dev/null +++ b/packer/nutanix/windows/windows-2022/autounattend.xml @@ -0,0 +1,265 @@ + + + + + + + + + e:\Windows Server 2022\x64 + + + + + + + + + 1 + 350 + Primary + + + 2 + true + Primary + + + + + NTFS + + 1 + 1 + 0x27 + + + 2 + 2 + C + + NTFS + + + 0 + true + + + + + + 0 + 2 + + + + /IMAGE/NAME + Windows Server 2022 SERVERSTANDARDCORE + + + + + + true + Administrator + Organization + + VDYBN-27WPP-V4HQT-9VMD4-VMK7H + OnError + + + true + + + + en-US + + 0409:00000409 + en-US + en-US + en-US + en-US + + + + + false + + + + + 1 + + + + + 0409:00000409 + en-US + en-US + en-US + en-US + + + true + + + 0 + + + + VDYBN-27WPP-V4HQT-9VMD4-VMK7H + + + + + + + S3cr3t0! + true</PlainText> + </Password> + <Enabled>true</Enabled> + <Username>Administrator</Username> + </AutoLogon> + <FirstLogonCommands> + <SynchronousCommand wcm:action="add"> + <Order>1</Order> + <Description>Set Execution Policy 64 Bit</Description> + <CommandLine>cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <Order>2</Order> + <Description>Set Execution Policy 32 Bit</Description> + <CommandLine>%SystemDrive%\Windows\SysWOW64\cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine> + <Order>3</Order> + <Description>Show file extensions in Explorer</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine> + <Order>4</Order> + <Description>Enable QuickEdit mode</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine> + <Order>5</Order> + <Description>Show Run command in Start Menu</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine> + <Order>6</Order> + <Description>Show Administrative Tools in Start Menu</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine> + <Order>7</Order> + <Description>Zero Hibernation File</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine> + <Order>8</Order> + <Description>Disable Hibernation Mode</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE</CommandLine> + <Order>9</Order> + <Description>Disable password expiration for Administrator user</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "WinRMCertificate"</CommandLine> + <Description>Certificate for WinRM</Description> + <Order>10</Order> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command Enable-PSRemoting -SkipNetworkProfileCheck -Force</CommandLine> + <Description>Enable WinRM</Description> + <Order>11</Order> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command ($cert = gci Cert:\LocalMachine\My\) -and (New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $cert.Thumbprint –Force)</CommandLine> + <Description>Add HTTPS WinRM listener with previously generated certificate</Description> + <Order>12</Order> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command New-NetFirewallRule -DisplayName 'Windows Remote Management (HTTPS-In)' -Name 'Windows Remote Management (HTTPS-In)' -Profile Any -LocalPort 5986 -Protocol TCP</CommandLine> + <Description>Add firewall exception to TCP port 5986 for WinRM over HTTPS</Description> + <Order>13</Order> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command Set-Item WSMan:\localhost\Service\Auth\Basic -Value $true</CommandLine> + <Description>Enable Basic authentication</Description> + <Order>14</Order> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c f:\disable-network-discovery.cmd</CommandLine> + <Description>Disable Network Discovery</Description> + <Order>15</Order> + </SynchronousCommand> + </FirstLogonCommands> + <OOBE> + <HideEULAPage>true</HideEULAPage> + <HideLocalAccountScreen>true</HideLocalAccountScreen> + <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen> + <HideOnlineAccountScreens>true</HideOnlineAccountScreens> + <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> + <NetworkLocation>Work</NetworkLocation> + <ProtectYourPC>1</ProtectYourPC> + <SkipMachineOOBE>true</SkipMachineOOBE> + <SkipUserOOBE>true</SkipUserOOBE> + </OOBE> + <RegisteredOrganization>Organization</RegisteredOrganization> + <RegisteredOwner>Owner</RegisteredOwner> + <DisableAutoDaylightTimeSet>false</DisableAutoDaylightTimeSet> + <TimeZone>Pacific Standard Time</TimeZone> + <UserAccounts> + <AdministratorPassword> + <Value>S3cr3t0!</Value> + <PlainText>true</PlainText> + </AdministratorPassword> + <LocalAccounts> + <LocalAccount wcm:action="add"> + <Description>Administrator</Description> + <DisplayName>Administrator</DisplayName> + <Group>Administrators</Group> + <Name>Administrator</Name> + </LocalAccount> + </LocalAccounts> + </UserAccounts> + </component> + </settings> +</unattend> diff --git a/packer/oci/oracle-linux-8.json b/packer/oci/oracle-linux-8.json new file mode 100644 index 0000000..3949ed1 --- /dev/null +++ b/packer/oci/oracle-linux-8.json @@ -0,0 +1,8 @@ +{ + "build_name": "oracle-linux-8", + "distribution": "Oracle Linux", + "operating_system": "Oracle Linux", + "operating_system_version": "8", + "redhat_epel_rpm": "oracle-epel-release-el8", + "ssh_username": "opc" +} diff --git a/packer/oci/oracle-linux-9.json b/packer/oci/oracle-linux-9.json new file mode 100644 index 0000000..fc13227 --- /dev/null +++ b/packer/oci/oracle-linux-9.json @@ -0,0 +1,8 @@ +{ + "build_name": "oracle-linux-9", + "distribution": "Oracle Linux", + "operating_system": "Oracle Linux", + "operating_system_version": "9", + "redhat_epel_rpm": "oracle-epel-release-el9", + "ssh_username": "opc" +} diff --git a/packer/oci/packer-windows.json b/packer/oci/packer-windows.json new file mode 100644 index 0000000..c9ee812 --- /dev/null +++ b/packer/oci/packer-windows.json @@ -0,0 +1,148 @@ +{ + "builders": [ + { + "availability_domain": "{{user `availability_domain`}}", + "base_image_filter": { + "operating_system": "{{user `operating_system`}}", + "operating_system_version": "{{user `operating_system_version`}}" + }, + "base_image_ocid": "{{user `base_image_ocid`}}", + "communicator": "winrm", + "compartment_ocid": "{{user `compartment_ocid`}}", + "image_name": "cluster-api-{{user `build_name`}}-{{user `kubernetes_semver`}}-{{user `build_timestamp`}}", + "shape": "{{user `shape`}}", + "shape_config": { + "ocpus": "{{user `ocpus`}}" + }, + "subnet_ocid": "{{user `subnet_ocid`}}", + "tenancy_ocid": "{{user `tenancy_ocid`}}", + "type": "oracle-oci", + "user_data_file": "packer/oci/scripts/winrm_bootstrap.txt", + "user_ocid": "{{user `user_ocid`}}", + "winrm_insecure": true, + "winrm_password": "{{user `opc_user_password`}}", + "winrm_port": 5986, + "winrm_timeout": "10m", + "winrm_use_ntlm": true, + "winrm_use_ssl": true, + "winrm_username": "opc" + } + ], + "post-processors": [ + { + "custom_data": { + "build_date": "{{isotime}}", + "build_name": "{{user `build_name`}}", + "build_timestamp": "{{user `build_timestamp`}}", + "build_type": "node", + "containerd_version": "{{user `containerd_version`}}", + "kubernetes_cni_semver": "{{user `kubernetes_cni_semver`}}", + "kubernetes_semver": "{{user `kubernetes_semver`}}", + "kubernetes_source_type": "{{user `kubernetes_source_type`}}", + "os_name": "{{user `distro_name`}}", + "resource_group_name": "{{user `resource_group_name`}}", + "storage_account_name": "{{user `storage_account_name`}}" + }, + "output": "{{user `manifest_output`}}", + "strip_path": true, + "type": "manifest" + } + ], + "provisioners": [ + { + "elevated_password": "{{.WinRMPassword}}", + "elevated_user": "opc", + "script": "ansible/windows/ansible_winrm.ps1", + "type": "powershell" + }, + { + "extra_arguments": [ + "-e", + "ansible_winrm_server_cert_validation=ignore ansible_winrm_operation_timeout_sec=120 ansible_winrm_read_timeout_sec=150", + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `azure_extra_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}" + ], + "max_retries": 5, + "pause_before": "15s", + "playbook_file": "ansible/windows/node_windows.yml", + "type": "ansible", + "use_proxy": false, + "user": "opc" + }, + { + "restart_timeout": "10m", + "type": "windows-restart" + }, + { + "destination": "C:\\Users\\opc\\", + "source": "./packer/oci/scripts/sysprep.ps1", + "type": "file" + }, + { + "destination": "C:\\Users\\opc\\", + "source": "./packer/oci/scripts/attach_secondary_vnic.ps1", + "type": "file" + }, + { + "destination": "C:\\Windows\\Setup\\Scripts\\", + "source": "./packer/oci/scripts/enable_second_nic.ps1", + "type": "file" + }, + { + "inline": [ + "rm -Force -Recurse C:\\var\\log\\kubelet\\*" + ], + "type": "powershell" + }, + { + "elevated_password": "{{.WinRMPassword}}", + "elevated_user": "opc", + "inline": [ + "C:\\Users\\opc\\sysprep.ps1" + ], + "type": "powershell" + } + ], + "variables": { + "additional_debug_files": null, + "ansible_common_vars": "", + "ansible_extra_vars": "", + "ansible_user_vars": "", + "azure_extra_vars": "wire_server_users={{user `wire_server_users`}}", + "build_name": null, + "build_timestamp": "{{timestamp}}", + "cloudbase_init_url": "https://github.com/cloudbase/cloudbase-init/releases/download/{{user `cloudbase_init_version`}}/CloudbaseInitSetup_{{user `cloudbase_init_version` | replace_all `.` `_` }}_x64.msi", + "cloudbase_logging_serial_port": "COM1,9600,N,8", + "cloudbase_metadata_services": "cloudbaseinit.metadata.services.httpservice.HttpService", + "cloudbase_metadata_services_unattend": "cloudbaseinit.metadata.services.httpservice.HttpService", + "cloudbase_plugins": "cloudbaseinit.plugins.common.ephemeraldisk.EphemeralDiskPlugin, cloudbaseinit.plugins.common.mtu.MTUPlugin, cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin", + "cloudbase_plugins_unattend": "cloudbaseinit.plugins.common.mtu.MTUPlugin", + "containerd_url": "", + "containerd_version": null, + "ib_version": "{{env `IB_VERSION`}}", + "image_version": "latest", + "kubernetes_base_url": "https://kubernetesreleases.blob.core.windows.net/kubernetes/{{user `kubernetes_semver`}}/binaries/node/windows/{{user `kubernetes_goarch`}}", + "manifest_output": "manifest.json", + "nssm_url": null, + "ocpus": "2", + "opc_user_password": "{{env `OPC_USER_PASSWORD`}}", + "prepull": null, + "private_virtual_network_with_public_ip": "", + "runtime": "containerd", + "shape": "VM.Standard.E4.Flex", + "virtual_network_name": "", + "virtual_network_resource_group_name": "", + "virtual_network_subnet_name": "", + "vm_size": "", + "windows_service_manager": null, + "windows_updates_kbs": null, + "wins_url": "", + "wire_server_users": "" + } +} diff --git a/packer/oci/packer.json b/packer/oci/packer.json new file mode 100644 index 0000000..7205ae6 --- /dev/null +++ b/packer/oci/packer.json @@ -0,0 +1,150 @@ +{ + "builders": [ + { + "availability_domain": "{{user `availability_domain`}}", + "base_image_filter": { + "operating_system": "{{user `operating_system`}}", + "operating_system_version": "{{user `operating_system_version`}}" + }, + "base_image_ocid": "{{user `base_image_ocid`}}", + "compartment_ocid": "{{user `compartment_ocid`}}", + "fingerprint": "{{user `fingerprint`}}", + "image_name": "cluster-api-{{user `build_name`}}-{{user `kubernetes_semver`}}-{{user `build_timestamp`}}", + "key_file": "{{user `key_file`}}", + "region": "{{user `region`}}", + "shape": "{{user `shape`}}", + "shape_config": { + "ocpus": "{{user `ocpus`}}" + }, + "ssh_private_key_file": "{{ user `ssh_private_key_file`}}", + "ssh_username": "{{user `ssh_username`}}", + "subnet_ocid": "{{user `subnet_ocid`}}", + "tags": { + "build_date": "{{isotime}}", + "build_timestamp": "{{user `build_timestamp`}}", + "containerd_version": "{{user `containerd_version`}}", + "distribution": "{{user `operating_system`}}", + "distribution_version": "{{user `operating_system_version`}}", + "image_builder_version": "{{user `ib_version`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}" + }, + "tenancy_ocid": "{{user `tenancy_ocid`}}", + "type": "oracle-oci", + "use_private_ip": "{{user `use_private_ip`}}", + "user_data": "{{user `user_data`}}", + "user_ocid": "{{user `user_ocid`}}" + } + ], + "provisioners": [ + { + "environment_vars": [ + "BUILD_NAME={{user `build_name`}}" + ], + "inline": [ + "if [ $BUILD_NAME != \"ubuntu-1804\" ] || [ $BUILD_NAME != \"ubuntu-2004\" ]; then exit 0; fi", + "while [ ! -f /var/lib/cloud/instance/boot-finished ]; do echo 'Waiting for cloud-init...'; sleep 1; done", + "sudo apt-get -qq update && sudo DEBIAN_FRONTEND=noninteractive apt-get -qqy install python python-pip" + ], + "type": "shell" + }, + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} {{user `ansible_common_ssh_args`}}'" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}" + ], + "playbook_file": "./ansible/node.yml", + "type": "ansible" + }, + { + "arch": "{{user `goss_arch`}}", + "download_path": "{{user `goss_download_path`}}", + "format": "{{user `goss_format`}}", + "format_options": "{{user `goss_format_options`}}", + "goss_file": "{{user `goss_entry_file`}}", + "inspect": "{{user `goss_inspect_mode`}}", + "remote_folder": "{{user `goss_remote_folder`}}", + "remote_path": "{{user `goss_remote_path`}}", + "skip_install": "{{user `goss_skip_install`}}", + "tests": [ + "{{user `goss_tests_dir`}}" + ], + "type": "goss", + "url": "{{user `goss_url`}}", + "use_sudo": true, + "vars_file": "{{user `goss_vars_file`}}", + "vars_inline": { + "ARCH": "amd64", + "OS": "{{user `distribution` | lower }}", + "PROVIDER": "oci", + "containerd_version": "{{user `containerd_version`}}", + "kubernetes_cni_deb_version": "{{ user `kubernetes_cni_deb_version` }}", + "kubernetes_cni_rpm_version": "{{ split (user `kubernetes_cni_rpm_version`) \"-\" 0 }}", + "kubernetes_cni_source_type": "{{user `kubernetes_cni_source_type`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver` | replace \"v\" \"\" 1}}", + "kubernetes_deb_version": "{{ user `kubernetes_deb_version` }}", + "kubernetes_rpm_version": "{{ split (user `kubernetes_rpm_version`) \"-\" 0 }}", + "kubernetes_source_type": "{{user `kubernetes_source_type`}}", + "kubernetes_version": "{{user `kubernetes_semver` | replace \"v\" \"\" 1}}" + }, + "version": "{{user `goss_version`}}" + } + ], + "variables": { + "ansible_common_vars": "", + "ansible_extra_vars": "", + "ansible_user_vars": "", + "availability_domain": "{{env `OCI_AVAILABILITY_DOMAIN`}}", + "base_image_ocid": "", + "build_timestamp": "{{timestamp}}", + "compartment_ocid": "", + "containerd_sha256": null, + "containerd_url": "https://github.com/containerd/containerd/releases/download/v{{user `containerd_version`}}/cri-containerd-cni-{{user `containerd_version`}}-linux-amd64.tar.gz", + "containerd_version": null, + "crictl_url": "https://github.com/kubernetes-sigs/cri-tools/releases/download/v{{user `crictl_version`}}/crictl-v{{user `crictl_version`}}-linux-amd64.tar.gz", + "crictl_version": null, + "disable_default_service_account": "", + "encrypted": "false", + "existing_ansible_ssh_args": "{{env `ANSIBLE_SSH_ARGS`}}", + "fingerprint": "{{env `OCI_USER_FINGERPRINT`}}", + "ib_version": "{{env `IB_VERSION`}}", + "key_file": "{{env `OCI_USER_KEY_FILE`}}", + "kubernetes_cni_deb_version": null, + "kubernetes_cni_http_source": null, + "kubernetes_cni_rpm_version": null, + "kubernetes_cni_semver": null, + "kubernetes_cni_source_type": null, + "kubernetes_container_registry": null, + "kubernetes_deb_gpg_key": null, + "kubernetes_deb_repo": null, + "kubernetes_deb_version": null, + "kubernetes_http_source": null, + "kubernetes_load_additional_imgs": null, + "kubernetes_rpm_gpg_check": null, + "kubernetes_rpm_gpg_key": null, + "kubernetes_rpm_repo": null, + "kubernetes_rpm_version": null, + "kubernetes_semver": null, + "kubernetes_series": null, + "kubernetes_source_type": null, + "ocpus": "1", + "operating_system": null, + "operating_system_version": null, + "region": "us-ashburn-1", + "shape": "VM.Standard.E4.Flex", + "ssh_private_key_file": "", + "ssh_username": null, + "subnet_ocid": "{{env `OCI_SUBNET_OCID`}}", + "tenancy_ocid": "{{env `OCI_TENANCY_OCID`}}", + "use_private_ip": "false", + "user_data": "", + "user_ocid": "{{env `OCI_USER_OCID`}}" + } +} diff --git a/packer/oci/scripts/attach_secondary_vnic.ps1 b/packer/oci/scripts/attach_secondary_vnic.ps1 new file mode 100644 index 0000000..4bbb53d --- /dev/null +++ b/packer/oci/scripts/attach_secondary_vnic.ps1 @@ -0,0 +1,39 @@ +function Get-Second-Vnic-Ocid() { + $ocid = "" + $vnics = Invoke-RestMethod -Uri "http://169.254.169.254/opc/v1/vnics/" + if ($vnics.Count -eq 2) { + $ocid = $vnics[1].vnicId + } else { + Write-Host "vnics count not equal 2" + } + return $ocid +} + +$vnicId = Get-Second-Vnic-Ocid +Write-Host "found vnic id: ${vnicId}" + + +$retryDelaySeconds = 30 +# We should continue to retry indefinitely until the vnic is +# detected by IMDS +# https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/gettingmetadata.htm +while($vnicId -eq "") { + $vnicId = Get-Second-Vnic-Ocid + Write-Host("Getting second vnic failed. Waiting " + $retryDelaySeconds + " seconds before next attempt.") + Start-Sleep -Seconds $retryDelaySeconds +} + +if ($vnicId -ne "") { + Write-Host "Pulling down the secondary_vnic_windows_configure.ps1" + Invoke-WebRequest -Uri "https://docs.oracle.com/en-us/iaas/Content/Resources/Assets/secondary_vnic_windows_configure.ps1" -OutFile "C:\Users\opc\secondary_vnic_windows_configure.ps1" + + Write-Host "calling script using ${vnicId}" + + , 'Y', 'A' | powershell "C:\Users\opc\secondary_vnic_windows_configure.ps1 ${vnicId}" + Write-Error "secondary_vnic_windows_configure.ps1 - done" + + $ipconfig = ipconfig + Write-Error "${ipconfig}" +}else{ + Write-Error "VNIC OCID is empty. Can't configure." +} \ No newline at end of file diff --git a/packer/oci/scripts/enable_second_nic.ps1 b/packer/oci/scripts/enable_second_nic.ps1 new file mode 100644 index 0000000..764cfe7 --- /dev/null +++ b/packer/oci/scripts/enable_second_nic.ps1 @@ -0,0 +1,47 @@ + +$newNetAdapterName = "Ethernet 2" + +# check for two nics +$netAdapters = Get-NetAdapter +if ($netAdapters.Length -le 1) { + Write-Output "Could not find multiple Network Adapters." + Exit 1 +} + +$secondNic = $netAdapters[1] + +# make sure the network adapter is known +if ($secondNic.Name -ne "") { + Write-Output "Changing ${secondNic.Name} to ${newNetAdapterName} ..." + try + { + Rename-NetAdapter -Name $secondNic.Name -NewName "${newNetAdapterName}" + $secondNic.Name = $newNetAdapterName + } + catch + { + Write-Output "Could not rename net adapter" + Write-Output $_ + } +} else { + Write-Output "Can not change network adapter named: ${secondNic.Name}" +} + +# check that second is disabled +if ($secondNic.Status -ne "up") { + + try + { + Enable-NetAdapter -Name $secondNic.Name + Write-Output "${secondNic.Name} enabled ..." + } + catch + { + Write-Output "Could not enable net adapter" + Write-Output $_ + } +} else { + Write-Output "${secondNic.Name} already enabled ..." +} + +Remove-Item -Path .\enable_second_nic.ps1 \ No newline at end of file diff --git a/packer/oci/scripts/set_bootstrap.sh b/packer/oci/scripts/set_bootstrap.sh new file mode 100755 index 0000000..3814f46 --- /dev/null +++ b/packer/oci/scripts/set_bootstrap.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script overrides the 'opc' password set in the winrm_bootstrap.txt file +# This script is assumed to be run from the make file hence the pathing to the winrm_bootstrap.txt + +set -o errexit +set -o nounset +set -o pipefail + +echo "Changing Password in winrm_bootstrap.txt" + +cp packer/oci/scripts/winrm_bootstrap_template.txt packer/oci/scripts/winrm_bootstrap.txt + +sed "s/(\[adsi\].*/([adsi](\"WinNT:\/\/\"+\$opcUser.caption).replace(\"\\\\\",\"\/\")).SetPassword(\"$OPC_USER_PASSWORD\")/g" packer/oci/scripts/winrm_bootstrap.txt | tee packer/oci/scripts/winrm_bootstrap.txt >/dev/null diff --git a/packer/oci/scripts/sysprep.ps1 b/packer/oci/scripts/sysprep.ps1 new file mode 100644 index 0000000..5f25fd7 --- /dev/null +++ b/packer/oci/scripts/sysprep.ps1 @@ -0,0 +1,37 @@ +# Copyright 2020 The Kubernetes Authors. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if( Test-Path $Env:SystemRoot\system32\Sysprep\unattend.xml ) { + Remove-Item $Env:SystemRoot\system32\Sysprep\unattend.xml -Force +} + +$unattendedXml = "$ENV:ProgramFiles\Cloudbase Solutions\Cloudbase-Init\conf\Unattend.xml" +$FileExists = Test-Path $unattendedXml +If ($FileExists -eq $True) { + # Use the Cloudbase-init provided unattend file during install + Write-Output "Using cloudbase-init unattend file for sysprep: $unattendedXml" + & $Env:SystemRoot\System32\Sysprep\Sysprep.exe /oobe /generalize /mode:vm /quit /quiet /unattend:$unattendedXml +}else { + & $Env:SystemRoot\System32\Sysprep\Sysprep.exe /oobe /generalize /mode:vm /quit /quiet +} + +# Wait for the image to be reset +while($true) { + $imageState = (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\State).ImageState + Write-Output $imageState + if ($imageState -eq 'IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE') { break } + Start-Sleep -s 5 +} + +Write-Output '>>> Sysprep complete ...' diff --git a/packer/oci/scripts/unset_bootstrap.sh b/packer/oci/scripts/unset_bootstrap.sh new file mode 100755 index 0000000..c2162da --- /dev/null +++ b/packer/oci/scripts/unset_bootstrap.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script overrides the 'opc' password set in the winrm_bootstrap.txt file +# This script is assumed to be run from the make file hence the pathing to the winrm_bootstrap.txt + +set -o errexit +set -o nounset +set -o pipefail + +echo "resetting Password in winrm_bootstrap.txt" + +rm packer/oci/scripts/winrm_bootstrap.txt diff --git a/packer/oci/scripts/winrm_bootstrap_template.txt b/packer/oci/scripts/winrm_bootstrap_template.txt new file mode 100644 index 0000000..31b7fbb --- /dev/null +++ b/packer/oci/scripts/winrm_bootstrap_template.txt @@ -0,0 +1,50 @@ +<powershell> + +# MAKE SURE IN YOUR PACKER CONFIG TO SET: +# +# +# "winrm_username": "Administrator", +# "winrm_insecure": true, +# "winrm_use_ssl": true, +# +# +#ps1_sysnative +cmd /C 'wmic UserAccount where Name="opc" set PasswordExpires=False' +$opcUser = get-wmiobject win32_useraccount | Where-Object { $_.Name -match 'opc' } +([adsi]("WinNT://"+$opcUser.caption).replace("\","/")).SetPassword("myTemp#Pa55_Word") + +write-output "Running User Data Script" +write-host "(host) Running User Data Script" + +Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force -ErrorAction Ignore + +# Don't set this before Set-ExecutionPolicy as it throws an error +$ErrorActionPreference = "stop" + +# Remove HTTP listener +Remove-Item -Path WSMan:\Localhost\listener\listener* -Recurse + +# Create a self-signed certificate to let ssl work +$Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "packer" +New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert.Thumbprint -Force + +# WinRM +write-output "Setting up WinRM" +write-host "(host) setting up WinRM" + +cmd.exe /c winrm quickconfig -q +cmd.exe /c winrm set "winrm/config" '@{MaxTimeoutms="1800000"}' +cmd.exe /c winrm set "winrm/config/winrs" '@{MaxMemoryPerShellMB="1024"}' +cmd.exe /c winrm set "winrm/config/service" '@{AllowUnencrypted="true"}' +cmd.exe /c winrm set "winrm/config/client" '@{AllowUnencrypted="true"}' +cmd.exe /c winrm set "winrm/config/service/auth" '@{Basic="true"}' +cmd.exe /c winrm set "winrm/config/client/auth" '@{Basic="true"}' +cmd.exe /c winrm set "winrm/config/service/auth" '@{CredSSP="true"}' +cmd.exe /c winrm set "winrm/config/listener?Address=*+Transport=HTTPS" "@{Port=`"5986`";Hostname=`"packer`";CertificateThumbprint=`"$($Cert.Thumbprint)`"}" +cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes +cmd.exe /c netsh firewall add portopening TCP 5986 "Port 5986" +cmd.exe /c net stop winrm +cmd.exe /c sc config winrm start= auto +cmd.exe /c net start winrm + +</powershell> \ No newline at end of file diff --git a/packer/oci/ubuntu-1804.json b/packer/oci/ubuntu-1804.json new file mode 100644 index 0000000..254297c --- /dev/null +++ b/packer/oci/ubuntu-1804.json @@ -0,0 +1,7 @@ +{ + "build_name": "ubuntu-1804", + "distribution": "ubuntu", + "operating_system": "Canonical Ubuntu", + "operating_system_version": "18.04", + "ssh_username": "ubuntu" +} diff --git a/packer/oci/ubuntu-2004.json b/packer/oci/ubuntu-2004.json new file mode 100644 index 0000000..82f82d0 --- /dev/null +++ b/packer/oci/ubuntu-2004.json @@ -0,0 +1,7 @@ +{ + "build_name": "ubuntu-2004", + "distribution": "ubuntu", + "operating_system": "Canonical Ubuntu", + "operating_system_version": "20.04", + "ssh_username": "ubuntu" +} diff --git a/packer/oci/ubuntu-2204.json b/packer/oci/ubuntu-2204.json new file mode 100644 index 0000000..b0d45bf --- /dev/null +++ b/packer/oci/ubuntu-2204.json @@ -0,0 +1,7 @@ +{ + "build_name": "ubuntu-2204", + "distribution": "ubuntu", + "operating_system": "Canonical Ubuntu", + "operating_system_version": "22.04", + "ssh_username": "ubuntu" +} diff --git a/packer/oci/windows-2019.json b/packer/oci/windows-2019.json new file mode 100644 index 0000000..a3b8bef --- /dev/null +++ b/packer/oci/windows-2019.json @@ -0,0 +1,7 @@ +{ + "build_name": "windows-2019", + "operating_system": "Windows", + "operating_system_version": "Server 2019 Standard", + "runtime": "containerd", + "ssh_username": "opc" +} diff --git a/packer/oci/windows-2022.json b/packer/oci/windows-2022.json new file mode 100644 index 0000000..c27b30f --- /dev/null +++ b/packer/oci/windows-2022.json @@ -0,0 +1,7 @@ +{ + "build_name": "windows-2022", + "operating_system": "Windows", + "operating_system_version": "Server 2022 Standard", + "runtime": "containerd", + "ssh_username": "opc" +} diff --git a/packer/outscale/ci/nightly/overwrite-1-21.json b/packer/outscale/ci/nightly/overwrite-1-21.json new file mode 100644 index 0000000..4d83489 --- /dev/null +++ b/packer/outscale/ci/nightly/overwrite-1-21.json @@ -0,0 +1,7 @@ +{ + "build_timestamp": "nightly", + "kubernetes_deb_version": "1.21.14-00", + "kubernetes_rpm_version": "1.21.14-0", + "kubernetes_semver": "v1.21.14", + "kubernetes_series": "v1.21" +} diff --git a/packer/outscale/ci/nightly/overwrite-1-22.json b/packer/outscale/ci/nightly/overwrite-1-22.json new file mode 100644 index 0000000..e06e114 --- /dev/null +++ b/packer/outscale/ci/nightly/overwrite-1-22.json @@ -0,0 +1,7 @@ +{ + "build_timestamp": "nightly", + "kubernetes_deb_version": "1.22.11-00", + "kubernetes_rpm_version": "1.22.11-0", + "kubernetes_semver": "v1.22.11", + "kubernetes_series": "v1.22" +} diff --git a/packer/outscale/ci/nightly/overwrite-1-23.json b/packer/outscale/ci/nightly/overwrite-1-23.json new file mode 100644 index 0000000..d723ef2 --- /dev/null +++ b/packer/outscale/ci/nightly/overwrite-1-23.json @@ -0,0 +1,7 @@ +{ + "build_timestamp": "nightly", + "kubernetes_deb_version": "1.23.8-00", + "kubernetes_rpm_version": "1.23.8-0", + "kubernetes_semver": "v1.23.8", + "kubernetes_series": "v1.23" +} diff --git a/packer/outscale/ci/nightly/overwrite-1-24.json b/packer/outscale/ci/nightly/overwrite-1-24.json new file mode 100644 index 0000000..9c89d61 --- /dev/null +++ b/packer/outscale/ci/nightly/overwrite-1-24.json @@ -0,0 +1,7 @@ +{ + "build_timestamp": "nightly", + "kubernetes_deb_version": "1.24.2-00", + "kubernetes_rpm_version": "1.24.2-0", + "kubernetes_semver": "v1.24.2", + "kubernetes_series": "v1.24" +} diff --git a/packer/outscale/ci/nightly/overwrite-1-25.json b/packer/outscale/ci/nightly/overwrite-1-25.json new file mode 100644 index 0000000..9f4b1cd --- /dev/null +++ b/packer/outscale/ci/nightly/overwrite-1-25.json @@ -0,0 +1,7 @@ +{ + "build_timestamp": "nightly", + "kubernetes_deb_version": "1.25.2-00", + "kubernetes_rpm_version": "1.25.2-0", + "kubernetes_semver": "v1.25.2", + "kubernetes_series": "v1.25" +} diff --git a/packer/outscale/packer.json b/packer/outscale/packer.json new file mode 100644 index 0000000..0c70ea8 --- /dev/null +++ b/packer/outscale/packer.json @@ -0,0 +1,124 @@ +{ + "builders": [ + { + "access_key": "{{ user `access_key` }}", + "omi_name": "{{user `build_name`}}-{{user `distribution_version`}}-kubernetes-{{user `kubernetes_semver`}}-{{isotime `2006-01-02`}}", + "region": "{{ user `region` }}", + "secret_key": "{{ user `secret_key` }}", + "source_omi": "{{ user `source_image` }}", + "source_omi_filter": { + "filters": { + "image-name": "{{ user `image_name` }}" + }, + "owners": [ + "Outscale" + ] + }, + "ssh_username": "outscale", + "tags": { + "Base_OMI_Name": "{{ .SourceOMIName }}", + "Extra": "{{ .SourceOMITags.TagName }}", + "OS_Version": "{{user `distribution_release`}}", + "Release": "{{user `distribution_version`}}", + "distribution_release": "{{user `distribution_release`}}", + "distribution_version": "{{user `distribution_version`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}" + }, + "type": "outscale-bsu", + "vm_type": "tinav5.c2r4p2" + } + ], + "provisioners": [ + { + "environment_vars": [ + "BUILD_NAME={{user `build_name`}}" + ], + "inline": [ + "if [ $BUILD_NAME != \"ubuntu-1804\" ]; then exit 0; fi", + "while [ ! -f /var/lib/cloud/instance/boot-finished ]; do echo 'Waiting for cloud-init...'; sleep 1; done", + "sudo apt-get -qq update && sudo DEBIAN_FRONTEND=noninteractive apt-get -qqy install python python-pip" + ], + "type": "shell" + }, + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} -o IdentitiesOnly=yes'" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}" + ], + "playbook_file": "./ansible/node.yml", + "type": "ansible" + }, + { + "arch": "{{user `goss_arch`}}", + "download_path": "{{user `goss_download_path`}}", + "format": "{{user `goss_format`}}", + "format_options": "{{user `goss_format_options`}}", + "goss_file": "{{user `goss_entry_file`}}", + "inspect": "{{user `goss_inspect_mode`}}", + "remote_folder": "{{user `goss_remote_folder`}}", + "remote_path": "{{user `goss_remote_path`}}", + "skip_install": "{{user `goss_skip_install`}}", + "tests": [ + "{{user `goss_tests_dir`}}" + ], + "type": "goss", + "url": "{{user `goss_url`}}", + "use_sudo": true, + "vars_file": "{{user `goss_vars_file`}}", + "vars_inline": { + "ARCH": "amd64", + "OS": "{{user `distribution` | lower}}", + "PROVIDER": "outscale", + "containerd_version": "{{user `containerd_version`}}", + "kubernetes_cni_deb_version": "{{ user `kubernetes_cni_deb_version` }}", + "kubernetes_cni_rpm_version": "{{ split (user `kubernetes_cni_rpm_version`) \"-\" 0 }}", + "kubernetes_cni_source_type": "{{user `kubernetes_cni_source_type`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver` | replace \"v\" \"\" 1}}", + "kubernetes_deb_version": "{{ user `kubernetes_deb_version` }}", + "kubernetes_rpm_version": "{{ split (user `kubernetes_rpm_version`) \"-\" 0 }}", + "kubernetes_source_type": "{{user `kubernetes_source_type`}}", + "kubernetes_version": "{{user `kubernetes_semver` | replace \"v\" \"\" 1}}" + }, + "version": "{{user `goss_version`}}" + } + ], + "variables": { + "access_key": "{{env `OSC_ACCESS_KEY`}}", + "ansible_common_vars": "", + "ansible_extra_vars": "", + "build_timestamp": "{{timestamp}}", + "containerd_sha256": null, + "containerd_url": "https://github.com/containerd/containerd/releases/download/v{{user `containerd_version`}}/cri-containerd-cni-{{user `containerd_version`}}-linux-amd64.tar.gz", + "containerd_version": null, + "crictl_url": "https://github.com/kubernetes-sigs/cri-tools/releases/download/v{{user `crictl_version`}}/crictl-v{{user `crictl_version`}}-linux-amd64.tar.gz", + "crictl_version": null, + "distribution_release": null, + "distribution_version": null, + "existing_ansible_ssh_args": "{{env `ANSIBLE_SSH_ARGS`}}", + "kubernetes_cni_deb_version": null, + "kubernetes_cni_http_source": null, + "kubernetes_cni_rpm_version": null, + "kubernetes_cni_semver": null, + "kubernetes_cni_source_type": null, + "kubernetes_container_registry": null, + "kubernetes_deb_gpg_key": null, + "kubernetes_deb_repo": null, + "kubernetes_deb_version": null, + "kubernetes_http_source": null, + "kubernetes_load_additional_imgs": null, + "kubernetes_rpm_gpg_check": null, + "kubernetes_rpm_gpg_key": null, + "kubernetes_rpm_repo": null, + "kubernetes_rpm_version": null, + "kubernetes_semver": null, + "kubernetes_series": null, + "kubernetes_source_type": null, + "region": "{{env `OSC_REGION`}}", + "secret_key": "{{env `OSC_SECRET_KEY`}}" + } +} diff --git a/packer/outscale/ubuntu-2004.json b/packer/outscale/ubuntu-2004.json new file mode 100644 index 0000000..10ce900 --- /dev/null +++ b/packer/outscale/ubuntu-2004.json @@ -0,0 +1,7 @@ +{ + "build_name": "ubuntu-2004", + "distribution": "ubuntu", + "distribution_release": "ubuntu", + "distribution_version": "2004", + "image_name": "Ubuntu-20.04-2022.03.10-0" +} diff --git a/packer/ova/OWNERS b/packer/ova/OWNERS new file mode 100644 index 0000000..0457bf8 --- /dev/null +++ b/packer/ova/OWNERS @@ -0,0 +1,4 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - cluster-api-vsphere-maintainers diff --git a/packer/ova/centos-7.json b/packer/ova/centos-7.json new file mode 100644 index 0000000..9caf8b0 --- /dev/null +++ b/packer/ova/centos-7.json @@ -0,0 +1,17 @@ +{ + "boot_command_prefix": "<tab> text ks=hd:fd0:", + "boot_command_suffix": "/7/ks.cfg<enter><wait>", + "boot_media_path": "/HTTP", + "build_name": "centos-7", + "distro_arch": "amd64", + "distro_name": "centos", + "distro_version": "7", + "floppy_dirs": "./packer/ova/linux/{{user `distro_name`}}/http/", + "guest_os_type": "centos7-64", + "iso_checksum": "07b94e6b1a0b0260b94c83d6bb76b26bf7a310dc78d7a9c7432809fb9bc6194a", + "iso_checksum_type": "sha256", + "iso_url": "https://mirrors.edge.kernel.org/centos/7.9.2009/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso", + "os_display_name": "CentOS 7", + "shutdown_command": "sys-unconfig", + "vsphere_guest_os_type": "centos7_64Guest" +} diff --git a/packer/ova/flatcar.json b/packer/ova/flatcar.json new file mode 100644 index 0000000..60ad617 --- /dev/null +++ b/packer/ova/flatcar.json @@ -0,0 +1,25 @@ +{ + "ansible_extra_vars": "guestinfo_datasource_slug={{user `guestinfo_datasource_slug`}} guestinfo_datasource_ref={{user `guestinfo_datasource_ref`}} guestinfo_datasource_script={{user `guestinfo_datasource_script`}} ansible_python_interpreter=/opt/bin/python", + "boot_command_prefix": "sudo systemctl mask sshd.socket --now<enter>curl -sLo /tmp/ignition.json https://raw.githubusercontent.com/kubernetes-sigs/image-builder/0bb5cd6db390516c75daeeaf27f19b1aa958428b/images/capi/packer/files/flatcar/ignition/bootstrap.json<enter>sed -i \"s|BUILDERPASSWORDHASH|$(mkpasswd -5 {{user `ssh_password`}})|\" /tmp/ignition.json<enter>sudo flatcar-install -d /dev/sda -o vmware_raw -C {{user `channel_name`}} -V {{user `release_version`}} -i /tmp/ignition.json<enter>sudo reboot<enter>", + "boot_wait": "60s", + "build_name": "flatcar-{{env `FLATCAR_CHANNEL`}}-{{env `FLATCAR_VERSION`}}", + "channel_name": "{{env `FLATCAR_CHANNEL`}}", + "containerd_cri_socket": "/run/docker/libcontainerd/docker-containerd.sock", + "crictl_source_type": "http", + "distro_name": "flatcar", + "guest_os_type": "flatcar-64", + "http_directory": "", + "iso_checksum": "https://{{env `FLATCAR_CHANNEL`}}.release.flatcar-linux.net/amd64-usr/{{env `FLATCAR_VERSION`}}/flatcar_production_iso_image.iso.DIGESTS.asc", + "iso_checksum_type": "file", + "iso_url": "https://{{env `FLATCAR_CHANNEL`}}.release.flatcar-linux.net/amd64-usr/{{env `FLATCAR_VERSION`}}/flatcar_production_iso_image.iso", + "kubernetes_cni_source_type": "http", + "kubernetes_source_type": "http", + "os_display_name": "Flatcar Container Linux ({{env `FLATCAR_CHANNEL`}} channel release {{env `FLATCAR_VERSION`}})", + "python_path": "/opt/bin/builder-env/site-packages", + "release_version": "{{env `FLATCAR_VERSION`}}", + "shutdown_command": "shutdown -P now", + "systemd_prefix": "/etc/systemd", + "sysusr_prefix": "/opt", + "sysusrlocal_prefix": "/opt", + "vsphere_guest_os_type": "other3xLinux64Guest" +} diff --git a/packer/ova/linux/centos/http/7/ks.cfg b/packer/ova/linux/centos/http/7/ks.cfg new file mode 100644 index 0000000..3053362 --- /dev/null +++ b/packer/ova/linux/centos/http/7/ks.cfg @@ -0,0 +1,95 @@ +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Perform a fresh install, not an upgrade +install +cdrom + +# Perform a text installation +text + +# Do not install an X server +skipx + +# Configure the locale/keyboard +lang en_US.UTF-8 +keyboard us + +# Configure networking +network --onboot yes --bootproto dhcp --hostname capv.vm +firewall --disabled +selinux --permissive +timezone UTC + +# Don't flip out if unsupported hardware is detected +unsupported_hardware + +# Configure the user(s) +auth --enableshadow --passalgo=sha512 --kickstart +user --name=builder --plaintext --password builder --groups=builder,wheel + +# Disable general install minutia +firstboot --disabled +eula --agreed + +# Create a single partition with no swap space +bootloader --location=mbr +zerombr +clearpart --all --initlabel +part / --grow --asprimary --fstype=ext4 --label=slash + +%packages --ignoremissing --excludedocs +openssh-server +sed +sudo + +# Remove unnecessary firmware +-*-firmware + +# Remove other unnecessary packages +-postfix +%end + +# Enable/disable the following services +services --enabled=sshd + +# Perform a reboot once the installation has completed +reboot + +# The %post section is essentially a shell script +%post --erroronfail + +# Update the root certificates +update-ca-trust force-enable + +# Ensure that the "builder" user doesn't require a password to use sudo, +# or else Ansible will fail +echo 'builder ALL=(ALL) NOPASSWD: ALL' >/etc/sudoers.d/builder +chmod 440 /etc/sudoers.d/builder + +# Install open-vm-tools +yum install -y open-vm-tools + +# Remove the package cache +yum -y clean all + +# Disable swap +swapoff -a +rm -f /swapfile +sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab + +# Ensure on next boot that network devices get assigned unique IDs. +sed -i '/^\(HWADDR\|UUID\)=/d' /etc/sysconfig/network-scripts/ifcfg-* + +%end diff --git a/packer/ova/linux/centos/http/8/ks.cfg b/packer/ova/linux/centos/http/8/ks.cfg new file mode 100644 index 0000000..59700d7 --- /dev/null +++ b/packer/ova/linux/centos/http/8/ks.cfg @@ -0,0 +1,75 @@ +# version=RHEL8 +# Install OS instead of upgrade +install +cdrom +auth --enableshadow --passalgo=sha512 --kickstart +# License agreement +eula --agreed +# Use text mode install +text +# Disable Initial Setup on first boot +firstboot --disable +# Keyboard layout +keyboard --vckeymap=us --xlayouts='us' +# System language +lang en_US.UTF-8 +# Network information +network --bootproto=dhcp --device=link --activate +network --hostname=rhel8 +firewall --disabled +# Root password +rootpw builder --plaintext +# SELinux configuration +selinux --permissive +# Do not configure the X Window System +skipx +# System timezone +timezone UTC +# Add a user named builder +user --groups=wheel --name=builder --password=builder --plaintext --gecos="builder" + +# System bootloader configuration +bootloader --location=mbr --boot-drive=sda +# Clear the Master Boot Record +zerombr +clearpart --all --initlabel --drives=sda +part / --fstype="ext4" --grow --asprimary --label=slash --ondisk=sda + +# Reboot after successful installation +reboot + +%packages --ignoremissing --excludedocs +# dnf group info minimal-environment +@^minimal-environment +@core +openssh-server +sed +sudo +python3 +open-vm-tools + +# Exclude unnecessary firmwares +-iwl*firmware +%end + +# Enable/disable the following services +services --enabled=sshd + +%post --nochroot --logfile=/mnt/sysimage/root/ks-post.log +# Disable quiet boot and splash screen +sed --follow-symlinks -i "s/ rhgb quiet//" /mnt/sysimage/etc/default/grub +sed --follow-symlinks -i "s/ rhgb quiet//" /mnt/sysimage/boot/grub2/grubenv + +# Passwordless sudo for the user 'builder' +echo "builder ALL=(ALL) NOPASSWD: ALL" >> /mnt/sysimage/etc/sudoers.d/builder +# Remove the package cache +yum -y clean all + +# Disable swap +swapoff -a +rm -f /swapfile +sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab + +sed -i '/^\(HWADDR\|UUID\)=/d' /etc/sysconfig/network-scripts/ifcfg-* + +%end \ No newline at end of file diff --git a/packer/ova/linux/photon/http/3/ks.json b/packer/ova/linux/photon/http/3/ks.json new file mode 100644 index 0000000..4b03b10 --- /dev/null +++ b/packer/ova/linux/photon/http/3/ks.json @@ -0,0 +1,60 @@ +{ + "disk": "/dev/sda", + "hostname": "localhost", + "packages": [ + "bash", + "bc", + "bridge-utils", + "bzip2", + "ca-certificates", + "cloud-init", + "cpio", + "cracklib-dicts", + "dbus", + "e2fsprogs", + "file", + "filesystem", + "findutils", + "gdbm", + "grep", + "gzip", + "iana-etc", + "initramfs", + "iptables", + "iproute2", + "iputils", + "libtool", + "linux", + "motd", + "net-tools", + "openssh-server", + "open-vm-tools", + "pkg-config", + "photon-release", + "photon-repos", + "procps-ng", + "rpm", + "sed", + "sudo", + "tdnf", + "tzdata", + "util-linux", + "vim", + "which" + ], + "password": { + "age": -1, + "crypted": true, + "text": "*" + }, + "postinstall": [ + "#!/bin/sh", + "useradd -U -d /home/builder -m --groups wheel builder && echo 'builder:builder' | chpasswd", + "echo 'builder ALL=(ALL) NOPASSWD: ALL' >/etc/sudoers.d/builder", + "chmod 440 /etc/sudoers.d/builder", + "systemctl enable sshd", + "tdnf clean all", + "swapoff -a", + "rm -f /swapfile" + ] +} diff --git a/packer/ova/linux/photon/http/4 b/packer/ova/linux/photon/http/4 new file mode 120000 index 0000000..e440e5c --- /dev/null +++ b/packer/ova/linux/photon/http/4 @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/packer/ova/linux/rhel b/packer/ova/linux/rhel new file mode 120000 index 0000000..95e1895 --- /dev/null +++ b/packer/ova/linux/rhel @@ -0,0 +1 @@ +centos \ No newline at end of file diff --git a/packer/ova/linux/rockylinux/http/8/ks.cfg b/packer/ova/linux/rockylinux/http/8/ks.cfg new file mode 100644 index 0000000..55b5d99 --- /dev/null +++ b/packer/ova/linux/rockylinux/http/8/ks.cfg @@ -0,0 +1,96 @@ +# Use CDROM installation media +repo --name="AppStream" --baseurl="http://download.rockylinux.org/pub/rocky/8/AppStream/x86_64/os/" +cdrom + +# Use text install +text + +# Don't run the Setup Agent on first boot +firstboot --disabled +eula --agreed + +# Keyboard layouts +keyboard --vckeymap=us --xlayouts='us' + +# System language +lang en_US.UTF-8 + +# Network information +network --bootproto=dhcp --onboot=on --ipv6=auto --activate --hostname=capv.vm + +# Lock Root account +rootpw --lock + +# Create builder user +user --name=builder --groups=wheel --password=builder --plaintext --shell=/bin/bash + +# System services +selinux --permissive +firewall --disabled +services --enabled="NetworkManager,sshd,chronyd" + +# System timezone +timezone UTC + +# System booloader configuration +bootloader --location=mbr --boot-drive=sda +zerombr +clearpart --all --initlabel --drives=sda +part / --fstype="ext4" --grow --asprimary --label=slash --ondisk=sda + +skipx + +%packages --ignoremissing --excludedocs +openssh-server +open-vm-tools +sudo +sed +python3 + +# unnecessary firmware +-aic94xx-firmware +-atmel-firmware +-b43-openfwwf +-bfa-firmware +-ipw2100-firmware +-ipw2200-firmware +-ivtv-firmware +-iwl*-firmware +-libertas-usb8388-firmware +-ql*-firmware +-rt61pci-firmware +-rt73usb-firmware +-xorg-x11-drv-ati-firmware +-zd1211-firmware +-cockpit +-quota +-alsa-* +-fprintd-pam +-intltool +-microcode_ctl +%end + +%addon com_redhat_kdump --disable +%end + +reboot + +%post + +echo 'builder ALL=(ALL) NOPASSWD: ALL' >/etc/sudoers.d/builder +chmod 440 /etc/sudoers.d/builder + +# Remove the package cache +yum -y clean all + +swapoff -a +rm -f /swapfile +sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab + +systemctl enable vmtoolsd +systemctl start vmtoolsd + +# Ensure on next boot that network devices get assigned unique IDs. +sed -i '/^\(HWADDR\|UUID\)=/d' /etc/sysconfig/network-scripts/ifcfg-* + +%end diff --git a/packer/ova/linux/ubuntu/http/18.04/preseed.cfg b/packer/ova/linux/ubuntu/http/18.04/preseed.cfg new file mode 100644 index 0000000..37918c4 --- /dev/null +++ b/packer/ova/linux/ubuntu/http/18.04/preseed.cfg @@ -0,0 +1,15 @@ +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +d-i preseed/include string ../base/preseed.cfg diff --git a/packer/ova/linux/ubuntu/http/20.04/preseed-efi.cfg b/packer/ova/linux/ubuntu/http/20.04/preseed-efi.cfg new file mode 100644 index 0000000..e6eed39 --- /dev/null +++ b/packer/ova/linux/ubuntu/http/20.04/preseed-efi.cfg @@ -0,0 +1,15 @@ +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +d-i preseed/include string ../base/preseed-efi.cfg diff --git a/packer/ova/linux/ubuntu/http/20.04/preseed.cfg b/packer/ova/linux/ubuntu/http/20.04/preseed.cfg new file mode 100644 index 0000000..37918c4 --- /dev/null +++ b/packer/ova/linux/ubuntu/http/20.04/preseed.cfg @@ -0,0 +1,15 @@ +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +d-i preseed/include string ../base/preseed.cfg diff --git a/packer/ova/linux/ubuntu/http/22.04/meta-data b/packer/ova/linux/ubuntu/http/22.04/meta-data new file mode 100644 index 0000000..e69de29 diff --git a/packer/ova/linux/ubuntu/http/22.04/user-data b/packer/ova/linux/ubuntu/http/22.04/user-data new file mode 100644 index 0000000..3e57f7c --- /dev/null +++ b/packer/ova/linux/ubuntu/http/22.04/user-data @@ -0,0 +1,87 @@ +#cloud-config +# Copyright 2022 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# For more information on how autoinstall is configured, please refer to +# https://ubuntu.com/server/docs/install/autoinstall-reference +autoinstall: + version: 1 + # Disable ssh server during installation, otherwise packer tries to connect and exceed max attempts + early-commands: + - systemctl stop ssh + # Configure the locale + locale: en_US.UTF-8 + keyboard: + layout: us + # Create a single-partition with no swap space. Kubernetes + # really dislikes the idea of anyone else managing memory. + # For more information on how partitioning is configured, + # please refer to https://curtin.readthedocs.io/en/latest/topics/storage.html. + storage: + config: + - type: disk + id: disk-0 + size: largest + grub_device: true + preserve: false + ptable: msdos + wipe: superblock + - type: partition + id: partition-0 + device: disk-0 + size: -1 + number: 1 + preserve: false + flag: boot + - type: format + id: format-0 + volume: partition-0 + fstype: ext4 + preserve: false + - type: mount + id: mount-0 + device: format-0 + path: / + updates: 'all' + ssh: + install-server: true + allow-pw: true + # Customize the list of packages installed. + packages: + - open-vm-tools + # Create the default user. + # Ensures the "builder" user doesn't require a password to use sudo. + user-data: + users: + - name: builder + # openssl passwd -6 -stdin <<< builder + passwd: $6$xyz$UtXVazU08Q5b8AW.TJ3MPYZglyXa3Ttf2RCel8MCUPlEYO1evWxeWBhZ2QqivU/Ij4tqYAxMCqc2ujEM4dMSe1 + groups: [adm, cdrom, dip, plugdev, lxd, sudo] + lock-passwd: false + sudo: ALL=(ALL) NOPASSWD:ALL + shell: /bin/bash + + # This command runs after all other steps; it: + # 1. Disables swapfiles + # 2. Removes the existing swapfile + # 3. Removes the swapfile entry from /etc/fstab + # 4. Cleans up any packages that are no longer required + # 5. Removes the cached list of packages + late-commands: + - swapoff -a + - rm -f /swapfile + - sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab + - apt-get purge --auto-remove -y + - rm -rf /var/lib/apt/lists/* diff --git a/packer/ova/linux/ubuntu/http/base/preseed-efi.cfg b/packer/ova/linux/ubuntu/http/base/preseed-efi.cfg new file mode 100644 index 0000000..6841226 --- /dev/null +++ b/packer/ova/linux/ubuntu/http/base/preseed-efi.cfg @@ -0,0 +1,128 @@ +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Configure the locale +d-i debian-installer/locale string en_US.utf8 +d-i console-setup/ask_detect boolean false +d-i console-setup/layout string us + +# Configure the clock +d-i time/zone string UTC +d-i clock-setup/utc-auto boolean true +d-i clock-setup/utc boolean true + +# Configure the keyboard +d-i kbd-chooser/method select American English + +# Configure networking +d-i netcfg/wireless_wep string + +# Select the kernel +d-i base-installer/kernel/override-image string linux-virtual + +# Configure a non-interactive install +debconf debconf/frontend select Noninteractive + +# Configure the base installation +d-i pkgsel/install-language-support boolean false +d-i pkgsel/language-packs multiselect +tasksel tasksel/first multiselect # standard, ubuntu-server + + +### Simple GPT configuration w/o LVM +d-i partman-auto/disk string /dev/sda + +d-i partman/alignment string cylinder +d-i partman/confirm_write_new_label boolean true +d-i partman-basicfilesystems/choose_label string gpt +d-i partman-basicfilesystems/default_label string gpt +d-i partman-partitioning/choose_label string gpt +d-i partman-partitioning/default_label string gpt +d-i partman/choose_label string gpt +d-i partman/default_label string gpt + +d-i partman-auto/method string regular +d-i partman-auto/choose_recipe select gpt-boot-root-swap +d-i partman-auto/expert_recipe string \ + gpt-boot-root-swap :: \ + 1 1 1 free \ + $bios_boot{ } \ + method{ biosgrub } . \ + 200 200 200 fat32 \ + $primary{ } \ + method{ efi } format{ } . \ + 512 512 512 ext3 \ + $primary{ } $bootable{ } \ + method{ format } format{ } \ + use_filesystem{ } filesystem{ ext3 } \ + mountpoint{ /boot } . \ + 1000 20000 -1 ext4 \ + $primary{ } \ + method{ format } format{ } \ + use_filesystem{ } filesystem{ ext4 } \ + mountpoint{ / } . + +d-i partman-partitioning/confirm_write_new_label boolean true +d-i partman/choose_partition select finish +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true + +# Create the default user. +d-i passwd/user-fullname string builder +d-i passwd/username string builder +d-i passwd/user-password password builder +d-i passwd/user-password-again password builder +d-i user-setup/encrypt-home boolean false +d-i user-setup/allow-password-weak boolean true + +# Disable upgrading packages upon installation. +d-i pkgsel/upgrade select none +d-i grub-installer/only_debian boolean true +d-i grub-installer/with_other_os boolean true +d-i finish-install/reboot_in_progress note +d-i pkgsel/update-policy select none + +# Disable use of the apt mirror during base install +# This means only packages available in the ISO can be installed +d-i apt-setup/use_mirror boolean false + +# Disable the security repo as well (it's on by default) +d-i apt-setup/services-select multiselect none + +# Customize the list of packages installed. +d-i pkgsel/include string openssh-server open-vm-tools + + +# Ensure questions about these packages do not bother the installer. +libssl1.1 libssl1.1/restart-without-asking boolean true +libssl1.1:amd64 libssl1.1/restart-without-asking boolean true +libssl1.1 libssl1.1/restart-services string +libssl1.1:amd64 libssl1.1/restart-services string + + +# This command runs after all other steps; it: +# 1. Ensures the "builder" user doesn't require a password to use sudo +# 2. Cleans up any packages that are no longer required +# 3. Cleans the package cache +# 4. Removes the cached list of packages +# 5. Disables swapfiles +# 6. Removes the existing swapfile +# 7. Removes the swapfile entry from /etc/fstab +d-i preseed/late_command string \ + echo 'builder ALL=(ALL) NOPASSWD: ALL' >/target/etc/sudoers.d/builder ; \ + in-target chmod 440 /etc/sudoers.d/builder ; \ + in-target swapoff -a ; \ + in-target rm -f /swapfile ; \ + in-target sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab ; \ + in-target rm -f /etc/udev/rules.d/70-persistent-net.rules diff --git a/packer/ova/linux/ubuntu/http/base/preseed.cfg b/packer/ova/linux/ubuntu/http/base/preseed.cfg new file mode 100644 index 0000000..f6e5d42 --- /dev/null +++ b/packer/ova/linux/ubuntu/http/base/preseed.cfg @@ -0,0 +1,128 @@ +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Configure the locale +d-i debian-installer/locale string en_US.utf8 +d-i debian-installer/add-kernel-opts console=ttyS0 +d-i console-setup/ask_detect boolean false +d-i console-setup/layout string us + +# Configure the clock +d-i time/zone string UTC +d-i clock-setup/utc-auto boolean true +d-i clock-setup/utc boolean true + +# Configure the keyboard +d-i kbd-chooser/method select American English + +# Configure networking +d-i netcfg/wireless_wep string + +# Select the kernel +d-i base-installer/kernel/override-image string linux-virtual + +# Configure a non-interactive install +debconf debconf/frontend select Noninteractive + +# Configure the base installation +d-i pkgsel/install-language-support boolean false +d-i pkgsel/language-packs multiselect +tasksel tasksel/first multiselect # standard, ubuntu-server + +# Create a single-partition with no swap space. For more information +# on how partitioning is configured, please refer to +# https://github.com/xobs/debian-installer/blob/master/doc/devel/partman-auto-recipe.txt. +d-i partman-auto/method string regular +d-i partman-lvm/device_remove_lvm boolean true +d-i partman-md/device_remove_md boolean true +d-i partman-lvm/confirm boolean true +d-i partman-auto-lvm/guided_size string max + +# Again, this creates a single-partition with no swap. Kubernetes +# really dislikes the idea of anyone else managing memory. +d-i partman-auto/expert_recipe string \ + slash :: \ + 0 0 -1 ext4 \ + $primary{ } $bootable{ } \ + method{ format } format{ } \ + use_filesystem{ } filesystem{ ext4 } \ + mountpoint{ / } \ + . + +d-i partman-partitioning/confirm_write_new_label boolean true +d-i partman/choose_partition select finish +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true +d-i partman-basicfilesystems/no_swap boolean false +d-i partman-md/confirm boolean true +d-i partman-partitioning/confirm_write_new_label boolean true +d-i partman/choose_partition select finish +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true +d-i partman-md/confirm_nooverwrite boolean true +d-i partman-lvm/confirm_nooverwrite boolean true +d-i partman-partitioning/no_bootable_gpt_biosgrub boolean true +d-i partman-partitioning/no_bootable_gpt_efi boolean false +d-i partman-efi/non_efi_system boolean false + +# Create the default user. +d-i passwd/user-fullname string builder +d-i passwd/username string builder +d-i passwd/user-password password builder +d-i passwd/user-password-again password builder +d-i user-setup/encrypt-home boolean false +d-i user-setup/allow-password-weak boolean true + +# Disable upgrading packages upon installation. +d-i pkgsel/upgrade select none +d-i grub-installer/only_debian boolean true +d-i grub-installer/with_other_os boolean true +d-i finish-install/reboot_in_progress note +d-i pkgsel/update-policy select none + +# Disable use of the apt mirror during base install +# This means only packages available in the ISO can be installed +d-i apt-setup/use_mirror boolean false + +# Disable the security repo as well (it's on by default) +d-i apt-setup/services-select multiselect none + +# Customize the list of packages installed. +d-i pkgsel/include string openssh-server open-vm-tools + + +# Ensure questions about these packages do not bother the installer. +libssl1.1 libssl1.1/restart-without-asking boolean true +libssl1.1:amd64 libssl1.1/restart-without-asking boolean true +libssl1.1 libssl1.1/restart-services string +libssl1.1:amd64 libssl1.1/restart-services string + + +# This command runs after all other steps; it: +# 1. Ensures the "builder" user doesn't require a password to use sudo +# 2. Cleans up any packages that are no longer required +# 3. Cleans the package cache +# 4. Removes the cached list of packages +# 5. Disables swapfiles +# 6. Removes the existing swapfile +# 7. Removes the swapfile entry from /etc/fstab +d-i preseed/late_command string \ + echo 'builder ALL=(ALL) NOPASSWD: ALL' >/target/etc/sudoers.d/builder ; \ + in-target chmod 440 /etc/sudoers.d/builder ; \ + in-target swapoff -a ; \ + in-target rm -f /swapfile ; \ + in-target sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab ; \ + in-target rm -f /etc/udev/rules.d/70-persistent-net.rules ; \ + in-target apt-get purge --auto-remove -y ; \ + in-target rm -rf /var/lib/apt/lists/* diff --git a/packer/ova/packer-common.json b/packer/ova/packer-common.json new file mode 100644 index 0000000..9505b42 --- /dev/null +++ b/packer/ova/packer-common.json @@ -0,0 +1,33 @@ +{ + "boot_wait": "10s", + "convert_to_template": "false", + "cpu": "4", + "cpu_cores": "1", + "disk_controller_type": "pvscsi", + "disk_thin_provisioned": "true", + "disk_type_id": "0", + "firmware": "bios", + "format": "", + "guestinfo_datasource_ref": "v1.4.1", + "guestinfo_datasource_script": "{{user `guestinfo_datasource_slug`}}/{{user `guestinfo_datasource_ref`}}/install.sh", + "guestinfo_datasource_slug": "https://raw.githubusercontent.com/vmware/cloud-init-vmware-guestinfo", + "headless": "true", + "insecure_connection": "false", + "memory": "8192", + "network": "", + "network_card": "vmxnet3", + "remote_datastore": "", + "remote_host": "", + "remote_password": "", + "remote_type": "", + "remote_username": "", + "skip_compaction": "false", + "ssh_password": "builder", + "ssh_timeout": "60m", + "ssh_username": "builder", + "vmx_version": "15", + "vnc_bind_address": "127.0.0.1", + "vnc_disable_password": "false", + "vnc_port_max": "6000", + "vnc_port_min": "5900" +} diff --git a/packer/ova/packer-node.json b/packer/ova/packer-node.json new file mode 100644 index 0000000..36363ac --- /dev/null +++ b/packer/ova/packer-node.json @@ -0,0 +1,485 @@ +{ + "builders": [ + { + "communicator": "ssh", + "disable_vnc": "True", + "format": "{{user `format`}}", + "headless": "{{user `headless`}}", + "http_directory": "{{user `http_directory`}}", + "http_port_max": "{{user `http_port_max`}}", + "http_port_min": "{{user `http_port_min`}}", + "name": "vmware-vmx", + "output_directory": "{{user `output_dir`}}", + "remote_datastore": "{{user `remote_datastore`}}", + "remote_host": "{{user `remote_host`}}", + "remote_password": "{{user `remote_password`}}", + "remote_type": "{{user `remote_type`}}", + "remote_username": "{{user `remote_username`}}", + "shutdown_command": "echo '{{user `ssh_password`}}' | sudo -S -E sh -c 'usermod -L {{user `ssh_username`}} && {{user `shutdown_command`}}'", + "skip_compaction": "{{user `skip_compaction`}}", + "source_path": "{{ user `source_path`}}", + "ssh_password": "{{user `ssh_password`}}", + "ssh_timeout": "4h", + "ssh_username": "{{user `ssh_username`}}", + "type": "vmware-vmx", + "vm_name": "{{user `build_version`}}", + "vmx_data": { + "ethernet0.networkName": "{{user `network`}}" + }, + "vnc_bind_address": "{{user `vnc_bind_address`}}", + "vnc_disable_password": "{{user `vnc_disable_password`}}", + "vnc_port_max": "{{user `vnc_port_max`}}", + "vnc_port_min": "{{user `vnc_port_min`}}" + }, + { + "boot_command": [ + "{{user `boot_command_prefix`}}", + "{{user `boot_media_path`}}", + "{{user `boot_command_suffix`}}" + ], + "boot_wait": "{{user `boot_wait`}}", + "communicator": "ssh", + "cores": "{{user `cpu_cores`}}", + "cpus": "{{user `cpu`}}", + "disk_adapter_type": "scsi", + "disk_size": "{{user `disk_size`}}", + "disk_type_id": "{{user `disk_type_id`}}", + "floppy_dirs": "{{ user `floppy_dirs`}}", + "format": "{{user `format`}}", + "guest_os_type": "{{user `guest_os_type`}}", + "headless": "{{user `headless`}}", + "http_directory": "{{ user `http_directory`}}", + "http_port_max": "{{user `http_port_max`}}", + "http_port_min": "{{user `http_port_min`}}", + "iso_checksum": "{{user `iso_checksum_type`}}:{{user `iso_checksum`}}", + "iso_url": "{{user `iso_url`}}", + "memory": "{{user `memory`}}", + "name": "vmware-iso-base", + "output_directory": "{{user `base_output_dir`}}", + "remote_datastore": "{{user `remote_datastore`}}", + "remote_host": "{{user `remote_host`}}", + "remote_password": "{{user `remote_password`}}", + "remote_type": "{{user `remote_type`}}", + "remote_username": "{{user `remote_username`}}", + "shutdown_command": "echo '{{user `ssh_password`}}' | sudo -S -E sh -c '{{user `shutdown_command`}}'", + "skip_compaction": "{{user `skip_compaction`}}", + "ssh_password": "{{user `ssh_password`}}", + "ssh_timeout": "4h", + "ssh_username": "{{user `ssh_username`}}", + "type": "vmware-iso", + "version": "{{user `vmx_version`}}", + "vm_name": "{{user `base_build_version`}}", + "vmdk_name": "{{user `base_build_version`}}", + "vmx_data": { + "ethernet0.networkName": "{{user `network`}}" + }, + "vnc_bind_address": "{{user `vnc_bind_address`}}", + "vnc_disable_password": "{{user `vnc_disable_password`}}", + "vnc_port_max": "{{user `vnc_port_max`}}", + "vnc_port_min": "{{user `vnc_port_min`}}" + }, + { + "boot_command": [ + "{{user `boot_command_prefix`}}", + "{{user `boot_media_path`}}", + "{{user `boot_command_suffix`}}" + ], + "boot_wait": "{{user `boot_wait`}}", + "communicator": "ssh", + "cores": "{{user `cpu_cores`}}", + "cpus": "{{user `cpu`}}", + "disk_adapter_type": "scsi", + "disk_size": "{{user `disk_size`}}", + "disk_type_id": "{{user `disk_type_id`}}", + "floppy_dirs": "{{ user `floppy_dirs`}}", + "format": "{{user `format`}}", + "guest_os_type": "{{user `guest_os_type`}}", + "headless": "{{user `headless`}}", + "http_directory": "{{ user `http_directory`}}", + "http_port_max": "{{user `http_port_max`}}", + "http_port_min": "{{user `http_port_min`}}", + "iso_checksum": "{{user `iso_checksum_type`}}:{{user `iso_checksum`}}", + "iso_url": "{{user `iso_url`}}", + "memory": "{{user `memory`}}", + "name": "vmware-iso", + "output_directory": "{{user `output_dir`}}", + "remote_datastore": "{{user `remote_datastore`}}", + "remote_host": "{{user `remote_host`}}", + "remote_password": "{{user `remote_password`}}", + "remote_type": "{{user `remote_type`}}", + "remote_username": "{{user `remote_username`}}", + "shutdown_command": "echo '{{user `ssh_password`}}' | sudo -S -E sh -c 'usermod -L {{user `ssh_username`}} && {{user `shutdown_command`}}'", + "skip_compaction": "{{user `skip_compaction`}}", + "ssh_password": "{{user `ssh_password`}}", + "ssh_timeout": "4h", + "ssh_username": "{{user `ssh_username`}}", + "type": "vmware-iso", + "version": "{{user `vmx_version`}}", + "vm_name": "{{user `build_version`}}", + "vmdk_name": "{{user `build_version`}}", + "vmx_data": { + "ethernet0.networkName": "{{user `network`}}" + }, + "vnc_bind_address": "{{user `vnc_bind_address`}}", + "vnc_disable_password": "{{user `vnc_disable_password`}}", + "vnc_port_max": "{{user `vnc_port_max`}}", + "vnc_port_min": "{{user `vnc_port_min`}}" + }, + { + "CPUs": "{{user `cpu`}}", + "RAM": "{{user `memory`}}", + "boot_command": [ + "{{user `boot_command_prefix`}}", + "{{user `boot_media_path`}}", + "{{user `boot_command_suffix`}}" + ], + "boot_wait": "{{user `boot_wait`}}", + "cluster": "{{user `cluster`}}", + "communicator": "ssh", + "convert_to_template": "{{user `convert_to_template`}}", + "cpu_cores": "{{user `cpu_cores`}}", + "create_snapshot": "{{user `create_snapshot`}}", + "datacenter": "{{user `datacenter`}}", + "datastore": "{{user `datastore`}}", + "disk_controller_type": "{{user `disk_controller_type`}}", + "firmware": "{{user `firmware`}}", + "floppy_dirs": "{{ user `floppy_dirs`}}", + "folder": "{{user `folder`}}", + "guest_os_type": "{{user `vsphere_guest_os_type`}}", + "host": "{{user `host`}}", + "http_directory": "{{ user `http_directory`}}", + "http_port_max": "{{user `http_port_max`}}", + "http_port_min": "{{user `http_port_min`}}", + "insecure_connection": "{{user `insecure_connection`}}", + "iso_checksum": "{{user `iso_checksum_type`}}:{{user `iso_checksum`}}", + "iso_urls": "{{user `iso_url`}}", + "name": "vsphere-iso-base", + "network_adapters": [ + { + "network": "{{user `network`}}", + "network_card": "{{user `network_card`}}" + } + ], + "password": "{{user `password`}}", + "shutdown_command": "echo '{{user `ssh_password`}}' | sudo -S -E sh -c '{{user `shutdown_command`}}'", + "ssh_clear_authorized_keys": "false", + "ssh_password": "{{user `ssh_password`}}", + "ssh_timeout": "4h", + "ssh_username": "{{user `ssh_username`}}", + "storage": [ + { + "disk_size": "{{user `disk_size`}}", + "disk_thin_provisioned": "{{user `disk_thin_provisioned`}}" + } + ], + "type": "vsphere-iso", + "username": "{{user `username`}}", + "vcenter_server": "{{user `vcenter_server`}}", + "vm_name": "{{user `base_build_version`}}", + "vm_version": "{{user `vmx_version`}}" + }, + { + "CPUs": "{{user `cpu`}}", + "RAM": "{{user `memory`}}", + "boot_command": [ + "{{user `boot_command_prefix`}}", + "{{user `boot_media_path`}}", + "{{user `boot_command_suffix`}}" + ], + "boot_wait": "{{user `boot_wait`}}", + "cluster": "{{user `cluster`}}", + "communicator": "ssh", + "convert_to_template": "{{user `convert_to_template`}}", + "cpu_cores": "{{user `cpu_cores`}}", + "datacenter": "{{user `datacenter`}}", + "datastore": "{{user `datastore`}}", + "disk_controller_type": "{{user `disk_controller_type`}}", + "export": { + "force": true, + "manifest": "{{ user `export_manifest`}}", + "output_directory": "{{user `output_dir`}}" + }, + "firmware": "{{user `firmware`}}", + "floppy_dirs": "{{ user `floppy_dirs`}}", + "folder": "{{user `folder`}}", + "guest_os_type": "{{user `vsphere_guest_os_type`}}", + "host": "{{user `host`}}", + "http_directory": "{{ user `http_directory`}}", + "http_port_max": "{{user `http_port_max`}}", + "http_port_min": "{{user `http_port_min`}}", + "insecure_connection": "{{user `insecure_connection`}}", + "iso_checksum": "{{user `iso_checksum_type`}}:{{user `iso_checksum`}}", + "iso_urls": "{{user `iso_url`}}", + "name": "vsphere", + "network_adapters": [ + { + "network": "{{user `network`}}", + "network_card": "{{user `network_card`}}" + } + ], + "password": "{{user `password`}}", + "shutdown_command": "echo '{{user `ssh_password`}}' | sudo -S -E sh -c 'usermod -L {{user `ssh_username`}} && {{user `shutdown_command`}}'", + "ssh_password": "{{user `ssh_password`}}", + "ssh_timeout": "4h", + "ssh_username": "{{user `ssh_username`}}", + "storage": [ + { + "disk_size": "{{user `disk_size`}}", + "disk_thin_provisioned": "{{user `disk_thin_provisioned`}}" + } + ], + "type": "vsphere-iso", + "username": "{{user `username`}}", + "vcenter_server": "{{user `vcenter_server`}}", + "vm_name": "{{user `build_version`}}", + "vm_version": "{{user `vmx_version`}}" + }, + { + "CPUs": "{{user `cpu`}}", + "RAM": "{{user `memory`}}", + "cluster": "{{user `cluster`}}", + "communicator": "ssh", + "convert_to_template": "{{user `convert_to_template`}}", + "cpu_cores": "{{user `cpu_cores`}}", + "create_snapshot": "{{user `create_snapshot`}}", + "datacenter": "{{user `datacenter`}}", + "datastore": "{{user `datastore`}}", + "export": { + "force": true, + "manifest": "{{ user `export_manifest`}}", + "output_directory": "{{user `output_dir`}}" + }, + "folder": "{{user `folder`}}", + "host": "{{user `host`}}", + "insecure_connection": "{{user `insecure_connection`}}", + "linked_clone": "{{user `linked_clone`}}", + "name": "vsphere-clone", + "network": "{{user `network`}}", + "password": "{{user `password`}}", + "shutdown_command": "echo '{{user `ssh_password`}}' | sudo -S -E sh -c 'usermod -L {{user `ssh_username`}} && {{user `shutdown_command`}}'", + "ssh_password": "{{user `ssh_password`}}", + "ssh_timeout": "4h", + "ssh_username": "{{user `ssh_username`}}", + "template": "{{user `template`}}", + "type": "vsphere-clone", + "username": "{{user `username`}}", + "vcenter_server": "{{user `vcenter_server`}}", + "vm_name": "{{user `build_version`}}" + } + ], + "post-processors": [ + { + "custom_data": { + "build_date": "{{isotime}}", + "build_name": "{{user `build_name`}}", + "build_timestamp": "{{user `build_timestamp`}}", + "containerd_version": "{{user `containerd_version`}}", + "disk_size": "{{user `disk_size`}}", + "distro_arch": "{{ user `distro_arch` }}", + "distro_name": "{{ user `distro_name` }}", + "distro_version": "{{ user `distro_version` }}", + "firmware": "{{user `firmware`}}", + "guest_os_type": "{{user `guest_os_type`}}", + "ib_version": "{{user `ib_version`}}", + "kubernetes_cni_semver": "{{user `kubernetes_cni_semver`}}", + "kubernetes_semver": "{{user `kubernetes_semver`}}", + "kubernetes_source_type": "{{user `kubernetes_source_type`}}", + "kubernetes_typed_version": "{{user `kubernetes_typed_version`}}", + "os_name": "{{user `os_display_name`}}", + "vsphere_guest_os_type": "{{user `vsphere_guest_os_type`}}" + }, + "except": [ + "vmware-iso-base", + "vsphere-iso-base" + ], + "name": "packer-manifest", + "output": "{{user `output_dir`}}/packer-manifest.json", + "strip_path": true, + "type": "manifest" + }, + { + "except": [ + "vsphere-iso-base" + ], + "inline": [ + "cd {{user `output_dir`}}", + "../../hack/image-build-ova.py --vmx {{user `vmx_version`}} --eula ../../hack/ovf_eula.txt --ovf_template ../../hack/ovf_template.xml --vmdk_file {{user `build_version`}}-disk-0.vmdk" + ], + "name": "vsphere", + "type": "shell-local" + }, + { + "except": [ + "vmware-iso-base" + ], + "inline": [ + "./hack/image-build-ova.py --stream_vmdk --vmx {{user `vmx_version`}} --eula ./hack/ovf_eula.txt --ovf_template ./hack/ovf_template.xml {{user `output_dir`}}", + "./hack/image-post-create-config.sh {{user `output_dir`}}" + ], + "name": "local", + "type": "shell-local" + }, + { + "environment_vars": [ + "CUSTOM_POST_PROCESSOR={{user `custom_post_processor`}}" + ], + "inline": [ + "if [ \"$CUSTOM_POST_PROCESSOR\" != \"true\" ]; then exit 0; fi", + "{{user `custom_post_processor_command`}}" + ], + "name": "custom-post-processor", + "type": "shell-local" + } + ], + "provisioners": [ + { + "environment_vars": [ + "BUILD_NAME={{user `build_name`}}" + ], + "execute_command": "BUILD_NAME={{user `build_name`}}; if [[ \"${BUILD_NAME}\" == *\"flatcar\"* ]]; then sudo {{.Vars}} -S -E bash '{{.Path}}'; fi", + "script": "./packer/files/flatcar/scripts/bootstrap-flatcar.sh", + "type": "shell" + }, + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} {{user `ansible_common_ssh_args`}}'" + ], + "except": [ + "vmware-iso-base", + "vsphere-iso-base" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}", + "--scp-extra-args", + "{{user `ansible_scp_extra_args`}}" + ], + "playbook_file": "./ansible/firstboot.yml", + "type": "ansible", + "user": "{{user `ssh_username`}}" + }, + { + "environment_vars": [ + "DISTRO_NAME={{user `distro_name`}}" + ], + "expect_disconnect": true, + "inline": [ + "if [ $DISTRO_NAME != \"photon\" ]; then exit 0; fi", + "sudo reboot now" + ], + "type": "shell" + }, + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} {{user `ansible_common_ssh_args`}}'" + ], + "except": [ + "vmware-iso-base", + "vsphere-iso-base" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}", + "--scp-extra-args", + "{{user `ansible_scp_extra_args`}}" + ], + "playbook_file": "./ansible/node.yml", + "type": "ansible", + "user": "{{user `ssh_username`}}" + }, + { + "arch": "{{user `goss_arch`}}", + "download_path": "{{user `goss_download_path`}}", + "except": [ + "vmware-iso-base", + "vsphere-iso-base" + ], + "format": "{{user `goss_format`}}", + "format_options": "{{user `goss_format_options`}}", + "goss_file": "{{user `goss_entry_file`}}", + "inspect": "{{user `goss_inspect_mode`}}", + "remote_folder": "{{user `goss_remote_folder`}}", + "remote_path": "{{user `goss_remote_path`}}", + "skip_install": "{{user `goss_skip_install`}}", + "tests": [ + "{{user `goss_tests_dir`}}" + ], + "type": "goss", + "url": "{{user `goss_url`}}", + "use_sudo": true, + "vars_file": "{{user `goss_vars_file`}}", + "vars_inline": { + "ARCH": "amd64", + "OS": "{{user `distro_name` | lower}}", + "OS_VERSION": "{{user `distro_version` | lower}}", + "PROVIDER": "ova", + "containerd_version": "{{user `containerd_version`}}", + "kubernetes_cni_deb_version": "{{ user `kubernetes_cni_deb_version` }}", + "kubernetes_cni_rpm_version": "{{ split (user `kubernetes_cni_rpm_version`) \"-\" 0 }}", + "kubernetes_cni_source_type": "{{user `kubernetes_cni_source_type`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver` | replace \"v\" \"\" 1}}", + "kubernetes_deb_version": "{{ user `kubernetes_deb_version` }}", + "kubernetes_rpm_version": "{{ split (user `kubernetes_rpm_version`) \"-\" 0 }}", + "kubernetes_source_type": "{{user `kubernetes_source_type`}}", + "kubernetes_version": "{{user `kubernetes_semver` | replace \"v\" \"\" 1}}" + }, + "version": "{{user `goss_version`}}" + } + ], + "variables": { + "ansible_common_vars": "", + "ansible_extra_vars": "guestinfo_datasource_slug={{user `guestinfo_datasource_slug`}} guestinfo_datasource_ref={{user `guestinfo_datasource_ref`}} guestinfo_datasource_script={{user `guestinfo_datasource_script`}}", + "ansible_scp_extra_args": "", + "ansible_user_vars": "", + "base_build_version": "base-{{user `build_name`}}", + "base_output_dir": "./output/{{user `base_build_version`}}", + "build_timestamp": "{{timestamp}}", + "build_version": "{{user `build_name`}}-kube-{{user `kubernetes_semver`}}", + "cluster": "", + "containerd_sha256": null, + "containerd_url": "https://github.com/containerd/containerd/releases/download/v{{user `containerd_version`}}/cri-containerd-cni-{{user `containerd_version`}}-linux-amd64.tar.gz", + "containerd_version": null, + "crictl_url": "https://github.com/kubernetes-sigs/cri-tools/releases/download/v{{user `crictl_version`}}/crictl-v{{user `crictl_version`}}-linux-amd64.tar.gz", + "crictl_version": null, + "datastore": "", + "disk_size": "20480", + "existing_ansible_ssh_args": "{{env `ANSIBLE_SSH_ARGS`}}", + "export_manifest": "none", + "folder": "", + "guest_os_type": null, + "http_directory": "./packer/ova/linux/{{user `distro_name`}}/http/", + "http_port_max": "", + "http_port_min": "", + "ib_version": "{{env `IB_VERSION`}}", + "kubernetes_cni_deb_version": null, + "kubernetes_cni_http_source": null, + "kubernetes_cni_rpm_version": null, + "kubernetes_cni_semver": null, + "kubernetes_cni_source_type": null, + "kubernetes_container_registry": null, + "kubernetes_deb_gpg_key": null, + "kubernetes_deb_repo": null, + "kubernetes_deb_version": null, + "kubernetes_http_source": null, + "kubernetes_load_additional_imgs": null, + "kubernetes_rpm_gpg_check": null, + "kubernetes_rpm_gpg_key": null, + "kubernetes_rpm_repo": null, + "kubernetes_rpm_version": null, + "kubernetes_semver": null, + "kubernetes_source_type": null, + "kubernetes_typed_version": "kube-{{user `kubernetes_semver`}}", + "output_dir": "./output/{{user `build_version`}}", + "username": "", + "vcenter_server": "", + "vsphere_guest_os_type": null + } +} diff --git a/packer/ova/packer-windows.json b/packer/ova/packer-windows.json new file mode 100644 index 0000000..98f9352 --- /dev/null +++ b/packer/ova/packer-windows.json @@ -0,0 +1,267 @@ +{ + "builders": [ + { + "content": "{\n \"unattend_timezone\" : \"{{user `unattend_timezone`}}\"\n}", + "target": "./packer_cache/unattend.json", + "type": "file" + }, + { + "boot_wait": "{{user `boot_wait`}}", + "communicator": "winrm", + "cpus": "{{user `cpu`}}", + "disk_adapter_type": "scsi", + "disk_size": "{{user `disk_size`}}", + "disk_type_id": "{{user `disk_type_id`}}", + "floppy_dirs": [ + "./packer/ova/windows/pvscsi" + ], + "floppy_files": [ + "./packer/ova/windows/{{user `build_name`}}/autounattend.xml", + "./packer/ova/windows/disable-network-discovery.cmd", + "./packer/ova/windows/disable-winrm.ps1", + "./packer/ova/windows/enable-winrm.ps1", + "./packer/ova/windows/sysprep.ps1" + ], + "guest_os_type": "{{user `local_guest_os_type`}}", + "http_port_max": "{{user `http_port_max`}}", + "http_port_min": "{{user `http_port_min`}}", + "iso_checksum": "{{user `iso_checksum` }}", + "iso_urls": [ + "{{user `os_iso_url`}}" + ], + "memory": "{{user `memory`}}", + "name": "vmware-iso", + "output_directory": "{{user `output_dir`}}", + "shutdown_command": "powershell A:/sysprep.ps1", + "shutdown_timeout": "1h", + "type": "vmware-iso", + "version": "{{user `vmx_version`}}", + "vm_name": "{{user `build_version`}}", + "vmdk_name": "{{user `build_version`}}", + "vmx_data": { + "numvcpus": "4", + "scsi0.virtualDev": "pvscsi" + }, + "winrm_password": "S3cr3t0!", + "winrm_timeout": "4h", + "winrm_username": "Administrator" + }, + { + "CPUs": "{{user `cpu`}}", + "RAM": "{{user `memory`}}", + "boot_wait": "{{user `boot_wait`}}", + "cluster": "{{user `cluster`}}", + "communicator": "winrm", + "convert_to_template": "{{user `convert_to_template`}}", + "datacenter": "{{user `datacenter`}}", + "datastore": "{{user `datastore`}}", + "disk_controller_type": "{{user `disk_controller_type`}}", + "export": { + "force": true, + "output_directory": "{{user `output_dir`}}" + }, + "firmware": "bios", + "floppy_dirs": [ + "./packer/ova/windows/pvscsi" + ], + "floppy_files": [ + "./packer/ova/windows/{{user `build_name`}}/autounattend.xml", + "./packer/ova/windows/disable-network-discovery.cmd", + "./packer/ova/windows/disable-winrm.ps1", + "./packer/ova/windows/enable-winrm.ps1", + "./packer/ova/windows/sysprep.ps1" + ], + "folder": "{{user `folder`}}", + "guest_os_type": "{{user `vsphere_guest_os_type`}}", + "host": "{{user `host`}}", + "http_port_max": "{{user `http_port_max`}}", + "http_port_min": "{{user `http_port_min`}}", + "insecure_connection": "{{user `insecure_connection`}}", + "iso_paths": [ + "{{user `os_iso_path`}}", + "{{user `vmtools_iso_path`}}" + ], + "name": "vsphere", + "network_adapters": [ + { + "network": "{{user `network`}}", + "network_card": "{{user `network_card`}}" + } + ], + "password": "{{user `password`}}", + "resource_pool": "{{user `resource_pool`}}", + "shutdown_command": "powershell A:/sysprep.ps1", + "shutdown_timeout": "1h", + "storage": [ + { + "disk_size": "{{user `disk_size`}}", + "disk_thin_provisioned": "{{user `disk_thin_provisioned`}}" + } + ], + "type": "vsphere-iso", + "username": "{{user `username`}}", + "vcenter_server": "{{user `vcenter_server`}}", + "vm_name": "{{user `build_version`}}", + "vm_version": "{{user `vmx_version`}}", + "winrm_insecure": true, + "winrm_password": "S3cr3t0!", + "winrm_timeout": "4h", + "winrm_username": "Administrator" + } + ], + "post-processors": [ + { + "custom_data": { + "build_date": "{{isotime}}", + "build_name": "{{user `build_name`}}", + "build_timestamp": "{{user `build_timestamp`}}", + "containerd_version": "{{user `containerd_version`}}", + "debug_tools": "{{user `debug_tools`}}", + "disable_hypervisor": "{{user `disable_hypervisor`}}", + "disk_size": "{{user `disk_size`}}", + "distro_arch": "{{user `distro_arch` }}", + "distro_name": "{{user `distro_name` }}", + "distro_version": "{{user `distro_version` }}", + "firmware": "{{user `firmware`}}", + "guest_os_type": "{{user `guest_os_type`}}", + "ib_version": "{{user `ib_version`}}", + "kubernetes_cni_semver": "{{user `kubernetes_cni_semver`}}", + "kubernetes_semver": "{{user `kubernetes_semver`}}", + "kubernetes_source_type": "{{user `kubernetes_source_type`}}", + "kubernetes_typed_version": "{{user `kubernetes_typed_version`}}", + "os_name": "{{user `os_display_name`}}", + "vsphere_guest_os_type": "{{user `vsphere_guest_os_type`}}" + }, + "except": [ + "file" + ], + "output": "{{user `output_dir`}}/packer-manifest.json", + "strip_path": true, + "type": "manifest" + }, + { + "except": [ + "file" + ], + "inline": [ + "cd {{user `output_dir`}}", + "../../hack/image-build-ova.py --vmx {{user `vmx_version`}} --eula ../../hack/ovf_eula.txt --ovf_template ../../hack/ovf_template.xml --vmdk_file {{user `build_version`}}-disk-0.vmdk" + ], + "name": "vsphere", + "type": "shell-local" + }, + { + "except": [ + "file" + ], + "inline": [ + "./hack/image-build-ova.py --stream_vmdk --vmx {{user `vmx_version`}} --eula ./hack/ovf_eula.txt --ovf_template ./hack/ovf_template.xml {{user `output_dir`}}", + "./hack/image-post-create-config.sh {{user `output_dir`}}" + ], + "name": "local", + "type": "shell-local" + } + ], + "provisioners": [ + { + "except": "file", + "extra_arguments": [ + "-e", + "ansible_winrm_server_cert_validation=ignore", + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}" + ], + "playbook_file": "ansible/windows/node_windows.yml", + "type": "ansible", + "use_proxy": false, + "user": "Administrator" + }, + { + "except": "file", + "restart_check_command": "powershell -command \"& {if ((get-content C:\\ProgramData\\lastboot.txt) -eq (Get-WmiObject win32_operatingsystem).LastBootUpTime) {Write-Output 'Sleeping for 600 seconds to wait for reboot'; start-sleep 600} else {Write-Output 'Reboot complete'}}\"", + "restart_command": "powershell \"& {(Get-WmiObject win32_operatingsystem).LastBootUpTime > C:\\ProgramData\\lastboot.txt; Restart-Computer -force}\"", + "type": "windows-restart" + }, + { + "arch": "{{user `goss_arch`}}", + "download_path": "{{user `goss_download_path`}}", + "except": "file", + "format": "{{user `goss_format`}}", + "format_options": "{{user `goss_format_options`}}", + "goss_file": "{{user `goss_entry_file`}}", + "inspect": "{{user `goss_inspect_mode`}}", + "remote_folder": "{{user `goss_remote_folder`}}", + "remote_path": "{{user `goss_remote_path`}}", + "skip_install": "{{user `goss_skip_install`}}", + "target_os": "Windows", + "tests": [ + "{{user `goss_tests_dir`}}" + ], + "type": "goss", + "url": "{{user `goss_url`}}", + "use_sudo": false, + "vars_env": { + "GOSS_MAX_CONCURRENT": "1", + "GOSS_USE_ALPHA": "1" + }, + "vars_file": "{{user `goss_vars_file`}}", + "vars_inline": { + "OS": "{{user `distro_name` | lower}}", + "PROVIDER": "ova", + "containerd_version": "{{user `containerd_version`}}", + "distribution_version": "{{user `distro_version`}}", + "docker_ee_version": "{{user `docker_ee_version`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}", + "pause_image": "{{user `pause_image`}}", + "runtime": "{{user `runtime`}}", + "ssh_source_url": "{{user `ssh_source_url`}}" + }, + "version": "{{user `goss_version`}}" + }, + { + "inline": [ + "rm -Force -Recurse C:\\var\\log\\kubelet\\*" + ], + "type": "powershell" + } + ], + "variables": { + "additional_debug_files": null, + "ansible_common_vars": "", + "ansible_extra_vars": "", + "ansible_user_vars": "", + "build_name": null, + "build_timestamp": "{{timestamp}}", + "build_version": "{{user `build_name`}}-kube-{{user `kubernetes_semver`}}", + "cloudbase_init_url": "https://github.com/cloudbase/cloudbase-init/releases/download/{{user `cloudbase_init_version`}}/CloudbaseInitSetup_{{user `cloudbase_init_version` | replace_all `.` `_` }}_x64.msi", + "cloudbase_metadata_services": "cloudbaseinit.metadata.services.vmwareguestinfoservice.VMwareGuestInfoService", + "cloudbase_metadata_services_unattend": "cloudbaseinit.metadata.services.vmwareguestinfoservice.VMwareGuestInfoService", + "cloudbase_plugins": "cloudbaseinit.plugins.windows.createuser.CreateUserPlugin, cloudbaseinit.plugins.common.setuserpassword.SetUserPasswordPlugin, cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin, cloudbaseinit.plugins.common.ephemeraldisk.EphemeralDiskPlugin, cloudbaseinit.plugins.common.mtu.MTUPlugin, cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin, cloudbaseinit.plugins.common.sshpublickeys.SetUserSSHPublicKeysPlugin, cloudbaseinit.plugins.common.userdata.UserDataPlugin, cloudbaseinit.plugins.common.localscripts.LocalScriptsPlugin, cloudbaseinit.plugins.windows.createuser.CreateUserPlugin, cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin", + "cloudbase_plugins_unattend": "cloudbaseinit.plugins.common.mtu.MTUPlugin", + "containerd_sha256": null, + "containerd_url": "", + "containerd_version": null, + "disable_hypervisor": null, + "disk_size": "81920", + "http_port_max": "", + "http_port_min": "", + "ib_version": "{{env `IB_VERSION`}}", + "kubernetes_base_url": "https://kubernetesreleases.blob.core.windows.net/kubernetes/{{user `kubernetes_semver`}}/binaries/node/windows/{{user `kubernetes_goarch`}}", + "kubernetes_http_package_url": "", + "kubernetes_typed_version": "kube-{{user `kubernetes_semver`}}", + "manifest_output": "manifest.json", + "netbios_host_name_compatibility": null, + "nssm_url": null, + "output_dir": "./output/{{user `build_version`}}", + "prepull": null, + "unattend_timezone": "Pacific Standard Time", + "windows_service_manager": null, + "windows_updates_categories": null, + "windows_updates_kbs": null, + "wins_url": "https://github.com/rancher/wins/releases/download/v{{user `wins_version`}}/wins.exe" + } +} diff --git a/packer/ova/photon-3.json b/packer/ova/photon-3.json new file mode 100644 index 0000000..80e013d --- /dev/null +++ b/packer/ova/photon-3.json @@ -0,0 +1,16 @@ +{ + "boot_command_prefix": "<esc><wait> vmlinuz initrd=initrd.img root/dev/ram0 loglevel=3 photon.media=cdrom ks=", + "boot_command_suffix": "/3/ks.json<enter><wait>", + "boot_media_path": "http://{{ .HTTPIP }}:{{ .HTTPPort }}", + "build_name": "photon-3", + "distro_arch": "amd64", + "distro_name": "photon", + "distro_version": "3", + "guest_os_type": "vmware-photon-64", + "iso_checksum": "76fbe13df3f7340c94cf5706a0ec33ffc377c47e", + "iso_checksum_type": "sha1", + "iso_url": "https://packages.vmware.com/photon/3.0/Rev3/iso/Update1/photon-minimal-3.0-913b49438.iso", + "os_display_name": "VMware Photon OS 64-bit", + "shutdown_command": "shutdown now", + "vsphere_guest_os_type": "vmwarePhoton64Guest" +} diff --git a/packer/ova/photon-4.json b/packer/ova/photon-4.json new file mode 100644 index 0000000..e3793c9 --- /dev/null +++ b/packer/ova/photon-4.json @@ -0,0 +1,16 @@ +{ + "boot_command_prefix": "<esc><wait> vmlinuz initrd=initrd.img root/dev/ram0 loglevel=3 photon.media=cdrom ks=", + "boot_command_suffix": "/4/ks.json insecure_installation=1<enter><wait>", + "boot_media_path": "http://{{ .HTTPIP }}:{{ .HTTPPort }}", + "build_name": "photon-4", + "distro_arch": "amd64", + "distro_name": "photon", + "distro_version": "4", + "guest_os_type": "vmware-photon-64", + "iso_checksum": "4d5b9c6c59bbb7b6f501b7fa5e8af669332155ed", + "iso_checksum_type": "sha1", + "iso_url": "https://packages.vmware.com/photon/4.0/Rev2/iso/photon-minimal-4.0-c001795b8.iso", + "os_display_name": "VMware Photon OS 64-bit", + "shutdown_command": "shutdown now", + "vsphere_guest_os_type": "vmwarePhoton64Guest" +} diff --git a/packer/ova/rhel-7.json b/packer/ova/rhel-7.json new file mode 100644 index 0000000..d503428 --- /dev/null +++ b/packer/ova/rhel-7.json @@ -0,0 +1,18 @@ +{ + "boot_command_prefix": "<tab><wait><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>quiet text inst.ks=hd:fd0:", + "boot_command_suffix": "/7/ks.cfg<enter><wait>", + "boot_media_path": "/HTTP", + "build_name": "rhel-7", + "distro_arch": "amd64", + "distro_name": "rhel", + "distro_version": "7", + "floppy_dirs": "./packer/ova/linux/{{user `distro_name`}}/http/", + "guest_os_type": "rhel7-64", + "iso_checksum": "19d653ce2f04f202e79773a0cbeda82070e7527557e814ebbce658773fbe8191", + "iso_checksum_type": "sha256", + "iso_url": "file:///rhel-server-7.9-x86_64-dvd.iso", + "os_display_name": "RHEL 7", + "redhat_epel_rpm": "https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm", + "shutdown_command": "sys-unconfig", + "vsphere_guest_os_type": "rhel7_64Guest" +} diff --git a/packer/ova/rhel-8.json b/packer/ova/rhel-8.json new file mode 100644 index 0000000..e5ffe44 --- /dev/null +++ b/packer/ova/rhel-8.json @@ -0,0 +1,19 @@ +{ + "boot_command_prefix": "<up><tab> text inst.ks=", + "boot_command_suffix": "/8/ks.cfg<enter><wait>", + "boot_media_path": "http://{{ .HTTPIP }}:{{ .HTTPPort }}", + "build_name": "rhel-8", + "distro_arch": "amd64", + "distro_name": "rhel", + "distro_version": "8", + "epel_rpm_gpg_key": "https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8", + "guest_os_type": "rhel8-64", + "http_directory": "./packer/ova/linux/{{user `distro_name`}}/http/", + "iso_checksum": "48f955712454c32718dcde858dea5aca574376a1d7a4b0ed6908ac0b85597811", + "iso_checksum_type": "sha256", + "iso_url": "file:///rhel-8.4-x86_64-dvd.iso", + "os_display_name": "RHEL 8", + "redhat_epel_rpm": "https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm", + "shutdown_command": "shutdown -P now", + "vsphere_guest_os_type": "rhel8_64Guest" +} diff --git a/packer/ova/rockylinux-8.json b/packer/ova/rockylinux-8.json new file mode 100644 index 0000000..2ec6ea5 --- /dev/null +++ b/packer/ova/rockylinux-8.json @@ -0,0 +1,18 @@ +{ + "boot_command_prefix": "<up><tab> text inst.ks=", + "boot_command_suffix": "/8/ks.cfg<enter><wait><enter>", + "boot_media_path": "http://{{ .HTTPIP }}:{{ .HTTPPort }}", + "build_name": "rockylinux-8", + "distro_arch": "amd64", + "distro_name": "rockylinux", + "distro_version": "8", + "epel_rpm_gpg_key": "https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8", + "guest_os_type": "centos8-64", + "iso_checksum": "13c3e7fca1fd32df61695584baafc14fa28d62816d0813116d23744f5394624b", + "iso_checksum_type": "sha256", + "iso_url": "https://download.rockylinux.org/pub/rocky/8/isos/x86_64/Rocky-8.7-x86_64-minimal.iso", + "os_display_name": "RockyLinux 8", + "redhat_epel_rpm": "https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm", + "shutdown_command": "/sbin/halt -h -p", + "vsphere_guest_os_type": "other4xLinux64Guest" +} diff --git a/packer/ova/ubuntu-1804.json b/packer/ova/ubuntu-1804.json new file mode 100644 index 0000000..d9e486c --- /dev/null +++ b/packer/ova/ubuntu-1804.json @@ -0,0 +1,18 @@ +{ + "boot_command_prefix": "<enter><wait><f6><wait><esc><wait><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>/install/vmlinuz auto console-setup/ask_detect=false console-setup/layoutcode=us debconf/frontend=noninteractive debian-installer=en_US fb=false initrd=/install/initrd.gz kbd-chooser/method=us keyboard-configuration/layout=USA keyboard-configuration/variant=USA locale=en_US netcfg/get_domain=local netcfg/get_hostname=localhost grub-installer/bootdev=/dev/sda ipv6.disable={{ user `boot_disable_ipv6` }} preseed/file=", + "boot_command_suffix": "/18.04/preseed.cfg -- <enter>", + "boot_disable_ipv6": "0", + "boot_media_path": "/media/HTTP", + "build_name": "ubuntu-1804", + "distro_arch": "amd64", + "distro_name": "ubuntu", + "distro_version": "18.04", + "floppy_dirs": "./packer/ova/linux/{{user `distro_name`}}/http/", + "guest_os_type": "ubuntu-64", + "iso_checksum": "f5cbb8104348f0097a8e513b10173a07dbc6684595e331cb06f93f385d0aecf6", + "iso_checksum_type": "sha256", + "iso_url": "http://cdimage.ubuntu.com/releases/18.04/release/ubuntu-18.04.6-server-amd64.iso", + "os_display_name": "Ubuntu 18.04", + "shutdown_command": "shutdown -P now", + "vsphere_guest_os_type": "ubuntu64Guest" +} diff --git a/packer/ova/ubuntu-2004-efi.json b/packer/ova/ubuntu-2004-efi.json new file mode 100644 index 0000000..9203dd1 --- /dev/null +++ b/packer/ova/ubuntu-2004-efi.json @@ -0,0 +1,20 @@ +{ + "boot_command_prefix": "<esc><wait><esc><wait><enter><wait>linux /install/vmlinuz auto console-setup/ask_detect=false console-setup/layoutcode=us console-setup/modelcode=pc105 debconf/frontend=noninteractive debian-installer=en_US fb=false kbd-chooser/method=us keyboard-configuration/layout=USA keyboard-configuration/variant=USA locale=en_US netcfg/get_domain=local netcfg/get_hostname=localhost ipv6.disable={{ user `boot_disable_ipv6` }} preseed/file=", + "boot_command_suffix": "/20.04/preseed-efi.cfg -- <wait><enter>initrd /install/initrd.gz<enter>boot<enter><wait>", + "boot_disable_ipv6": "0", + "boot_media_path": "/media/HTTP", + "build_name": "ubuntu-2004-efi", + "cdrom_type": "sata", + "distro_arch": "amd64", + "distro_name": "ubuntu", + "distro_version": "20.04", + "firmware": "efi", + "floppy_dirs": "./packer/ova/linux/{{user `distro_name`}}/http/", + "guest_os_type": "ubuntu-64", + "iso_checksum": "f11bda2f2caed8f420802b59f382c25160b114ccc665dbac9c5046e7fceaced2", + "iso_checksum_type": "sha256", + "iso_url": "http://cdimage.ubuntu.com/ubuntu-legacy-server/releases/20.04/release/ubuntu-20.04.1-legacy-server-amd64.iso", + "os_display_name": "Ubuntu 20.04", + "shutdown_command": "shutdown -P now", + "vsphere_guest_os_type": "ubuntu64Guest" +} diff --git a/packer/ova/ubuntu-2004.json b/packer/ova/ubuntu-2004.json new file mode 100644 index 0000000..6b641f4 --- /dev/null +++ b/packer/ova/ubuntu-2004.json @@ -0,0 +1,18 @@ +{ + "boot_command_prefix": "<esc><wait><esc><wait><enter><wait>/install/vmlinuz auto console-setup/ask_detect=false console-setup/layoutcode=us console-setup/modelcode=pc105 debconf/frontend=noninteractive debian-installer=en_US fb=false initrd=/install/initrd.gz kbd-chooser/method=us keyboard-configuration/layout=USA keyboard-configuration/variant=USA locale=en_US netcfg/get_domain=local netcfg/get_hostname=localhost ipv6.disable={{ user `boot_disable_ipv6` }} grub-installer/bootdev=/dev/sda preseed/file=", + "boot_command_suffix": "/20.04/preseed.cfg -- <wait><enter><wait>", + "boot_disable_ipv6": "0", + "boot_media_path": "/media/HTTP", + "build_name": "ubuntu-2004", + "distro_arch": "amd64", + "distro_name": "ubuntu", + "distro_version": "20.04", + "floppy_dirs": "./packer/ova/linux/{{user `distro_name`}}/http/", + "guest_os_type": "ubuntu-64", + "iso_checksum": "f11bda2f2caed8f420802b59f382c25160b114ccc665dbac9c5046e7fceaced2", + "iso_checksum_type": "sha256", + "iso_url": "http://cdimage.ubuntu.com/ubuntu-legacy-server/releases/20.04/release/ubuntu-20.04.1-legacy-server-amd64.iso", + "os_display_name": "Ubuntu 20.04", + "shutdown_command": "shutdown -P now", + "vsphere_guest_os_type": "ubuntu64Guest" +} diff --git a/packer/ova/ubuntu-2204.json b/packer/ova/ubuntu-2204.json new file mode 100644 index 0000000..64609a7 --- /dev/null +++ b/packer/ova/ubuntu-2204.json @@ -0,0 +1,17 @@ +{ + "boot_command_prefix": "c<wait>linux /casper/vmlinuz --- autoinstall ds='nocloud-net;s=http://{{ .HTTPIP }}:{{ .HTTPPort }}/22.04/'<enter><wait>initrd /casper/initrd<enter><wait>boot<enter>", + "boot_disable_ipv6": "0", + "boot_media_path": "/media/HTTP", + "build_name": "ubuntu-2204", + "distro_arch": "amd64", + "distro_name": "ubuntu", + "distro_version": "22.04", + "floppy_dirs": "./packer/ova/linux/{{user `distro_name`}}/http/", + "guest_os_type": "ubuntu-64", + "iso_checksum": "10f19c5b2b8d6db711582e0e27f5116296c34fe4b313ba45f9b201a5007056cb", + "iso_checksum_type": "sha256", + "iso_url": "https://releases.ubuntu.com/22.04/ubuntu-22.04.1-live-server-amd64.iso", + "os_display_name": "Ubuntu 22.04", + "shutdown_command": "shutdown -P now", + "vsphere_guest_os_type": "ubuntu64Guest" +} diff --git a/packer/ova/vmx.json b/packer/ova/vmx.json new file mode 100644 index 0000000..68504c1 --- /dev/null +++ b/packer/ova/vmx.json @@ -0,0 +1,3 @@ +{ + "source_path": "" +} diff --git a/packer/ova/vsphere.json b/packer/ova/vsphere.json new file mode 100644 index 0000000..e27a976 --- /dev/null +++ b/packer/ova/vsphere.json @@ -0,0 +1,16 @@ +{ + "cluster": "", + "convert_to_template": "false", + "create_snapshot": "true", + "datacenter": "", + "datastore": "", + "folder": "", + "insecure_connection": "false", + "linked_clone": "true", + "network": "", + "password": "", + "resource_pool": "", + "template": "", + "username": "", + "vcenter_server": "" +} diff --git a/packer/ova/windows-2004.json b/packer/ova/windows-2004.json new file mode 100644 index 0000000..347fece --- /dev/null +++ b/packer/ova/windows-2004.json @@ -0,0 +1,15 @@ +{ + "build_name": "windows-2004", + "disk_controller_type": "pvscsi", + "distro_arch": "amd64", + "distro_name": "windows", + "distro_version": "2004", + "guest_os_type": "Windows2004Server-64", + "iso_checksum": "none", + "local_guest_os_type": "windows9srv-64", + "os_display_name": "Windows Server 2004", + "os_iso_path": "[datastore] ISO/en_windows_server_version_2004_x64_dvd_765aeb22.iso", + "os_iso_url": "file:/path/en_windows_server_version_2004_x64_dvd_765aeb22.iso", + "vmtools_iso_path": "[datastore] ISO/vmtools/windows-11.1.5.iso", + "vsphere_guest_os_type": "windows9Server64Guest" +} diff --git a/packer/ova/windows-2019.json b/packer/ova/windows-2019.json new file mode 100644 index 0000000..ac4360a --- /dev/null +++ b/packer/ova/windows-2019.json @@ -0,0 +1,16 @@ +{ + "build_name": "windows-2019", + "disk_controller_type": "pvscsi", + "distro_arch": "amd64", + "distro_name": "windows", + "distro_version": "2019", + "guest_os_type": "Windows2019Server-64", + "iso_checksum": "none", + "local_guest_os_type": "windows9srv-64", + "os_display_name": "Windows Server 2019", + "os_iso_path": "[datastore] ISO/en_windows_server_2019_x64_dvd_4cb967d8.iso", + "os_iso_url": "file:/path/en_windows_server_2019_x64_dvd_4cb967d8.iso", + "vmtools_iso_path": "[datastore] ISO/vmtools/windows-11.1.5.iso", + "vmtools_iso_url": "file:/path/VMware-tools-windows-11.1.5-16724464.iso", + "vsphere_guest_os_type": "windows9Server64Guest" +} diff --git a/packer/ova/windows-2022.json b/packer/ova/windows-2022.json new file mode 100644 index 0000000..38f42d1 --- /dev/null +++ b/packer/ova/windows-2022.json @@ -0,0 +1,16 @@ +{ + "build_name": "windows-2022", + "disk_controller_type": "pvscsi", + "distro_arch": "amd64", + "distro_name": "windows", + "distro_version": "2022", + "guest_os_type": "Windows2019Server-64", + "iso_checksum": "none", + "local_guest_os_type": "windows9srv-64", + "os_display_name": "Windows Server 2022", + "os_iso_path": "[datastore] ISO/en-us_windows_server_2022_x64_dvd_620d7eac.iso", + "os_iso_url": "file:/path/en-us_windows_server_2022_x64_dvd_620d7eac.iso", + "vmtools_iso_path": "[datastore] ISO/vmtools/windows-11.1.5.iso", + "vmtools_iso_url": "file:/path/VMware-tools-windows-11.1.5-16724464.iso", + "vsphere_guest_os_type": "windows9Server64Guest" +} diff --git a/packer/ova/windows/disable-network-discovery.cmd b/packer/ova/windows/disable-network-discovery.cmd new file mode 100644 index 0000000..d2c47db --- /dev/null +++ b/packer/ova/windows/disable-network-discovery.cmd @@ -0,0 +1,2 @@ +reg ADD HKLM\SYSTEM\CurrentControlSet\Control\Network\NewNetworkWindowOff /f +netsh advfirewall firewall set rule group="Network Discovery" new enable=No \ No newline at end of file diff --git a/packer/ova/windows/disable-winrm.ps1 b/packer/ova/windows/disable-winrm.ps1 new file mode 100644 index 0000000..1ce9273 --- /dev/null +++ b/packer/ova/windows/disable-winrm.ps1 @@ -0,0 +1,8 @@ +netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=block +netsh advfirewall firewall set rule group="Windows Remote Management" new enable=yes +$winrmService = Get-Service -Name WinRM +if ($winrmService.Status -eq "Running"){ + Disable-PSRemoting -Force +} +Stop-Service winrm +Set-Service -Name winrm -StartupType Disabled diff --git a/packer/ova/windows/enable-winrm.ps1 b/packer/ova/windows/enable-winrm.ps1 new file mode 100644 index 0000000..e6f30b1 --- /dev/null +++ b/packer/ova/windows/enable-winrm.ps1 @@ -0,0 +1,18 @@ + +$NetworkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}")) +$Connections = $NetworkListManager.GetNetworkConnections() +$Connections | ForEach-Object { $_.GetNetwork().SetCategory(1) } + +Enable-PSRemoting -Force +winrm quickconfig -q +winrm quickconfig -transport:http +winrm set winrm/config '@{MaxTimeoutms="1800000"}' +winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="800"}' +winrm set winrm/config/service '@{AllowUnencrypted="true"}' +winrm set winrm/config/service/auth '@{Basic="true"}' +winrm set winrm/config/client/auth '@{Basic="true"}' +winrm set winrm/config/listener?Address=*+Transport=HTTP '@{Port="5985"}' +netsh advfirewall firewall set rule group="Windows Remote Administration" new enable=yes +netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=allow +Set-Service winrm -startuptype "auto" +Restart-Service winrm diff --git a/packer/ova/windows/pvscsi/amd64/pvscsi.cat b/packer/ova/windows/pvscsi/amd64/pvscsi.cat new file mode 100644 index 0000000..b290faa Binary files /dev/null and b/packer/ova/windows/pvscsi/amd64/pvscsi.cat differ diff --git a/packer/ova/windows/pvscsi/amd64/pvscsi.inf b/packer/ova/windows/pvscsi/amd64/pvscsi.inf new file mode 100644 index 0000000..03359ca --- /dev/null +++ b/packer/ova/windows/pvscsi/amd64/pvscsi.inf @@ -0,0 +1,221 @@ + +;pvscsi.inf +;This file contains the information required to load the driver for the VMware PVSCSI Controller +; Copyright (C) 2001 - 2019, VMware, Inc. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[version] +Signature="$Windows NT$" +Class=SCSIAdapter +ClassGuid={4D36E97B-E325-11CE-BFC1-08002BE10318} +Provider=%VMWARE% +DriverVer=08/02/2019,1.3.15.0 +CatalogFile=pvscsi.cat + +[ControlFlags] +ExcludeFromSelect = * + +[SourceDisksNames] +1 = %DSKID1%,pvscsi.sys,, + +[SourceDisksFiles] +pvscsi.sys = 1,, + +[Manufacturer] + + + + + + + +%VMWARE%=pvscsi,NTamd64.6.2 + + + + +; ################################################## + +; Other architectures are unsupported, as are older versions of Windows on all platforms. +[pvscsi] + + + + + + + + + + + + + + + + + + + + +[pvscsi.NTamd64.6.2] +%DEVICE%=DDInstall.x64.vista, PCI\VEN_15AD&DEV_07C0 + + + +; ################################################## + + + + + + +[DDInstall.x64.vista.NT] +CopyFiles=pvscsi.x64.CopyFiles + + +; ################################################## + +[DDInstall.x64.vista.NT.HW] +AddReg=enableMSI.reg +Include=machine.inf +Needs=PciIoSpaceNotRequired + + + +; ################################################## + +[pvscsi.x64.CopyFiles] +pvscsi.sys,,,2 + + +; ################################################## + +[DDInstall.x64.NT.Services] +AddService=pvscsi,2,Service_Install.x64,EventLog_Install + +[DDInstall.x64.vista.NT.Services] +AddService=pvscsi,2,Service_Install.x64,EventLog_Install + + +; ################################################## + +[DestinationDirs] +pvscsi.x64.CopyFiles = 12 +DefaultDestDir=12 + +; ################################################## + +[Service_Install.x64] +DisplayName=%pvscsi.DiskName% +ServiceType=1 ; %SERVICE_KERNEL_DRIVER% +StartType=0 ; %SERVICE_BOOT_START% +ErrorControl=1 ; %SERVICE_ERROR_NORMAL% +ServiceBinary=%12%\pvscsi.sys +LoadOrderGroup=SCSI Miniport + +; We need to force the use of \Driver\pvscsi32 as the driver object name, +; otherwise the crash dump driver loader functions cannot find the driver. +; StartName entry defined in the INF format is supposed to facilitate that, +; but at least on win2k3sp2-32 and win2k8-datacenter-32 the driver installer +; interpretes StartName as the name of the account to start the service under, +; which is an incorrect interpretation for SERVICE_KERNEL_DRIVER type. As a +; work around ObjectName registry entry is added directly using brute-force. + +AddReg=busTypeSAS,pnpsafe_pci_addreg,vmware_installers_addreg +DelReg=driverObjectName.del + + + + + + + + +; ################################################## + +[busTypeSAS] +HKR, "Parameters", "BusType", 0x00010001, 0x0000000A ; BusTypeSAS + +[enableMSI.reg] +HKR, Interrupt Management,, %FLG_ADDREG_KEYONLY% +HKR, Interrupt Management\MessageSignaledInterruptProperties,, %FLG_ADDREG_KEYONLY% +HKR, Interrupt Management\MessageSignaledInterruptProperties, MSISupported, \ + %FLG_ADDREG_TYPE_DWORD%, 1 +HKR, Interrupt Management\MessageSignaledInterruptProperties, MessageNumberLimit, \ + %FLG_ADDREG_TYPE_DWORD%, 1 + +[pnpsafe_pci_addreg] +HKR, "Parameters\PnpInterface", "5", 0x00010001, 0x00000001 + +[vmware_installers_addreg] +HKR,, %pvscsi.installers.value.name%, %FLG_ADDREG_KEYONLY%, %pvscsi.installers.value.windows% +;; FLG_ADDREG_KEYONLY +HKR,, %pvscsi.installers.value.name%, 0x00010002, %pvscsi.installers.value.windows% +;; FLG_ADDREG_NOCLOBBER | FLG_ADDREG_TYPE_MULTI_SZ + +[driverObjectName.del] +HKR, , "ObjectName" + +[EventLog_Install] +AddReg = EventLog_AddReg + +[EventLog_AddReg] +HKR,,EventMessageFile,%FLG_ADDREG_TYPE_EXPAND_SZ%,"%%SystemRoot%%\System32\IoLogMsg.dll" +HKR,,TypesSupported,%FLG_ADDREG_TYPE_DWORD%,7 + +[strings] +pvscsi.installers.value.name="vwdk.installers" +pvscsi.installers.value.windows="Windows" +pvscsi.DiskName="pvscsi Storage Controller Driver" +VMWARE="VMware, Inc." +DEVICE="VMware PVSCSI Controller" +DSKID1="VMware PVSCSI Controller Installation Disk 1" +FLG_ADDREG_KEYONLY = 0x00000010 +FLG_ADDREG_TYPE_DWORD = 0x00010001 +FLG_ADDREG_TYPE_EXPAND_SZ = 0x00020000 +FLG_DELREG_MULTI_SZ_DELSTRING = 0x00018002 diff --git a/packer/ova/windows/pvscsi/amd64/pvscsi.sys b/packer/ova/windows/pvscsi/amd64/pvscsi.sys new file mode 100644 index 0000000..bf6d2e2 Binary files /dev/null and b/packer/ova/windows/pvscsi/amd64/pvscsi.sys differ diff --git a/packer/ova/windows/pvscsi/amd64/txtsetup.oem b/packer/ova/windows/pvscsi/amd64/txtsetup.oem new file mode 100644 index 0000000..662d6f0 --- /dev/null +++ b/packer/ova/windows/pvscsi/amd64/txtsetup.oem @@ -0,0 +1,35 @@ + +; txtsetup.oem file. +; Required to install the pvscsi driver at install time. + +[Disks] +;"directory" should specify the full-path as per the documentation, but only +; relative paths worked during testing. + + + + + + + + + + + +[Defaults] +SCSI = pvscsi + +[SCSI] +pvscsi = "VMware PVSCSI Controller" + +[Files.SCSI.pvscsi] +driver = disk,pvscsi.sys,pvscsi +inf = disk,pvscsi.inf +catalog = disk,pvscsi.cat + +[Config.pvscsi] +value = Parameters\PnpInterface, 5 ,REG_DWORD, 1 +value = Parameters, BusType, REG_DWORD, A + +[HardwareIds.scsi.pvscsi] +id = "PCI\VEN_15AD&DEV_07C0", "pvscsi" diff --git a/packer/ova/windows/pvscsi/i386/pvscsi.cat b/packer/ova/windows/pvscsi/i386/pvscsi.cat new file mode 100644 index 0000000..d8654ec Binary files /dev/null and b/packer/ova/windows/pvscsi/i386/pvscsi.cat differ diff --git a/packer/ova/windows/pvscsi/i386/pvscsi.inf b/packer/ova/windows/pvscsi/i386/pvscsi.inf new file mode 100644 index 0000000..58b06ac --- /dev/null +++ b/packer/ova/windows/pvscsi/i386/pvscsi.inf @@ -0,0 +1,221 @@ + +;pvscsi.inf +;This file contains the information required to load the driver for the VMware PVSCSI Controller +; Copyright (C) 2001 - 2019, VMware, Inc. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[version] +Signature="$Windows NT$" +Class=SCSIAdapter +ClassGuid={4D36E97B-E325-11CE-BFC1-08002BE10318} +Provider=%VMWARE% +DriverVer=08/02/2019,1.3.15.0 +CatalogFile=pvscsi.cat + +[ControlFlags] +ExcludeFromSelect = * + +[SourceDisksNames] +1 = %DSKID1%,pvscsi.sys,, + +[SourceDisksFiles] +pvscsi.sys = 1,, + +[Manufacturer] + + + + + + + +%VMWARE%=pvscsi,NTx86.6.2 + + + + +; ################################################## + +; Other architectures are unsupported, as are older versions of Windows on all platforms. +[pvscsi] + + + + + + + + + + + + + + + + + + + + +[pvscsi.NTx86.6.2] +%DEVICE%=DDInstall.x86.vista, PCI\VEN_15AD&DEV_07C0 + + + +; ################################################## + + + + + + +[DDInstall.x86.vista.NT] +CopyFiles=pvscsi.x86.CopyFiles + + +; ################################################## + +[DDInstall.x86.vista.NT.HW] +AddReg=enableMSI.reg +Include=machine.inf +Needs=PciIoSpaceNotRequired + + + +; ################################################## + +[pvscsi.x86.CopyFiles] +pvscsi.sys,,,2 + + +; ################################################## + +[DDInstall.x86.NT.Services] +AddService=pvscsi,2,Service_Install.x86,EventLog_Install + +[DDInstall.x86.vista.NT.Services] +AddService=pvscsi,2,Service_Install.x86,EventLog_Install + + +; ################################################## + +[DestinationDirs] +pvscsi.x86.CopyFiles = 12 +DefaultDestDir=12 + +; ################################################## + +[Service_Install.x86] +DisplayName=%pvscsi.DiskName% +ServiceType=1 ; %SERVICE_KERNEL_DRIVER% +StartType=0 ; %SERVICE_BOOT_START% +ErrorControl=1 ; %SERVICE_ERROR_NORMAL% +ServiceBinary=%12%\pvscsi.sys +LoadOrderGroup=SCSI Miniport + +; We need to force the use of \Driver\pvscsi32 as the driver object name, +; otherwise the crash dump driver loader functions cannot find the driver. +; StartName entry defined in the INF format is supposed to facilitate that, +; but at least on win2k3sp2-32 and win2k8-datacenter-32 the driver installer +; interpretes StartName as the name of the account to start the service under, +; which is an incorrect interpretation for SERVICE_KERNEL_DRIVER type. As a +; work around ObjectName registry entry is added directly using brute-force. + +AddReg=busTypeSAS,pnpsafe_pci_addreg,vmware_installers_addreg +DelReg=driverObjectName.del + + + + + + + + +; ################################################## + +[busTypeSAS] +HKR, "Parameters", "BusType", 0x00010001, 0x0000000A ; BusTypeSAS + +[enableMSI.reg] +HKR, Interrupt Management,, %FLG_ADDREG_KEYONLY% +HKR, Interrupt Management\MessageSignaledInterruptProperties,, %FLG_ADDREG_KEYONLY% +HKR, Interrupt Management\MessageSignaledInterruptProperties, MSISupported, \ + %FLG_ADDREG_TYPE_DWORD%, 1 +HKR, Interrupt Management\MessageSignaledInterruptProperties, MessageNumberLimit, \ + %FLG_ADDREG_TYPE_DWORD%, 1 + +[pnpsafe_pci_addreg] +HKR, "Parameters\PnpInterface", "5", 0x00010001, 0x00000001 + +[vmware_installers_addreg] +HKR,, %pvscsi.installers.value.name%, %FLG_ADDREG_KEYONLY%, %pvscsi.installers.value.windows% +;; FLG_ADDREG_KEYONLY +HKR,, %pvscsi.installers.value.name%, 0x00010002, %pvscsi.installers.value.windows% +;; FLG_ADDREG_NOCLOBBER | FLG_ADDREG_TYPE_MULTI_SZ + +[driverObjectName.del] +HKR, , "ObjectName" + +[EventLog_Install] +AddReg = EventLog_AddReg + +[EventLog_AddReg] +HKR,,EventMessageFile,%FLG_ADDREG_TYPE_EXPAND_SZ%,"%%SystemRoot%%\System32\IoLogMsg.dll" +HKR,,TypesSupported,%FLG_ADDREG_TYPE_DWORD%,7 + +[strings] +pvscsi.installers.value.name="vwdk.installers" +pvscsi.installers.value.windows="Windows" +pvscsi.DiskName="pvscsi Storage Controller Driver" +VMWARE="VMware, Inc." +DEVICE="VMware PVSCSI Controller" +DSKID1="VMware PVSCSI Controller Installation Disk 1" +FLG_ADDREG_KEYONLY = 0x00000010 +FLG_ADDREG_TYPE_DWORD = 0x00010001 +FLG_ADDREG_TYPE_EXPAND_SZ = 0x00020000 +FLG_DELREG_MULTI_SZ_DELSTRING = 0x00018002 diff --git a/packer/ova/windows/pvscsi/i386/pvscsi.sys b/packer/ova/windows/pvscsi/i386/pvscsi.sys new file mode 100644 index 0000000..0b5ccf0 Binary files /dev/null and b/packer/ova/windows/pvscsi/i386/pvscsi.sys differ diff --git a/packer/ova/windows/pvscsi/i386/txtsetup.oem b/packer/ova/windows/pvscsi/i386/txtsetup.oem new file mode 100644 index 0000000..662d6f0 --- /dev/null +++ b/packer/ova/windows/pvscsi/i386/txtsetup.oem @@ -0,0 +1,35 @@ + +; txtsetup.oem file. +; Required to install the pvscsi driver at install time. + +[Disks] +;"directory" should specify the full-path as per the documentation, but only +; relative paths worked during testing. + + + + + + + + + + + +[Defaults] +SCSI = pvscsi + +[SCSI] +pvscsi = "VMware PVSCSI Controller" + +[Files.SCSI.pvscsi] +driver = disk,pvscsi.sys,pvscsi +inf = disk,pvscsi.inf +catalog = disk,pvscsi.cat + +[Config.pvscsi] +value = Parameters\PnpInterface, 5 ,REG_DWORD, 1 +value = Parameters, BusType, REG_DWORD, A + +[HardwareIds.scsi.pvscsi] +id = "PCI\VEN_15AD&DEV_07C0", "pvscsi" diff --git a/packer/ova/windows/sysprep.ps1 b/packer/ova/windows/sysprep.ps1 new file mode 100644 index 0000000..7efb732 --- /dev/null +++ b/packer/ova/windows/sysprep.ps1 @@ -0,0 +1,13 @@ +Write-Output '>>> Sysprepping VM ...' +if( Test-Path $Env:SystemRoot\system32\Sysprep\unattend.xml ) { + Remove-Item $Env:SystemRoot\system32\Sysprep\unattend.xml -Force +} +$unattendedXml = "$ENV:ProgramFiles\Cloudbase Solutions\Cloudbase-Init\conf\Unattend.xml" +$FileExists = Test-Path $unattendedXml +If ($FileExists -eq $True) { + # Use the Cloudbase-init provided unattend file during install + Write-Output "Using cloudbase-init unattend file for sysprep: $unattendedXml" + & $Env:SystemRoot\System32\Sysprep\Sysprep.exe /oobe /generalize /mode:vm /shutdown /quiet /unattend:$unattendedXml +}else { + & $Env:SystemRoot\System32\Sysprep\Sysprep.exe /oobe /generalize /mode:vm /shutdown /quiet +} diff --git a/packer/ova/windows/windows-2004/autounattend.xml b/packer/ova/windows/windows-2004/autounattend.xml new file mode 100644 index 0000000..fd86747 --- /dev/null +++ b/packer/ova/windows/windows-2004/autounattend.xml @@ -0,0 +1,231 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--************************************************* +Windows Server 2004 Answer File + +Installation Notes +Location: +Notes: We currently assume your image is using a licesnsed media, and hard code product keys accordingly +Users will want to modify this file. +Installation Notes: +- We currently assume your image is using a licesnsed media, and hard code product keys accordingly +- ProductKey: must be removed if using an eval version +- The OOBE and UserAccounts sections: might be removed for administrator details +- The Timezone in this file should match the location your using (otherwise you hit race conditions related to time.windows.com) +- We hard code an administrative passcode in here, which administrators may need to modify +- There are many other parameters in here which may need to be changed. Over time we will parameterize these as part of the image-builder process +**************************************************--> +<unattend xmlns="urn:schemas-microsoft-com:unattend"> + <settings pass="windowsPE"> + <component name="Microsoft-Windows-PnpCustomizationsWinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <DriverPaths> + <PathAndCredentials wcm:action="add" wcm:keyValue="A"> + <Path>a:\</Path> + </PathAndCredentials> + </DriverPaths> + </component> + <component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <DiskConfiguration> + <Disk wcm:action="add"> + <CreatePartitions> + <CreatePartition wcm:action="add"> + <Order>1</Order> + <Type>Primary</Type> + <Size>350</Size> + </CreatePartition> + <CreatePartition wcm:action="add"> + <Extend>true</Extend> + <Order>2</Order> + <Type>Primary</Type> + </CreatePartition> + </CreatePartitions> + <ModifyPartitions> + <ModifyPartition wcm:action="add"> + <Order>1</Order> + <Label>System</Label> + <Format>NTFS</Format> + <PartitionID>1</PartitionID> + <TypeID>0x27</TypeID> + </ModifyPartition> + <ModifyPartition wcm:action="add"> + <Order>2</Order> + <PartitionID>2</PartitionID> + <Letter>C</Letter> + <Label>OS</Label> + <Format>NTFS</Format> + </ModifyPartition> + </ModifyPartitions> + <DiskID>0</DiskID> + <WillWipeDisk>true</WillWipeDisk> + </Disk> + </DiskConfiguration> + <ImageInstall> + <OSImage> + <InstallFrom> + <MetaData wcm:action="add"> + <Key>/IMAGE/NAME</Key> + <Value>Windows Server SERVERSTANDARDACORE</Value> + </MetaData> + </InstallFrom> + <InstallTo> + <DiskID>0</DiskID> + <PartitionID>2</PartitionID> + </InstallTo> + </OSImage> + </ImageInstall> + <UserData> + <ProductKey> + <Key>N2KJX-J94YW-TQVFB-DG9YT-724CC</Key> + <WillShowUI>OnError</WillShowUI> + </ProductKey> + <AcceptEula>true</AcceptEula> + <FullName>Administrator</FullName> + <Organization>Organization</Organization> + </UserData> + <EnableFirewall>true</EnableFirewall> + </component> + <component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <SetupUILanguage> + <UILanguage>en-US</UILanguage> + </SetupUILanguage> + <InputLocale>0409:00000409</InputLocale> + <SystemLocale>en-US</SystemLocale> + <UILanguage>en-US</UILanguage> + <UILanguageFallback>en-US</UILanguageFallback> + <UserLocale>en-US</UserLocale> + </component> + </settings> + <settings pass="offlineServicing"> + <component name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <EnableLUA>false</EnableLUA> + </component> + </settings> + <settings pass="generalize"> + <component name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <SkipRearm>1</SkipRearm> + </component> + </settings> + <settings pass="specialize"> + <component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <RunSynchronous> + <RunSynchronousCommand wcm:action="add"> + <WillReboot>Always</WillReboot> + <Path>e:\setup64.exe /s /v "/qb REBOOT=R ADDLOCAL=ALL"</Path> + <Order>1</Order> + </RunSynchronousCommand> + </RunSynchronous> + </component> + <component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <InputLocale>0409:00000409</InputLocale> + <SystemLocale>en-US</SystemLocale> + <UILanguage>en-US</UILanguage> + <UILanguageFallback>en-US</UILanguageFallback> + <UserLocale>en-US</UserLocale> + </component> + <component name="Microsoft-Windows-Security-SPP-UX" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <SkipAutoActivation>true</SkipAutoActivation> + </component> + <component name="Microsoft-Windows-SQMApi" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <CEIPEnabled>0</CEIPEnabled> + </component> + <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <ProductKey>N2KJX-J94YW-TQVFB-DG9YT-724CC</ProductKey> + </component> + </settings> + <settings pass="oobeSystem"> + <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <RegisteredOrganization>Organization</RegisteredOrganization> + <RegisteredOwner>Owner</RegisteredOwner> + <DisableAutoDaylightTimeSet>false</DisableAutoDaylightTimeSet> + <TimeZone>Pacific Standard Time</TimeZone> + <UserAccounts> + <AdministratorPassword> + <Value>S3cr3t0!</Value> + <PlainText>true</PlainText> + </AdministratorPassword> + <LocalAccounts> + <LocalAccount wcm:action="add"> + <Password> + <Value>S3cr3t0!</Value> + <PlainText>true</PlainText> + </Password> + <Name>Administrator</Name> + <Group>Administrators</Group> + <DisplayName>Administrator</DisplayName> + <Description>Administrator</Description> + </LocalAccount> + </LocalAccounts> + </UserAccounts> + <FirstLogonCommands> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c powershell -Command &quot;Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force&quot;</CommandLine> + <Description>Set Execution Policy 64 Bit</Description> + <Order>1</Order> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <Order>2</Order> + <Description>Set Execution Policy 32 Bit</Description> + <CommandLine>%SystemRoot%\SysWOW64\cmd.exe /c powershell -Command &quot;Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force&quot;</CommandLine> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine> + <Description>Zero Hibernation File</Description> + <Order>3</Order> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine> + <Description>Disable Hibernation</Description> + <Order>4</Order> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <Order>5</Order> + <CommandLine>cmd.exe /c wmic useraccount where &quot;name=&apos;Administrator&apos;&quot; set PasswordExpires=FALSE</CommandLine> + <Description>Disable password expiration for Administrator user</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c %SystemDrive%\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\enable-winrm.ps1</CommandLine> + <Description>Enable WinRM</Description> + <Order>6</Order> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c a:\disable-network-discovery.cmd</CommandLine> + <Description>Disable Network Discovery</Description> + <Order>7</Order> + </SynchronousCommand> + </FirstLogonCommands> + <AutoLogon> + <Password> + <Value>S3cr3t0!</Value> + <PlainText>true</PlainText> + </Password> + <Enabled>true</Enabled> + <Username>Administrator</Username> + </AutoLogon> + </component> + </settings> + <cpi:offlineImage cpi:source="wim:c:/windows-2004/sources/install.wim#Windows Server SERVERSTANDARDACORE" + xmlns:cpi="urn:schemas-microsoft-com:cpi" /> +</unattend> diff --git a/packer/ova/windows/windows-2019/autounattend.xml b/packer/ova/windows/windows-2019/autounattend.xml new file mode 100644 index 0000000..cd4aef2 --- /dev/null +++ b/packer/ova/windows/windows-2019/autounattend.xml @@ -0,0 +1,255 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--************************************************* +Windows Server 2019 Answer File Generator +Created using Windows AFG found at: +;http://www.windowsafg.com + +Installation Notes: +- We currently assume your image is using a licesnsed media, and hard code product keys accordingly +- ProductKey: must be removed if using an eval version +- The OOBE and UserAccounts sections: might be removed for administrator details +- The Timezone in this file should match the location your using (otherwise you hit race conditions related to time.windows.com) +- We hard code an administrative passcode in here, which administrators may need to modify +- There are many other parameters in here which may need to be changed. Over time we will parameterize these as part of the image-builder process +**************************************************--> +<unattend xmlns="urn:schemas-microsoft-com:unattend"> + <settings pass="windowsPE"> + <component name="Microsoft-Windows-PnpCustomizationsWinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <DriverPaths> + <PathAndCredentials wcm:action="add" wcm:keyValue="A"> + <Path>a:\</Path> + </PathAndCredentials> + </DriverPaths> + </component> + <component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <DiskConfiguration> + <Disk wcm:action="add"> + <CreatePartitions> + <CreatePartition wcm:action="add"> + <Order>1</Order> + <Size>350</Size> + <Type>Primary</Type> + </CreatePartition> + <CreatePartition wcm:action="add"> + <Order>2</Order> + <Extend>true</Extend> + <Type>Primary</Type> + </CreatePartition> + </CreatePartitions> + <ModifyPartitions> + <ModifyPartition wcm:action="add"> + <Format>NTFS</Format> + <Label>System</Label> + <Order>1</Order> + <PartitionID>1</PartitionID> + <TypeID>0x27</TypeID> + </ModifyPartition> + <ModifyPartition wcm:action="add"> + <Order>2</Order> + <PartitionID>2</PartitionID> + <Letter>C</Letter> + <Label>OS</Label> + <Format>NTFS</Format> + </ModifyPartition> + </ModifyPartitions> + <DiskID>0</DiskID> + <WillWipeDisk>true</WillWipeDisk> + </Disk> + </DiskConfiguration> + <ImageInstall> + <OSImage> + <InstallTo> + <DiskID>0</DiskID> + <PartitionID>2</PartitionID> + </InstallTo> + <InstallFrom> + <MetaData wcm:action="add"> + <Key>/IMAGE/NAME</Key> + <Value>Windows Server 2019 SERVERSTANDARDCORE</Value> + </MetaData> + </InstallFrom> + </OSImage> + </ImageInstall> + <UserData> + <AcceptEula>true</AcceptEula> + <FullName>Administrator</FullName> + <Organization>Organization</Organization> + <ProductKey> + <Key>N69G4-B89J2-4G8F4-WWYCC-J464C</Key> + <WillShowUI>OnError</WillShowUI> + </ProductKey> + </UserData> + <EnableFirewall>true</EnableFirewall> + </component> + <component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <SetupUILanguage> + <UILanguage>en-US</UILanguage> + </SetupUILanguage> + <InputLocale>0409:00000409</InputLocale> + <SystemLocale>en-US</SystemLocale> + <UILanguage>en-US</UILanguage> + <UILanguageFallback>en-US</UILanguageFallback> + <UserLocale>en-US</UserLocale> + </component> + </settings> + <settings pass="offlineServicing"> + <component name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <EnableLUA>false</EnableLUA> + </component> + </settings> + <settings pass="generalize"> + <component name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <SkipRearm>1</SkipRearm> + </component> + </settings> + <settings pass="specialize"> + <component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <RunSynchronous> + <RunSynchronousCommand wcm:action="add"> + <WillReboot>Always</WillReboot> + <Path>e:\setup64.exe /s /v "/qb REBOOT=R ADDLOCAL=ALL"</Path> + <Order>1</Order> + </RunSynchronousCommand> + </RunSynchronous> + </component> + <component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <InputLocale>0409:00000409</InputLocale> + <SystemLocale>en-US</SystemLocale> + <UILanguage>en-US</UILanguage> + <UILanguageFallback>en-US</UILanguageFallback> + <UserLocale>en-US</UserLocale> + </component> + <component name="Microsoft-Windows-Security-SPP-UX" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <SkipAutoActivation>true</SkipAutoActivation> + </component> + <component name="Microsoft-Windows-SQMApi" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <CEIPEnabled>0</CEIPEnabled> + </component> + <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <ComputerName></ComputerName> + <ProductKey>N69G4-B89J2-4G8F4-WWYCC-J464C</ProductKey> + </component> + </settings> + <settings pass="oobeSystem"> + <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <AutoLogon> + <Password> + <Value>S3cr3t0!</Value> + <PlainText>true</PlainText> + </Password> + <Enabled>true</Enabled> + <Username>Administrator</Username> + </AutoLogon> + <FirstLogonCommands> + <SynchronousCommand wcm:action="add"> + <Order>1</Order> + <Description>Set Execution Policy 64 Bit</Description> + <CommandLine>cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <Order>2</Order> + <Description>Set Execution Policy 32 Bit</Description> + <CommandLine>%SystemDrive%\Windows\SysWOW64\cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine> + <Order>3</Order> + <Description>Show file extensions in Explorer</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine> + <Order>4</Order> + <Description>Enable QuickEdit mode</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine> + <Order>5</Order> + <Description>Show Run command in Start Menu</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine> + <Order>6</Order> + <Description>Show Administrative Tools in Start Menu</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine> + <Order>7</Order> + <Description>Zero Hibernation File</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine> + <Order>8</Order> + <Description>Disable Hibernation Mode</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE</CommandLine> + <Order>9</Order> + <Description>Disable password expiration for Administrator user</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c %SystemDrive%\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\enable-winrm.ps1</CommandLine> + <Description>Enable WinRM</Description> + <Order>10</Order> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c a:\disable-network-discovery.cmd</CommandLine> + <Description>Disable Network Discovery</Description> + <Order>11</Order> + </SynchronousCommand> + </FirstLogonCommands> + <OOBE> + <HideEULAPage>true</HideEULAPage> + <HideLocalAccountScreen>true</HideLocalAccountScreen> + <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen> + <HideOnlineAccountScreens>true</HideOnlineAccountScreens> + <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> + <NetworkLocation>Work</NetworkLocation> + <ProtectYourPC>1</ProtectYourPC> + <SkipMachineOOBE>true</SkipMachineOOBE> + <SkipUserOOBE>true</SkipUserOOBE> + </OOBE> + <RegisteredOrganization>Organization</RegisteredOrganization> + <RegisteredOwner>Owner</RegisteredOwner> + <DisableAutoDaylightTimeSet>false</DisableAutoDaylightTimeSet> + <TimeZone>Pacific Standard Time</TimeZone> + <UserAccounts> + <AdministratorPassword> + <Value>S3cr3t0!</Value> + <PlainText>true</PlainText> + </AdministratorPassword> + <LocalAccounts> + <LocalAccount wcm:action="add"> + <Description>Administrator</Description> + <DisplayName>Administrator</DisplayName> + <Group>Administrators</Group> + <Name>Administrator</Name> + </LocalAccount> + </LocalAccounts> + </UserAccounts> + </component> + </settings> +</unattend> diff --git a/packer/ova/windows/windows-2022/autounattend.xml b/packer/ova/windows/windows-2022/autounattend.xml new file mode 100644 index 0000000..5688b74 --- /dev/null +++ b/packer/ova/windows/windows-2022/autounattend.xml @@ -0,0 +1,256 @@ +<!--************************************************* +Windows Server 2019 Answer File Generator +Created using Windows AFG found at: +;http://www.windowsafg.com + +Installation Notes: +- We currently assume your image is using a licesnsed media, and hard code product keys accordingly +- ProductKey: must be removed if using an eval version +- The OOBE and UserAccounts sections: might be removed for administrator details +- The Timezone in this file should match the location your using (otherwise you hit race conditions related to time.windows.com) +- We hard code an administrative passcode in here, which administrators may need to modify +- There are many other parameters in here which may need to be changed. Over time we will parameterize these as part of the image-builder process +**************************************************--> + +<?xml version="1.0" encoding="utf-8"?> +<unattend xmlns="urn:schemas-microsoft-com:unattend"> + <settings pass="windowsPE"> + <component name="Microsoft-Windows-PnpCustomizationsWinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <DriverPaths> + <PathAndCredentials wcm:action="add" wcm:keyValue="A"> + <Path>a:\</Path> + </PathAndCredentials> + </DriverPaths> + </component> + <component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <DiskConfiguration> + <Disk wcm:action="add"> + <CreatePartitions> + <CreatePartition wcm:action="add"> + <Order>1</Order> + <Size>350</Size> + <Type>Primary</Type> + </CreatePartition> + <CreatePartition wcm:action="add"> + <Order>2</Order> + <Extend>true</Extend> + <Type>Primary</Type> + </CreatePartition> + </CreatePartitions> + <ModifyPartitions> + <ModifyPartition wcm:action="add"> + <Format>NTFS</Format> + <Label>System</Label> + <Order>1</Order> + <PartitionID>1</PartitionID> + <TypeID>0x27</TypeID> + </ModifyPartition> + <ModifyPartition wcm:action="add"> + <Order>2</Order> + <PartitionID>2</PartitionID> + <Letter>C</Letter> + <Label>OS</Label> + <Format>NTFS</Format> + </ModifyPartition> + </ModifyPartitions> + <DiskID>0</DiskID> + <WillWipeDisk>true</WillWipeDisk> + </Disk> + </DiskConfiguration> + <ImageInstall> + <OSImage> + <InstallTo> + <DiskID>0</DiskID> + <PartitionID>2</PartitionID> + </InstallTo> + <InstallFrom> + <MetaData wcm:action="add"> + <Key>/IMAGE/NAME</Key> + <Value>Windows Server 2022 SERVERSTANDARDCORE</Value> + </MetaData> + </InstallFrom> + </OSImage> + </ImageInstall> + <UserData> + <AcceptEula>true</AcceptEula> + <FullName>Administrator</FullName> + <Organization>Organization</Organization> + <ProductKey> + <Key>VDYBN-27WPP-V4HQT-9VMD4-VMK7H</Key> + <WillShowUI>OnError</WillShowUI> + </ProductKey> + </UserData> + <EnableFirewall>true</EnableFirewall> + </component> + <component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <SetupUILanguage> + <UILanguage>en-US</UILanguage> + </SetupUILanguage> + <InputLocale>0409:00000409</InputLocale> + <SystemLocale>en-US</SystemLocale> + <UILanguage>en-US</UILanguage> + <UILanguageFallback>en-US</UILanguageFallback> + <UserLocale>en-US</UserLocale> + </component> + </settings> + <settings pass="offlineServicing"> + <component name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <EnableLUA>false</EnableLUA> + </component> + </settings> + <settings pass="generalize"> + <component name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <SkipRearm>1</SkipRearm> + </component> + </settings> + <settings pass="specialize"> + <component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <RunSynchronous> + <RunSynchronousCommand wcm:action="add"> + <WillReboot>Always</WillReboot> + <Path>e:\setup64.exe /s /v "/qb REBOOT=R ADDLOCAL=ALL"</Path> + <Order>1</Order> + </RunSynchronousCommand> + </RunSynchronous> + </component> + <component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <InputLocale>0409:00000409</InputLocale> + <SystemLocale>en-US</SystemLocale> + <UILanguage>en-US</UILanguage> + <UILanguageFallback>en-US</UILanguageFallback> + <UserLocale>en-US</UserLocale> + </component> + <component name="Microsoft-Windows-Security-SPP-UX" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <SkipAutoActivation>true</SkipAutoActivation> + </component> + <component name="Microsoft-Windows-SQMApi" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <CEIPEnabled>0</CEIPEnabled> + </component> + <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <ComputerName></ComputerName> + <ProductKey>VDYBN-27WPP-V4HQT-9VMD4-VMK7H</ProductKey> + </component> + </settings> + <settings pass="oobeSystem"> + <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <AutoLogon> + <Password> + <Value>S3cr3t0!</Value> + <PlainText>true</PlainText> + </Password> + <Enabled>true</Enabled> + <Username>Administrator</Username> + </AutoLogon> + <FirstLogonCommands> + <SynchronousCommand wcm:action="add"> + <Order>1</Order> + <Description>Set Execution Policy 64 Bit</Description> + <CommandLine>cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <Order>2</Order> + <Description>Set Execution Policy 32 Bit</Description> + <CommandLine>%SystemDrive%\Windows\SysWOW64\cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine> + <Order>3</Order> + <Description>Show file extensions in Explorer</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine> + <Order>4</Order> + <Description>Enable QuickEdit mode</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine> + <Order>5</Order> + <Description>Show Run command in Start Menu</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine> + <Order>6</Order> + <Description>Show Administrative Tools in Start Menu</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine> + <Order>7</Order> + <Description>Zero Hibernation File</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine> + <Order>8</Order> + <Description>Disable Hibernation Mode</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE</CommandLine> + <Order>9</Order> + <Description>Disable password expiration for Administrator user</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c %SystemDrive%\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\enable-winrm.ps1</CommandLine> + <Description>Enable WinRM</Description> + <Order>10</Order> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c a:\disable-network-discovery.cmd</CommandLine> + <Description>Disable Network Discovery</Description> + <Order>11</Order> + </SynchronousCommand> + </FirstLogonCommands> + <OOBE> + <HideEULAPage>true</HideEULAPage> + <HideLocalAccountScreen>true</HideLocalAccountScreen> + <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen> + <HideOnlineAccountScreens>true</HideOnlineAccountScreens> + <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> + <NetworkLocation>Work</NetworkLocation> + <ProtectYourPC>1</ProtectYourPC> + <SkipMachineOOBE>true</SkipMachineOOBE> + <SkipUserOOBE>true</SkipUserOOBE> + </OOBE> + <RegisteredOrganization>Organization</RegisteredOrganization> + <RegisteredOwner>Owner</RegisteredOwner> + <DisableAutoDaylightTimeSet>false</DisableAutoDaylightTimeSet> + <TimeZone>Pacific Standard Time</TimeZone> + <UserAccounts> + <AdministratorPassword> + <Value>S3cr3t0!</Value> + <PlainText>true</PlainText> + </AdministratorPassword> + <LocalAccounts> + <LocalAccount wcm:action="add"> + <Description>Administrator</Description> + <DisplayName>Administrator</DisplayName> + <Group>Administrators</Group> + <Name>Administrator</Name> + </LocalAccount> + </LocalAccounts> + </UserAccounts> + </component> + </settings> +</unattend> diff --git a/packer/powervs/centos-8.json b/packer/powervs/centos-8.json new file mode 100644 index 0000000..eb1c1a2 --- /dev/null +++ b/packer/powervs/centos-8.json @@ -0,0 +1,9 @@ +{ + "build_name": "centos-streams8", + "epel_rpm_gpg_key": "https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8", + "redhat_epel_rpm": "https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm", + "source_cos_bucket": "power-oss-bucket", + "source_cos_object": "centos-streams-8.ova.gz", + "source_cos_region": "us-south", + "ssh_username": "root" +} diff --git a/packer/powervs/packer.json b/packer/powervs/packer.json new file mode 100644 index 0000000..b3fb49f --- /dev/null +++ b/packer/powervs/packer.json @@ -0,0 +1,107 @@ +{ + "builders": [ + { + "account_id": "{{user `account_id`}}", + "api_key": "{{user `apikey`}}", + "capture": { + "cos": { + "access_key": "{{user `capture_cos_access_key`}}", + "bucket": "{{user `capture_cos_bucket`}}", + "region": "{{user `capture_cos_region`}}", + "secret_key": "{{user `capture_cos_secret_key`}}" + }, + "name": "capibm-powervs-{{user `build_name`}}-{{user `kubernetes_rpm_version` | clean_resource_name}}-{{user `build_timestamp`}}" + }, + "instance_name": "capibm-{{user `build_name`}}-{{user `build_timestamp`}}", + "key_pair_name": "{{user `key_pair_name`}}", + "region": "{{user `region`}}", + "service_instance_id": "{{user `service_instance_id`}}", + "source": { + "cos": { + "bucket": "{{user `source_cos_bucket`}}", + "object": "{{user `source_cos_object`}}", + "region": "{{user `source_cos_region`}}" + } + }, + "ssh_private_key_file": "{{user `ssh_private_key_file`}}", + "ssh_timeout": "{{user `ssh_timeout`}}", + "ssh_username": "{{user `ssh_username`}}", + "type": "powervs", + "zone": "{{user `zone`}}" + } + ], + "post-processors": [ + { + "custom_data": { + "containerd_version": "{{user `containerd_version`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}" + }, + "output": "{{user `manifest_output`}}", + "type": "manifest" + } + ], + "provisioners": [ + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} {{user `ansible_common_ssh_args`}}'" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}", + "--scp-extra-args", + "{{user `ansible_scp_extra_args`}}" + ], + "playbook_file": "./ansible/node.yml", + "type": "ansible" + } + ], + "variables": { + "account_id": "", + "ansible_common_vars": "", + "ansible_extra_vars": "", + "ansible_scp_extra_args": "", + "ansible_user_vars": "", + "apikey": "", + "build_timestamp": "{{timestamp}}", + "capture_cos_access_key": "", + "capture_cos_bucket": "", + "capture_cos_region": "", + "capture_cos_secret_key": "", + "containerd_sha256": null, + "containerd_url": null, + "containerd_version": null, + "crictl_url": null, + "crictl_version": null, + "existing_ansible_ssh_args": "{{env `ANSIBLE_SSH_ARGS`}}", + "key_pair_name": "", + "kubernetes_cni_deb_version": null, + "kubernetes_cni_http_source": null, + "kubernetes_cni_rpm_version": null, + "kubernetes_cni_semver": null, + "kubernetes_cni_source_type": null, + "kubernetes_container_registry": null, + "kubernetes_deb_gpg_key": null, + "kubernetes_deb_repo": null, + "kubernetes_deb_version": null, + "kubernetes_http_source": null, + "kubernetes_load_additional_imgs": null, + "kubernetes_rpm_gpg_check": null, + "kubernetes_rpm_gpg_key": null, + "kubernetes_rpm_repo": null, + "kubernetes_rpm_version": null, + "kubernetes_semver": null, + "kubernetes_source_type": null, + "manifest_output": "manifest.json", + "python_path": "", + "region": "", + "service_instance_id": "", + "ssh_private_key_file": "", + "ssh_timeout": "30m", + "zone": "" + } +} diff --git a/packer/qemu/OWNERS b/packer/qemu/OWNERS new file mode 100644 index 0000000..e651a62 --- /dev/null +++ b/packer/qemu/OWNERS @@ -0,0 +1,11 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - cluster-api-openstack-maintainers + - cluster-api-cloudstack-maintainers + +reviewers: + - cluster-api-openstack-maintainers + - image-builder-openstack-reviewers + - cluster-api-cloudstack-maintainers + - image-builder-cloudstack-reviewers diff --git a/packer/qemu/README.md b/packer/qemu/README.md new file mode 100644 index 0000000..6c51ee0 --- /dev/null +++ b/packer/qemu/README.md @@ -0,0 +1,6 @@ +To build an image using a specific version of Kubernetes use the "PACKER_FLAGS" env var like in the example below: + +PACKER_FLAGS="--var 'kubernetes_rpm_version=1.25.3-0' --var 'kubernetes_semver=v1.25.3' --var 'kubernetes_series=v1.25' --var 'kubernetes_deb_version=1.25.3-00'" make build-kubevirt-qemu-ubuntu-2004 + +P.S: In order to change disk size(defaults to 20GB as of 31.10.22) you can update PACKER_FLAGS with: +--var 'disk_size=<disk size in mb>' \ No newline at end of file diff --git a/packer/qemu/linux b/packer/qemu/linux new file mode 120000 index 0000000..2df9464 --- /dev/null +++ b/packer/qemu/linux @@ -0,0 +1 @@ +../ova/linux \ No newline at end of file diff --git a/packer/qemu/packer.json b/packer/qemu/packer.json new file mode 100644 index 0000000..58e4027 --- /dev/null +++ b/packer/qemu/packer.json @@ -0,0 +1,194 @@ +{ + "builders": [ + { + "accelerator": "{{user `accelerator`}}", + "boot_command": [ + "{{user `boot_command_prefix`}}", + "{{user `boot_media_path`}}", + "{{user `boot_command_suffix`}}" + ], + "boot_wait": "{{user `boot_wait`}}", + "cpus": "{{user `cpus`}}", + "disk_compression": "{{ user `disk_compression`}}", + "disk_discard": "{{user `disk_discard`}}", + "disk_interface": "virtio-scsi", + "disk_size": "{{user `disk_size`}}", + "firmware": "{{user `firmware`}}", + "format": "{{user `format`}}", + "headless": "{{user `headless`}}", + "http_directory": "{{user `http_directory`}}", + "iso_checksum": "{{user `iso_checksum_type`}}:{{user `iso_checksum`}}", + "iso_url": "{{user `iso_url`}}", + "memory": "{{user `memory`}}", + "net_device": "virtio-net", + "output_directory": "{{user `output_directory`}}", + "qemu_binary": "{{user `qemu_binary`}}", + "shutdown_command": "echo '{{user `ssh_password`}}' | sudo -S -E sh -c 'usermod -L {{user `ssh_username`}} && {{user `shutdown_command`}}'", + "ssh_password": "{{user `ssh_password`}}", + "ssh_timeout": "2h", + "ssh_username": "{{user `ssh_username`}}", + "type": "qemu", + "vm_name": "{{user `build_name`}}-kube-{{user `kubernetes_semver`}}" + } + ], + "post-processors": [ + { + "environment_vars": [ + "CUSTOM_POST_PROCESSOR={{user `custom_post_processor`}}" + ], + "inline": [ + "if [ \"$CUSTOM_POST_PROCESSOR\" != \"true\" ]; then exit 0; fi", + "{{user `custom_post_processor_command`}}" + ], + "name": "custom-post-processor", + "type": "shell-local" + }, + { + "environment_vars": [ + "OUTPUT_DIR={{user `output_directory`}}", + "ARTIFACT_NAME={{user `artifact_name`}}", + "KUBEVIRT={{user `kubevirt`}}" + ], + "inline": [ + "if [ \"$KUBEVIRT\" != \"true\" ]; then", + "exit 0", + "else", + "bash ./packer/qemu/scripts/build_kubevirt_image.sh {{user `build_name`}}-container-disk", + "fi" + ], + "name": "kubevirt", + "type": "shell-local" + } + ], + "provisioners": [ + { + "execute_command": "BUILD_NAME={{user `build_name`}}; if [[ \"${BUILD_NAME}\" == *\"flatcar\"* ]]; then sudo {{.Vars}} -S -E bash '{{.Path}}'; fi", + "script": "./packer/files/flatcar/scripts/bootstrap-flatcar.sh", + "type": "shell" + }, + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} {{user `ansible_common_ssh_args`}}'", + "KUBEVIRT={{user `kubevirt`}}" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}", + "--scp-extra-args", + "{{user `ansible_scp_extra_args`}}" + ], + "playbook_file": "./ansible/firstboot.yml", + "type": "ansible", + "user": "builder" + }, + { + "expect_disconnect": true, + "inline": [ + "sudo reboot now" + ], + "inline_shebang": "/bin/bash -e", + "type": "shell" + }, + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} {{user `ansible_common_ssh_args`}}'", + "KUBEVIRT={{user `kubevirt`}}" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}", + "--scp-extra-args", + "{{user `ansible_scp_extra_args`}}" + ], + "playbook_file": "./ansible/node.yml", + "type": "ansible", + "user": "builder" + }, + { + "arch": "{{user `goss_arch`}}", + "format": "{{user `goss_format`}}", + "format_options": "{{user `goss_format_options`}}", + "goss_file": "{{user `goss_entry_file`}}", + "inspect": "{{user `goss_inspect_mode`}}", + "tests": [ + "{{user `goss_tests_dir`}}" + ], + "type": "goss", + "url": "{{user `goss_url`}}", + "use_sudo": true, + "vars_file": "{{user `goss_vars_file`}}", + "vars_inline": { + "ARCH": "amd64", + "OS": "{{user `distro_name` | lower}}", + "PROVIDER": "qemu", + "containerd_version": "{{user `containerd_version`}}", + "kubernetes_cni_deb_version": "{{ user `kubernetes_cni_deb_version` }}", + "kubernetes_cni_rpm_version": "{{ split (user `kubernetes_cni_rpm_version`) \"-\" 0 }}", + "kubernetes_cni_source_type": "{{user `kubernetes_cni_source_type`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver` | replace \"v\" \"\" 1}}", + "kubernetes_deb_version": "{{ user `kubernetes_deb_version` }}", + "kubernetes_rpm_version": "{{ split (user `kubernetes_rpm_version`) \"-\" 0 }}", + "kubernetes_source_type": "{{user `kubernetes_source_type`}}", + "kubernetes_version": "{{user `kubernetes_semver` | replace \"v\" \"\" 1}}" + }, + "version": "{{user `goss_version`}}" + } + ], + "variables": { + "accelerator": "kvm", + "ansible_common_vars": "", + "ansible_extra_vars": "ansible_python_interpreter=/usr/bin/python3", + "ansible_user_vars": "", + "artifact_name": "{{user `build_name`}}-kube-{{user `kubernetes_semver`}}", + "boot_media_path": "http://{{ .HTTPIP }}:{{ .HTTPPort }}", + "boot_wait": "10s", + "build_timestamp": "{{timestamp}}", + "containerd_sha256": null, + "containerd_url": "https://github.com/containerd/containerd/releases/download/v{{user `containerd_version`}}/cri-containerd-cni-{{user `containerd_version`}}-linux-amd64.tar.gz", + "containerd_version": null, + "cpus": "1", + "crictl_url": "https://github.com/kubernetes-sigs/cri-tools/releases/download/v{{user `crictl_version`}}/crictl-v{{user `crictl_version`}}-linux-amd64.tar.gz", + "crictl_version": null, + "disk_compression": "false", + "disk_discard": "unmap", + "disk_size": "20480", + "existing_ansible_ssh_args": "{{env `ANSIBLE_SSH_ARGS`}}", + "firmware": "", + "format": "qcow2", + "headless": "true", + "http_directory": "./packer/qemu/linux/{{user `distro_name`}}/http/", + "kubernetes_cni_deb_version": null, + "kubernetes_cni_http_source": null, + "kubernetes_cni_semver": null, + "kubernetes_cni_source_type": null, + "kubernetes_container_registry": null, + "kubernetes_deb_gpg_key": null, + "kubernetes_deb_repo": null, + "kubernetes_deb_version": null, + "kubernetes_http_source": null, + "kubernetes_load_additional_imgs": null, + "kubernetes_rpm_gpg_check": null, + "kubernetes_rpm_gpg_key": null, + "kubernetes_rpm_repo": null, + "kubernetes_rpm_version": null, + "kubernetes_semver": null, + "kubernetes_series": null, + "kubernetes_source_type": null, + "machine_id_mode": "444", + "memory": "2048", + "oem_id": "", + "output_directory": "./output/{{user `build_name`}}-kube-{{user `kubernetes_semver`}}", + "python_path": "", + "qemu_binary": "qemu-system-x86_64", + "ssh_password": "builder", + "ssh_username": "builder" + } +} diff --git a/packer/qemu/qemu-centos-7.json b/packer/qemu/qemu-centos-7.json new file mode 100644 index 0000000..58f7130 --- /dev/null +++ b/packer/qemu/qemu-centos-7.json @@ -0,0 +1,15 @@ +{ + "ansible_extra_vars": "ansible_python_interpreter=/usr/bin/python extra_arguments =vvvv", + "boot_command_prefix": "<tab> text ks=", + "boot_command_suffix": "/7/ks.cfg<enter><wait>", + "build_name": "centos-7", + "distro_arch": "amd64", + "distro_name": "centos", + "distro_version": "7", + "guest_os_type": "centos7-64", + "iso_checksum": "07b94e6b1a0b0260b94c83d6bb76b26bf7a310dc78d7a9c7432809fb9bc6194a", + "iso_checksum_type": "sha256", + "iso_url": "https://mirrors.edge.kernel.org/centos/7.9.2009/isos/x86_64/CentOS-7-x86_64-Minimal-2009.iso", + "os_display_name": "CentOS 7", + "shutdown_command": "sys-unconfig" +} diff --git a/packer/qemu/qemu-flatcar.json b/packer/qemu/qemu-flatcar.json new file mode 100644 index 0000000..201dad6 --- /dev/null +++ b/packer/qemu/qemu-flatcar.json @@ -0,0 +1,25 @@ +{ + "ansible_extra_vars": "ansible_python_interpreter=/opt/bin/python oem_id={{user `oem_id`}}", + "boot_command_prefix": "sudo systemctl mask sshd.socket --now<enter>curl -sLo /tmp/ignition.json ", + "boot_command_suffix": "/bootstrap.json<enter>sed -i \"s|BUILDERPASSWORDHASH|$(mkpasswd -5 {{user `ssh_password`}})|\" /tmp/ignition.json<enter>sudo flatcar-install -d /dev/sda -C {{user `channel_name`}} -V {{user `release_version`}} -i /tmp/ignition.json<enter>sudo reboot<enter>", + "boot_wait": "120s", + "build_name": "flatcar-{{env `FLATCAR_CHANNEL`}}-{{env `FLATCAR_VERSION`}}", + "channel_name": "{{env `FLATCAR_CHANNEL`}}", + "crictl_source_type": "http", + "distro_name": "flatcar", + "guest_os_type": "linux-64", + "http_directory": "./packer/files/flatcar/ignition/", + "iso_checksum": "https://{{env `FLATCAR_CHANNEL`}}.release.flatcar-linux.net/amd64-usr/{{env `FLATCAR_VERSION`}}/flatcar_production_iso_image.iso.DIGESTS.asc", + "iso_checksum_type": "file", + "iso_url": "https://{{env `FLATCAR_CHANNEL`}}.release.flatcar-linux.net/amd64-usr/{{env `FLATCAR_VERSION`}}/flatcar_production_iso_image.iso", + "kubernetes_cni_source_type": "http", + "kubernetes_source_type": "http", + "oem_id": "{{env `OEM_ID`}}", + "os_display_name": "Flatcar Container Linux ({{env `FLATCAR_CHANNEL`}} channel release {{env `FLATCAR_VERSION`}})", + "python_path": "/opt/bin/builder-env/site-packages", + "release_version": "{{env `FLATCAR_VERSION`}}", + "shutdown_command": "shutdown -P now", + "systemd_prefix": "/etc/systemd", + "sysusr_prefix": "/opt", + "sysusrlocal_prefix": "/opt" +} diff --git a/packer/qemu/qemu-rhel-8.json b/packer/qemu/qemu-rhel-8.json new file mode 100644 index 0000000..7bb3adf --- /dev/null +++ b/packer/qemu/qemu-rhel-8.json @@ -0,0 +1,15 @@ +{ + "boot_command_prefix": "<tab> text inst.ks=", + "boot_command_suffix": "/8/ks.cfg<enter><wait>", + "build_name": "rhel-8", + "distro_name": "rhel", + "distro_version": "8", + "epel_rpm_gpg_key": "https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8", + "guest_os_type": "RedHat_64", + "iso_checksum": "48f955712454c32718dcde858dea5aca574376a1d7a4b0ed6908ac0b85597811", + "iso_checksum_type": "sha256", + "iso_url": "rhel-8.4-x86_64-dvd.iso", + "os_display_name": "RHEL 8", + "redhat_epel_rpm": "https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm", + "shutdown_command": "shutdown -P now" +} diff --git a/packer/qemu/qemu-rockylinux-8.json b/packer/qemu/qemu-rockylinux-8.json new file mode 100644 index 0000000..11d852d --- /dev/null +++ b/packer/qemu/qemu-rockylinux-8.json @@ -0,0 +1,16 @@ +{ + "boot_command_prefix": "<up><tab> text inst.ks=", + "boot_command_suffix": "/8/ks.cfg<enter><wait><enter>", + "build_name": "rockylinux-8", + "distro_arch": "amd64", + "distro_name": "rockylinux", + "distro_version": "8", + "epel_rpm_gpg_key": "https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8", + "guest_os_type": "centos8-64", + "iso_checksum": "13c3e7fca1fd32df61695584baafc14fa28d62816d0813116d23744f5394624b", + "iso_checksum_type": "sha256", + "iso_url": "https://download.rockylinux.org/pub/rocky/8/isos/x86_64/Rocky-8.7-x86_64-minimal.iso", + "os_display_name": "RockyLinux 8", + "redhat_epel_rpm": "https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm", + "shutdown_command": "/sbin/halt -h -p" +} diff --git a/packer/qemu/qemu-ubuntu-1804.json b/packer/qemu/qemu-ubuntu-1804.json new file mode 100644 index 0000000..70bd6cd --- /dev/null +++ b/packer/qemu/qemu-ubuntu-1804.json @@ -0,0 +1,12 @@ +{ + "boot_command_prefix": "<esc><wait><esc><wait><enter><wait>/install/vmlinuz auto console-setup/ask_detect=false console-setup/layoutcode=us console-setup/modelcode=pc105 debconf/frontend=noninteractive debian-installer=en_US fb=false initrd=/install/initrd.gz kbd-chooser/method=us keyboard-configuration/layout=USA keyboard-configuration/variant=USA locale=en_US netcfg/get_domain=local netcfg/get_hostname=localhost grub-installer/bootdev=/dev/sda preseed/url=", + "boot_command_suffix": "/18.04/preseed.cfg -- <enter>", + "build_name": "ubuntu-1804", + "distro_name": "ubuntu", + "guest_os_type": "ubuntu-64", + "iso_checksum": "f5cbb8104348f0097a8e513b10173a07dbc6684595e331cb06f93f385d0aecf6", + "iso_checksum_type": "sha256", + "iso_url": "http://cdimage.ubuntu.com/releases/18.04/release/ubuntu-18.04.6-server-amd64.iso", + "os_display_name": "Ubuntu 18.04", + "shutdown_command": "shutdown -P now" +} diff --git a/packer/qemu/qemu-ubuntu-2004-efi.json b/packer/qemu/qemu-ubuntu-2004-efi.json new file mode 100644 index 0000000..c84597f --- /dev/null +++ b/packer/qemu/qemu-ubuntu-2004-efi.json @@ -0,0 +1,13 @@ +{ + "boot_command_prefix": "<esc><wait><esc><wait><enter><wait>linux /install/vmlinuz auto console-setup/ask_detect=false console-setup/layoutcode=us console-setup/modelcode=pc105 debconf/frontend=noninteractive debian-installer=en_US fb=false kbd-chooser/method=us keyboard-configuration/layout=USA keyboard-configuration/variant=USA locale=en_US netcfg/get_domain=local netcfg/get_hostname=localhost preseed/url=", + "boot_command_suffix": "/20.04/preseed-efi.cfg -- <wait><enter>initrd /install/initrd.gz<enter>boot<enter><wait>", + "build_name": "ubuntu-2004", + "distro_name": "ubuntu", + "firmware": "OVMF.fd", + "guest_os_type": "ubuntu-64", + "iso_checksum": "f11bda2f2caed8f420802b59f382c25160b114ccc665dbac9c5046e7fceaced2", + "iso_checksum_type": "sha256", + "iso_url": "http://cdimage.ubuntu.com/ubuntu-legacy-server/releases/20.04/release/ubuntu-20.04.1-legacy-server-amd64.iso", + "os_display_name": "Ubuntu 20.04", + "shutdown_command": "shutdown -P now" +} diff --git a/packer/qemu/qemu-ubuntu-2004.json b/packer/qemu/qemu-ubuntu-2004.json new file mode 100644 index 0000000..1a19728 --- /dev/null +++ b/packer/qemu/qemu-ubuntu-2004.json @@ -0,0 +1,12 @@ +{ + "boot_command_prefix": "<esc><wait><esc><wait><enter><wait>/install/vmlinuz auto console-setup/ask_detect=false console-setup/layoutcode=us console-setup/modelcode=pc105 debconf/frontend=noninteractive debian-installer=en_US fb=false initrd=/install/initrd.gz kbd-chooser/method=us keyboard-configuration/layout=USA keyboard-configuration/variant=USA locale=en_US netcfg/get_domain=local netcfg/get_hostname=localhost grub-installer/bootdev=/dev/sda preseed/url=", + "boot_command_suffix": "/20.04/preseed.cfg -- <wait><enter><wait>", + "build_name": "ubuntu-2004", + "distro_name": "ubuntu", + "guest_os_type": "ubuntu-64", + "iso_checksum": "f11bda2f2caed8f420802b59f382c25160b114ccc665dbac9c5046e7fceaced2", + "iso_checksum_type": "sha256", + "iso_url": "http://cdimage.ubuntu.com/ubuntu-legacy-server/releases/20.04/release/ubuntu-20.04.1-legacy-server-amd64.iso", + "os_display_name": "Ubuntu 20.04", + "shutdown_command": "shutdown -P now" +} diff --git a/packer/qemu/qemu-ubuntu-2204.json b/packer/qemu/qemu-ubuntu-2204.json new file mode 100644 index 0000000..2bfdfb2 --- /dev/null +++ b/packer/qemu/qemu-ubuntu-2204.json @@ -0,0 +1,12 @@ +{ + "boot_command_prefix": "c<wait>linux /casper/vmlinuz --- autoinstall ds='nocloud-net;s=http://{{ .HTTPIP }}:{{ .HTTPPort }}/22.04/'<enter><wait>initrd /casper/initrd<enter><wait>boot<enter>", + "build_name": "ubuntu-2204", + "distro_name": "ubuntu", + "guest_os_type": "ubuntu-64", + "iso_checksum": "10f19c5b2b8d6db711582e0e27f5116296c34fe4b313ba45f9b201a5007056cb", + "iso_checksum_type": "sha256", + "iso_url": "https://releases.ubuntu.com/22.04/ubuntu-22.04.1-live-server-amd64.iso", + "os_display_name": "Ubuntu 22.04", + "shutdown_command": "shutdown -P now", + "unmount_iso": "true" +} diff --git a/packer/qemu/scripts/build_kubevirt_image.sh b/packer/qemu/scripts/build_kubevirt_image.sh new file mode 100644 index 0000000..1fb0277 --- /dev/null +++ b/packer/qemu/scripts/build_kubevirt_image.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +echo "OUTPUT_DIR:$OUTPUT_DIR" +echo "ARTIFACT_NAME:$ARTIFACT_NAME" +echo "########" +env +cd $OUTPUT_DIR + +echo "FROM registry.access.redhat.com/ubi8/ubi:latest AS builder +ADD --chown=107:107 $ARTIFACT_NAME /disk/image.qcow2 + +FROM scratch +COPY --from=builder /disk/* /disk/" > ./kubevirt-Dockerfile + +docker build -f ./kubevirt-Dockerfile . -t $1 \ No newline at end of file diff --git a/packer/raw/OWNERS b/packer/raw/OWNERS new file mode 100644 index 0000000..f3b10c3 --- /dev/null +++ b/packer/raw/OWNERS @@ -0,0 +1,8 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - image-builder-raw-maintainers + +reviewers: + - image-builder-raw-maintainers + - image-builder-raw-reviewers diff --git a/packer/raw/linux/ubuntu/http/18.04/preseed.cfg b/packer/raw/linux/ubuntu/http/18.04/preseed.cfg new file mode 100644 index 0000000..37918c4 --- /dev/null +++ b/packer/raw/linux/ubuntu/http/18.04/preseed.cfg @@ -0,0 +1,15 @@ +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +d-i preseed/include string ../base/preseed.cfg diff --git a/packer/raw/linux/ubuntu/http/20.04/preseed-efi.cfg b/packer/raw/linux/ubuntu/http/20.04/preseed-efi.cfg new file mode 100644 index 0000000..b628670 --- /dev/null +++ b/packer/raw/linux/ubuntu/http/20.04/preseed-efi.cfg @@ -0,0 +1,15 @@ +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +d-i preseed/include string ../base/preseed-efi.cfg diff --git a/packer/raw/linux/ubuntu/http/20.04/preseed.cfg b/packer/raw/linux/ubuntu/http/20.04/preseed.cfg new file mode 100644 index 0000000..37918c4 --- /dev/null +++ b/packer/raw/linux/ubuntu/http/20.04/preseed.cfg @@ -0,0 +1,15 @@ +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +d-i preseed/include string ../base/preseed.cfg diff --git a/packer/raw/linux/ubuntu/http/base/preseed-efi.cfg b/packer/raw/linux/ubuntu/http/base/preseed-efi.cfg new file mode 100644 index 0000000..14cb400 --- /dev/null +++ b/packer/raw/linux/ubuntu/http/base/preseed-efi.cfg @@ -0,0 +1,128 @@ +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Configure the locale +d-i debian-installer/locale string en_US.utf8 +d-i console-setup/ask_detect boolean false +d-i console-setup/layout string us + +# Configure the clock +d-i time/zone string UTC +d-i clock-setup/utc-auto boolean true +d-i clock-setup/utc boolean true + +# Configure the keyboard +d-i kbd-chooser/method select American English + +# Configure networking +d-i netcfg/wireless_wep string + +# Select the kernel +d-i base-installer/kernel/override-image string linux-server + +# Configure a non-interactive install +debconf debconf/frontend select Noninteractive + +# Configure the base installation +d-i pkgsel/install-language-support boolean false +d-i pkgsel/language-packs multiselect +tasksel tasksel/first multiselect # standard, ubuntu-server + + +### Simple GPT configuration w/o LVM +d-i partman-auto/disk string /dev/sda + +d-i partman/alignment string cylinder +d-i partman/confirm_write_new_label boolean true +d-i partman-basicfilesystems/choose_label string gpt +d-i partman-basicfilesystems/default_label string gpt +d-i partman-partitioning/choose_label string gpt +d-i partman-partitioning/default_label string gpt +d-i partman/choose_label string gpt +d-i partman/default_label string gpt + +d-i partman-auto/method string regular +d-i partman-auto/choose_recipe select gpt-boot-root-swap +d-i partman-auto/expert_recipe string \ + gpt-boot-root-swap :: \ + 1 1 1 free \ + $bios_boot{ } \ + method{ biosgrub } . \ + 200 200 200 fat32 \ + $primary{ } \ + method{ efi } format{ } . \ + # 512 512 512 ext3 \ + # $primary{ } $bootable{ } \ + # method{ format } format{ } \ + # use_filesystem{ } filesystem{ ext3 } \ + # mountpoint{ /boot } . \ + 512 20000 -1 ext4 \ + $primary{ } \ + method{ format } format{ } \ + use_filesystem{ } filesystem{ ext4 } \ + mountpoint{ / } . + +d-i partman-partitioning/confirm_write_new_label boolean true +d-i partman/choose_partition select finish +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true + +# Create the default user. +d-i passwd/user-fullname string builder +d-i passwd/username string builder +d-i passwd/user-password password builder +d-i passwd/user-password-again password builder +d-i user-setup/encrypt-home boolean false +d-i user-setup/allow-password-weak boolean true + +# Disable upgrading packages upon installation. +d-i pkgsel/upgrade select none +d-i grub-installer/only_debian boolean true +d-i grub-installer/with_other_os boolean true +d-i finish-install/reboot_in_progress note +d-i pkgsel/update-policy select none + +# Disable use of the apt mirror during base install +# This means only packages available in the ISO can be installed +d-i apt-setup/use_mirror boolean false + +# Disable the security repo as well (it's on by default) +d-i apt-setup/services-select multiselect none + +# Customize the list of packages installed. +d-i pkgsel/include string openssh-server + + +# Ensure questions about these packages do not bother the installer. +libssl1.1 libssl1.1/restart-without-asking boolean true +libssl1.1:amd64 libssl1.1/restart-without-asking boolean true +libssl1.1 libssl1.1/restart-services string +libssl1.1:amd64 libssl1.1/restart-services string + + +# This command runs after all other steps; it: +# 1. Ensures the "builder" user doesn't require a password to use sudo +# 2. Cleans up any packages that are no longer required +# 3. Cleans the package cache +# 4. Removes the cached list of packages +# 5. Disables swapfiles +# 6. Removes the existing swapfile +# 7. Removes the swapfile entry from /etc/fstab +d-i preseed/late_command string \ + echo 'builder ALL=(ALL) NOPASSWD: ALL' >/target/etc/sudoers.d/builder ; \ + in-target chmod 440 /etc/sudoers.d/builder ; \ + in-target swapoff -a ; \ + in-target rm -f /swapfile ; \ + in-target sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab ; \ + in-target rm -f /etc/udev/rules.d/70-persistent-net.rules diff --git a/packer/raw/linux/ubuntu/http/base/preseed.cfg b/packer/raw/linux/ubuntu/http/base/preseed.cfg new file mode 100644 index 0000000..e6ff331 --- /dev/null +++ b/packer/raw/linux/ubuntu/http/base/preseed.cfg @@ -0,0 +1,126 @@ +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Configure the locale +d-i debian-installer/locale string en_US.utf8 +d-i debian-installer/add-kernel-opts console=ttyS0 +d-i console-setup/ask_detect boolean false +d-i console-setup/layout string us + +# Configure the clock +d-i time/zone string UTC +d-i clock-setup/utc-auto boolean true +d-i clock-setup/utc boolean true + +# Configure the keyboard +d-i kbd-chooser/method select American English + +# Configure networking +d-i netcfg/wireless_wep string + +# Select the kernel +d-i base-installer/kernel/override-image string linux-server + +# Configure a non-interactive install +debconf debconf/frontend select Noninteractive + +# Configure the base installation +d-i pkgsel/install-language-support boolean false +d-i pkgsel/language-packs multiselect +tasksel tasksel/first multiselect # standard, ubuntu-server + +# Create a single-partition with no swap space. For more information +# on how partitioning is configured, please refer to +# https://github.com/xobs/debian-installer/blob/master/doc/devel/partman-auto-recipe.txt. +d-i partman-auto/method string regular +d-i partman-lvm/device_remove_lvm boolean true +d-i partman-md/device_remove_md boolean true +d-i partman-lvm/confirm boolean true +d-i partman-auto-lvm/guided_size string max + +# Again, this creates a single-partition with no swap. Kubernetes +# really dislikes the idea of anyone else managing memory. +d-i partman-auto/expert_recipe string \ + slash :: \ + 0 0 -1 ext4 \ + $primary{ } $bootable{ } \ + method{ format } format{ } \ + use_filesystem{ } filesystem{ ext4 } \ + mountpoint{ / } \ + . + +d-i partman-partitioning/confirm_write_new_label boolean true +d-i partman/choose_partition select finish +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true +d-i partman-basicfilesystems/no_swap boolean false +d-i partman-md/confirm boolean true +d-i partman-partitioning/confirm_write_new_label boolean true +d-i partman/choose_partition select finish +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true +d-i partman-md/confirm_nooverwrite boolean true +d-i partman-lvm/confirm_nooverwrite boolean true +d-i partman-partitioning/no_bootable_gpt_biosgrub boolean true +d-i partman-partitioning/no_bootable_gpt_efi boolean false +d-i partman-efi/non_efi_system boolean false + +# Create the default user. +d-i passwd/user-fullname string builder +d-i passwd/username string builder +d-i passwd/user-password password builder +d-i passwd/user-password-again password builder +d-i user-setup/encrypt-home boolean false +d-i user-setup/allow-password-weak boolean true + +# Disable upgrading packages upon installation. +d-i pkgsel/upgrade select none +d-i grub-installer/only_debian boolean true +d-i grub-installer/with_other_os boolean true +d-i finish-install/reboot_in_progress note +d-i pkgsel/update-policy select none + +# Disable use of the apt mirror during base install +# This means only packages available in the ISO can be installed +d-i apt-setup/use_mirror boolean false + +# Disable the security repo as well (it's on by default) +d-i apt-setup/services-select multiselect none + +# Customize the list of packages installed. +d-i pkgsel/include string openssh-server + + +# Ensure questions about these packages do not bother the installer. +libssl1.1 libssl1.1/restart-without-asking boolean true +libssl1.1:amd64 libssl1.1/restart-without-asking boolean true +libssl1.1 libssl1.1/restart-services string +libssl1.1:amd64 libssl1.1/restart-services string + + +# This command runs after all other steps; it: +# 1. Ensures the "builder" user doesn't require a password to use sudo +# 2. Cleans up any packages that are no longer required +# 3. Cleans the package cache +# 4. Removes the cached list of packages +# 5. Disables swapfiles +# 6. Removes the existing swapfile +# 7. Removes the swapfile entry from /etc/fstab +d-i preseed/late_command string \ + echo 'builder ALL=(ALL) NOPASSWD: ALL' >/target/etc/sudoers.d/builder ; \ + in-target chmod 440 /etc/sudoers.d/builder ; \ + in-target swapoff -a ; \ + in-target rm -f /swapfile ; \ + in-target sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab ; \ + in-target rm -f /etc/udev/rules.d/70-persistent-net.rules diff --git a/packer/raw/packer.json b/packer/raw/packer.json new file mode 100644 index 0000000..315b242 --- /dev/null +++ b/packer/raw/packer.json @@ -0,0 +1,179 @@ +{ + "builders": [ + { + "accelerator": "{{user `accelerator`}}", + "boot_command": [ + "{{user `boot_command_prefix`}}", + "{{user `boot_media_path`}}", + "{{user `boot_command_suffix`}}" + ], + "boot_wait": "{{user `boot_wait`}}", + "cpus": "{{user `cpus`}}", + "disk_compression": "{{ user `disk_compression`}}", + "disk_discard": "{{user `disk_discard`}}", + "disk_interface": "virtio-scsi", + "disk_size": "{{user `disk_size`}}", + "firmware": "{{user `firmware`}}", + "format": "{{user `format`}}", + "headless": "{{user `headless`}}", + "http_directory": "{{user `http_directory`}}", + "iso_checksum": "{{user `iso_checksum_type`}}:{{user `iso_checksum`}}", + "iso_url": "{{user `iso_url`}}", + "memory": "{{user `memory`}}", + "net_device": "virtio-net", + "output_directory": "{{user `output_directory`}}", + "qemu_binary": "{{user `qemu_binary`}}", + "shutdown_command": "echo '{{user `ssh_password`}}' | sudo -S -E sh -c 'usermod -L {{user `ssh_username`}} && {{user `shutdown_command`}}'", + "ssh_password": "{{user `ssh_password`}}", + "ssh_timeout": "2h", + "ssh_username": "{{user `ssh_username`}}", + "type": "qemu", + "vm_name": "{{user `build_name`}}-kube-{{user `kubernetes_semver`}}" + } + ], + "post-processors": [ + { + "output": "./output/{{user `build_name`}}-kube-{{user `kubernetes_semver`}}.gz", + "type": "compress" + }, + { + "environment_vars": [ + "CUSTOM_POST_PROCESSOR={{user `custom_post_processor`}}" + ], + "inline": [ + "if [ \"$CUSTOM_POST_PROCESSOR\" != \"true\" ]; then exit 0; fi", + "{{user `custom_post_processor_command`}}" + ], + "name": "custom-post-processor", + "type": "shell-local" + } + ], + "provisioners": [ + { + "execute_command": "BUILD_NAME={{user `build_name`}}; if [[ \"${BUILD_NAME}\" == *\"flatcar\"* ]]; then sudo {{.Vars}} -S -E bash '{{.Path}}'; fi", + "script": "./packer/files/flatcar/scripts/bootstrap-flatcar.sh", + "type": "shell" + }, + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} {{user `ansible_common_ssh_args`}}'" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}", + "--scp-extra-args", + "{{user `ansible_scp_extra_args`}}" + ], + "playbook_file": "./ansible/firstboot.yml", + "type": "ansible", + "user": "builder" + }, + { + "expect_disconnect": true, + "inline": [ + "sudo reboot now" + ], + "inline_shebang": "/bin/bash -e", + "type": "shell" + }, + { + "ansible_env_vars": [ + "ANSIBLE_SSH_ARGS='{{user `existing_ansible_ssh_args`}} -o IdentitiesOnly=yes'" + ], + "extra_arguments": [ + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}", + "--scp-extra-args", + "{{user `ansible_scp_extra_args`}}" + ], + "playbook_file": "./ansible/node.yml", + "type": "ansible", + "user": "builder" + }, + { + "arch": "{{user `goss_arch`}}", + "format": "{{user `goss_format`}}", + "format_options": "{{user `goss_format_options`}}", + "goss_file": "{{user `goss_entry_file`}}", + "inspect": "{{user `goss_inspect_mode`}}", + "tests": [ + "{{user `goss_tests_dir`}}" + ], + "type": "goss", + "url": "{{user `goss_url`}}", + "use_sudo": true, + "vars_file": "{{user `goss_vars_file`}}", + "vars_inline": { + "ARCH": "amd64", + "OS": "{{user `distro_name` | lower}}", + "PROVIDER": "raw", + "containerd_version": "{{user `containerd_version`}}", + "kubernetes_cni_deb_version": "{{ user `kubernetes_cni_deb_version` }}", + "kubernetes_cni_rpm_version": "{{ split (user `kubernetes_cni_rpm_version`) \"-\" 0 }}", + "kubernetes_cni_source_type": "{{user `kubernetes_cni_source_type`}}", + "kubernetes_cni_version": "{{user `kubernetes_cni_semver` | replace \"v\" \"\" 1}}", + "kubernetes_deb_version": "{{ user `kubernetes_deb_version` }}", + "kubernetes_rpm_version": "{{ split (user `kubernetes_rpm_version`) \"-\" 0 }}", + "kubernetes_source_type": "{{user `kubernetes_source_type`}}", + "kubernetes_version": "{{user `kubernetes_semver` | replace \"v\" \"\" 1}}" + }, + "version": "{{user `goss_version`}}" + } + ], + "variables": { + "accelerator": "kvm", + "ansible_common_vars": "", + "ansible_extra_vars": "ansible_python_interpreter=/usr/bin/python3", + "ansible_scp_extra_args": "", + "ansible_user_vars": "", + "boot_media_path": "http://{{ .HTTPIP }}:{{ .HTTPPort }}", + "boot_wait": "10s", + "build_timestamp": "{{timestamp}}", + "containerd_sha256": null, + "containerd_url": "https://github.com/containerd/containerd/releases/download/v{{user `containerd_version`}}/cri-containerd-cni-{{user `containerd_version`}}-linux-amd64.tar.gz", + "containerd_version": null, + "cpus": "1", + "crictl_url": "https://github.com/kubernetes-sigs/cri-tools/releases/download/v{{user `crictl_version`}}/crictl-v{{user `crictl_version`}}-linux-amd64.tar.gz", + "crictl_version": null, + "disk_compression": "false", + "disk_discard": "unmap", + "disk_size": "6144", + "existing_ansible_ssh_args": "{{env `ANSIBLE_SSH_ARGS`}}", + "firmware": "", + "format": "raw", + "headless": "true", + "http_directory": "./packer/raw/linux/{{user `distro_name`}}/http/", + "kubernetes_cni_deb_version": null, + "kubernetes_cni_http_source": null, + "kubernetes_cni_semver": null, + "kubernetes_cni_source_type": null, + "kubernetes_container_registry": null, + "kubernetes_deb_gpg_key": null, + "kubernetes_deb_repo": null, + "kubernetes_deb_version": null, + "kubernetes_http_source": null, + "kubernetes_load_additional_imgs": null, + "kubernetes_rpm_gpg_check": null, + "kubernetes_rpm_gpg_key": null, + "kubernetes_rpm_repo": null, + "kubernetes_rpm_version": null, + "kubernetes_semver": null, + "kubernetes_series": null, + "kubernetes_source_type": null, + "machine_id_mode": "444", + "memory": "2048", + "output_directory": "./output/{{user `build_name`}}-kube-{{user `kubernetes_semver`}}", + "python_path": "", + "qemu_binary": "qemu-system-x86_64", + "ssh_password": "builder", + "ssh_username": "builder" + } +} diff --git a/packer/raw/raw-flatcar.json b/packer/raw/raw-flatcar.json new file mode 100644 index 0000000..a517a9e --- /dev/null +++ b/packer/raw/raw-flatcar.json @@ -0,0 +1,24 @@ +{ + "ansible_extra_vars": "ansible_python_interpreter=/opt/bin/python", + "boot_command_prefix": "sudo systemctl mask sshd.socket --now<enter>curl -sLo /tmp/ignition.json ", + "boot_command_suffix": "/bootstrap.json<enter>sed -i \"s|BUILDERPASSWORDHASH|$(mkpasswd -5 {{user `ssh_password`}})|\" /tmp/ignition.json<enter>sudo flatcar-install -d /dev/sda -C {{user `channel_name`}} -V {{user `release_version`}} -i /tmp/ignition.json<enter>sudo reboot<enter>", + "boot_wait": "120s", + "build_name": "flatcar-{{env `FLATCAR_CHANNEL`}}-{{env `FLATCAR_VERSION`}}", + "channel_name": "{{env `FLATCAR_CHANNEL`}}", + "crictl_source_type": "http", + "distro_name": "flatcar", + "guest_os_type": "linux-64", + "http_directory": "./packer/files/flatcar/ignition/", + "iso_checksum": "https://{{env `FLATCAR_CHANNEL`}}.release.flatcar-linux.net/amd64-usr/{{env `FLATCAR_VERSION`}}/flatcar_production_iso_image.iso.DIGESTS.asc", + "iso_checksum_type": "file", + "iso_url": "https://{{env `FLATCAR_CHANNEL`}}.release.flatcar-linux.net/amd64-usr/{{env `FLATCAR_VERSION`}}/flatcar_production_iso_image.iso", + "kubernetes_cni_source_type": "http", + "kubernetes_source_type": "http", + "os_display_name": "Flatcar Container Linux ({{env `FLATCAR_CHANNEL`}} channel release {{env `FLATCAR_VERSION`}})", + "python_path": "/opt/bin/builder-env/site-packages", + "release_version": "{{env `FLATCAR_VERSION`}}", + "shutdown_command": "shutdown -P now", + "systemd_prefix": "/etc/systemd", + "sysusr_prefix": "/opt", + "sysusrlocal_prefix": "/opt" +} diff --git a/packer/raw/raw-ubuntu-1804.json b/packer/raw/raw-ubuntu-1804.json new file mode 100644 index 0000000..46ef18d --- /dev/null +++ b/packer/raw/raw-ubuntu-1804.json @@ -0,0 +1,13 @@ +{ + "boot_command_prefix": "<esc><wait><esc><wait><enter><wait>/install/vmlinuz auto console-setup/ask_detect=false console-setup/layoutcode=us console-setup/modelcode=pc105 debconf/frontend=noninteractive debian-installer=en_US fb=false initrd=/install/initrd.gz kbd-chooser/method=us keyboard-configuration/layout=USA keyboard-configuration/variant=USA locale=en_US netcfg/get_domain=local netcfg/get_hostname=localhost grub-installer/bootdev=/dev/sda preseed/url=", + "boot_command_suffix": "/18.04/preseed.cfg -- <enter>", + "build_name": "ubuntu-1804", + "build_target": "raw", + "distro_name": "ubuntu", + "guest_os_type": "ubuntu-64", + "iso_checksum": "f5cbb8104348f0097a8e513b10173a07dbc6684595e331cb06f93f385d0aecf6", + "iso_checksum_type": "sha256", + "iso_url": "http://cdimage.ubuntu.com/releases/18.04/release/ubuntu-18.04.6-server-amd64.iso", + "os_display_name": "Ubuntu 18.04", + "shutdown_command": "shutdown -P now" +} diff --git a/packer/raw/raw-ubuntu-2004-efi.json b/packer/raw/raw-ubuntu-2004-efi.json new file mode 100644 index 0000000..7ed3ac8 --- /dev/null +++ b/packer/raw/raw-ubuntu-2004-efi.json @@ -0,0 +1,14 @@ +{ + "boot_command_prefix": "<esc><wait><esc><wait><enter><wait>linux /install/vmlinuz auto console-setup/ask_detect=false console-setup/layoutcode=us console-setup/modelcode=pc105 debconf/frontend=noninteractive debian-installer=en_US fb=false kbd-chooser/method=us keyboard-configuration/layout=USA keyboard-configuration/variant=USA locale=en_US netcfg/get_domain=local netcfg/get_hostname=localhost preseed/url=", + "boot_command_suffix": "/20.04/preseed-efi.cfg -- <wait><enter>initrd /install/initrd.gz<enter>boot<enter><wait>", + "build_name": "ubuntu-2004", + "build_target": "raw", + "distro_name": "ubuntu", + "firmware": "OVMF.fd", + "guest_os_type": "ubuntu-64", + "iso_checksum": "f11bda2f2caed8f420802b59f382c25160b114ccc665dbac9c5046e7fceaced2", + "iso_checksum_type": "sha256", + "iso_url": "http://cdimage.ubuntu.com/ubuntu-legacy-server/releases/20.04/release/ubuntu-20.04.1-legacy-server-amd64.iso", + "os_display_name": "Ubuntu 20.04", + "shutdown_command": "shutdown -P now" +} diff --git a/packer/raw/raw-ubuntu-2004.json b/packer/raw/raw-ubuntu-2004.json new file mode 100644 index 0000000..9e78e63 --- /dev/null +++ b/packer/raw/raw-ubuntu-2004.json @@ -0,0 +1,13 @@ +{ + "boot_command_prefix": "<esc><wait><esc><wait><enter><wait>/install/vmlinuz auto console-setup/ask_detect=false console-setup/layoutcode=us console-setup/modelcode=pc105 debconf/frontend=noninteractive debian-installer=en_US fb=false initrd=/install/initrd.gz kbd-chooser/method=us keyboard-configuration/layout=USA keyboard-configuration/variant=USA locale=en_US netcfg/get_domain=local netcfg/get_hostname=localhost grub-installer/bootdev=/dev/sda preseed/url=", + "boot_command_suffix": "/20.04/preseed.cfg -- <wait><enter><wait>", + "build_name": "ubuntu-2004", + "build_target": "raw", + "distro_name": "ubuntu", + "guest_os_type": "ubuntu-64", + "iso_checksum": "f11bda2f2caed8f420802b59f382c25160b114ccc665dbac9c5046e7fceaced2", + "iso_checksum_type": "sha256", + "iso_url": "http://cdimage.ubuntu.com/ubuntu-legacy-server/releases/20.04/release/ubuntu-20.04.1-legacy-server-amd64.iso", + "os_display_name": "Ubuntu 20.04", + "shutdown_command": "shutdown -P now" +} diff --git a/packer/vbox/OWNERS b/packer/vbox/OWNERS new file mode 100644 index 0000000..7890663 --- /dev/null +++ b/packer/vbox/OWNERS @@ -0,0 +1,5 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - image-builder-windows-maintainers + diff --git a/packer/vbox/packer-common.json b/packer/vbox/packer-common.json new file mode 100644 index 0000000..052d06c --- /dev/null +++ b/packer/vbox/packer-common.json @@ -0,0 +1,8 @@ +{ + "boot_wait": "10s", + "cpu": "4", + "memory": "8192", + "ssh_password": "vagrant", + "ssh_timeout": "60m", + "ssh_username": "vagrant" +} diff --git a/packer/vbox/packer-windows.json b/packer/vbox/packer-windows.json new file mode 100644 index 0000000..782c3e1 --- /dev/null +++ b/packer/vbox/packer-windows.json @@ -0,0 +1,125 @@ +{ + "builders": [ + { + "boot_wait": "{{user `boot_wait`}}", + "communicator": "winrm", + "cpus": "{{user `cpu`}}", + "disk_size": "{{user `disk_size`}}", + "floppy_files": [ + "./packer/vbox/windows/{{user `build_name`}}/autounattend.xml", + "./packer/vbox/windows/enable-winrm.ps1", + "./packer/vbox/windows/sysprep.ps1" + ], + "guest_additions_mode": "disable", + "guest_os_type": "{{user `local_guest_os_type`}}", + "iso_checksum": "{{user `iso_checksum`}}", + "iso_urls": [ + "{{user `os_iso_url`}}" + ], + "memory": "{{user `memory`}}", + "name": "virtualbox-iso", + "output_directory": "{{user `output_dir`}}", + "shutdown_command": "powershell A:/sysprep.ps1", + "shutdown_timeout": "1h", + "type": "virtualbox-iso", + "vm_name": "{{user `build_version`}}", + "winrm_password": "S3cr3t0!", + "winrm_timeout": "4h", + "winrm_username": "Administrator" + } + ], + "post-processors": [ + { + "keep_input_artifact": true, + "output": "./output/windows-2019.box", + "type": "vagrant", + "vagrantfile_template": "./packer/vbox/vagrantfile-windows_2019.template" + } + ], + "provisioners": [ + { + "extra_arguments": [ + "-e", + "ansible_winrm_scheme=http", + "--extra-vars", + "{{user `ansible_common_vars`}}", + "--extra-vars", + "{{user `ansible_extra_vars`}}", + "--extra-vars", + "{{user `ansible_user_vars`}}" + ], + "playbook_file": "ansible/windows/node_windows.yml", + "type": "ansible", + "use_proxy": false, + "user": "Administrator" + }, + { + "restart_check_command": "powershell -command \"& {if ((get-content C:\\ProgramData\\lastboot.txt) -eq (Get-WmiObject win32_operatingsystem).LastBootUpTime) {Write-Output 'Sleeping for 600 seconds to wait for reboot'; start-sleep 600} else {Write-Output 'Reboot complete'}}\"", + "restart_command": "powershell \"& {(Get-WmiObject win32_operatingsystem).LastBootUpTime > C:\\ProgramData\\lastboot.txt; Restart-Computer -force}\"", + "type": "windows-restart" + }, + { + "arch": "{{user `goss_arch`}}", + "download_path": "{{user `goss_download_path`}}", + "format": "{{user `goss_format`}}", + "format_options": "{{user `goss_format_options`}}", + "goss_file": "{{user `goss_entry_file`}}", + "inspect": "{{user `goss_inspect_mode`}}", + "remote_folder": "{{user `goss_remote_folder`}}", + "remote_path": "{{user `goss_remote_path`}}", + "skip_install": "{{user `goss_skip_install`}}", + "target_os": "Windows", + "tests": [ + "{{user `goss_tests_dir`}}" + ], + "type": "goss", + "url": "{{user `goss_url`}}", + "use_sudo": false, + "vars_env": { + "GOSS_MAX_CONCURRENT": "1", + "GOSS_USE_ALPHA": "1" + }, + "vars_file": "{{user `goss_vars_file`}}", + "vars_inline": { + "OS": "{{user `distro_name` | lower}}", + "PROVIDER": "virtualbox", + "containerd_version": "{{user `containerd_version`}}", + "distribution_version": "{{user `distro_version`}}", + "docker_ee_version": "{{user `docker_ee_version`}}", + "kubernetes_version": "{{user `kubernetes_semver`}}", + "pause_image": "{{user `pause_image`}}", + "runtime": "{{user `runtime`}}", + "ssh_source_url": "{{user `ssh_source_url`}}" + }, + "version": "{{user `goss_version`}}" + } + ], + "variables": { + "ansible_common_vars": "", + "ansible_extra_vars": "", + "ansible_user_vars": "", + "build_name": null, + "build_timestamp": "{{timestamp}}", + "build_version": "{{user `build_name`}}-kube-{{user `kubernetes_semver`}}", + "cloudbase_init_url": "https://github.com/cloudbase/cloudbase-init/releases/download/{{user `cloudbase_init_version`}}/CloudbaseInitSetup_{{user `cloudbase_init_version` | replace_all `.` `_` }}_x64.msi", + "cloudbase_plugins": "cloudbaseinit.plugins.windows.createuser.CreateUserPlugin, cloudbaseinit.plugins.common.setuserpassword.SetUserPasswordPlugin, cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin, cloudbaseinit.plugins.common.ephemeraldisk.EphemeralDiskPlugin, cloudbaseinit.plugins.common.mtu.MTUPlugin, cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin, cloudbaseinit.plugins.common.sshpublickeys.SetUserSSHPublicKeysPlugin, cloudbaseinit.plugins.common.userdata.UserDataPlugin, cloudbaseinit.plugins.common.localscripts.LocalScriptsPlugin, cloudbaseinit.plugins.windows.createuser.CreateUserPlugin, cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin", + "cloudbase_plugins_unattend": "cloudbaseinit.plugins.common.mtu.MTUPlugin", + "containerd_sha256": null, + "containerd_url": "", + "containerd_version": null, + "disable_hypervisor": null, + "disk_size": "81920", + "ib_version": "{{env `IB_VERSION`}}", + "kubernetes_base_url": "https://kubernetesreleases.blob.core.windows.net/kubernetes/{{user `kubernetes_semver`}}/binaries/node/windows/{{user `kubernetes_goarch`}}", + "kubernetes_http_package_url": "", + "kubernetes_typed_version": "kube-{{user `kubernetes_semver`}}", + "manifest_output": "manifest.json", + "netbios_host_name_compatibility": null, + "nssm_url": null, + "output_dir": "./output/{{user `build_version`}}", + "prepull": null, + "windows_service_manager": null, + "windows_updates_categories": null, + "windows_updates_kbs": null + } +} diff --git a/packer/vbox/vagrantfile-windows_2019.template b/packer/vbox/vagrantfile-windows_2019.template new file mode 100644 index 0000000..ac77601 --- /dev/null +++ b/packer/vbox/vagrantfile-windows_2019.template @@ -0,0 +1,24 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +Vagrant.require_version ">= 1.6.2" + +Vagrant.configure("2") do |config| + config.vm.define "vagrant-windows-2019" + config.vm.box = "windows_2019" + config.vm.communicator = "winrm" + + config.vm.guest = :windows + config.windows.halt_timeout = 15 + + config.vm.network :forwarded_port, guest: 3389, host: 3389, id: "rdp", auto_correct: true + + config.vm.provider :virtualbox do |v, override| + #v.gui = true + v.customize ["modifyvm", :id, "--memory", 6144] + v.customize ["modifyvm", :id, "--cpus", 2] + v.customize ["modifyvm", :id, "--vram", 128] + v.customize ["modifyvm", :id, "--clipboard", "bidirectional"] + v.customize ["setextradata", "global", "GUI/SuppressMessages", "all" ] + end +end diff --git a/packer/vbox/windows-2019.json b/packer/vbox/windows-2019.json new file mode 100644 index 0000000..2dc1f45 --- /dev/null +++ b/packer/vbox/windows-2019.json @@ -0,0 +1,10 @@ +{ + "build_name": "windows-2019", + "distro_arch": "amd64", + "distro_name": "windows", + "distro_version": "2019", + "iso_checksum": "none", + "local_guest_os_type": "windows9srv-64", + "os_display_name": "Windows Server 2019", + "os_iso_url": "file:/path/en_windows_server_2019_x64_dvd_4cb967d8.iso" +} diff --git a/packer/vbox/windows/enable-winrm.ps1 b/packer/vbox/windows/enable-winrm.ps1 new file mode 100644 index 0000000..e6f30b1 --- /dev/null +++ b/packer/vbox/windows/enable-winrm.ps1 @@ -0,0 +1,18 @@ + +$NetworkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}")) +$Connections = $NetworkListManager.GetNetworkConnections() +$Connections | ForEach-Object { $_.GetNetwork().SetCategory(1) } + +Enable-PSRemoting -Force +winrm quickconfig -q +winrm quickconfig -transport:http +winrm set winrm/config '@{MaxTimeoutms="1800000"}' +winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="800"}' +winrm set winrm/config/service '@{AllowUnencrypted="true"}' +winrm set winrm/config/service/auth '@{Basic="true"}' +winrm set winrm/config/client/auth '@{Basic="true"}' +winrm set winrm/config/listener?Address=*+Transport=HTTP '@{Port="5985"}' +netsh advfirewall firewall set rule group="Windows Remote Administration" new enable=yes +netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=allow +Set-Service winrm -startuptype "auto" +Restart-Service winrm diff --git a/packer/vbox/windows/sysprep.ps1 b/packer/vbox/windows/sysprep.ps1 new file mode 100644 index 0000000..7efb732 --- /dev/null +++ b/packer/vbox/windows/sysprep.ps1 @@ -0,0 +1,13 @@ +Write-Output '>>> Sysprepping VM ...' +if( Test-Path $Env:SystemRoot\system32\Sysprep\unattend.xml ) { + Remove-Item $Env:SystemRoot\system32\Sysprep\unattend.xml -Force +} +$unattendedXml = "$ENV:ProgramFiles\Cloudbase Solutions\Cloudbase-Init\conf\Unattend.xml" +$FileExists = Test-Path $unattendedXml +If ($FileExists -eq $True) { + # Use the Cloudbase-init provided unattend file during install + Write-Output "Using cloudbase-init unattend file for sysprep: $unattendedXml" + & $Env:SystemRoot\System32\Sysprep\Sysprep.exe /oobe /generalize /mode:vm /shutdown /quiet /unattend:$unattendedXml +}else { + & $Env:SystemRoot\System32\Sysprep\Sysprep.exe /oobe /generalize /mode:vm /shutdown /quiet +} diff --git a/packer/vbox/windows/windows-2019/autounattend.xml b/packer/vbox/windows/windows-2019/autounattend.xml new file mode 100644 index 0000000..396caa8 --- /dev/null +++ b/packer/vbox/windows/windows-2019/autounattend.xml @@ -0,0 +1,250 @@ +<!--************************************************* +Windows Server 2019 Answer File Generator +Created using Windows AFG found at: +;http://www.windowsafg.com + +Installation Notes: +- We currently assume your image is using a licesnsed media, and hard code product keys accordingly +- ProductKey: must be removed if using an eval version +- The OOBE and UserAccounts sections: might be removed for administrator details +- The Timezone in this file should match the location your using (otherwise you hit race conditions related to time.windows.com) +- We hard code an administrative passcode in here, which administrators may need to modify +- There are many other parameters in here which may need to be changed. Over time we will parameterize these as part of the image-builder process +**************************************************--> + +<?xml version="1.0" encoding="utf-8"?> +<unattend xmlns="urn:schemas-microsoft-com:unattend"> + <settings pass="windowsPE"> + <component name="Microsoft-Windows-PnpCustomizationsWinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <DriverPaths> + <PathAndCredentials wcm:action="add" wcm:keyValue="A"> + <Path>a:\</Path> + </PathAndCredentials> + </DriverPaths> + </component> + <component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <DiskConfiguration> + <Disk wcm:action="add"> + <CreatePartitions> + <CreatePartition wcm:action="add"> + <Order>1</Order> + <Size>350</Size> + <Type>Primary</Type> + </CreatePartition> + <CreatePartition wcm:action="add"> + <Order>2</Order> + <Extend>true</Extend> + <Type>Primary</Type> + </CreatePartition> + </CreatePartitions> + <ModifyPartitions> + <ModifyPartition wcm:action="add"> + <Format>NTFS</Format> + <Label>System</Label> + <Order>1</Order> + <PartitionID>1</PartitionID> + <TypeID>0x27</TypeID> + </ModifyPartition> + <ModifyPartition wcm:action="add"> + <Order>2</Order> + <PartitionID>2</PartitionID> + <Letter>C</Letter> + <Label>OS</Label> + <Format>NTFS</Format> + </ModifyPartition> + </ModifyPartitions> + <DiskID>0</DiskID> + <WillWipeDisk>true</WillWipeDisk> + </Disk> + </DiskConfiguration> + <ImageInstall> + <OSImage> + <InstallTo> + <DiskID>0</DiskID> + <PartitionID>2</PartitionID> + </InstallTo> + <InstallFrom> + <MetaData wcm:action="add"> + <Key>/IMAGE/NAME</Key> + <Value>Windows Server 2019 SERVERSTANDARDCORE</Value> + </MetaData> + </InstallFrom> + </OSImage> + </ImageInstall> + <UserData> + <AcceptEula>true</AcceptEula> + <FullName>Administrator</FullName> + <Organization>Organization</Organization> + <!-- <ProductKey> --> + <!-- <Key>N69G4-B89J2-4G8F4-WWYCC-J464C</Key> --> + <!-- <WillShowUI>OnError</WillShowUI> --> + <!-- </ProductKey> --> + </UserData> + <EnableFirewall>true</EnableFirewall> + </component> + <component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <SetupUILanguage> + <UILanguage>en-US</UILanguage> + </SetupUILanguage> + <InputLocale>0409:00000409</InputLocale> + <SystemLocale>en-US</SystemLocale> + <UILanguage>en-US</UILanguage> + <UILanguageFallback>en-US</UILanguageFallback> + <UserLocale>en-US</UserLocale> + </component> + </settings> + <settings pass="offlineServicing"> + <component name="Microsoft-Windows-LUA-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <EnableLUA>false</EnableLUA> + </component> + </settings> + <settings pass="generalize"> + <component name="Microsoft-Windows-Security-SPP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <SkipRearm>1</SkipRearm> + </component> + </settings> + <settings pass="specialize"> + <component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <InputLocale>0409:00000409</InputLocale> + <SystemLocale>en-US</SystemLocale> + <UILanguage>en-US</UILanguage> + <UILanguageFallback>en-US</UILanguageFallback> + <UserLocale>en-US</UserLocale> + </component> + <component name="Microsoft-Windows-Security-SPP-UX" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <SkipAutoActivation>true</SkipAutoActivation> + </component> + <component name="Microsoft-Windows-SQMApi" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <CEIPEnabled>0</CEIPEnabled> + </component> + <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <ComputerName></ComputerName> + <ProductKey>N69G4-B89J2-4G8F4-WWYCC-J464C</ProductKey> + </component> + </settings> + <settings pass="oobeSystem"> + <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" + xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <AutoLogon> + <Password> + <Value>S3cr3t0!</Value> + <PlainText>true</PlainText> + </Password> + <Enabled>true</Enabled> + <Username>Administrator</Username> + </AutoLogon> + <FirstLogonCommands> + <SynchronousCommand wcm:action="add"> + <Order>1</Order> + <Description>Set Execution Policy 64 Bit</Description> + <CommandLine>cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <Order>2</Order> + <Description>Set Execution Policy 32 Bit</Description> + <CommandLine>%SystemDrive%\Windows\SysWOW64\cmd.exe /c powershell -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force"</CommandLine> + <RequiresUserInput>true</RequiresUserInput> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine> + <Order>3</Order> + <Description>Show file extensions in Explorer</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine> + <Order>4</Order> + <Description>Enable QuickEdit mode</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine> + <Order>5</Order> + <Description>Show Run command in Start Menu</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine> + <Order>6</Order> + <Description>Show Administrative Tools in Start Menu</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine> + <Order>7</Order> + <Description>Zero Hibernation File</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>%SystemRoot%\System32\reg.exe ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine> + <Order>8</Order> + <Description>Disable Hibernation Mode</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE</CommandLine> + <Order>9</Order> + <Description>Disable password expiration for Administrator user</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c a:\install-vm-tools.cmd</CommandLine> + <Order>10</Order> + <Description>Install VMware Tools</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c %SystemDrive%\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File a:\enable-winrm.ps1</CommandLine> + <Description>Enable WinRM</Description> + <Order>11</Order> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <CommandLine>cmd.exe /c a:\disable-network-discovery.cmd</CommandLine> + <Description>Disable Network Discovery</Description> + <Order>12</Order> + </SynchronousCommand> + </FirstLogonCommands> + <OOBE> + <HideEULAPage>true</HideEULAPage> + <HideLocalAccountScreen>true</HideLocalAccountScreen> + <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen> + <HideOnlineAccountScreens>true</HideOnlineAccountScreens> + <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> + <NetworkLocation>Work</NetworkLocation> + <ProtectYourPC>1</ProtectYourPC> + <SkipMachineOOBE>true</SkipMachineOOBE> + <SkipUserOOBE>true</SkipUserOOBE> + </OOBE> + <RegisteredOrganization>Organization</RegisteredOrganization> + <RegisteredOwner>Owner</RegisteredOwner> + <DisableAutoDaylightTimeSet>false</DisableAutoDaylightTimeSet> + <TimeZone>Pacific Standard Time</TimeZone> + <UserAccounts> + <AdministratorPassword> + <Value>S3cr3t0!</Value> + <PlainText>true</PlainText> + </AdministratorPassword> + <LocalAccounts> + <LocalAccount wcm:action="add"> + <Description>Administrator</Description> + <DisplayName>Administrator</DisplayName> + <Group>Administrators</Group> + <Name>Administrator</Name> + </LocalAccount> + </LocalAccounts> + </UserAccounts> + </component> + </settings> +</unattend> diff --git a/scripts/ci-azure-e2e.sh b/scripts/ci-azure-e2e.sh new file mode 100755 index 0000000..2fbacd7 --- /dev/null +++ b/scripts/ci-azure-e2e.sh @@ -0,0 +1,122 @@ +#!/bin/bash + +# Copyright 2020 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +############################################################################### + +# This script is executed by presubmit `pull-cluster-api-provider-azure-e2e` +# To run locally, set AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +CAPI_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +cd "${CAPI_ROOT}" || exit 1 + +export ARTIFACTS="${ARTIFACTS:-${PWD}/_artifacts}" +mkdir -p "${ARTIFACTS}/azure-sigs" "${ARTIFACTS}/azure-vhds" + +# Get list of Azure target names from common file +source azure_targets.sh + +# Convert single line entries into arrays +IFS=' ' read -r -a VHD_CI_TARGETS <<< "${VHD_CI_TARGETS}" +IFS=' ' read -r -a SIG_CI_TARGETS <<< "${SIG_CI_TARGETS}" +IFS=' ' read -r -a SIG_GEN2_CI_TARGETS <<< "${SIG_GEN2_CI_TARGETS}" + +# Append the "gen2" targets to the original SIG list +for element in "${SIG_GEN2_CI_TARGETS[@]}" +do + SIG_CI_TARGETS+=("${element}-gen2") +done + +# shellcheck source=parse-prow-creds.sh +source "packer/azure/scripts/parse-prow-creds.sh" + +# Verify the required Environment Variables are present. +: "${AZURE_SUBSCRIPTION_ID:?Environment variable empty or not defined.}" +: "${AZURE_TENANT_ID:?Environment variable empty or not defined.}" +: "${AZURE_CLIENT_ID:?Environment variable empty or not defined.}" +: "${AZURE_CLIENT_SECRET:?Environment variable empty or not defined.}" + +get_random_region() { + local REGIONS=("eastus" "eastus2" "southcentralus" "westus2" "westeurope") + echo "${REGIONS[${RANDOM} % ${#REGIONS[@]}]}" +} + +export PATH=${PWD}/.local/bin:$PATH +export PATH=${PYTHON_BIN_DIR:-"/root/.local/bin"}:$PATH + +export AZURE_LOCATION="${AZURE_LOCATION:-$(get_random_region)}" +export RESOURCE_GROUP_NAME="image-builder-e2e-$(head /dev/urandom | LC_ALL=C tr -dc a-z0-9 | head -c 6 ; echo '')" + +# timestamp is in RFC-3339 format to match kubetest +export TIMESTAMP="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" +export JOB_NAME="${JOB_NAME:-"image-builder-e2e"}" +export TAGS="creationTimestamp=${TIMESTAMP} jobName=${JOB_NAME}" + +cleanup() { + az group delete -n ${RESOURCE_GROUP_NAME} --yes --no-wait || true +} + +trap cleanup EXIT + +make deps-azure + +# Latest Flatcar version is often available on Azure with a delay, so resolve ourselves +az login --service-principal -u ${AZURE_CLIENT_ID} -p ${AZURE_CLIENT_SECRET} --tenant ${AZURE_TENANT_ID} +get_flatcar_version() { + az vm image show --urn kinvolk:flatcar-container-linux-free:stable:latest --query 'name' -o tsv +} +export FLATCAR_VERSION="$(get_flatcar_version)" + +# Pre-pulling windows images takes 10-20 mins +# Disable them for CI runs so don't run into timeouts +export PACKER_VAR_FILES="packer/azure/scripts/disable-windows-prepull.json scripts/ci-disable-goss-inspect.json" + +declare -A PIDS +if [[ "${AZURE_BUILD_FORMAT:-vhd}" == "sig" ]]; then + for target in ${SIG_CI_TARGETS[@]}; + do + make build-azure-sig-${target} > ${ARTIFACTS}/azure-sigs/${target}.log 2>&1 & + PIDS["sig-${target}"]=$! + done +else + for target in ${VHD_CI_TARGETS[@]}; + do + make build-azure-vhd-${target} > ${ARTIFACTS}/azure-vhds/${target}.log 2>&1 & + PIDS["vhd-${target}"]=$! + done +fi + +# need to unset errexit so that failed child tasks don't cause script to exit +set +o errexit +exit_err=false +for target in "${!PIDS[@]}"; do + wait ${PIDS[$target]} + if [[ $? -ne 0 ]]; then + exit_err=true + echo "${target}: FAILED. See logs in the artifacts folder." + else + echo "${target}: SUCCESS" + fi +done + +if [[ "${exit_err}" = true ]]; then + exit 1 +fi diff --git a/scripts/ci-container-image.sh b/scripts/ci-container-image.sh new file mode 100755 index 0000000..ff52227 --- /dev/null +++ b/scripts/ci-container-image.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +############################################################################### + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +CAPI_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +cd "${CAPI_ROOT}" || exit 1 + +make docker-build diff --git a/scripts/ci-disable-goss-inspect.json b/scripts/ci-disable-goss-inspect.json new file mode 100644 index 0000000..379f064 --- /dev/null +++ b/scripts/ci-disable-goss-inspect.json @@ -0,0 +1,3 @@ +{ + "goss_inspect_mode": "false" +} diff --git a/scripts/ci-gce-nightly.sh b/scripts/ci-gce-nightly.sh new file mode 100755 index 0000000..6d2ca43 --- /dev/null +++ b/scripts/ci-gce-nightly.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################################################################ +# usage: ci-gce-nightly.sh +# This program build all images for capi gce for the nightly build +################################################################################ + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +CAPI_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +cd "${CAPI_ROOT}" || exit 1 + +# Verify the required Environment Variables are present. +: "${GCP_PROJECT:?Environment variable empty or not defined.}" + +# to list and check if have the properly access to the service account +gcloud auth list + +# assume we are running in the CI environment as root +# Add a user for ansible to work properly +groupadd -r packer && useradd -m -s /bin/bash -r -g packer packer +chown -R packer:packer /home/prow/go/src/sigs.k8s.io/image-builder +# use the packer user to run the build + +# build image for 1.23 +# using PACKER_FLAGS=-force to overwrite the previous image and keep the same name +su - packer -c "bash -c 'cd /home/prow/go/src/sigs.k8s.io/image-builder/images/capi && PATH=$PATH:~packer/.local/bin:/home/prow/go/src/sigs.k8s.io/image-builder/images/capi/.local/bin GCP_PROJECT_ID=$GCP_PROJECT PACKER_VAR_FILES=packer/gce/ci/nightly/overwrite-1-23.json PACKER_FLAGS=-force make deps-gce build-gce-all'" + +# build image for 1.24 +# using PACKER_FLAGS=-force to overwrite the previous image and keep the same name +su - packer -c "bash -c 'cd /home/prow/go/src/sigs.k8s.io/image-builder/images/capi && PATH=$PATH:~packer/.local/bin:/home/prow/go/src/sigs.k8s.io/image-builder/images/capi/.local/bin GCP_PROJECT_ID=$GCP_PROJECT PACKER_VAR_FILES=packer/gce/ci/nightly/overwrite-1-24.json PACKER_FLAGS=-force make deps-gce build-gce-all'" + +# build image for 1.25 +# using PACKER_FLAGS=-force to overwrite the previous image and keep the same name +su - packer -c "bash -c 'cd /home/prow/go/src/sigs.k8s.io/image-builder/images/capi && PATH=$PATH:~packer/.local/bin:/home/prow/go/src/sigs.k8s.io/image-builder/images/capi/.local/bin GCP_PROJECT_ID=$GCP_PROJECT PACKER_VAR_FILES=packer/gce/ci/nightly/overwrite-1-25.json PACKER_FLAGS=-force make deps-gce build-gce-all'" + +# build image for 1.26 +# using PACKER_FLAGS=-force to overwrite the previous image and keep the same name +su - packer -c "bash -c 'cd /home/prow/go/src/sigs.k8s.io/image-builder/images/capi && PATH=$PATH:~packer/.local/bin:/home/prow/go/src/sigs.k8s.io/image-builder/images/capi/.local/bin GCP_PROJECT_ID=$GCP_PROJECT PACKER_VAR_FILES=packer/gce/ci/nightly/overwrite-1-26.json PACKER_FLAGS=-force make deps-gce build-gce-all'" + +echo "Displaying the generated image information" +filter="name~cluster-api-ubuntu-*" +gcloud compute images list --project "$GCP_PROJECT" \ + --no-standard-images --filter="${filter}" + +echo "Making images public to use in CI" +(gcloud compute images list --project "$GCP_PROJECT" --no-standard-images --filter="${filter}" --format="value(name[])" | \ +awk '{print "gcloud compute images add-iam-policy-binding --project '"$GCP_PROJECT"' " $1 " --member='"'allAuthenticatedUsers'"' --role='"'roles/compute.imageUser'"' \n"}' | bash) diff --git a/scripts/ci-gce.sh b/scripts/ci-gce.sh new file mode 100755 index 0000000..a4510af --- /dev/null +++ b/scripts/ci-gce.sh @@ -0,0 +1,94 @@ +#!/bin/bash + +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################################################################ +# usage: ci-gce.sh +# This program build all images for capi gce +################################################################################ + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +CAPI_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +cd "${CAPI_ROOT}" || exit 1 + +# shellcheck source=ensure-go.sh +source "./hack/ensure-go.sh" +# shellcheck source=ensure-boskosctl.sh +source "./hack/ensure-boskosctl.sh" + +# Verify the required Environment Variables are present. +: "${GOOGLE_APPLICATION_CREDENTIALS:?Environment variable empty or not defined.}" + +function boskosctlwrapper() { + boskosctl --server-url http://"${BOSKOS_HOST}" --owner-name "cluster-api-provider-gcp" "${@}" +} + +cleanup() { + echo "Cleaning up image" + filter="name~cluster-api-ubuntu-*" + (gcloud compute images list --project "$GCP_PROJECT" \ + --no-standard-images --format="table[no-heading](name)" --filter="${filter}" \ + | awk '{print "gcloud compute images delete --quiet --project '"$GCP_PROJECT"' "$1" " "\n"}' \ + | bash ) || true + + # stop boskos heartbeat + if [ -n "${BOSKOS_HOST:-}" ]; then + boskosctlwrapper release --name "${RESOURCE_NAME}" --target-state used + fi + + exit "${test_status}" +} +trap cleanup EXIT + +if [[ -z "$GOOGLE_APPLICATION_CREDENTIALS" ]]; then + cat <<EOF +GOOGLE_APPLICATION_CREDENTIALS is not set. +Please set this to the path of the service account used to run this script. +EOF + return 2 +else + gcloud auth activate-service-account --key-file="${GOOGLE_APPLICATION_CREDENTIALS}" +fi + +# If BOSKOS_HOST is set then acquire an GCP account from Boskos. +if [ -n "${BOSKOS_HOST:-}" ]; then + echo "Boskos acquire - ${BOSKOS_HOST}" + export BOSKOS_RESOURCE="$( boskosctlwrapper acquire --type gce-project --state free --target-state busy --timeout 1h )" + export RESOURCE_NAME=$(echo $BOSKOS_RESOURCE | jq -r ".name") + export GCP_PROJECT=$(echo $BOSKOS_RESOURCE | jq -r ".name") + + # send a heartbeat in the background to keep the lease while using the resource + echo "Starting Boskos HeartBeat" + boskosctlwrapper heartbeat --resource "${BOSKOS_RESOURCE}" & +fi + +# assume we are running in the CI environment as root +# Add a user for ansible to work properly +groupadd -r packer && useradd -m -s /bin/bash -r -g packer packer +chown -R packer:packer /home/prow/go/src/sigs.k8s.io/image-builder +# use the packer user to run the build +su - packer -c "bash -c 'cd /home/prow/go/src/sigs.k8s.io/image-builder/images/capi && PATH=$PATH:~packer/.local/bin:/home/prow/go/src/sigs.k8s.io/image-builder/images/capi/.local/bin GCP_PROJECT_ID=$GCP_PROJECT GOOGLE_APPLICATION_CREDENTIALS=$GOOGLE_APPLICATION_CREDENTIALS PACKER_VAR_FILES=scripts/ci-disable-goss-inspect.json make deps-gce build-gce-all'" +test_status="${?}" + +echo "Displaying the generated image information" +filter="name~cluster-api-ubuntu-*" +gcloud compute images list --project "$GCP_PROJECT" --no-standard-images --filter="${filter}" + +exit "${test_status}" diff --git a/scripts/ci-goss-populate.sh b/scripts/ci-goss-populate.sh new file mode 100755 index 0000000..9d84bb1 --- /dev/null +++ b/scripts/ci-goss-populate.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +############################################################################### + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +CAPI_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +cd "${CAPI_ROOT}" || exit 1 + +source hack/utils.sh +ensure_py3 + +_version="v0.3.16" +_bin_url="https://github.com/aelsabbahy/goss/releases/download/${_version}/goss-linux-amd64" + +if ! command -v goss >/dev/null 2>&1; then + if [[ ${HOSTOS} == "linux" ]]; then + curl -SsL "${_bin_url}" -o goss + chmod +x goss + mkdir -p "${PWD}/.local/bin" + mv goss "${PWD}/.local/bin" + export PATH=${PWD}/.local/bin:$PATH + fi +fi + +export GOSS_USE_ALPHA=1 +hack/generate-goss-specs.py diff --git a/scripts/ci-json-sort.sh b/scripts/ci-json-sort.sh new file mode 100755 index 0000000..563ce5d --- /dev/null +++ b/scripts/ci-json-sort.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +############################################################################### + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +CAPI_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +cd "${CAPI_ROOT}" || exit 1 + +cleanup() { + returnCode="$?" + exit "${returnCode}" +} + +trap cleanup EXIT + +json_files=$(find . -type f -name "*.json" | sort -u) +for f in ${json_files} +do + if ! diff <(jq -S . ${f}) ${f} >> /dev/null; then + echo "json files are not sorted!! Please sort them with \"make json-sort\" in \"images/capi\" before commit" + echo "Unsorted file: ${f}" + exit 1 + fi +done diff --git a/scripts/ci-outscale-nightly.sh b/scripts/ci-outscale-nightly.sh new file mode 100755 index 0000000..7a011b2 --- /dev/null +++ b/scripts/ci-outscale-nightly.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +PACKER_VAR_FILES=packer/outscale/ci/nightly/overwrite-1-21.json make build-osc-all +PACKER_VAR_FILES=packer/outscale/ci/nightly/overwrite-1-22.json make build-osc-all +PACKER_VAR_FILES=packer/outscale/ci/nightly/overwrite-1-23.json make build-osc-all +PACKER_VAR_FILES=packer/outscale/ci/nightly/overwrite-1-24.json make build-osc-all +PACKER_VAR_FILES=packer/outscale/ci/nightly/overwrite-1-25.json make build-osc-all diff --git a/scripts/ci-ova.sh b/scripts/ci-ova.sh new file mode 100755 index 0000000..172dbec --- /dev/null +++ b/scripts/ci-ova.sh @@ -0,0 +1,157 @@ +#!/bin/bash + +# Copyright 2020 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit # exits immediately on any unexpected error (does not bypass traps) +set -o nounset # will error if variables are used without first being defined +set -o pipefail # any non-zero exit code in a piped command causes the pipeline to fail with that code + +CAPI_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +cd "${CAPI_ROOT}" || exit 1 + +export ARTIFACTS="${ARTIFACTS:-${PWD}/_artifacts}" +TARGETS=("ubuntu-1804" "ubuntu-2004" "ubuntu-2204" "photon-3" "photon-4" "centos-7" "rockylinux-8" "flatcar") + +on_exit() { + # kill the VPN + docker kill vpn +} + +cleanup_build_vm() { + # Setup govc to delete build VM after + curl -L https://github.com/vmware/govmomi/releases/download/v0.23.0/govc_linux_amd64.gz | gunzip > govc + chmod +x govc + mv govc /usr/local/bin/govc + + for target in ${TARGETS[@]}; + do + govc vm.destroy capv-ci-${target}-${TIMESTAMP} + done + +} + +trap on_exit EXIT + +export PATH=${PWD}/.local/bin:$PATH +export PATH=${PYTHON_BIN_DIR:-"/root/.local/bin"}:$PATH +export GC_KIND="false" +export TIMESTAMP="$(date -u '+%Y%m%dT%H%M%S')" +export GOVC_DATACENTER="SDDC-Datacenter" +export GOVC_INSECURE=true + +cat << EOF > packer/ova/vsphere.json +{ + "vcenter_server":"${GOVC_URL}", + "insecure_connection": "${GOVC_INSECURE}", + "username":"${GOVC_USERNAME}", + "password":"${GOVC_PASSWORD}", + "datastore":"WorkloadDatastore", + "datacenter":"${GOVC_DATACENTER}", + "cluster": "Cluster-1", + "network": "sddc-cgw-network-8", + "folder": "Workloads/ci/imagebuilder" +} +EOF + +# Since access to esxi is blocked due to firewall rules, +# `export`, `post-processor` sections from `packer-node.json` are removed. +cat packer/ova/packer-node.json | jq 'del(.builders[] | select( .name == "vsphere" ).export)' > packer/ova/packer-node.json.tmp && mv packer/ova/packer-node.json.tmp packer/ova/packer-node.json +cat packer/ova/packer-node.json | jq 'del(.builders[] | select( .name == "vsphere-clone" ).export)' > packer/ova/packer-node.json.tmp && mv packer/ova/packer-node.json.tmp packer/ova/packer-node.json +cat packer/ova/packer-node.json | jq 'del(."post-processors"[])' > packer/ova/packer-node.json.tmp && mv packer/ova/packer-node.json.tmp packer/ova/packer-node.json + +# Run the vpn client in container +docker run --rm -d --name vpn -v "${HOME}/.openvpn/:${HOME}/.openvpn/" \ + -w "${HOME}/.openvpn/" --cap-add=NET_ADMIN --net=host --device=/dev/net/tun \ + gcr.io/cluster-api-provider-vsphere/extra/openvpn:latest + +# Tail the vpn logs +docker logs vpn + +# install deps and build all images +make deps-ova + +declare -A PIDS +for target in ${TARGETS[@]}; +do + export PACKER_VAR_FILES="ci-${target}.json scripts/ci-disable-goss-inspect.json" + if [[ "${target}" == 'photon-3' ]]; then +cat << EOF > ci-${target}.json +{ +"build_version": "capv-ci-${target}-${TIMESTAMP}", +"linked_clone": "true", +"template": "base-photon-3-20220623" +} +EOF + make build-node-ova-vsphere-clone-${target} > ${ARTIFACTS}/${target}.log 2>&1 & + + elif [[ "${target}" == 'photon-4' ]]; then +cat << EOF > ci-${target}.json +{ +"build_version": "capv-ci-${target}-${TIMESTAMP}", +"linked_clone": "true", +"template": "base-photon-4" +} +EOF + make build-node-ova-vsphere-clone-${target} > ${ARTIFACTS}/${target}.log 2>&1 & + + elif [[ "${target}" == 'rockylinux-8' ]]; then + cat << EOF > ci-${target}.json +{ +"build_version": "capv-ci-${target}-${TIMESTAMP}", +"linked_clone": "true", +"template": "base-rockylinux-8-20220623" +} +EOF + make build-node-ova-vsphere-clone-${target} > ${ARTIFACTS}/${target}.log 2>&1 & + + elif [[ "${target}" == 'ubuntu-2204' ]]; then + cat << EOF > ci-${target}.json +{ +"build_version": "capv-ci-${target}-${TIMESTAMP}", +"linked_clone": "true", +"template": "base-ubuntu-2204" +} +EOF + make build-node-ova-vsphere-clone-${target} > ${ARTIFACTS}/${target}.log 2>&1 & + + else +cat << EOF > ci-${target}.json +{ +"build_version": "capv-ci-${target}-${TIMESTAMP}" +} +EOF + make build-node-ova-vsphere-${target} > ${ARTIFACTS}/${target}.log 2>&1 & + fi + PIDS["${target}"]=$! +done + +# need to unset errexit so that failed child tasks don't cause script to exit +set +o errexit +exit_err=false +for target in "${!PIDS[@]}"; do + wait "${PIDS[$target]}" + if [[ $? -ne 0 ]]; then + exit_err=true + echo "${target}: FAILED. See logs in the artifacts folder." + else + echo "${target}: SUCCESS" + fi +done +set -o errexit + +cleanup_build_vm +if [[ "${exit_err}" = true ]]; then + exit 1 +fi diff --git a/scripts/ci-packer-validate.sh b/scripts/ci-packer-validate.sh new file mode 100755 index 0000000..e70f040 --- /dev/null +++ b/scripts/ci-packer-validate.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Copyright 2021 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +############################################################################### + +set -o errexit +set -o nounset +set -o pipefail + +[[ -n ${DEBUG:-} ]] && set -o xtrace + +CAPI_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +cd "${CAPI_ROOT}" || exit 1 + +export PATH=${PWD}/.local/bin:$PATH +export PATH=${PYTHON_BIN_DIR:-"${HOME}/.local/bin"}:$PATH + +# OCI packer builder requires a valid private key file, hence creating a temporary one +openssl genrsa -out /tmp/oci_api_key.pem 2048 + +AZURE_LOCATION=fake RESOURCE_GROUP_NAME=fake STORAGE_ACCOUNT_NAME=fake \ + DIGITALOCEAN_ACCESS_TOKEN=fake GCP_PROJECT_ID=fake \ + OCI_AVAILABILITY_DOMAIN=fake OCI_SUBNET_OCID=fake OCI_USER_FINGERPRINT=fake \ + OCI_TENANCY_OCID=fake OCI_USER_OCID=fake OCI_USER_KEY_FILE=/tmp/oci_api_key.pem \ + make validate-all