From 3040e886dcd9ab53754d0bfed9165ff54634b740 Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Tue, 31 Aug 2021 11:14:03 -0700 Subject: [PATCH] Refactor build --- .dockerignore | 4 + .drone.yml | 81 +++ .gitignore | 7 + .golangci.json | 27 + Dockerfile | 95 ++-- Dockerfile.dapper | 22 + Makefile | 81 ++- cmd/ros-installer/main.go | 19 + files/etc/cos/bootargs.cfg | 8 - files/etc/dracut.conf.d/50-cos-initrd.conf | 5 - files/etc/issue.d/10-SUSE | 9 - files/etc/os-release | 1 - files/etc/selinux/config.enforcing | 14 - .../systemd/system/cos-setup-rootfs.service | 14 - files/lib/systemd/system/rancherd.service | 22 - files/system/oem/03_branding.yaml | 5 - files/system/oem/04_accounting.yaml | 41 -- files/system/oem/07_cloud-metadata.yaml | 14 - files/system/oem/08_rancherd.yaml | 11 - files/usr/bin/self-upgrade | 5 - files/usr/lib/os-release.tmpl | 12 - .../rancherd/config.yaml.d/50-defaults.yaml | 21 - {files => framework/files}/etc/luet/luet.yaml | 9 +- .../multi-user.target.wants/rancherd.service | 1 + .../multi-user.target.wants/sshd.service | 0 .../system/rancherd.service.d/override.conf | 3 + .../files}/system/oem/00_ros-rootfs.yaml | 28 +- .../files/system/oem/03_branding.yaml | 0 framework/files/system/oem/04_accounting.yaml | 16 + .../system/oem/05_elemental-installer.yaml | 23 + framework/files/usr/libexec/.placeholder | 0 framework/files/usr/sbin/self-upgrade | 5 + framework/files/usr/sbin/suc-upgrade | 18 + go.mod | 26 + go.sum | 523 ++++++++++++++++++ .../files}/etc/bash.bashrc.local | 0 pkg/config/coerce.go | 86 +++ pkg/config/config.go | 47 ++ pkg/config/read.go | 104 ++++ pkg/config/rename.go | 49 ++ pkg/config/write.go | 32 ++ pkg/install/ask.go | 190 +++++++ pkg/install/install.go | 104 ++++ pkg/questions/questions.go | 142 +++++ pkg/util/crypt.go | 13 + pkg/util/prompt.go | 90 +++ ros-image-build | 185 +++++++ scripts/ci | 8 + scripts/entry | 11 + scripts/package | 34 ++ scripts/run | 30 + scripts/test | 7 + scripts/validate | 21 + scripts/version | 27 + tools/iso/iso.yaml | 24 - tools/usr/bin/makeiso | 16 - 56 files changed, 2098 insertions(+), 292 deletions(-) create mode 100644 .dockerignore create mode 100644 .drone.yml create mode 100644 .gitignore create mode 100644 .golangci.json create mode 100644 Dockerfile.dapper create mode 100644 cmd/ros-installer/main.go delete mode 100644 files/etc/cos/bootargs.cfg delete mode 100644 files/etc/dracut.conf.d/50-cos-initrd.conf delete mode 100644 files/etc/issue.d/10-SUSE delete mode 120000 files/etc/os-release delete mode 100644 files/etc/selinux/config.enforcing delete mode 100644 files/lib/systemd/system/cos-setup-rootfs.service delete mode 100644 files/lib/systemd/system/rancherd.service delete mode 100644 files/system/oem/03_branding.yaml delete mode 100644 files/system/oem/04_accounting.yaml delete mode 100644 files/system/oem/07_cloud-metadata.yaml delete mode 100644 files/system/oem/08_rancherd.yaml delete mode 100755 files/usr/bin/self-upgrade delete mode 100644 files/usr/lib/os-release.tmpl delete mode 100644 files/usr/share/rancher/rancherd/config.yaml.d/50-defaults.yaml rename {files => framework/files}/etc/luet/luet.yaml (52%) create mode 120000 framework/files/etc/systemd/system/multi-user.target.wants/rancherd.service rename {files => framework/files}/etc/systemd/system/multi-user.target.wants/sshd.service (100%) create mode 100644 framework/files/etc/systemd/system/rancherd.service.d/override.conf rename {files => framework/files}/system/oem/00_ros-rootfs.yaml (65%) rename files/usr/libexec/.placeholder => framework/files/system/oem/03_branding.yaml (100%) create mode 100644 framework/files/system/oem/04_accounting.yaml create mode 100644 framework/files/system/oem/05_elemental-installer.yaml create mode 100644 framework/files/usr/libexec/.placeholder create mode 100755 framework/files/usr/sbin/self-upgrade create mode 100755 framework/files/usr/sbin/suc-upgrade create mode 100644 go.mod create mode 100644 go.sum rename {files => opensuse/files}/etc/bash.bashrc.local (100%) create mode 100644 pkg/config/coerce.go create mode 100644 pkg/config/config.go create mode 100644 pkg/config/read.go create mode 100644 pkg/config/rename.go create mode 100644 pkg/config/write.go create mode 100644 pkg/install/ask.go create mode 100644 pkg/install/install.go create mode 100644 pkg/questions/questions.go create mode 100644 pkg/util/crypt.go create mode 100644 pkg/util/prompt.go create mode 100755 ros-image-build create mode 100755 scripts/ci create mode 100755 scripts/entry create mode 100755 scripts/package create mode 100755 scripts/run create mode 100755 scripts/test create mode 100755 scripts/validate create mode 100755 scripts/version delete mode 100644 tools/iso/iso.yaml delete mode 100755 tools/usr/bin/makeiso diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..ba8222c6 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +./.dapper +./.cache +./dist +./build diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 00000000..56e0a79e --- /dev/null +++ b/.drone.yml @@ -0,0 +1,81 @@ +--- +kind: pipeline +name: amd64 + +platform: + os: linux + arch: amd64 + +steps: +- name: build + image: rancher/dapper:v0.4.1 + commands: + - dapper ci + environment: + DOCKER_PASSWORD: + from_secret: docker_password + DOCKER_USERNAME: + from_secret: docker_username + ARCH: "amd64" + volumes: + - name: docker + path: /var/run/docker.sock + +- name: github_binary_release + image: plugins/github-release + settings: + api_key: + from_secret: github_token + prerelease: true + checksum: + - sha256 + checksum_file: CHECKSUMsum-amd64.txt + checksum_flatten: true + files: + - "dist/artifacts/*" + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +volumes: +- name: docker + host: + path: /var/run/docker.sock + +--- +kind: pipeline +name: manifest + +platform: + os: linux + arch: amd64 + +steps: +- name: manifest + image: plugins/manifest:1.0.2 + settings: + username: + from_secret: docker_username + password: + from_secret: docker_password + platforms: + - linux/amd64 + - linux/arm64 + target: "rancher/os:${DRONE_TAG}" + template: "rancher/os:${DRONE_TAG}-ARCH" + when: + instance: + - drone-publish.rancher.io + ref: + - refs/head/master + - refs/tags/* + event: + - tag + +depends_on: +- amd64 diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..2a490a4e --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/.dapper +/.cache +/bin +/dist +/build +*.swp +.idea diff --git a/.golangci.json b/.golangci.json new file mode 100644 index 00000000..7d91b013 --- /dev/null +++ b/.golangci.json @@ -0,0 +1,27 @@ +{ + "linters": { + "disable-all": true, + "enable": [ + "govet", + "revive", + "goimports", + "misspell", + "ineffassign", + "gofmt" + ] + }, + "run": { + "skip-files": [ + "/zz_generated_" + ], + "deadline": "5m" + }, + "issues": { + "exclude-rules": [ + { + "linters": "revive", + "text": "should have comment or be unexported" + } + ] + } +} diff --git a/Dockerfile b/Dockerfile index 48433412..02f57c71 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,26 +1,42 @@ -ARG LUET_VERSION=0.16.7 -FROM quay.io/luet/base:$LUET_VERSION AS luet +FROM opensuse/leap:15.3 AS build +RUN zypper in -y squashfs xorriso go1.16 upx busybox-static +COPY go.mod go.sum /usr/src/ +COPY cmd /usr/src/cmd +COPY pkg /usr/src/pkg +RUN cd /usr/src && \ + CGO_ENABLED=0 go build -ldflags "-extldflags -static -s" -o /usr/sbin/ros-installer ./cmd/ros-installer && \ + upx /usr/sbin/ros-installer -FROM registry.suse.com/suse/sle15:15.3 AS base +FROM scratch AS framework +COPY --from=build /usr/bin/busybox-static /usr/bin/busybox +COPY --from=quay.io/luet/base:0.17.8 /usr/bin/luet /usr/bin/luet +COPY framework/files/etc/luet/luet.yaml /etc/luet/luet.yaml +COPY --from=build /etc/ssl/certs /etc/ssl/certs -# Copy luet from the official images -COPY --from=luet /usr/bin/luet /usr/bin/luet - -ARG ARCH=amd64 -ENV ARCH=${ARCH} -RUN zypper rm -y container-suseconnect -RUN zypper ar --priority=200 http://download.opensuse.org/distribution/leap/15.3/repo/oss repo-oss -RUN zypper --no-gpg-checks ref -COPY files/etc/luet/luet.yaml /etc/luet/luet.yaml - -FROM base as tools +ARG CACHEBUST ENV LUET_NOLOCK=true -RUN zypper in -y squashfs xorriso -COPY tools / -RUN luet install -y toolchain/luet-makeiso +RUN ["luet", \ + "install", "--no-spinner", "-d", "-y", \ + "selinux/k3s", \ + "selinux/rancher", \ + "system/base-dracut-modules", \ + "system/cloud-config", \ + "system/cos-setup", \ + "system/grub2-config", \ + "system/immutable-rootfs", \ + "toolchain/yip", \ + "utils/installer", \ + "utils/k9s", \ + "utils/nerdctl"] -FROM base +COPY --from=build /usr/sbin/ros-installer /usr/sbin/ros-installer +COPY framework/files/ / +RUN ["/usr/bin/busybox", "rm", "-rf", "/var", "/etc/ssl", "/usr/bin/busybox"] + +# Make OS image +FROM opensuse/leap:15.3 as os RUN zypper in -y \ + avahi \ bash-completion \ conntrack-tools \ coreutils \ @@ -55,47 +71,44 @@ RUN zypper in -y \ mdadm \ multipath-tools \ nano \ + netcat-openbsd \ nfs-utils \ open-iscsi \ open-vm-tools \ parted \ pigz \ policycoreutils \ + psmisc \ procps \ python-azure-agent \ qemu-guest-agent \ - rng-tools \ rsync \ squashfs \ strace \ + SUSEConnect \ systemd \ systemd-sysvinit \ + tcpdump \ tar \ timezone \ vim \ which -ARG CACHEBUST -RUN luet install -y \ - toolchain/yip \ - utils/installer \ - system/cloud-config \ - system/cos-setup \ - system/immutable-rootfs \ - system/grub-config \ - selinux/k3s \ - selinux/rancher \ - utils/k9s \ - utils/nerdctl \ - utils/rancherd +# Copy in some local OS customizations +COPY opensuse/files / -COPY files/ / +# Starting from here are the lines needed for RancherOS to work + +# IMPORTANT: Setup rancheros-release used for versioning/upgrade. The +# values here should reflect the tag of the image building built +ARG IMAGE_REPO=norepo +ARG IMAGE_TAG=latest +RUN echo "IMAGE_REPO=${IMAGE_REPO}" > /usr/lib/rancheros-release && \ + echo "IMAGE_TAG=${IMAGE_TAG}" >> /usr/lib/rancheros-release && \ + echo "IMAGE=${IMAGE_REPO}:${IMAGE_TAG}" >> /usr/lib/rancheros-release + +# Copy in framework runtime +COPY --from=framework / / + +# Rebuild initrd to setup dracut with the boot configurations RUN mkinitrd - -ARG OS_NAME=RancherOS -ARG OS_VERSION=999 -ARG OS_GIT=dirty -ARG OS_REPO=norepo/norepo -ARG OS_LABEL=latest -RUN envsubst >/usr/lib/os-release .dapper.tmp + @@chmod +x .dapper.tmp + @./.dapper.tmp -v + @mv .dapper.tmp .dapper + +.PHONY: validate +ci: .dapper + ./.dapper ci + +.PHONY: clean +clean: + rm -rf build .PHONY: build build: docker build \ - --build-arg CACHEBUST="${CACHEBUST}" \ - --build-arg OS_LABEL=${LABEL} \ - --build-arg OS_REPO=${REPO} \ + --build-arg CACHEBUST=${CACHEBUST} \ + --build-arg IMAGE_TAG=${TAG} \ + --build-arg IMAGE_REPO=${REPO} \ -t ${IMAGE} . .PHONY: push push: build docker push ${IMAGE} -.PHONY: tools -tools: - docker build -t ${TOOLS} --target tools . - .PHONY: iso -iso: tools - mkdir -p build - rm -f build/iso-container - docker run -it --cidfile=build/iso-container ${TOOLS} makeiso ${IMAGE} - docker cp $$(cat build/iso-container):/output.iso build/output.iso - docker rm -fv $$(cat build/iso-container) - rm -f build/iso-container +iso: build + ./ros-image-build ${IMAGE} iso + @echo "INFO: ISO available at build/output.iso" + +.PHONY: qcow +qcow: build + ./ros-image-build ${IMAGE} qcow + @echo "INFO: QCOW image available at build/output.qcow.gz" + +.PHONY: ami-% +ami-%: + AWS_DEFAULT_REGION=$* ./ros-image-build ${IMAGE} ami + +.PHONY: ami +ami: + ./ros-image-build ${IMAGE} ami + +.PHONY: run +run: + ./scripts/run + +all-amis: \ + ami-us-west-1 \ + ami-us-west-2 + #ami-ap-east-1 \ + #ami-ap-northeast-1 \ + #ami-ap-northeast-2 \ + #ami-ap-northeast-3 \ + #ami-ap-southeast-1 \ + #ami-ap-southeast-2 \ + #ami-ca-central-1 \ + #ami-eu-central-1 \ + #ami-eu-south-1 \ + #ami-eu-west-1 \ + #ami-eu-west-2 \ + #ami-eu-west-3 \ + #ami-me-south-1 \ + #ami-sa-east-1 \ + #ami-us-east-1 \ + #ami-us-east-2 \ diff --git a/cmd/ros-installer/main.go b/cmd/ros-installer/main.go new file mode 100644 index 00000000..a52fc7aa --- /dev/null +++ b/cmd/ros-installer/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "flag" + + "github.com/rancher/os/pkg/install" + "github.com/sirupsen/logrus" +) + +var ( + output = flag.Bool("automatic", false, "Check for and run automatic installation") +) + +func main() { + flag.Parse() + if err := install.Run(*output); err != nil { + logrus.Fatal(err) + } +} diff --git a/files/etc/cos/bootargs.cfg b/files/etc/cos/bootargs.cfg deleted file mode 100644 index f2801b85..00000000 --- a/files/etc/cos/bootargs.cfg +++ /dev/null @@ -1,8 +0,0 @@ -set kernel=/boot/vmlinuz -if [ -n "$recoverylabel" ]; then - set kernelcmd="console=tty1 console=ttyS0 root=live:LABEL=$recoverylabel rd.live.dir=/ rd.live.squashimg=$img panic=5" -else - set kernelcmd="console=tty1 console=ttyS0 root=LABEL=$label cos-img/filename=$img panic=5 security=selinux selinux=1" -fi - -set initramfs=/boot/initrd diff --git a/files/etc/dracut.conf.d/50-cos-initrd.conf b/files/etc/dracut.conf.d/50-cos-initrd.conf deleted file mode 100644 index dd5bfdc7..00000000 --- a/files/etc/dracut.conf.d/50-cos-initrd.conf +++ /dev/null @@ -1,5 +0,0 @@ -hostonly_cmdline="no" -hostonly="no" -compress="xz" -omit_dracutmodules+=" multipath " -add_dracutmodules+=" dmsquash-live " diff --git a/files/etc/issue.d/10-SUSE b/files/etc/issue.d/10-SUSE deleted file mode 100644 index 12db49a7..00000000 --- a/files/etc/issue.d/10-SUSE +++ /dev/null @@ -1,9 +0,0 @@ - , , ______ _ _____ _____TM - ,------------|'------'| | ___ \\ | | / _ / ___| - / . '-' |- | |_/ /__ _ _ __ ___| |__ ___ _ __ | | | \\ '--. - \\/| | | | // _' | '_ \\ / __| '_ \\ / _ \\ '__' | | | |'--. \\ - | .________.'----' | |\\ \\ (_| | | | | (__| | | | __/ | | \\_/ /\\__/ / - | | | | \\_| \\_\\__,_|_| |_|\\___|_| |_|\\___|_| \\___/\\____/ - \\___/ \\___/ \s \r - - RancherOS \v \n \l diff --git a/files/etc/os-release b/files/etc/os-release deleted file mode 120000 index c4c75b41..00000000 --- a/files/etc/os-release +++ /dev/null @@ -1 +0,0 @@ -../usr/lib/os-release \ No newline at end of file diff --git a/files/etc/selinux/config.enforcing b/files/etc/selinux/config.enforcing deleted file mode 100644 index f4e15123..00000000 --- a/files/etc/selinux/config.enforcing +++ /dev/null @@ -1,14 +0,0 @@ -# This file controls the state of SELinux on the system. -# SELinux can be completly disabled with the "selinux=0" kernel -# commandline option. -# -# SELINUX= can take one of these three values: -# enforcing - SELinux security policy is enforced. -# permissive - SELinux prints warnings instead of enforcing. -SELINUX=enforcing -# SELINUXTYPE= can take one of these three values: -# targeted - Targeted processes are protected, -# minimum - Modification of targeted policy. Only selected processes are protected. -# mls - Multi Level Security protection. -SELINUXTYPE=targeted - diff --git a/files/lib/systemd/system/cos-setup-rootfs.service b/files/lib/systemd/system/cos-setup-rootfs.service deleted file mode 100644 index 48520528..00000000 --- a/files/lib/systemd/system/cos-setup-rootfs.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=cOS system early rootfs setup -DefaultDependencies=no -After=initrd-root-fs.target -Requires=initrd-root-fs.target -Conflicts=initrd-switch-root.target - -[Service] -Type=oneshot -ExecStartPre=/usr/bin/ln -sf -t / /sysroot/system -ExecStart=/usr/bin/cos-setup rootfs - -[Install] -RequiredBy=initrd-fs.target diff --git a/files/lib/systemd/system/rancherd.service b/files/lib/systemd/system/rancherd.service deleted file mode 100644 index 891f3a63..00000000 --- a/files/lib/systemd/system/rancherd.service +++ /dev/null @@ -1,22 +0,0 @@ -[Unit] -Description=Rancher Bootstrap -Documentation=https://github.com/rancher/rancherd -Wants=network-online.target -After=network-online.target - -[Install] -WantedBy=multi-user.target - -[Service] -Type=oneshot -EnvironmentFile=-/etc/default/%N -EnvironmentFile=-/etc/sysconfig/%N -KillMode=process -# Having non-zero Limit*s causes performance problems due to accounting overhead -# in the kernel. We recommend using cgroups to do container-local accounting. -LimitNOFILE=1048576 -LimitNPROC=infinity -LimitCORE=infinity -TasksMax=infinity -TimeoutStartSec=0 -ExecStart=/usr/bin/rancherd bootstrap diff --git a/files/system/oem/03_branding.yaml b/files/system/oem/03_branding.yaml deleted file mode 100644 index c86eecef..00000000 --- a/files/system/oem/03_branding.yaml +++ /dev/null @@ -1,5 +0,0 @@ -name: "Branding" -stages: - initramfs: - - name: "Branding" - hostname: "rancher" diff --git a/files/system/oem/04_accounting.yaml b/files/system/oem/04_accounting.yaml deleted file mode 100644 index 9265fbee..00000000 --- a/files/system/oem/04_accounting.yaml +++ /dev/null @@ -1,41 +0,0 @@ -name: "Default user" -stages: - initramfs: - - name: "Setup groups" - ensure_entities: - - entity: | - kind: "group" - group_name: "admin" - password: "x" - gid: 900 - - entity: | - kind: "group" - group_name: "rancher" - password: "x" - gid: 1000 - - name: "Setup users" - users: - rancher: - name: "rancher" - passwd: "$6$mL4eOZ/wHV4MtjaZ$ASiwT66Yj9I/61cc7/vzdl6I8p5xK11Yn1EtSEO1CytZszfmP3R5iA05g0voxfZ5Dkj5BYdicE8lLnf3atbzE/" - groups: - - "admin" - - "systemd-journal" - primary_group: "rancher" - shell: /bin/bash - homedir: "/home/rancher" - - name: "Setup sudo" - files: - - path: "/etc/sudoers" - owner: 0 - group: 0 - permsisions: 0600 - content: | - Defaults always_set_home - Defaults secure_path="/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/bin:/usr/local/sbin" - Defaults env_reset - Defaults env_keep = "LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_ATIME LC_ALL LANGUAGE LINGUAS XDG_SESSION_COOKIE" - Defaults !insults - root ALL=(ALL) ALL - %admin ALL=(ALL) NOPASSWD: ALL - @includedir /etc/sudoers.d diff --git a/files/system/oem/07_cloud-metadata.yaml b/files/system/oem/07_cloud-metadata.yaml deleted file mode 100644 index 879bb6a7..00000000 --- a/files/system/oem/07_cloud-metadata.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# Default cOS OEM configuration file -# -# This file is part of cOS and will get reset during upgrades. -# -# Before you change this file manually, -# consider copying this file to /usr/local/cloud-config or -# copy the file with a prefix starting by 90, e.g. /oem/91_custom.yaml -name: "Cloud providers metadata" -stages: - network: - - name: "Cloud providers datasources" - datasource: - providers: ["aws", "gcp", "cdrom", "openstack"] - path: "/oem" diff --git a/files/system/oem/08_rancherd.yaml b/files/system/oem/08_rancherd.yaml deleted file mode 100644 index 0957f248..00000000 --- a/files/system/oem/08_rancherd.yaml +++ /dev/null @@ -1,11 +0,0 @@ -name: "Rancherd" -stages: - initramfs: - - name: "Rancherd" - commands: - - | - if grep -q root=live:CDLABEL=COS_LIVE /proc/cmdline || [ -n "$(blkid -L COS_SYSTEM)" ]; then - systemctl disable rancherd.service - else - systemctl enable rancherd.service - fi diff --git a/files/usr/bin/self-upgrade b/files/usr/bin/self-upgrade deleted file mode 100755 index 2bcc1406..00000000 --- a/files/usr/bin/self-upgrade +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -set -e -x -source /etc/os-release -sudo cos-upgrade --no-verify --docker-image "${IMAGE}" -sudo reboot diff --git a/files/usr/lib/os-release.tmpl b/files/usr/lib/os-release.tmpl deleted file mode 100644 index e510bd83..00000000 --- a/files/usr/lib/os-release.tmpl +++ /dev/null @@ -1,12 +0,0 @@ -NAME="${OS_NAME}" -VERSION="v${OS_VERSION} (${OS_GIT})" -ID="rancheros" -ID_LIKE="suse opensuse" -VERSION_ID="${OS_VERSION}" -PRETTY_NAME="${OS_NAME} v${OS_VERSION} (${OS_GIT})" -ANSI_COLOR="0;32" -BUG_REPORT_URL="https://github.com/rancher/os/issues" -HOME_URL="https://github.com/rancher/os" -IMAGE="${OS_REPO}:${OS_LABEL}" -IMAGE_REPO="${OS_REPO}" -IMAGE_LABEL="${OS_LABEL}" diff --git a/files/usr/share/rancher/rancherd/config.yaml.d/50-defaults.yaml b/files/usr/share/rancher/rancherd/config.yaml.d/50-defaults.yaml deleted file mode 100644 index 3ad2a547..00000000 --- a/files/usr/share/rancher/rancherd/config.yaml.d/50-defaults.yaml +++ /dev/null @@ -1,21 +0,0 @@ -rancherValues: - rancherImagePullPolicy: Always - rancherImage: ibuildthecloud/rancher - rancherImageTag: dev - extraEnv: - - name: CATTLE_SYSTEM_AGENT_UPGRADE_IMAGE - value: ibuildthecloud/suc -rancherInstallerImage: ibuildthecloud/system-agent-installer-rancher:dev -bootstrapResources: -- kind: Deployment - apiVersion: apps/v1 - metadata: - name: rancher-webhook - namespace: cattle-system - spec: - template: - spec: - containers: - - name: rancher-webhook - image: ibuildthecloud/rancher-webhook:dev - imagePullPolicy: Always diff --git a/files/etc/luet/luet.yaml b/framework/files/etc/luet/luet.yaml similarity index 52% rename from files/etc/luet/luet.yaml rename to framework/files/etc/luet/luet.yaml index 4273416a..faa7a4fb 100644 --- a/files/etc/luet/luet.yaml +++ b/framework/files/etc/luet/luet.yaml @@ -5,13 +5,8 @@ general: debug: false spinner_charset: 9 repositories: -- name: "cos" - description: "cOS official" +- name: "cos-toolkit-green" type: "docker" enable: true - cached: true - priority: 1 - verify: false urls: - - "quay.io/costoolkit/releases-opensuse" - + - "quay.io/costoolkit/releases-green" diff --git a/framework/files/etc/systemd/system/multi-user.target.wants/rancherd.service b/framework/files/etc/systemd/system/multi-user.target.wants/rancherd.service new file mode 120000 index 00000000..f57150d7 --- /dev/null +++ b/framework/files/etc/systemd/system/multi-user.target.wants/rancherd.service @@ -0,0 +1 @@ +/usr/lib/systemd/system/rancherd.service \ No newline at end of file diff --git a/files/etc/systemd/system/multi-user.target.wants/sshd.service b/framework/files/etc/systemd/system/multi-user.target.wants/sshd.service similarity index 100% rename from files/etc/systemd/system/multi-user.target.wants/sshd.service rename to framework/files/etc/systemd/system/multi-user.target.wants/sshd.service diff --git a/framework/files/etc/systemd/system/rancherd.service.d/override.conf b/framework/files/etc/systemd/system/rancherd.service.d/override.conf new file mode 100644 index 00000000..7c0e65e6 --- /dev/null +++ b/framework/files/etc/systemd/system/rancherd.service.d/override.conf @@ -0,0 +1,3 @@ +[Unit] +ConditionPathExists=!/run/cos/live_mode +ConditionPathExists=!/run/cos/rescue_mode diff --git a/files/system/oem/00_ros-rootfs.yaml b/framework/files/system/oem/00_ros-rootfs.yaml similarity index 65% rename from files/system/oem/00_ros-rootfs.yaml rename to framework/files/system/oem/00_ros-rootfs.yaml index 0c8f786b..7e19fc1b 100644 --- a/files/system/oem/00_ros-rootfs.yaml +++ b/framework/files/system/oem/00_ros-rootfs.yaml @@ -1,7 +1,7 @@ name: "ROS Rootfs Layout Settings" stages: initramfs: - - if: '[ -z "$(blkid -L COS_SYSTEM || true)" ]' + - if: '[ ! -f /run/cos/recovery_mode ]' commands: - | target=/usr/local/.ros-state @@ -10,6 +10,11 @@ stages: mkdir -p ${target}/etc/systemd/ rsync -av /etc/systemd/ ${target}/etc/systemd/ + if [ ! -e /usr/local/etc/hostname ]; then + echo rancher-${RANDOM} > /usr/local/etc/hostname + fi + ln -sf /usr/local/etc/hostname /etc/hostname + # Only populate ssh conf once if [ ! -e ${target}/etc/ssh ]; then mkdir -p ${target}/etc/ssh/ @@ -36,10 +41,27 @@ stages: # ensure /var/log/journal exists so it's labeled correctly nsenter -m -t 1 -- mkdir -p /sysroot/var/log/journal initramfs.after: - - if: '[ -z "$(blkid -L COS_SYSTEM || true)" ]' + - if: '[ ! -f /run/cos/recovery_mode ]' commands: - restorecon -R -v /etc /home /opt /var /usr/local /tmp /srv /root fs.before: - - if: '[ -z "$(blkid -L COS_SYSTEM || true)" ]' + - name: "Pull data from provider (local)" + datasource: + providers: ["aws", "gcp", "openstack", "cdrom"] + path: "/oem" + - if: '[ ! -f /run/cos/recovery_mode ]' commands: - restorecon -R -v /etc /home /opt /var /usr/local /tmp /srv /root + rootfs.after: + - if: '[ ! -f /run/cos/recovery_mode ] && [ ! -f /run/cos/live_mode ]' + name: "Grow persistent" + layout: + device: + label: COS_PERSISTENT + expand_partition: + size: 0 + fs.before: + - if: '[ ! -f "/run/cos/recovery_mode" ] && [ ! -f /run/cos/live_mode ]' + name: "Grow persistent fs" + commands: + - resize2fs $(blkid -L COS_PERSISTENT) diff --git a/files/usr/libexec/.placeholder b/framework/files/system/oem/03_branding.yaml similarity index 100% rename from files/usr/libexec/.placeholder rename to framework/files/system/oem/03_branding.yaml diff --git a/framework/files/system/oem/04_accounting.yaml b/framework/files/system/oem/04_accounting.yaml new file mode 100644 index 00000000..3b82b061 --- /dev/null +++ b/framework/files/system/oem/04_accounting.yaml @@ -0,0 +1,16 @@ +name: "Default user" +stages: + initramfs: + - if: | + cat /proc/cmdline | grep -q "CDLABEL" + name: "Setup user for live CD" + files: + - path: /etc/issue.d/99_passwd + content: | + Login with username=root, password=cos + ensure_entities: + - path: /etc/shadow + entity: | + kind: "shadow" + username: "root" + password: "cos" diff --git a/framework/files/system/oem/05_elemental-installer.yaml b/framework/files/system/oem/05_elemental-installer.yaml new file mode 100644 index 00000000..5bbfc5c5 --- /dev/null +++ b/framework/files/system/oem/05_elemental-installer.yaml @@ -0,0 +1,23 @@ +name: "Elemental Installer" +stages: + initramfs: + - if: '[ -f /run/cos/live_mode ]' + files: + - path: /etc/motd + content: | + + Run "ros-installer" to install to disk + + permissions: 0644 + - path: /etc/systemd/system/serial-getty@ttyS0.service.d/override.conf + content: | + [Service] + ExecStart= + ExecStart=-/sbin/agetty --autologin root --noclear %I $TERM + permissions: 0644 + - path: /etc/systemd/system/getty@tty1.service.d/override.conf + content: | + [Service] + ExecStart= + ExecStart=-/sbin/agetty --autologin root --noclear %I $TERM + permissions: 0644 diff --git a/framework/files/usr/libexec/.placeholder b/framework/files/usr/libexec/.placeholder new file mode 100644 index 00000000..e69de29b diff --git a/framework/files/usr/sbin/self-upgrade b/framework/files/usr/sbin/self-upgrade new file mode 100755 index 00000000..f4ee9e99 --- /dev/null +++ b/framework/files/usr/sbin/self-upgrade @@ -0,0 +1,5 @@ +#!/bin/bash +set -e -x +source /usr/lib/rancheros-release +cos-upgrade --no-verify --docker-image "${IMAGE}" +reboot diff --git a/framework/files/usr/sbin/suc-upgrade b/framework/files/usr/sbin/suc-upgrade new file mode 100755 index 00000000..ad71af43 --- /dev/null +++ b/framework/files/usr/sbin/suc-upgrade @@ -0,0 +1,18 @@ +#!/bin/bash +set -x -e +HOST_DIR="${HOST_DIR:-/host}" +RELEASE_FILE="${RELEASE_FILE:-/etc/os-release}" + +if [ "$FORCE" != "true" ]; then + if diff $RELEASE_FILE ${HOST_DIR}${RELEASE_FILE} >/dev/null; then + echo Update to date with + cat /etc/os-release + exit 0 + fi +fi + +mount --rbind $HOST_DIR/dev /dev +mount --rbind $HOST_DIR/run /run +bash -x cos-upgrade --directory / +nsenter -i -m -t 1 -- reboot +exit 1 diff --git a/go.mod b/go.mod new file mode 100644 index 00000000..c811709a --- /dev/null +++ b/go.mod @@ -0,0 +1,26 @@ +module github.com/rancher/os + +go 1.16 + +require ( + github.com/mattn/go-isatty v0.0.10 + github.com/pkg/errors v0.9.1 + github.com/rancher/wrangler v0.8.3 + github.com/sirupsen/logrus v1.4.2 + github.com/stretchr/testify v1.4.0 + github.com/tredoe/osutil v1.0.5 + golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 + sigs.k8s.io/yaml v1.2.0 +) + +replace ( + k8s.io/api => github.com/rancher/kubernetes/staging/src/k8s.io/api v1.16.3-k3s.2 + k8s.io/apiextensions-apiserver => github.com/rancher/kubernetes/staging/src/k8s.io/apiextensions-apiserver v1.16.3-k3s.2 + k8s.io/apimachinery => github.com/rancher/kubernetes/staging/src/k8s.io/apimachinery v1.16.3-k3s.2 + k8s.io/apiserver => github.com/rancher/kubernetes/staging/src/k8s.io/apiserver v1.16.3-k3s.2 + k8s.io/client-go => github.com/rancher/kubernetes/staging/src/k8s.io/client-go v1.16.3-k3s.2 + k8s.io/code-generator => github.com/rancher/kubernetes/staging/src/k8s.io/code-generator v1.16.3-k3s.2 + k8s.io/component-base => github.com/rancher/kubernetes/staging/src/k8s.io/component-base v1.16.3-k3s.2 + k8s.io/kube-aggregator => github.com/rancher/kubernetes/staging/src/k8s.io/kube-aggregator v1.16.3-k3s.2 + k8s.io/metrics => github.com/rancher/kubernetes/staging/src/k8s.io/metrics v1.16.3-k3s.2 +) diff --git a/go.sum b/go.sum new file mode 100644 index 00000000..891120cd --- /dev/null +++ b/go.sum @@ -0,0 +1,523 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +github.com/360EntSecGroup-Skylar/excelize v1.4.1/go.mod h1:vnax29X2usfl7HHkBrX5EvSCJcmH3dT9luvxzu8iGAE= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustmop/soup v1.1.2-0.20190516214245-38228baa104e/go.mod h1:CgNC6SGbT+Xb8wGGvzilttZL1mc5sQ/5KkcxsZttMIk= +github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= +github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= +github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= +github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= +github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= +github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= +github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= +github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= +github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= +github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= +github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= +github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= +github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= +github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I= +github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho= +github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8= +github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= +github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.4.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.3.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu//Vk= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/qri-io/starlib v0.4.2-0.20200213133954-ff2e8cd5ef8d/go.mod h1:7DPO4domFU579Ga6E61sB9VFNaniPVwJP5C4bBCu3wA= +github.com/rancher/kubernetes/staging/src/k8s.io/api v1.16.3-k3s.2/go.mod h1:cHpnPcbNeE90PrTRnTu13OM+FN+ROt82odVbEh++81o= +github.com/rancher/kubernetes/staging/src/k8s.io/apiextensions-apiserver v1.16.3-k3s.2/go.mod h1:tXCXeG1YI6F9buUotzmBdjCRCJfM0xfoNX5782iBQPA= +github.com/rancher/kubernetes/staging/src/k8s.io/apimachinery v1.16.3-k3s.2 h1:F+iNcKS5f6cFP4HCuGulrsX5XIkUnVhrRBQwUy01t2c= +github.com/rancher/kubernetes/staging/src/k8s.io/apimachinery v1.16.3-k3s.2/go.mod h1:I9gveEHn8RBUsRZ1zR7UbePt/ySCzzxsG1dWwpKNN5E= +github.com/rancher/kubernetes/staging/src/k8s.io/apiserver v1.16.3-k3s.2/go.mod h1:+c9OY4l2MPZsWcuJPzAJfdMb6wpt6srdvgaOEvuSfcA= +github.com/rancher/kubernetes/staging/src/k8s.io/client-go v1.16.3-k3s.2/go.mod h1:GiGfbsjtP4tOW6zgpL8/vCUoyXAV5+9X2onLursPi08= +github.com/rancher/kubernetes/staging/src/k8s.io/code-generator v1.16.3-k3s.2/go.mod h1:uzCZz0cC/uXDgpjpMZ7lFzglGU/9tXyTiPDcX92d6OI= +github.com/rancher/kubernetes/staging/src/k8s.io/component-base v1.16.3-k3s.2/go.mod h1:spPP+vRNS8EsnNNIhFCZTTuRO3XhV1WoF18HJySoZn8= +github.com/rancher/kubernetes/staging/src/k8s.io/kube-aggregator v1.16.3-k3s.2/go.mod h1:ttKFRQ6/4l0mjLwPJ/Ccn9k/vc/6y5dJ98r88NLLiGw= +github.com/rancher/kubernetes/staging/src/k8s.io/metrics v1.16.3-k3s.2/go.mod h1:vQHTmz0IaEb7/OXPSor1uga8Er0V+2M5aSdXG832NbU= +github.com/rancher/lasso v0.0.0-20210616224652-fc3ebd901c08/go.mod h1:9qZd/S8DqWzfKtjKGgSoHqGEByYmUE3qRaBaaAHwfEM= +github.com/rancher/wrangler v0.8.3 h1:m3d5ChOQj2Pdozy6nkGiSzAgQxlQlXRis2zSRwaO83k= +github.com/rancher/wrangler v0.8.3/go.mod h1:dKEaHNB4izxmPUtpq1Hvr3z3Oh+9k5pCZyFO9sUhlaY= +github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.3-0.20181224173747-660f15d67dbb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tredoe/fileutil v1.0.0/go.mod h1:PBayWPFCURwkmW0u6E8E8C6Jtd9ZzWq/U1iMa6BLRPg= +github.com/tredoe/goutil v0.0.0-20200111155331-68cefb6d3cdc/go.mod h1:dp4VPOLeEFYbsf1ikgd+uytWDnpCdMiTHMg6mh7hHuQ= +github.com/tredoe/osutil v1.0.5 h1:mfXjHBJU46GoJDOUcHyV895fauUuVikR9U8yRbGBrqw= +github.com/tredoe/osutil v1.0.5/go.mod h1:DDO4G4Mwys6NJi5JmEVLnfFbQWIfVVri8L6HuXb/v98= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= +github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8= +github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.starlark.net v0.0.0-20190528202925-30ae18b8564f/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg= +go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= +go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180117170059-2c42eef0765b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20171227012246-e19ae1496984/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191017205301-920acffc3e65/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.0.0/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +k8s.io/cli-runtime v0.0.0-20191214191754-e6dc6d5c8724/go.mod h1:wzlq80lvjgHW9if6MlE4OIGC86MDKsy5jtl9nxz/IYY= +k8s.io/cli-runtime v0.17.2/go.mod h1:aa8t9ziyQdbkuizkNLAw3qe3srSyWh9zlSB7zTqRNPI= +k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= +k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= +k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= +k8s.io/kubectl v0.0.0-20191219154910-1528d4eea6dd/go.mod h1:9ehGcuUGjXVZh0qbYSB0vvofQw2JQe6c6cO0k4wu/Oo= +k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= +modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= +modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= +modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +sigs.k8s.io/cli-utils v0.16.0/go.mod h1:9Jqm9K2W6ShhCxsEuaz6HSRKKOXigPUx3ZfypGgxBLY= +sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns= +sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= +sigs.k8s.io/kustomize/kyaml v0.4.0/go.mod h1:XJL84E6sOFeNrQ7CADiemc1B0EjIxHo3OhW4o1aJYNw= +sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= +sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI= diff --git a/files/etc/bash.bashrc.local b/opensuse/files/etc/bash.bashrc.local similarity index 100% rename from files/etc/bash.bashrc.local rename to opensuse/files/etc/bash.bashrc.local diff --git a/pkg/config/coerce.go b/pkg/config/coerce.go new file mode 100644 index 00000000..85f25dc0 --- /dev/null +++ b/pkg/config/coerce.go @@ -0,0 +1,86 @@ +package config + +import ( + "github.com/rancher/wrangler/pkg/data" + "github.com/rancher/wrangler/pkg/data/convert" + schemas2 "github.com/rancher/wrangler/pkg/schemas" + "github.com/rancher/wrangler/pkg/schemas/mappers" +) + +type Converter func(val interface{}) interface{} + +type fieldConverter struct { + mappers.DefaultMapper + fieldName string + converter Converter +} + +func (f fieldConverter) ToInternal(data data.Object) error { + val, ok := data[f.fieldName] + if !ok { + return nil + } + data[f.fieldName] = f.converter(val) + return nil +} + +type typeConverter struct { + mappers.DefaultMapper + converter Converter + fieldType string + mappers schemas2.Mappers +} + +func (t *typeConverter) ToInternal(data data.Object) error { + return t.mappers.ToInternal(data) +} + +func (t *typeConverter) ModifySchema(schema *schemas2.Schema, schemas *schemas2.Schemas) error { + for name, field := range schema.ResourceFields { + if field.Type == t.fieldType { + t.mappers = append(t.mappers, fieldConverter{ + fieldName: name, + converter: t.converter, + }) + } + } + return nil +} + +func NewTypeConverter(fieldType string, converter Converter) schemas2.Mapper { + return &typeConverter{ + fieldType: fieldType, + converter: converter, + } +} + +func NewToMap() schemas2.Mapper { + return NewTypeConverter("map[string]", func(val interface{}) interface{} { + if m, ok := val.(map[string]interface{}); ok { + obj := make(map[string]string, len(m)) + for k, v := range m { + obj[k] = convert.ToString(v) + } + return obj + } + return val + }) +} + +func NewToSlice() schemas2.Mapper { + return NewTypeConverter("array[string]", func(val interface{}) interface{} { + if str, ok := val.(string); ok { + return []string{str} + } + return val + }) +} + +func NewToBool() schemas2.Mapper { + return NewTypeConverter("boolean", func(val interface{}) interface{} { + if str, ok := val.(string); ok { + return str == "true" + } + return val + }) +} diff --git a/pkg/config/config.go b/pkg/config/config.go new file mode 100644 index 00000000..eb5e7431 --- /dev/null +++ b/pkg/config/config.go @@ -0,0 +1,47 @@ +package config + +type Elemental struct { + Install Install `json:"install,omitempty"` +} + +type Install struct { + Automatic bool `json:"automatic,omitempty"` + ForceEFI bool `json:"forceEfi,omitempty"` + Device string `json:"device,omitempty"` + ConfigURL string `json:"configUrl,omitempty"` + Silent bool `json:"silent,omitempty"` + ISOURL string `json:"isoUrl,omitempty"` + PowerOff bool `json:"powerOff,omitempty"` + NoFormat bool `json:"noFormat,omitempty"` + Debug bool `json:"debug,omitempty"` + TTY string `json:"tty,omitempty"` + ServerURL string `json:"serverUrl,omitempty"` + Token string `json:"token,omitempty"` + Password string `json:"password,omitempty"` +} + +type Config struct { + SSHAuthorizedKeys []string `json:"sshAuthorizedKeys,omitempty"` + Elemental Elemental `json:"elemental,omitempty"` +} + +type YipConfig struct { + Stages map[string][]Stage `json:"stages,omitempty"` + Rancherd Rancherd `json:"rancherd,omitempty"` +} + +type Stage struct { + Users map[string]User `json:"users,omitempty"` +} + +type Rancherd struct { + Server string `json:"server,omitempty"` + Role string `json:"role,omitempty"` + Token string `json:"token,omitempty"` +} + +type User struct { + Name string `json:"name,omitempty"` + PasswordHash string `json:"passwd,omitempty"` + SSHAuthorizedKeys []string `json:"ssh_authorized_keys,omitempty"` +} diff --git a/pkg/config/read.go b/pkg/config/read.go new file mode 100644 index 00000000..78703444 --- /dev/null +++ b/pkg/config/read.go @@ -0,0 +1,104 @@ +package config + +import ( + "fmt" + "io/ioutil" + "os" + "regexp" + "strings" + + values "github.com/rancher/wrangler/pkg/data" + "github.com/rancher/wrangler/pkg/data/convert" + schemas2 "github.com/rancher/wrangler/pkg/schemas" +) + +var ( + schemas = schemas2.EmptySchemas().Init(func(s *schemas2.Schemas) *schemas2.Schemas { + s.DefaultMapper = func() schemas2.Mapper { + return schemas2.Mappers{ + NewToMap(), + NewToSlice(), + NewToBool(), + &FuzzyNames{}, + } + } + return s + }).MustImport(Config{}) + schema = schemas.Schema("config") +) + +func ToEnv(cfg Config) ([]string, error) { + data, err := convert.EncodeToMap(&cfg) + if err != nil { + return nil, err + } + + return mapToEnv("", data), nil +} + +func mapToEnv(prefix string, data map[string]interface{}) []string { + var result []string + for k, v := range data { + keyName := strings.ToUpper(prefix + convert.ToYAMLKey(k)) + keyName = strings.ReplaceAll(keyName, "ELEMENTAL_", "COS_") + if data, ok := v.(map[string]interface{}); ok { + subResult := mapToEnv(keyName+"_", data) + result = append(result, subResult...) + } else { + result = append(result, fmt.Sprintf("%s=%v", keyName, v)) + } + } + return result +} + +func ReadConfig() (Config, error) { + result := Config{} + + data, err := readCmdline() + if err != nil { + return result, err + } + if err := schema.Mapper.ToInternal(data); err != nil { + return result, err + } + + return result, convert.ToObj(data, &result) +} + +func readCmdline() (map[string]interface{}, error) { + //supporting regex https://regexr.com/4mq0s + parser, err := regexp.Compile(`(\"[^\"]+\")|([^\s]+=(\"[^\"]+\")|([^\s]+))`) + if err != nil { + return nil, nil + } + + bytes, err := ioutil.ReadFile("/proc/cmdline") + if os.IsNotExist(err) { + return nil, nil + } else if err != nil { + return nil, err + } + + data := map[string]interface{}{} + for _, item := range parser.FindAllString(string(bytes), -1) { + parts := strings.SplitN(item, "=", 2) + value := "true" + if len(parts) > 1 { + value = strings.Trim(parts[1], `"`) + } + keys := strings.Split(strings.Trim(parts[0], `"`), ".") + existing, ok := values.GetValue(data, keys...) + if ok { + switch v := existing.(type) { + case string: + values.PutValue(data, []string{v, value}, keys...) + case []string: + values.PutValue(data, append(v, value), keys...) + } + } else { + values.PutValue(data, value, keys...) + } + } + + return data, nil +} diff --git a/pkg/config/rename.go b/pkg/config/rename.go new file mode 100644 index 00000000..0a0176da --- /dev/null +++ b/pkg/config/rename.go @@ -0,0 +1,49 @@ +package config + +import ( + "strings" + + "github.com/rancher/wrangler/pkg/data" + "github.com/rancher/wrangler/pkg/data/convert" + schemas2 "github.com/rancher/wrangler/pkg/schemas" + "github.com/rancher/wrangler/pkg/schemas/mappers" +) + +type FuzzyNames struct { + mappers.DefaultMapper + names map[string]string +} + +func (f *FuzzyNames) ToInternal(data data.Object) error { + for k, v := range data { + if newK, ok := f.names[k]; ok && newK != k { + data[newK] = v + } + } + return nil +} + +func (f *FuzzyNames) addName(name, toName string) { + f.names[strings.ToLower(name)] = toName + f.names[convert.ToYAMLKey(name)] = toName + f.names[strings.ToLower(convert.ToYAMLKey(name))] = toName +} + +func (f *FuzzyNames) ModifySchema(schema *schemas2.Schema, schemas *schemas2.Schemas) error { + f.names = map[string]string{} + + for name := range schema.ResourceFields { + if strings.HasSuffix(name, "s") && len(name) > 1 { + f.addName(name[:len(name)-1], name) + } + if strings.HasSuffix(name, "es") && len(name) > 2 { + f.addName(name[:len(name)-2], name) + } + f.addName(name, name) + } + + f.names["pass"] = "passphrase" + f.names["password"] = "passphrase" + + return nil +} diff --git a/pkg/config/write.go b/pkg/config/write.go new file mode 100644 index 00000000..303062d7 --- /dev/null +++ b/pkg/config/write.go @@ -0,0 +1,32 @@ +package config + +import ( + "github.com/rancher/wrangler/pkg/data/convert" + "sigs.k8s.io/yaml" +) + +func PrintInstall(cfg Config) ([]byte, error) { + if cfg.Elemental.Install.Password != "" { + cfg.Elemental.Install.Password = "******" + } + data, err := convert.EncodeToMap(cfg.Elemental.Install) + if err != nil { + return nil, err + } + + toYAMLKeys(data) + return yaml.Marshal(data) +} + +func toYAMLKeys(data map[string]interface{}) { + for k, v := range data { + if sub, ok := v.(map[string]interface{}); ok { + toYAMLKeys(sub) + } + newK := convert.ToYAMLKey(k) + if newK != k { + delete(data, k) + data[newK] = v + } + } +} diff --git a/pkg/install/ask.go b/pkg/install/ask.go new file mode 100644 index 00000000..c4ccdc23 --- /dev/null +++ b/pkg/install/ask.go @@ -0,0 +1,190 @@ +package install + +import ( + "os/exec" + "strings" + + "github.com/rancher/os/pkg/config" + "github.com/rancher/os/pkg/questions" + "github.com/rancher/os/pkg/util" +) + +func Ask(cfg *config.Config) error { + if cfg.Elemental.Install.Silent { + return nil + } + + if err := AskInstallDevice(cfg); err != nil { + return err + } + + if err := AskConfigURL(cfg); err != nil { + return err + } + + if cfg.Elemental.Install.ConfigURL == "" { + if err := AskGithub(cfg); err != nil { + return err + } + + if err := AskPassword(cfg); err != nil { + return err + } + + if err := AskServerAgent(cfg); err != nil { + return err + } + } + + return nil +} + +func AskInstallDevice(cfg *config.Config) error { + if cfg.Elemental.Install.Device != "" { + return nil + } + + output, err := exec.Command("/bin/sh", "-c", "lsblk -r -o NAME,TYPE | grep -w disk | grep -v fd0 | awk '{print $1}'").CombinedOutput() + if err != nil { + return err + } + fields := strings.Fields(string(output)) + i, err := questions.PromptFormattedOptions("Installation target. Device will be formatted", -1, fields...) + if err != nil { + return err + } + + cfg.Elemental.Install.Device = "/dev/" + fields[i] + return nil +} + +func AskToken(cfg *config.Config, server bool) error { + var ( + token string + err error + ) + + if cfg.Elemental.Install.Token != "" { + return nil + } + + msg := "Token or cluster secret" + if server { + msg += " (optional)" + } + if server { + token, err = questions.PromptOptional(msg+": ", "") + } else { + token, err = questions.Prompt(msg+": ", "") + } + cfg.Elemental.Install.Token = token + + return err +} + +func isServer(cfg *config.Config) (bool, error) { + opts := []string{"server", "agent"} + i, err := questions.PromptFormattedOptions("Run as server or agent?", 0, opts...) + if err != nil { + return false, err + } + + return i == 0, nil +} + +func AskServerAgent(cfg *config.Config) error { + if cfg.Elemental.Install.ServerURL != "" { + return nil + } + + server, err := isServer(cfg) + if err != nil { + return err + } + + if server { + return AskToken(cfg, true) + } + + url, err := questions.Prompt("URL of server: ", "") + if err != nil { + return err + } + cfg.Elemental.Install.ServerURL = url + + return AskToken(cfg, false) +} + +func AskPassword(cfg *config.Config) error { + if cfg.Elemental.Install.Silent || cfg.Elemental.Install.Password != "" { + return nil + } + + var ( + ok = false + err error + pass string + ) + + for !ok { + pass, ok, err = util.PromptPassword() + if err != nil { + return err + } + } + + if pass != "" { + pass, err = util.GetEncryptedPasswd(pass) + if err != nil { + return err + } + } + + cfg.Elemental.Install.Password = pass + return nil +} + +func AskGithub(cfg *config.Config) error { + if len(cfg.SSHAuthorizedKeys) > 0 || cfg.Elemental.Install.Password != "" { + return nil + } + + ok, err := questions.PromptBool("Authorize GitHub users to root SSH?", false) + if !ok || err != nil { + return err + } + + str, err := questions.Prompt("Comma separated list of GitHub users to authorize: ", "") + if err != nil { + return err + } + + for _, s := range strings.Split(str, ",") { + cfg.SSHAuthorizedKeys = append(cfg.SSHAuthorizedKeys, "github:"+strings.TrimSpace(s)) + } + + return nil +} + +func AskConfigURL(cfg *config.Config) error { + if cfg.Elemental.Install.ConfigURL != "" { + return nil + } + + ok, err := questions.PromptBool("Configure system using an Elemental config file?", false) + if err != nil { + return err + } + + if !ok { + return nil + } + + str, err := questions.Prompt("Elemental config file location (file path or http URL): ", "") + if err != nil { + return err + } + + cfg.Elemental.Install.ConfigURL = str + return nil +} diff --git a/pkg/install/install.go b/pkg/install/install.go new file mode 100644 index 00000000..248d44ae --- /dev/null +++ b/pkg/install/install.go @@ -0,0 +1,104 @@ +package install + +import ( + "io/ioutil" + "os" + "os/exec" + + "github.com/rancher/os/pkg/config" + "github.com/rancher/os/pkg/questions" + "sigs.k8s.io/yaml" +) + +func Run(automatic bool) error { + cfg, err := config.ReadConfig() + if err != nil { + return err + } + + if automatic && !cfg.Elemental.Install.Automatic { + return nil + } else if automatic { + cfg.Elemental.Install.Silent = true + } + + err = Ask(&cfg) + if err != nil { + return err + } + + tempFile, err := ioutil.TempFile("", "elemental-install") + if err != nil { + return err + } + if err := tempFile.Close(); err != nil { + return err + } + + return runInstall(cfg, tempFile.Name()) +} + +func runInstall(cfg config.Config, output string) error { + installBytes, err := config.PrintInstall(cfg) + if err != nil { + return err + } + + if !cfg.Elemental.Install.Silent { + val, err := questions.PromptBool("\nConfiguration\n"+"-------------\n\n"+ + string(installBytes)+ + "\nYour disk will be formatted and installed with the above configuration.\nContinue?", false) + if err != nil || !val { + return err + } + } + + if cfg.Elemental.Install.ConfigURL == "" { + yip := config.YipConfig{ + Rancherd: config.Rancherd{ + Server: cfg.Elemental.Install.ServerURL, + Token: cfg.Elemental.Install.Token, + }, + } + if cfg.Elemental.Install.ServerURL == "" { + yip.Rancherd.Role = "cluster-init" + } else { + yip.Rancherd.Role = "agent" + } + if cfg.Elemental.Install.Password != "" || len(cfg.SSHAuthorizedKeys) > 0 { + yip.Stages = map[string][]config.Stage{ + "initramfs": {{ + Users: map[string]config.User{ + "root": { + Name: "root", + PasswordHash: cfg.Elemental.Install.Password, + SSHAuthorizedKeys: cfg.SSHAuthorizedKeys, + }, + }}, + }} + cfg.Elemental.Install.Password = "" + } + + data, err := yaml.Marshal(yip) + if err != nil { + return err + } + + if err := ioutil.WriteFile(output+".yip", data, 0600); err != nil { + return err + } + cfg.Elemental.Install.ConfigURL = output + ".yip" + } + + ev, err := config.ToEnv(cfg) + if err != nil { + return err + } + + cmd := exec.Command("cos-installer") + cmd.Env = append(os.Environ(), ev...) + cmd.Stdout = os.Stdout + cmd.Stdin = os.Stdin + cmd.Stderr = os.Stderr + return cmd.Run() +} diff --git a/pkg/questions/questions.go b/pkg/questions/questions.go new file mode 100644 index 00000000..1ae9ff88 --- /dev/null +++ b/pkg/questions/questions.go @@ -0,0 +1,142 @@ +package questions + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" + + "github.com/mattn/go-isatty" +) + +func PromptFormattedOptions(text string, def int, options ...string) (int, error) { + var newOptions []string + for i := range options { + newOptions = append(newOptions, fmt.Sprintf("%d. %s\n", i+1, options[i])) + } + return PromptOptions(text+"\n", def, newOptions...) +} + +func PromptOptions(text string, def int, options ...string) (int, error) { + if len(options) == 1 { + return 0, nil + } + + PrintToTerm(text) + for _, option := range options { + PrintToTerm(option) + } + + defString := "" + if def >= 0 { + defString = strconv.Itoa(def + 1) + } + + for { + ans, err := Prompt(fmt.Sprintf("Select Number [%s]: ", defString), defString) + if err != nil { + return 0, err + } + num, err := strconv.Atoi(ans) + if err != nil { + PrintfToTerm("Invalid number: %s\n", ans) + continue + } + + num-- + if num < 0 || num >= len(options) { + PrintlnToTerm("Select a number between 1 and", +len(options)) + continue + } + + return num, nil + } +} + +func PromptBool(text string, def bool) (bool, error) { + msg := fmt.Sprintf("%s [y/N]: ", text) + defStr := "n" + if def { + msg = fmt.Sprintf("%s [Y/n]: ", text) + defStr = "y" + } + + for { + yn, err := Prompt(msg, defStr) + if err != nil { + return false, err + } + + switch strings.ToLower(yn) { + case "y": + return true, nil + case "n": + return false, nil + default: + fmt.Println("Enter y or n") + } + } +} + +func PrintToTerm(text ...interface{}) { + if isatty.IsTerminal(os.Stdout.Fd()) { + fmt.Print(text...) + } else { + fmt.Fprint(os.Stderr, text...) + } +} + +func PrintlnToTerm(text ...interface{}) { + if isatty.IsTerminal(os.Stdout.Fd()) { + fmt.Println(text...) + } else { + fmt.Fprintln(os.Stderr, text...) + } +} + +func PrintfToTerm(msg string, format ...interface{}) { + if isatty.IsTerminal(os.Stdout.Fd()) { + fmt.Printf(msg, format...) + } else { + fmt.Fprintf(os.Stderr, msg, format...) + } +} + +func Prompt(text, def string) (string, error) { + for { + PrintToTerm(text) + answer, err := bufio.NewReader(os.Stdin).ReadString('\n') + if err != nil { + return "", err + } + + answer = strings.TrimSpace(answer) + if answer == "" { + answer = def + } + + if answer == "" { + continue + } + + return answer, nil + } +} + +func PromptOptional(text, def string) (string, error) { + for { + PrintToTerm(text) + answer, err := bufio.NewReader(os.Stdin).ReadString('\n') + if err != nil { + return "", err + } + + answer = strings.TrimSpace(answer) + if answer == "" { + answer = def + } + + return answer, nil + } +} diff --git a/pkg/util/crypt.go b/pkg/util/crypt.go new file mode 100644 index 00000000..846dab4e --- /dev/null +++ b/pkg/util/crypt.go @@ -0,0 +1,13 @@ +package util + +import ( + "github.com/tredoe/osutil/user/crypt/common" + "github.com/tredoe/osutil/user/crypt/sha512_crypt" +) + +func GetEncryptedPasswd(key string) (string, error) { + c := sha512_crypt.New() + salt := common.Salt{} + saltBytes := salt.Generate(16) + return c.Generate([]byte(key), saltBytes) +} diff --git a/pkg/util/prompt.go b/pkg/util/prompt.go new file mode 100644 index 00000000..75c3d320 --- /dev/null +++ b/pkg/util/prompt.go @@ -0,0 +1,90 @@ +package util + +import ( + "bytes" + "fmt" + "io" + "os" + + "github.com/pkg/errors" + "golang.org/x/crypto/ssh/terminal" +) + +var ( + bs = []byte("\b \b") + mask = []byte("*") + maxBytes = 512 +) + +func PromptPassword() (string, bool, error) { + fmt.Print("Please enter password for [root]: ") + p, err := MaskPassword(os.Stdin, os.Stdout) + if err != nil { + return "", false, errors.Wrapf(err, "failed to set password") + } + if string(p) == "" { + fmt.Printf("Not setting password, leaving root disabled\n") + return "", true, nil + } + fmt.Print("Confirm password for [root]: ") + c, err := MaskPassword(os.Stdin, os.Stdout) + if err != nil { + return "", false, errors.Wrapf(err, "failed to confirm password") + } + return string(c), bytes.Compare(p, c) == 0, nil +} + +func MaskPassword(r *os.File, w io.Writer) ([]byte, error) { + var p []byte + var err error + fd := int(r.Fd()) + if terminal.IsTerminal(fd) { + s, e := terminal.MakeRaw(fd) + if e != nil { + return p, e + } + defer func() { + terminal.Restore(fd, s) + fmt.Fprintln(w) + }() + } + // Reference: ascii-table-0-127 + var i int + for i = 0; i <= maxBytes; i++ { + if v, e := getCharacter(r); e != nil { + err = e + break + } else if v == 127 || v == 8 { + // Delete || Backspace + if l := len(p); l > 0 { + p = p[:l-1] + fmt.Fprint(w, string(bs)) + } + } else if v == 13 || v == 10 { + // CR || LF + break + } else if v == 3 { + // End + err = fmt.Errorf("interrupted") + break + } else if v != 0 { + p = append(p, v) + fmt.Fprint(w, string(mask)) + } + } + if i > maxBytes { + err = fmt.Errorf("maximum password length is %v bytes", maxBytes) + } + return p, err +} + +func getCharacter(r io.Reader) (byte, error) { + buf := make([]byte, 1) + if n, err := r.Read(buf); n == 0 || err != nil { + if err != nil { + return 0, err + } + return 0, io.EOF + } + return buf[0], nil +} diff --git a/ros-image-build b/ros-image-build new file mode 100755 index 00000000..90a50196 --- /dev/null +++ b/ros-image-build @@ -0,0 +1,185 @@ +#!/bin/bash +set -e + +build() +{ + dockerfile | docker build -f - --build-arg IMAGE="${IMAGE}" . "${@}" +} + +dockerfile() +{ + cat << "EOF" +ARG IMAGE=rancher/os:dev + +FROM ${IMAGE} AS os + +FROM opensuse/leap:15.3 AS tools +ENV LUET_NOLOCK=true +# Copy luet from the official images +RUN zypper in -y squashfs xorriso curl unzip git qemu-kvm qemu-tools tar pigz +RUN cd /usr/sbin && \ + rm packer && \ + curl https://releases.hashicorp.com/packer/1.7.4/packer_1.7.4_linux_amd64.zip > tmp && \ + unzip tmp && \ + rm tmp +RUN cd /usr/src && \ + git clone https://github.com/rancher-sandbox/cOS-toolkit +COPY --from=quay.io/luet/base:0.17.8 /usr/bin/luet /usr/bin/luet +RUN mkdir /iso /etc/luet +RUN echo -e \ +'logging:\n'\ +' color: false\n'\ +' enable_emoji: false\n'\ +'general:\n'\ +' debug: false\n'\ +' spinner_charset: 9\n'\ +'repositories:\n'\ +'- name: "cos-toolkit-green"\n'\ +' type: "docker"\n'\ +' enable: true\n'\ +' urls:\n'\ +' - "quay.io/costoolkit/releases-green"\n' > /etc/luet/luet.yaml +RUN echo -e \ +'packages:\n'\ +' uefi:\n'\ +' - live/grub2-efi-image\n'\ +' isoimage:\n'\ +' - live/grub2\n'\ +' - live/grub2-efi-image\n'\ +'\n'\ +'boot_file: "boot/x86_64/loader/eltorito.img"\n'\ +'boot_catalog: "boot/x86_64/boot.catalog"\n'\ +'isohybrid_mbr: "boot/x86_64/loader/boot_hybrid.img"\n'\ +'\n'\ +'initramfs:\n'\ +' kernel_file: "vmlinuz"\n'\ +' rootfs_file: "initrd"\n'\ +'\n'\ +'overlay:\n'\ +' rootfs: /iso/overlay\n'\ +'\n'\ +'image_prefix: "output"\n'\ +'label: "COS_LIVE"\n'\ +'\n'\ +'squashfs_options:\n'\ +' compression: gzip\n'\ +'\n'\ +'luet:\n'\ +' repositories:\n'\ +' - name: "cos-toolkit-green"\n'\ +' type: "docker"\n'\ +' enable: true\n'\ +' urls:\n'\ +' - "quay.io/costoolkit/releases-green"\n' > /iso/iso.yaml +RUN luet install --no-spinner -y toolchain/luet-makeiso +WORKDIR /usr/src/cOS-toolkit/packer + +FROM tools AS iso-build +COPY --from=os / /iso/overlay +RUN cd /iso && \ + luet-makeiso iso.yaml + +FROM iso-build AS qcow-build +RUN packer build \ + -var "iso=/iso/output.iso" \ + -var "accelerator=tcg" \ + -only qemu.cos . +RUN mkdir /output && \ + mv *.box /output/output.box && \ + pigz -dc *.tar.gz | tar xvf - && \ + cat cOS | pigz -c > /output/output.qcow.gz + +FROM scratch AS qcow +COPY --from=qcow-build /output/ / + +FROM scratch AS iso +COPY --from=iso-build /iso/output.iso / + +FROM tools AS ami +ARG AWS_ACCESS_KEY_ID +ARG AWS_SECRET_ACCESS_KEY +ARG AWS_DEFAULT_REGION +ARG IMAGE=rancher/os:dev +ARG NAME=RancherOS-Image-dev +ARG VERSION=1 +ARG GIT_COMMIT=HEAD +RUN packer build \ + -var "cos_version=${VERSION}" \ + -var "git_sha=${GIT_COMMIT}" \ + -var 'aws_source_ami_filter_owners=["053594193760"]' \ + -var "aws_cos_deploy_args=cos-deploy --no-verify --docker-image ${IMAGE}" \ + -var "name=${NAME}" \ + -only amazon-ebs.cos . +EOF +} + + +iso() +{ + build --target iso -o build/ +} + +qcow() +{ + build --target qcow -o build/ +} + +ami() +{ + if [ -z "${AWS_ACCESS_KEY_ID}" ] || [ -z "${AWS_SECRET_ACCESS_KEY}" ] || [ -z "${AWS_DEFAULT_REGION}" ]; then + echo ERROR: The following environment variables must be set: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY AWS_DEFAULT_REGION + exit 1 + fi + + build --target ami \ + --build-arg AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \ + --build-arg AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \ + --build-arg AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \ + --build-arg NAME="${NAME}" \ + --build-arg GIT_COMMIT="${GIT_COMMIT}" \ + --build-arg VERSION="${VERSION}" +} + +usage() +{ + echo "Usage:" + echo " $0 IMAGE OUTPUT" + echo + echo " IMAGE: a Docker image" + echo " OUTPUT: Comma seperated value of output image formats. Valid: aws,iso,qcow" +} + +IMAGE=$1 +OUTPUT=$2 +VERSION=${IMAGE##*:} +NAME=${IMAGE%%:${VERSION}} +NAME=${NAME//[^a-zA-Z0-9-@.\/_]/-} + +if [ -z "${OUTPUT}" ] || [ -z "${IMAGE}" ] || echo "$@" | grep -q -- -h; then + usage + exit 1 +fi + +{ + IFS=, + for i in ${OUTPUT}; do + case $i in + ami) + ami + ;; + qcow) + qcow + ;; + iso) + iso + ;; + dockerfile) + dockerfile + exit 0 + ;; + *) + echo Unknown format $i + exit 1 + esac + done +} diff --git a/scripts/ci b/scripts/ci new file mode 100755 index 00000000..fe8a2df1 --- /dev/null +++ b/scripts/ci @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +cd $(dirname $0) + +./test +./validate +./package diff --git a/scripts/entry b/scripts/entry new file mode 100755 index 00000000..78fb5679 --- /dev/null +++ b/scripts/entry @@ -0,0 +1,11 @@ +#!/bin/bash +set -e + +mkdir -p bin dist +if [ -e ./scripts/$1 ]; then + ./scripts/"$@" +else + exec "$@" +fi + +chown -R $DAPPER_UID:$DAPPER_GID . diff --git a/scripts/package b/scripts/package new file mode 100755 index 00000000..9645b4d5 --- /dev/null +++ b/scripts/package @@ -0,0 +1,34 @@ +#!/bin/bash +set -e + +source $(dirname $0)/version + +cd $(dirname $0)/.. + +export TAG +make iso +TARGETS="iso" + +if [ -n "$DOCKER_PASSWORD" ]; then + docker login -u "$DOCKER_USERNAME" -p "${DOCKER_PASSWORD}" + PUSH=true +fi + +if [ "$PUSH" = "true" ]; then + make push +fi + + +TARGETS=qcow +if [ "$PUSH" = "true" ] && [ -n "$AWS_SECRET_ACCESS_KEY" ]; then + TARGETS="${TARGETS} all-amis" +fi + +export GIT_COMMIT=${COMMIT} +make -j8 ${TARGETS} + +mkdir -p dist +for i in build/output.*; do + mv -f $i dist/rancheros-${TAG}${i##build/output} + echo Built: dist/rancheros-${TAG}${i##build/output} +done diff --git a/scripts/run b/scripts/run new file mode 100755 index 00000000..f40122ba --- /dev/null +++ b/scripts/run @@ -0,0 +1,30 @@ +#!/bin/bash +set -e -x + +mkdir -p build +cd build + +if [ ! -e disk.img ]; then + qemu-img create -f qcow2 disk.img 40g +fi + +touch meta-data +touch user-data +rm -f seed.iso +genisoimage -output seed.iso -volid cidata -joliet -rock user-data meta-data + + #-bios /usr/share/qemu/OVMF.fd \ +qemu-system-x86_64 \ + -enable-kvm \ + -m ${MEMORY:=4096} \ + -machine accel=${ACCEL:="kvm"} \ + -smp cores=4 \ + -nographic \ + -serial mon:stdio \ + -rtc base=utc,clock=rt \ + -chardev socket,path=qga.sock,server,nowait,id=qga0 \ + -device virtio-serial \ + -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 \ + -drive if=virtio,media=disk,file=disk.img \ + -drive if=ide,media=cdrom,file=${1:-output.iso} \ + -drive if=ide,media=cdrom,file=seed.iso diff --git a/scripts/test b/scripts/test new file mode 100755 index 00000000..08662432 --- /dev/null +++ b/scripts/test @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +cd $(dirname $0)/.. + +echo Running tests +go test -cover -tags=test ./... diff --git a/scripts/validate b/scripts/validate new file mode 100755 index 00000000..7f98128b --- /dev/null +++ b/scripts/validate @@ -0,0 +1,21 @@ +#!/bin/bash +set -e + +cd $(dirname $0)/.. + +echo Running validation + +PACKAGES="$(go list ./...)" + +if ! command -v golangci-lint; then + echo Skipping validation: no golangci-lint available + exit +fi + +echo Running validation + +echo Running: golangci-lint +golangci-lint run + +echo Running: go fmt +test -z "$(go fmt ${PACKAGES} | tee /dev/stderr)" diff --git a/scripts/version b/scripts/version new file mode 100755 index 00000000..1646092e --- /dev/null +++ b/scripts/version @@ -0,0 +1,27 @@ +#!/bin/bash + +if [ -n "$(git status --porcelain --untracked-files=no)" ]; then + DIRTY="-dirty" +fi + +COMMIT=$(git rev-parse --short HEAD) +GIT_TAG=${DRONE_TAG:-$(git tag -l --contains HEAD | head -n 1)} + +if [[ -z "$DIRTY" && -n "$GIT_TAG" ]]; then + VERSION=$GIT_TAG +else + VERSION="${COMMIT}${DIRTY}" +fi + +if [ -z "$ARCH" ]; then + ARCH=$(go env GOHOSTARCH) +fi + +SUFFIX="-${ARCH}" + +TAG=${TAG:-${VERSION}${SUFFIX}} +REPO=${REPO:-rancher} + +if echo $TAG | grep -q dirty; then + TAG=dev +fi diff --git a/tools/iso/iso.yaml b/tools/iso/iso.yaml deleted file mode 100644 index 5d27b473..00000000 --- a/tools/iso/iso.yaml +++ /dev/null @@ -1,24 +0,0 @@ -packages: - uefi: - - live/systemd-boot - - live/boot - isoimage: - - live/syslinux - - live/boot - -initramfs: - kernel_file: "vmlinuz" - rootfs_file: "initrd" - -overlay: true -image_prefix: "distro" -image_date: true -label: "COS_LIVE" - -luet: - repositories: - - name: cOS - enable: true - urls: - - quay.io/costoolkit/releases-opensuse - type: docker diff --git a/tools/usr/bin/makeiso b/tools/usr/bin/makeiso deleted file mode 100755 index 52bba1b2..00000000 --- a/tools/usr/bin/makeiso +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -IMAGE=$1 - -if [ -z "$IMAGE" ]; then - echo "Image name is required as the first argument" - echo - echo Usage: $0 [DOCKER_IMAGE] - exit 1 -fi - -cd /iso - -luet-makeiso iso.yaml --image "$IMAGE" - -cp distro*iso /output.iso