Merge pull request #725 from Azure/aro-operator

ARO operator
This commit is contained in:
Jim Minter 2020-07-31 19:48:33 +01:00 коммит произвёл GitHub
Родитель b109acc26f a6c7f6cf3f
Коммит ebdf715096
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
616 изменённых файлов: 101858 добавлений и 1019 удалений

Просмотреть файл

@ -33,6 +33,10 @@ jobs:
displayName: ⚙️ Building ARO RP Golang binary
workingDirectory: ${{ variables.modulePath }}
condition: eq(variables['RP_MODE'], 'development')
- template: ./templates/template-push-images-to-acr.yml
parameters:
workingDirectory: ${{ variables.modulePath }}
rpImageACR: $(RP_IMAGE_ACR)
- template: ./templates/template-az-cli-set-context.yml
parameters:
workingDirectory: ${{ variables.modulePath }}

252
Gopkg.lock сгенерированный
Просмотреть файл

@ -48,7 +48,7 @@
version = "v42.3.0"
[[projects]]
digest = "1:4621d189edcc3acfc8f9e1b98513f24d9b318574df1406b28cde265d598e8c85"
digest = "1:837909599d3b4e95163a3f819453b7013c345bc7455cd13e5fe74108a38d6925"
name = "github.com/Azure/go-autorest"
packages = [
"autorest",
@ -63,8 +63,8 @@
"tracing",
]
pruneopts = "UT"
revision = "778ae565bde392f58e04c3c8ff07c2ac506d00c9"
version = "v14.1.1"
revision = "e7b391b759b050d6719cc6fd8bb87b6dc038bca6"
version = "v14.2.0"
[[projects]]
digest = "1:9f3b30d9f8e0d7040f729b82dcbc8f0dead820a133b3147ce355fc451f32d761"
@ -432,6 +432,14 @@
revision = "bf22ed9311622d93e213ba31e4ae7a5771e5d379"
version = "v4.6.0"
[[projects]]
digest = "1:bde2a1ce1de28312f165a88926c12f4acd19dc4d7da96a445dfa5a29eae07a93"
name = "github.com/fatih/color"
packages = ["."]
pruneopts = "UT"
revision = "daf2830f2741ebb735b21709a520c5f37d642d85"
version = "v1.9.0"
[[projects]]
digest = "1:2cd7915ab26ede7d95b8749e6b1f933f1c6d5398030684e6505940a10f31cfda"
name = "github.com/ghodss/yaml"
@ -451,6 +459,14 @@
revision = "ff7109080027ec152dabb369e157c4f359b76f31"
version = "v3.1.2"
[[projects]]
digest = "1:edd2fa4578eb086265db78a9201d15e76b298dfd0d5c379da83e9c61712cf6df"
name = "github.com/go-logr/logr"
packages = ["."]
pruneopts = "UT"
revision = "9fb12b3b21c5415d16ac18dc5cd42c1cfdd40c4e"
version = "v0.1.0"
[[projects]]
digest = "1:ed15647db08b6d63666bf9755d337725960c302bbfa5e23754b4b915a4797e42"
name = "github.com/go-openapi/jsonpointer"
@ -483,6 +499,14 @@
revision = "8a84ec635f1b280a7062edeab609f0667a053248"
version = "v0.19.6"
[[projects]]
digest = "1:eec9b9a9f07a9b0de09431545481e22c233181b1af40170d0bc1f50b83690738"
name = "github.com/gobuffalo/flect"
packages = ["."]
pruneopts = "UT"
revision = "7a04ff140e0fd2ea77adfd5b8bd2b0c80ab739a9"
version = "v0.2.1"
[[projects]]
digest = "1:582e25eccee928dc12416ea4c23b6dae8f3b5687730632aa1473ebebe80a2359"
name = "github.com/gogo/protobuf"
@ -632,6 +656,17 @@
pruneopts = "UT"
revision = "901d90724c7919163f472a9812253fb26761123d"
[[projects]]
digest = "1:e631368e174090a276fc00b48283f92ac4ccfbbb1945bcfcee083f5f9210dc00"
name = "github.com/hashicorp/golang-lru"
packages = [
".",
"simplelru",
]
pruneopts = "UT"
revision = "14eae340515388ca95aa8e7b86f0de668e981f54"
version = "v0.5.4"
[[projects]]
digest = "1:a1038ef593beb4771c8f0f9c26e8b00410acd800af5c6864651d9bf160ea1813"
name = "github.com/hpcloud/tail"
@ -654,6 +689,14 @@
revision = "1afb36080aec31e0d1528973ebe6721b191b0369"
version = "v0.3.8"
[[projects]]
digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be"
name = "github.com/inconshreveable/mousetrap"
packages = ["."]
pruneopts = "UT"
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
version = "v1.0"
[[projects]]
branch = "master"
digest = "1:11a561b078819a1cd5d9d9c52031e8476e9ee7622f2b3b054850940a7d167971"
@ -1165,6 +1208,14 @@
pruneopts = "UT"
revision = "da87dd6d947d66eb810d74622fb7664289148423"
[[projects]]
digest = "1:7a8874002044d748dd5ec9f4f1cb6053d8125e7a29ab9665ef64f7628f910141"
name = "github.com/operator-framework/operator-sdk"
packages = ["pkg/status"]
pruneopts = "UT"
revision = "8e28aca60994c5cb1aec0251b85f0116cc4c9427"
version = "v0.19.0"
[[projects]]
branch = "master"
digest = "1:78a8e7c73f3409bc2a9361e12ccfe0dee905f292e514400122299a5079348bea"
@ -1300,6 +1351,14 @@
revision = "839c75faf7f98a33d445d181f3018b5c3409a45e"
version = "v1.4.2"
[[projects]]
digest = "1:f6adcf4df6c030a53a14a8fdbb3fade7cac3d014ff78a4e0de500b4c0cf5154f"
name = "github.com/spf13/cobra"
packages = ["."]
pruneopts = "UT"
revision = "a684a6d7f5e37385d954dd3b5a14fc6912c6ab9d"
version = "v1.0.0"
[[projects]]
digest = "1:524b71991fc7d9246cc7dc2d9e0886ccb97648091c63e30eef619e6862c955dd"
name = "github.com/spf13/pflag"
@ -1543,7 +1602,7 @@
[[projects]]
branch = "master"
digest = "1:8bb1d2f050249349dbaeda1ce06e22d9f185acda87c0a5c5a4c43da45d46ed69"
digest = "1:5e0fb9e9d8578aed12222c1a7eb7e57f35f6eb305b7aab02eeabbe4d36c60442"
name = "golang.org/x/tools"
packages = [
"cmd/goimports",
@ -1554,6 +1613,7 @@
"go/internal/packagesdriver",
"go/packages",
"go/types/typeutil",
"imports",
"internal/fastwalk",
"internal/gopathwalk",
"internal/imports",
@ -1564,6 +1624,14 @@
pruneopts = "UT"
revision = "dbc83e6dc05ede08439f32f7024b36e4e9e5b406"
[[projects]]
digest = "1:a4e6161ffbea6b872a122961fff978f81af9c064f1757c559e21d2d322f13958"
name = "gomodules.xyz/jsonpatch"
packages = ["v2"]
pruneopts = "UT"
revision = "1c2a0262323edc27502942d9727c95646b1c3cbe"
version = "v2.1.0"
[[projects]]
digest = "1:f3661f6218166acf60f5d551b44a537f7ecb8686be02ece061c5950cbfc9ba17"
name = "google.golang.org/api"
@ -1707,11 +1775,20 @@
revision = "1f64d6156d11335c3f22d9330b0ad14fc1e789ce"
version = "v2.2.7"
[[projects]]
branch = "v3"
digest = "1:229cb0f6192914f518cc1241ede6d6f1f458b31debfa18bf3a5c9e4f7b01e24b"
name = "gopkg.in/yaml.v3"
packages = ["."]
pruneopts = "UT"
revision = "eeeca48fe7764f320e4870d231902bf9c1be2c08"
[[projects]]
branch = "origin-4.4-kubernetes-1.17.1"
digest = "1:cd7322a2669aba7fe506383dc31ece3881fc3e39ccac5334360c50f946a8ade4"
digest = "1:5cb5278f126e316f9e793b2ed967f113d3d5407694e7a789cbf6e2137579b504"
name = "k8s.io/api"
packages = [
"admission/v1beta1",
"admissionregistration/v1",
"admissionregistration/v1beta1",
"apps/v1",
@ -1757,17 +1834,36 @@
revision = "7643814f1c97f24ccfb38c2b85a7bb3c7f494346"
source = "https://github.com/openshift/kubernetes-api"
[[projects]]
branch = "release-1.17"
digest = "1:f0b431fe72d7510dfe7f3f177317391621ddb500843f5661dab7520d22735a66"
name = "k8s.io/apiextensions-apiserver"
packages = [
"pkg/apis/apiextensions",
"pkg/apis/apiextensions/v1",
"pkg/apis/apiextensions/v1beta1",
"pkg/client/clientset/clientset",
"pkg/client/clientset/clientset/scheme",
"pkg/client/clientset/clientset/typed/apiextensions/v1",
"pkg/client/clientset/clientset/typed/apiextensions/v1beta1",
]
pruneopts = "UT"
revision = "88d23e1d281b9aa0cb534c4cdf3ed01af4b180b9"
[[projects]]
branch = "origin-4.4-kubernetes-1.17.1"
digest = "1:fac15195ebd43a8833c5cabfcfe87a6497fa12cf04df21b3a797bfcb933a4181"
digest = "1:ecc89c50eb2d0860f5b7a63d5f2672d82c0df9b2b213fbfd1239c11f889cd446"
name = "k8s.io/apimachinery"
packages = [
"pkg/api/equality",
"pkg/api/errors",
"pkg/api/meta",
"pkg/api/resource",
"pkg/apis/meta/internalversion",
"pkg/apis/meta/v1",
"pkg/apis/meta/v1/unstructured",
"pkg/apis/meta/v1/validation",
"pkg/apis/meta/v1beta1",
"pkg/conversion",
"pkg/conversion/queryparams",
"pkg/fields",
@ -1782,7 +1878,9 @@
"pkg/runtime/serializer/versioning",
"pkg/selection",
"pkg/types",
"pkg/util/cache",
"pkg/util/clock",
"pkg/util/diff",
"pkg/util/errors",
"pkg/util/framer",
"pkg/util/httpstream",
@ -1796,6 +1894,7 @@
"pkg/util/runtime",
"pkg/util/sets",
"pkg/util/strategicpatch",
"pkg/util/uuid",
"pkg/util/validation",
"pkg/util/validation/field",
"pkg/util/wait",
@ -1812,13 +1911,14 @@
[[projects]]
branch = "origin-4.4-kubernetes-1.17.1"
digest = "1:f51508c5ebfc8da2cb944a2aeb3c6a9f321a6b76c9cafd5c3464bbca1f4004e2"
digest = "1:72e2d2937f1e2315cfdb5887de8976d53038fab35d23116c44958464807a294c"
name = "k8s.io/client-go"
packages = [
"discovery",
"discovery/cached/disk",
"discovery/fake",
"dynamic",
"dynamic/fake",
"kubernetes",
"kubernetes/fake",
"kubernetes/scheme",
@ -1909,13 +2009,20 @@
"plugin/pkg/client/auth/exec",
"rest",
"rest/watch",
"restmapper",
"testing",
"tools/auth",
"tools/cache",
"tools/clientcmd",
"tools/clientcmd/api",
"tools/clientcmd/api/latest",
"tools/clientcmd/api/v1",
"tools/leaderelection",
"tools/leaderelection/resourcelock",
"tools/metrics",
"tools/pager",
"tools/record",
"tools/record/util",
"tools/reference",
"transport",
"util/cert",
@ -1930,6 +2037,42 @@
revision = "bb38286aebfbd8b39c317114442ed28d37c7617e"
source = "https://github.com/openshift/kubernetes-client-go"
[[projects]]
digest = "1:349858f235d044e8de69128b54440553ffe3be06dd8b1343d60f18484b7201f5"
name = "k8s.io/code-generator"
packages = [
"cmd/client-gen",
"cmd/client-gen/args",
"cmd/client-gen/generators",
"cmd/client-gen/generators/fake",
"cmd/client-gen/generators/scheme",
"cmd/client-gen/generators/util",
"cmd/client-gen/path",
"cmd/client-gen/types",
"cmd/deepcopy-gen",
"cmd/deepcopy-gen/args",
"pkg/namer",
"pkg/util",
]
pruneopts = "UT"
revision = "e95606b614f049ef6087115cb340d8d5805b8da7"
version = "kubernetes-1.17.1"
[[projects]]
digest = "1:28514fabca4356625720ffb012408790a9d00d31963a9bd9daf7b5ccd894c301"
name = "k8s.io/gengo"
packages = [
"args",
"examples/deepcopy-gen/generators",
"examples/set-gen/sets",
"generator",
"namer",
"parser",
"types",
]
pruneopts = "UT"
revision = "f8a0810f38afb8478882b3835a615aebfda39afa"
[[projects]]
digest = "1:93e82f25d75aba18436ad1ac042cb49493f096011f2541075721ed6f9e05c044"
name = "k8s.io/klog"
@ -1950,11 +2093,13 @@
revision = "30be4d16710ac61bce31eb28a01054596fe6a9f1"
[[projects]]
digest = "1:01dbe4c86aa758aaa7502784c7e81642f3f0995c0fd6a094a8daaf5cb962ac73"
digest = "1:bb09c1841fd8100fe09b784fa13563ebffd9921d18012e72c8727ce9d4ea0144"
name = "k8s.io/utils"
packages = [
"buffer",
"integer",
"pointer",
"trace",
]
pruneopts = "UT"
revision = "581e00157fb1a0435d4fac54a52d1ca1e481d60e"
@ -1997,12 +2142,71 @@
source = "https://github.com/openshift/cluster-api-provider-openstack.git"
[[projects]]
branch = "release-0.2"
digest = "1:c4e8f6509ee8cec911985a812ed3f9cc024404acc45ac613fa103f735cf3222a"
branch = "release-0.5"
digest = "1:adf6def2bee7c9fa8a026e8193770e6665258666ad2e0d63438701248c7fbf30"
name = "sigs.k8s.io/controller-runtime"
packages = ["pkg/scheme"]
packages = [
".",
"pkg/builder",
"pkg/cache",
"pkg/cache/internal",
"pkg/client",
"pkg/client/apiutil",
"pkg/client/config",
"pkg/controller",
"pkg/controller/controllerutil",
"pkg/conversion",
"pkg/event",
"pkg/handler",
"pkg/healthz",
"pkg/internal/controller",
"pkg/internal/controller/metrics",
"pkg/internal/log",
"pkg/internal/recorder",
"pkg/leaderelection",
"pkg/log",
"pkg/manager",
"pkg/manager/signals",
"pkg/metrics",
"pkg/predicate",
"pkg/ratelimiter",
"pkg/reconcile",
"pkg/recorder",
"pkg/runtime/inject",
"pkg/scheme",
"pkg/source",
"pkg/source/internal",
"pkg/webhook",
"pkg/webhook/admission",
"pkg/webhook/conversion",
"pkg/webhook/internal/certwatcher",
"pkg/webhook/internal/metrics",
]
pruneopts = "UT"
revision = "fc5542c693e3340f8abbe91c6345bd64c494a60c"
revision = "fef04902823b5a3bed3ba29518e50cbf6560594d"
[[projects]]
digest = "1:a2ae73d1f36d28a2936c672c0976782c506562ee21a07fb8f589136c5cef3fd2"
name = "sigs.k8s.io/controller-tools"
packages = [
"cmd/controller-gen",
"pkg/crd",
"pkg/crd/markers",
"pkg/deepcopy",
"pkg/genall",
"pkg/genall/help",
"pkg/genall/help/pretty",
"pkg/loader",
"pkg/markers",
"pkg/rbac",
"pkg/schemapatcher",
"pkg/schemapatcher/internal/yaml",
"pkg/version",
"pkg/webhook",
]
pruneopts = "UT"
revision = "93a4eed983cf9670deabcf3cfa837a4b69988c6e"
version = "v0.2.9"
[[projects]]
digest = "1:7719608fe0b52a4ece56c2dde37bedd95b938677d1ab0f84b8a7852e4c59f849"
@ -2053,6 +2257,7 @@
"github.com/dgrijalva/jwt-go",
"github.com/ghodss/yaml",
"github.com/go-bindata/go-bindata/go-bindata",
"github.com/go-logr/logr",
"github.com/golang/mock/gomock",
"github.com/golang/mock/mockgen",
"github.com/google/go-cmp/cmp",
@ -2111,6 +2316,7 @@
"github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1",
"github.com/openshift/machine-config-operator/pkg/generated/clientset/versioned",
"github.com/openshift/machine-config-operator/pkg/generated/clientset/versioned/fake",
"github.com/operator-framework/operator-sdk/pkg/status",
"github.com/pkg/errors",
"github.com/prometheus/common/model",
"github.com/satori/go.uuid",
@ -2124,33 +2330,55 @@
"golang.org/x/tools/cmd/goimports",
"golang.org/x/tools/go/ast/astutil",
"golang.org/x/tools/go/packages",
"gopkg.in/yaml.v2",
"k8s.io/api/apps/v1",
"k8s.io/api/core/v1",
"k8s.io/api/rbac/v1",
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1",
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset",
"k8s.io/apimachinery/pkg/api/errors",
"k8s.io/apimachinery/pkg/api/meta",
"k8s.io/apimachinery/pkg/api/resource",
"k8s.io/apimachinery/pkg/apis/meta/v1",
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
"k8s.io/apimachinery/pkg/labels",
"k8s.io/apimachinery/pkg/runtime",
"k8s.io/apimachinery/pkg/runtime/schema",
"k8s.io/apimachinery/pkg/runtime/serializer",
"k8s.io/apimachinery/pkg/types",
"k8s.io/apimachinery/pkg/util/httpstream",
"k8s.io/apimachinery/pkg/util/httpstream/spdy",
"k8s.io/apimachinery/pkg/util/runtime",
"k8s.io/apimachinery/pkg/util/wait",
"k8s.io/apimachinery/pkg/version",
"k8s.io/apimachinery/pkg/watch",
"k8s.io/client-go/discovery",
"k8s.io/client-go/discovery/cached/disk",
"k8s.io/client-go/discovery/fake",
"k8s.io/client-go/dynamic",
"k8s.io/client-go/dynamic/fake",
"k8s.io/client-go/kubernetes",
"k8s.io/client-go/kubernetes/fake",
"k8s.io/client-go/kubernetes/scheme",
"k8s.io/client-go/kubernetes/typed/apps/v1",
"k8s.io/client-go/kubernetes/typed/core/v1",
"k8s.io/client-go/rest",
"k8s.io/client-go/testing",
"k8s.io/client-go/tools/clientcmd",
"k8s.io/client-go/tools/clientcmd/api/v1",
"k8s.io/client-go/tools/metrics",
"k8s.io/client-go/util/flowcontrol",
"k8s.io/client-go/util/retry",
"k8s.io/code-generator/cmd/client-gen",
"k8s.io/code-generator/cmd/deepcopy-gen",
"k8s.io/gengo/generator",
"sigs.k8s.io/controller-runtime",
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil",
"sigs.k8s.io/controller-runtime/pkg/event",
"sigs.k8s.io/controller-runtime/pkg/predicate",
"sigs.k8s.io/controller-runtime/pkg/reconcile",
"sigs.k8s.io/controller-runtime/pkg/scheme",
"sigs.k8s.io/controller-tools/cmd/controller-gen",
]
solver-name = "gps-cdcl"
solver-version = 1

Просмотреть файл

@ -6,8 +6,12 @@ required = [
"golang.org/x/tools/cmd/goimports",
"github.com/jstemmer/go-junit-report",
"github.com/axw/gocov/gocov",
"github.com/AlekSi/gocov-xml",
"github.com/metal3-io/baremetal-operator/pkg/apis/metal3/v1alpha1"
"github.com/metal3-io/baremetal-operator/pkg/apis/metal3/v1alpha1",
"github.com/AlekSi/gocov-xml",
"k8s.io/code-generator/cmd/client-gen",
"k8s.io/code-generator/cmd/deepcopy-gen",
"k8s.io/gengo/generator",
"sigs.k8s.io/controller-tools/cmd/controller-gen",
]
[[constraint]]
@ -18,6 +22,26 @@ required = [
name = "github.com/Azure/azure-sdk-for-go"
version = "42.1.0"
[[override]]
name = "k8s.io/code-generator"
version = "kubernetes-1.17.1"
[[override]]
name = "sigs.k8s.io/controller-tools"
version = "v0.2.5"
[[override]]
name = "sigs.k8s.io/controller-runtime"
branch = "release-0.5"
[[override]]
name = "k8s.io/apiextensions-apiserver"
branch = "release-1.17"
[[constraint]]
name = "k8s.io/gengo"
revision = "f8a0810f38afb8478882b3835a615aebfda39afa"
[[override]]
name = "github.com/containers/image"
version = "v2.0.1"

Просмотреть файл

@ -1,5 +1,7 @@
SHELL = /bin/bash
COMMIT = $(shell git rev-parse --short HEAD)$(shell [[ $$(git status --porcelain) = "" ]] || echo -dirty)
BRANCH = $(shell git rev-parse --abbrev-ref HEAD)
ARO_IMAGE ?= ${RP_IMAGE_ACR}.azurecr.io/aro:$(COMMIT)
aro: generate
go build -ldflags "-X github.com/Azure/ARO-RP/pkg/util/version.GitCommit=$(COMMIT)" ./cmd/aro
@ -54,7 +56,7 @@ generate:
image-aro: aro e2e.test
docker pull registry.access.redhat.com/ubi8/ubi-minimal
docker build -f Dockerfile.aro -t ${RP_IMAGE_ACR}.azurecr.io/aro:$(COMMIT) .
docker build -f Dockerfile.aro -t $(ARO_IMAGE) .
image-fluentbit:
docker build --build-arg VERSION=1.3.9-1 \
@ -72,7 +74,11 @@ image-routefix:
docker build -f Dockerfile.routefix -t ${RP_IMAGE_ACR}.azurecr.io/routefix:$(COMMIT) .
publish-image-aro: image-aro
docker push ${RP_IMAGE_ACR}.azurecr.io/aro:$(COMMIT)
docker push $(ARO_IMAGE)
ifeq ("${RP_IMAGE_ACR}-$(BRANCH)","arointsvc-master")
docker tag $(ARO_IMAGE) arointsvc.azurecr.io/aro:latest
docker push arointsvc.azurecr.io/aro:latest
endif
publish-image-fluentbit: image-fluentbit
docker push ${RP_IMAGE_ACR}.azurecr.io/fluentbit:1.3.9-1

Просмотреть файл

@ -31,7 +31,7 @@
"component": {
"type": "git",
"git": {
"commitHash": "778ae565bde392f58e04c3c8ff07c2ac506d00c9",
"commitHash": "e7b391b759b050d6719cc6fd8bb87b6dc038bca6",
"repositoryUrl": "https://github.com/Azure/go-autorest/"
}
}
@ -306,6 +306,15 @@
}
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "daf2830f2741ebb735b21709a520c5f37d642d85",
"repositoryUrl": "https://github.com/fatih/color/"
}
}
},
{
"component": {
"type": "git",
@ -324,6 +333,15 @@
}
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "9fb12b3b21c5415d16ac18dc5cd42c1cfdd40c4e",
"repositoryUrl": "https://github.com/go-logr/logr/"
}
}
},
{
"component": {
"type": "git",
@ -360,6 +378,15 @@
}
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "7a04ff140e0fd2ea77adfd5b8bd2b0c80ab739a9",
"repositoryUrl": "https://github.com/gobuffalo/flect/"
}
}
},
{
"component": {
"type": "git",
@ -477,6 +504,15 @@
}
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "14eae340515388ca95aa8e7b86f0de668e981f54",
"repositoryUrl": "https://github.com/hashicorp/golang-lru/"
}
}
},
{
"component": {
"type": "git",
@ -495,6 +531,15 @@
}
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75",
"repositoryUrl": "https://github.com/inconshreveable/mousetrap/"
}
}
},
{
"component": {
"type": "git",
@ -828,6 +873,15 @@
}
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "8e28aca60994c5cb1aec0251b85f0116cc4c9427",
"repositoryUrl": "https://github.com/operator-framework/operator-sdk/"
}
}
},
{
"component": {
"type": "git",
@ -963,6 +1017,15 @@
}
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "a684a6d7f5e37385d954dd3b5a14fc6912c6ab9d",
"repositoryUrl": "https://github.com/spf13/cobra/"
}
}
},
{
"component": {
"type": "git",
@ -1107,6 +1170,15 @@
}
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "1c2a0262323edc27502942d9727c95646b1c3cbe",
"repositoryUrl": "https://gomodules.xyz/jsonpatch/"
}
}
},
{
"component": {
"type": "git",
@ -1197,6 +1269,15 @@
}
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "eeeca48fe7764f320e4870d231902bf9c1be2c08",
"repositoryUrl": "https://gopkg.in/yaml.v3/"
}
}
},
{
"component": {
"type": "git",
@ -1206,6 +1287,15 @@
}
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "88d23e1d281b9aa0cb534c4cdf3ed01af4b180b9",
"repositoryUrl": "https://github.com/kubernetes/apiextensions-apiserver/"
}
}
},
{
"component": {
"type": "git",
@ -1224,6 +1314,24 @@
}
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "e95606b614f049ef6087115cb340d8d5805b8da7",
"repositoryUrl": "https://github.com/kubernetes/code-generator/"
}
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "f8a0810f38afb8478882b3835a615aebfda39afa",
"repositoryUrl": "https://github.com/kubernetes/gengo/"
}
}
},
{
"component": {
"type": "git",
@ -1282,11 +1390,20 @@
"component": {
"type": "git",
"git": {
"commitHash": "fc5542c693e3340f8abbe91c6345bd64c494a60c",
"commitHash": "fef04902823b5a3bed3ba29518e50cbf6560594d",
"repositoryUrl": "https://sigs.k8s.io/controller-runtime/"
}
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "93a4eed983cf9670deabcf3cfa837a4b69988c6e",
"repositoryUrl": "https://sigs.k8s.io/controller-tools/"
}
}
},
{
"component": {
"type": "git",

Просмотреть файл

@ -13,6 +13,7 @@ import (
"time"
utillog "github.com/Azure/ARO-RP/pkg/util/log"
_ "github.com/Azure/ARO-RP/pkg/util/scheme"
"github.com/Azure/ARO-RP/pkg/util/version"
)
@ -22,6 +23,7 @@ func usage() {
fmt.Fprintf(flag.CommandLine.Output(), " %s mirror\n", os.Args[0])
fmt.Fprintf(flag.CommandLine.Output(), " %s monitor\n", os.Args[0])
fmt.Fprintf(flag.CommandLine.Output(), " %s rp\n", os.Args[0])
fmt.Fprintf(flag.CommandLine.Output(), " %s operator {master,worker}\n", os.Args[0])
flag.PrintDefaults()
}
@ -50,6 +52,9 @@ func main() {
case "deploy":
checkArgs(3)
err = deploy(ctx, log)
case "operator":
checkArgs(2)
err = operator(ctx, log)
default:
usage()
os.Exit(2)

89
cmd/aro/operator.go Normal file
Просмотреть файл

@ -0,0 +1,89 @@
package main
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"context"
"flag"
"fmt"
securityclient "github.com/openshift/client-go/security/clientset/versioned"
"github.com/sirupsen/logrus"
"k8s.io/client-go/kubernetes"
ctrl "sigs.k8s.io/controller-runtime"
pkgoperator "github.com/Azure/ARO-RP/pkg/operator"
aroclient "github.com/Azure/ARO-RP/pkg/operator/clientset/versioned/typed/aro.openshift.io/v1alpha1"
"github.com/Azure/ARO-RP/pkg/operator/controllers"
utillog "github.com/Azure/ARO-RP/pkg/util/log"
// +kubebuilder:scaffold:imports
)
func operator(ctx context.Context, log *logrus.Entry) error {
role := flag.Arg(1)
switch role {
case pkgoperator.RoleMaster, pkgoperator.RoleWorker:
default:
return fmt.Errorf("invalid role %s", role)
}
ctrl.SetLogger(utillog.LogrWrapper(log))
restConfig, err := ctrl.GetConfig()
if err != nil {
return err
}
mgr, err := ctrl.NewManager(restConfig, ctrl.Options{
MetricsBindAddress: "0", // disabled
Port: 8443,
})
if err != nil {
return err
}
kubernetescli, err := kubernetes.NewForConfig(restConfig)
if err != nil {
return err
}
securitycli, err := securityclient.NewForConfig(restConfig)
if err != nil {
return err
}
arocli, err := aroclient.NewForConfig(restConfig)
if err != nil {
return err
}
if role == pkgoperator.RoleMaster {
if err = (controllers.NewGenevaloggingReconciler(
log.WithField("controller", controllers.GenevaLoggingControllerName),
kubernetescli, securitycli, arocli,
restConfig)).SetupWithManager(mgr); err != nil {
return fmt.Errorf("unable to create controller Genevalogging: %v", err)
}
if err = (controllers.NewPullSecretReconciler(
log.WithField("controller", controllers.PullSecretControllerName),
kubernetescli, arocli)).SetupWithManager(mgr); err != nil {
return fmt.Errorf("unable to create controller PullSecret: %v", err)
}
if err = (controllers.NewAlertWebhookReconciler(
log.WithField("controller", controllers.AlertwebhookControllerName),
kubernetescli)).SetupWithManager(mgr); err != nil {
return fmt.Errorf("unable to create controller AlertWebhook: %v", err)
}
}
if err = (controllers.NewInternetChecker(
log.WithField("controller", controllers.InternetCheckerControllerName),
kubernetescli, arocli,
role,
)).SetupWithManager(mgr); err != nil {
return fmt.Errorf("unable to create controller InternetChecker: %v", err)
}
// +kubebuilder:scaffold:builder
log.Info("starting manager")
return mgr.Start(ctrl.SetupSignalHandler())
}

Просмотреть файл

@ -1,3 +1,4 @@
export LOCATION=eastus
export ARO_IMAGE=arointsvc.azurecr.io/aro:latest
. secrets/env

Просмотреть файл

@ -42,8 +42,8 @@ deploy_env_dev() {
"proxyCert=$(base64 -w0 <secrets/proxy.crt)" \
"proxyClientCert=$(base64 -w0 <secrets/proxy-client.crt)" \
"proxyDomainNameLabel=$(cut -d. -f2 <<<$PROXY_HOSTNAME)" \
"proxyImage=arosvc.azurecr.io/proxy:latest" \
"proxyImageAuth=$(jq -r '.auths["arosvc.azurecr.io"].auth' <<<$PULL_SECRET)" \
"proxyImage=arointsvc.azurecr.io/proxy:latest" \
"proxyImageAuth=$(jq -r '.auths["arointsvc.azurecr.io"].auth' <<<$PULL_SECRET)" \
"proxyKey=$(base64 -w0 <secrets/proxy.key)" \
"sshPublicKey=$(<secrets/proxy_id_rsa.pub)" \
"vpnCACertificate=$(base64 -w0 <secrets/vpn-ca.crt)" >/dev/null
@ -59,8 +59,8 @@ deploy_env_dev_override() {
"proxyCert=$(base64 -w0 <secrets/proxy.crt)" \
"proxyClientCert=$(base64 -w0 <secrets/proxy-client.crt)" \
"proxyDomainNameLabel=$(cut -d. -f2 <<<$PROXY_HOSTNAME)" \
"proxyImage=arosvc.azurecr.io/proxy:latest" \
"proxyImageAuth=$(jq -r '.auths["arosvc.azurecr.io"].auth' <<<$PULL_SECRET)" \
"proxyImage=arointsvc.azurecr.io/proxy:latest" \
"proxyImageAuth=$(jq -r '.auths["arointsvc.azurecr.io"].auth' <<<$PULL_SECRET)" \
"proxyKey=$(base64 -w0 <secrets/proxy.key)" \
"sshPublicKey=$(<secrets/proxy_id_rsa.pub)" \
"vpnCACertificate=$(base64 -w0 <secrets/vpn-ca.crt)" \

Просмотреть файл

@ -0,0 +1,2 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.

Просмотреть файл

@ -11,7 +11,6 @@ import (
"encoding/base64"
"fmt"
"math/big"
"os"
"regexp"
"strings"
"time"
@ -126,14 +125,7 @@ func (m *Manager) Create(ctx context.Context) error {
return err
}
pullSecret := os.Getenv("PULL_SECRET")
pullSecret, err = pullsecret.Merge(pullSecret, string(m.doc.OpenShiftCluster.Properties.ClusterProfile.PullSecret))
if err != nil {
return err
}
pullSecret, _, err = pullsecret.SetRegistryProfiles(pullSecret, m.doc.OpenShiftCluster.Properties.RegistryProfiles...)
pullSecret, err := pullsecret.Build(m.doc.OpenShiftCluster, string(m.doc.OpenShiftCluster.Properties.ClusterProfile.PullSecret))
if err != nil {
return err
}
@ -150,7 +142,7 @@ func (m *Manager) Create(ctx context.Context) error {
return err
}
vnetID, masterSubnetName, err := subnet.Split(m.doc.OpenShiftCluster.Properties.MasterProfile.SubnetID)
_, masterSubnetName, err := subnet.Split(m.doc.OpenShiftCluster.Properties.MasterProfile.SubnetID)
if err != nil {
return err
}

Просмотреть файл

@ -0,0 +1,43 @@
package dynamichelper
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
// rather than list every GK, just list the ones whose creation really has to be
// brought forward
var createOrder = map[string]int{
// non-namespaced resources
"CustomResourceDefinition.apiextensions.k8s.io": 1, // before custom resources
"ClusterRole.rbac.authorization.k8s.io": 2, // before workload resources
"ClusterRoleBinding.rbac.authorization.k8s.io": 3, // before workload resources
"SecurityContextConstraints.security.openshift.io": 4, // before workload resources
"Namespace": 10, // before namespaced resources
// namespaced resources
"ConfigMap": 11, // before workload resources
"Secret": 12, // before workload resources
"ServiceAccount": 13, // before workload resources
}
const createOrderMax = 99
// CreateOrder is to be used in a sort.Slice() comparison. It is to help make
// sure that resources are created in an order that causes a reliable startup.
func CreateOrder(i, j *unstructured.Unstructured) bool {
io, ok := createOrder[i.GroupVersionKind().GroupKind().String()]
if !ok {
io = createOrderMax
}
jo, ok := createOrder[j.GroupVersionKind().GroupKind().String()]
if !ok {
jo = createOrderMax
}
return io < jo
}

Просмотреть файл

@ -0,0 +1,38 @@
package dynamichelper
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"reflect"
"sort"
"testing"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
func TestCreateOrder(t *testing.T) {
test := []*unstructured.Unstructured{
{Object: map[string]interface{}{"apiVersion": "v1", "kind": "ServiceAccount"}},
{Object: map[string]interface{}{"apiVersion": "apps/v1", "kind": "Deployment"}},
{Object: map[string]interface{}{"apiVersion": "v1", "kind": "Namespace"}},
{Object: map[string]interface{}{"apiVersion": "security.openshift.io/v1", "kind": "SecurityContextConstraints"}},
{Object: map[string]interface{}{"apiVersion": "v1", "kind": "ConfigMap"}},
}
expect := []*unstructured.Unstructured{
{Object: map[string]interface{}{"apiVersion": "security.openshift.io/v1", "kind": "SecurityContextConstraints"}},
{Object: map[string]interface{}{"apiVersion": "v1", "kind": "Namespace"}},
{Object: map[string]interface{}{"apiVersion": "v1", "kind": "ConfigMap"}},
{Object: map[string]interface{}{"apiVersion": "v1", "kind": "ServiceAccount"}},
{Object: map[string]interface{}{"apiVersion": "apps/v1", "kind": "Deployment"}},
}
sort.Slice(test, func(i, j int) bool {
return CreateOrder(test[i], test[j])
})
if !reflect.DeepEqual(expect, test) {
t.Error(test)
}
}

Просмотреть файл

Просмотреть файл

@ -0,0 +1,7 @@
package discovery
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
//go:generate go run ../../../vendor/github.com/go-bindata/go-bindata/go-bindata -nometadata -pkg $GOPACKAGE -ignore=generate.go -ignore=bindata.go -prefix ./cache ./cache/...
//go:generate gofmt -s -l -w ../../../pkg/dynamichelper/discovery/bindata.go

Просмотреть файл

@ -0,0 +1,264 @@
package dynamichelper
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"net/http"
"reflect"
"strings"
"github.com/sirupsen/logrus"
"github.com/ugorji/go/codec"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/discovery"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest"
"k8s.io/client-go/util/retry"
"github.com/Azure/ARO-RP/pkg/api"
kadiscovery "github.com/Azure/ARO-RP/pkg/dynamichelper/discovery"
"github.com/Azure/ARO-RP/pkg/util/cmp"
)
type DynamicHelper interface {
RefreshAPIResources() error
CreateOrUpdate(obj *unstructured.Unstructured) error
Delete(groupKind, namespace, name string) error
Ensure(o *unstructured.Unstructured) error
Get(groupKind, namespace, name string) (*unstructured.Unstructured, error)
List(groupKind, namespace string) (*unstructured.UnstructuredList, error)
}
type dynamicHelper struct {
log *logrus.Entry
restconfig *rest.Config
dyn dynamic.Interface
apiresources []*metav1.APIResourceList
}
func New(log *logrus.Entry, restconfig *rest.Config) (DynamicHelper, error) {
dh := &dynamicHelper{
log: log,
restconfig: restconfig,
}
var err error
dh.dyn, err = dynamic.NewForConfig(dh.restconfig)
if err != nil {
return nil, err
}
err = dh.RefreshAPIResources()
if err != nil {
return nil, err
}
return dh, nil
}
func (dh *dynamicHelper) RefreshAPIResources() error {
var cli discovery.DiscoveryInterface
cli, err := discovery.NewDiscoveryClientForConfig(dh.restconfig)
if err != nil {
return err
}
cli = kadiscovery.NewCacheFallbackDiscoveryClient(dh.log, cli)
_, dh.apiresources, err = cli.ServerGroupsAndResources()
return err
}
func (dh *dynamicHelper) findGVR(groupKind, optionalVersion string) (*schema.GroupVersionResource, error) {
var matches []*schema.GroupVersionResource
for _, apiresources := range dh.apiresources {
gv, err := schema.ParseGroupVersion(apiresources.GroupVersion)
if err != nil {
// this returns a fmt.Errorf which will result in a 500
// in this case, this seems correct as the GV in kubernetes is wrong
return nil, err
}
if optionalVersion != "" && gv.Version != optionalVersion {
continue
}
for _, apiresource := range apiresources.APIResources {
if strings.ContainsRune(apiresource.Name, '/') { // no subresources
continue
}
gk := schema.GroupKind{
Group: gv.Group,
Kind: apiresource.Kind,
}
if strings.EqualFold(gk.String(), groupKind) {
return &schema.GroupVersionResource{
Group: gv.Group,
Version: gv.Version,
Resource: apiresource.Name,
}, nil
}
if strings.EqualFold(apiresource.Kind, groupKind) {
matches = append(matches, &schema.GroupVersionResource{
Group: gv.Group,
Version: gv.Version,
Resource: apiresource.Name,
})
}
}
}
if len(matches) == 0 {
return nil, api.NewCloudError(
http.StatusBadRequest, api.CloudErrorCodeNotFound,
"", "The groupKind '%s' was not found.", groupKind)
}
if len(matches) > 1 {
var matchesGK []string
for _, match := range matches {
matchesGK = append(matchesGK, groupKind+"."+match.Group)
}
return nil, api.NewCloudError(
http.StatusBadRequest, api.CloudErrorCodeInvalidParameter,
"", "The groupKind '%s' matched multiple groupKinds (%s).", groupKind, strings.Join(matchesGK, ", "))
}
return matches[0], nil
}
// CreateOrUpdate does nothing more than an Update call (and a Create if that
// call returned 404). We don't add any fancy behaviour because this is called
// from the Geneva Admin context and we don't want to get in the SRE's way.
func (dh *dynamicHelper) CreateOrUpdate(o *unstructured.Unstructured) error {
gvr, err := dh.findGVR(o.GroupVersionKind().GroupKind().String(), o.GroupVersionKind().Version)
if err != nil {
return err
}
_, err = dh.dyn.Resource(*gvr).Namespace(o.GetNamespace()).Update(o, metav1.UpdateOptions{})
if !errors.IsNotFound(err) {
return err
}
_, err = dh.dyn.Resource(*gvr).Namespace(o.GetNamespace()).Create(o, metav1.CreateOptions{})
return err
}
func (dh *dynamicHelper) Delete(groupKind, namespace, name string) error {
gvr, err := dh.findGVR(groupKind, "")
if err != nil {
return err
}
return dh.dyn.Resource(*gvr).Namespace(namespace).Delete(name, &metav1.DeleteOptions{})
}
// Ensure is called by the operator deploy tool and individual controllers. It
// is intended to ensure that an object matches a desired state. It is tolerant
// of unspecified fields in the desired state (e.g. it will leave typically
// leave .status untouched).
func (dh *dynamicHelper) Ensure(o *unstructured.Unstructured) error {
gvr, err := dh.findGVR(o.GroupVersionKind().GroupKind().String(), o.GroupVersionKind().Version)
if err != nil {
return err
}
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
existing, err := dh.dyn.Resource(*gvr).Namespace(o.GetNamespace()).Get(o.GetName(), metav1.GetOptions{})
if errors.IsNotFound(err) {
dh.log.Printf("Create %s", keyFuncO(o))
_, err = dh.dyn.Resource(*gvr).Namespace(o.GetNamespace()).Create(o, metav1.CreateOptions{})
return err
}
if err != nil {
return err
}
o, changed, diff, err := merge(existing, o)
if err != nil || !changed {
return err
}
dh.log.Printf("Update %s: %s", keyFuncO(o), diff)
_, err = dh.dyn.Resource(*gvr).Namespace(o.GetNamespace()).Update(o, metav1.UpdateOptions{})
return err
})
}
func (dh *dynamicHelper) Get(groupKind, namespace, name string) (*unstructured.Unstructured, error) {
gvr, err := dh.findGVR(groupKind, "")
if err != nil {
return nil, err
}
return dh.dyn.Resource(*gvr).Namespace(namespace).Get(name, metav1.GetOptions{})
}
func (dh *dynamicHelper) List(groupKind, namespace string) (*unstructured.UnstructuredList, error) {
gvr, err := dh.findGVR(groupKind, "")
if err != nil {
return nil, err
}
return dh.dyn.Resource(*gvr).Namespace(namespace).List(metav1.ListOptions{})
}
func diff(existing, o *unstructured.Unstructured) string {
if o.GroupVersionKind().GroupKind().String() == "Secret" { // Don't show a diff if kind is Secret
return ""
}
return cmp.Diff(existing.Object, o.Object)
}
// merge merges delta onto base using ugorji/go/codec semantics. It returns the
// newly merged object (the inputs are untouched) plus a flag indicating if a
// change took place and a printable diff as appropriate
func merge(base, delta *unstructured.Unstructured) (*unstructured.Unstructured, bool, string, error) {
copy := base.DeepCopy()
h := &codec.JsonHandle{}
var b []byte
err := codec.NewEncoderBytes(&b, h).Encode(delta.Object)
if err != nil {
return nil, false, "", err
}
err = codec.NewDecoderBytes(b, h).Decode(&copy.Object)
if err != nil {
return nil, false, "", err
}
// all new objects have a null creationTimestamp that causes every object to
// be updated.
copy.SetCreationTimestamp(base.GetCreationTimestamp())
status, found, err := unstructured.NestedMap(base.Object, "status")
if err == nil && found {
unstructured.SetNestedMap(copy.Object, status, "status")
}
return copy, !reflect.DeepEqual(base, copy), diff(base, copy), nil
}
func keyFuncO(o *unstructured.Unstructured) string {
return keyFunc(o.GroupVersionKind().GroupKind(), o.GetNamespace(), o.GetName())
}
func keyFunc(gk schema.GroupKind, namespace, name string) string {
s := gk.String()
if namespace != "" {
s += "/" + namespace
}
s += "/" + name
return s
}

Просмотреть файл

@ -0,0 +1,433 @@
package dynamichelper
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"net/http"
"reflect"
"testing"
"github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic/fake"
ktesting "k8s.io/client-go/testing"
"github.com/Azure/ARO-RP/pkg/api"
)
func TestFindGVR(t *testing.T) {
tests := []struct {
name string
resources []*metav1.APIResourceList
kind string
want *schema.GroupVersionResource
wantErr error
}{
{
name: "find one",
resources: []*metav1.APIResourceList{
{
GroupVersion: "v1",
APIResources: []metav1.APIResource{
{
Name: "configmaps",
Kind: "ConfigMap",
},
},
},
},
kind: "configmap",
want: &schema.GroupVersionResource{Group: "", Version: "v1", Resource: "configmaps"},
},
{
name: "find best version",
resources: []*metav1.APIResourceList{
{
GroupVersion: "v1",
APIResources: []metav1.APIResource{
{
Name: "configmaps",
Kind: "ConfigMap",
},
},
},
{
GroupVersion: "v1beta1",
APIResources: []metav1.APIResource{
{
Name: "configmaps",
Kind: "ConfigMap",
},
},
},
},
kind: "configmap",
want: &schema.GroupVersionResource{Group: "", Version: "v1", Resource: "configmaps"},
},
{
name: "find full group.resource",
resources: []*metav1.APIResourceList{
{
GroupVersion: "metal3.io/v1alpha1",
APIResources: []metav1.APIResource{
{
Name: "baremetalhosts",
Kind: "BareMetalHost",
},
},
},
},
kind: "baremetalhost.metal3.io",
want: &schema.GroupVersionResource{Group: "metal3.io", Version: "v1alpha1", Resource: "baremetalhosts"},
},
{
name: "no sub.resources",
resources: []*metav1.APIResourceList{
{
GroupVersion: "metal3.io/v1alpha1",
APIResources: []metav1.APIResource{
{
Name: "baremetalhosts/status",
Kind: "BareMetalHost",
},
},
},
},
kind: "baremetalhost/status",
wantErr: api.NewCloudError(
http.StatusBadRequest, api.CloudErrorCodeNotFound,
"", "The groupKind '%s' was not found.", "baremetalhost/status"),
},
{
name: "empty resources",
kind: "configmap",
wantErr: api.NewCloudError(
http.StatusBadRequest, api.CloudErrorCodeNotFound,
"", "The groupKind '%s' was not found.", "configmap"),
},
{
name: "find all kinds",
resources: []*metav1.APIResourceList{
{
GroupVersion: "metal3.io/v1alpha1",
APIResources: []metav1.APIResource{
{
Name: "baremetalhosts",
Kind: "BareMetalHost",
},
},
},
{
GroupVersion: "plastic.io/v1alpha1",
APIResources: []metav1.APIResource{
{
Name: "plastichosts",
Kind: "BareMetalHost",
},
},
},
},
kind: "baremetalhost",
want: nil,
wantErr: api.NewCloudError(
http.StatusBadRequest, api.CloudErrorCodeInvalidParameter,
"", "The groupKind '%s' matched multiple groupKinds (baremetalhost.metal3.io, baremetalhost.plastic.io).", "baremetalhost"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ka := &dynamicHelper{apiresources: tt.resources}
got, err := ka.findGVR(tt.kind, "")
if !reflect.DeepEqual(err, tt.wantErr) {
t.Error(err)
}
if !reflect.DeepEqual(got, tt.want) {
t.Error(got)
}
})
}
}
func TestEnsure(t *testing.T) {
tests := []struct {
name string
existing []runtime.Object
new *unstructured.Unstructured
wantCreate bool
wantUpdate bool
wantErr string
}{
{
name: "create",
new: &unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"namespace": "openshift-azure-logging",
"name": "config",
},
},
},
wantCreate: true,
},
{
name: "update",
existing: []runtime.Object{
&unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "ConfigMap",
"apiVersion": "v1",
"metadata": map[string]interface{}{
"namespace": "openshift-azure-logging",
"name": "config",
},
"data": map[string]interface{}{
"audit.conf": "1",
},
},
},
},
new: &unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "ConfigMap",
"apiVersion": "v1",
"metadata": map[string]interface{}{
"namespace": "openshift-azure-logging",
"name": "config",
},
"data": map[string]interface{}{
"audit.conf": "2",
},
},
},
wantUpdate: true,
},
{
name: "no update needed",
existing: []runtime.Object{
&unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "ConfigMap",
"apiVersion": "v1",
"metadata": map[string]interface{}{
"namespace": "openshift-azure-logging",
"name": "config",
},
"data": map[string]interface{}{
"audit.conf": "2",
},
},
},
},
new: &unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "ConfigMap",
"apiVersion": "v1",
"metadata": map[string]interface{}{
"namespace": "openshift-azure-logging",
"name": "config",
},
"data": map[string]interface{}{
"audit.conf": "2",
},
},
},
},
{
name: "no update needed either",
existing: []runtime.Object{
&unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "ConfigMap",
"apiVersion": "v1",
"metadata": map[string]interface{}{
"namespace": "openshift-azure-logging",
"name": "config",
"generation": "4", // <- should be ignored by merge
},
"data": map[string]interface{}{
"audit.conf": "2",
},
},
},
},
new: &unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "ConfigMap",
"apiVersion": "v1",
"metadata": map[string]interface{}{
"namespace": "openshift-azure-logging",
"name": "config",
},
"data": map[string]interface{}{
"audit.conf": "2",
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var created, updated bool
fakeDyn := fake.NewSimpleDynamicClient(runtime.NewScheme(), tt.existing...)
fakeDyn.PrependReactor("create", "configmaps", func(action ktesting.Action) (handled bool, ret runtime.Object, err error) {
created = true
return false, nil, nil
})
fakeDyn.PrependReactor("update", "configmaps", func(action ktesting.Action) (handled bool, ret runtime.Object, err error) {
updated = true
return false, nil, nil
})
dh := &dynamicHelper{
log: logrus.NewEntry(logrus.StandardLogger()),
dyn: fakeDyn,
apiresources: []*metav1.APIResourceList{
{
GroupVersion: "v1",
APIResources: []metav1.APIResource{
{
Name: "configmaps",
Kind: "ConfigMap",
},
},
},
},
}
err := dh.Ensure(tt.new)
if err != nil && err.Error() != tt.wantErr ||
err == nil && tt.wantErr != "" {
t.Error(err)
}
if tt.wantCreate != created {
t.Error(created)
}
if tt.wantUpdate != updated {
t.Error(updated)
}
})
}
}
func TestMerge(t *testing.T) {
for _, tt := range []struct {
name string
base *unstructured.Unstructured
delta *unstructured.Unstructured
want *unstructured.Unstructured
wantChanged bool
}{
{
name: "changed",
base: &unstructured.Unstructured{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"creationTimestamp": "2020-01-01T00:00:00Z", // untouched
},
"spec": map[string]interface{}{
"key1": "overwritten",
"key2": "untouched",
},
"status": map[string]interface{}{
"key1": "untouched",
},
},
},
delta: &unstructured.Unstructured{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"creationTimestamp": nil,
},
"spec": map[string]interface{}{
"key1": "new value",
},
"status": map[string]interface{}{
"key1": "ignored",
},
},
},
want: &unstructured.Unstructured{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"creationTimestamp": "2020-01-01T00:00:00Z",
},
"spec": map[string]interface{}{
"key1": "new value",
"key2": "untouched",
},
"status": map[string]interface{}{
"key1": "untouched",
},
},
},
wantChanged: true,
},
{
name: "no change",
base: &unstructured.Unstructured{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"creationTimestamp": "2020-01-01T00:00:00Z", // untouched
},
"spec": map[string]interface{}{
"key1": "untouched",
},
"status": map[string]interface{}{
"key1": "untouched",
},
},
},
delta: &unstructured.Unstructured{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"creationTimestamp": nil,
},
"spec": map[string]interface{}{
"key1": "untouched",
},
"status": map[string]interface{}{
"key1": "ignored",
},
},
},
want: &unstructured.Unstructured{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"creationTimestamp": "2020-01-01T00:00:00Z",
},
"spec": map[string]interface{}{
"key1": "untouched",
},
"status": map[string]interface{}{
"key1": "untouched",
},
},
},
},
} {
t.Run(tt.name, func(t *testing.T) {
result, changed, _, err := merge(tt.base, tt.delta)
if err != nil {
t.Fatal(err)
}
if changed != tt.wantChanged {
t.Error(changed)
}
if !reflect.DeepEqual(result, tt.want) {
t.Error(result)
}
})
}
}

Просмотреть файл

@ -0,0 +1,96 @@
package dynamichelper
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"sort"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// HashWorkloadConfigs iterates daemonsets, walks their volumes, and updates
// their pod templates with annotations that include the hashes of the content
// for each configmap or secret.
func HashWorkloadConfigs(resources []runtime.Object) error {
// map config resources to their hashed content
configToHash := map[string]string{}
for _, o := range resources {
switch o := o.(type) {
case *v1.Secret:
configToHash[keyFunc(schema.GroupKind{Kind: "Secret"}, o.Namespace, o.Name)] = getHashSecret(o)
case *v1.ConfigMap:
configToHash[keyFunc(schema.GroupKind{Kind: "ConfigMap"}, o.Namespace, o.Name)] = getHashConfigMap(o)
}
}
// iterate over workload controllers and add annotations with the hashes of
// every config map or secret appropriately to force redeployments on config
// updates.
for _, o := range resources {
switch o := o.(type) {
case *appsv1.DaemonSet:
for _, v := range o.Spec.Template.Spec.Volumes {
if v.Secret != nil {
if hash, found := configToHash[keyFunc(schema.GroupKind{Kind: "Secret"}, o.Namespace, v.Secret.SecretName)]; found {
if o.Spec.Template.Annotations == nil {
o.Spec.Template.Annotations = map[string]string{}
}
o.Spec.Template.Annotations["checksum/secret-"+v.Secret.SecretName] = hash
}
}
if v.ConfigMap != nil {
if hash, found := configToHash[keyFunc(schema.GroupKind{Kind: "ConfigMap"}, o.Namespace, v.ConfigMap.Name)]; found {
if o.Spec.Template.Annotations == nil {
o.Spec.Template.Annotations = map[string]string{}
}
o.Spec.Template.Annotations["checksum/configmap-"+v.ConfigMap.Name] = hash
}
}
}
case *appsv1.Deployment, *appsv1.StatefulSet:
// TODO: add as/when needed
return fmt.Errorf("unimplemented: %T", o)
}
}
return nil
}
func getHashSecret(o *v1.Secret) string {
keys := make([]string, 0, len(o.Data))
for key := range o.Data {
keys = append(keys, key)
}
sort.Strings(keys)
h := sha256.New()
for _, key := range keys {
fmt.Fprintf(h, "%s: %s\n", key, string(o.Data[key]))
}
return hex.EncodeToString(h.Sum(nil))
}
func getHashConfigMap(o *v1.ConfigMap) string {
keys := make([]string, 0, len(o.Data))
for key := range o.Data {
keys = append(keys, key)
}
sort.Strings(keys)
h := sha256.New()
for _, key := range keys {
fmt.Fprintf(h, "%s: %s\n", key, o.Data[key])
}
return hex.EncodeToString(h.Sum(nil))
}

Просмотреть файл

@ -0,0 +1,107 @@
package dynamichelper
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"reflect"
"testing"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
func TestHashWorkloadConfigs(t *testing.T) {
sec := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "certificates",
Namespace: "openshift-azure-logging",
},
Data: map[string][]byte{
"stuff": []byte("9485958"),
},
}
cm := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "fluent-config",
Namespace: "openshift-azure-logging",
},
Data: map[string]string{
"audit.conf": "auditConf",
"containers.conf": "containersConf",
"journal.conf": "journalConf",
"parsers.conf": "parsersConf",
},
}
ds := &appsv1.DaemonSet{
ObjectMeta: metav1.ObjectMeta{
Name: "mdsd",
Namespace: "openshift-azure-logging",
},
Spec: appsv1.DaemonSetSpec{
Template: v1.PodTemplateSpec{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
Name: "certificates",
VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{
SecretName: "certificates",
},
},
},
{
Name: "fluent-config",
VolumeSource: v1.VolumeSource{
ConfigMap: &v1.ConfigMapVolumeSource{
LocalObjectReference: v1.LocalObjectReference{
Name: "fluent-config",
},
},
},
},
},
Containers: []v1.Container{
{
Name: "fluentbit-audit",
Image: "fluentbitImage",
VolumeMounts: []v1.VolumeMount{
{
Name: "fluent-config",
ReadOnly: true,
MountPath: "/etc/td-agent-bit",
},
},
},
{
Name: "mdsd",
Image: "mdsdImage",
VolumeMounts: []v1.VolumeMount{
{
Name: "certificates",
MountPath: "/etc/mdsd.d/secret",
},
},
},
},
},
},
},
}
err := HashWorkloadConfigs([]runtime.Object{cm, sec, ds})
if err != nil {
t.Fatal(err)
}
expect := map[string]string{
"checksum/configmap-fluent-config": "aad6b208b25ce1becb4b9b6f14fce290f4e1bafd287813decc1e773ac2ec9c4e",
"checksum/secret-certificates": "e6963d3f1943a7bf44ebfda9d0dc2c2c8f2295dbeed320c654f3489c2aed1344",
}
if !reflect.DeepEqual(expect, ds.Spec.Template.Annotations) {
t.Error(ds.Spec.Template.Annotations)
}
}

10
pkg/env/dev.go поставляемый
Просмотреть файл

@ -31,6 +31,7 @@ import (
"github.com/Azure/ARO-RP/pkg/util/clientauthorizer"
"github.com/Azure/ARO-RP/pkg/util/instancemetadata"
"github.com/Azure/ARO-RP/pkg/util/refreshable"
"github.com/Azure/ARO-RP/pkg/util/version"
)
type conn struct {
@ -161,8 +162,13 @@ func (d *dev) InitializeAuthorizers() error {
return nil
}
func (d *dev) ACRName() string {
return "arosvc"
func (d *dev) AROOperatorImage() string {
override := os.Getenv("ARO_IMAGE")
if override != "" {
return override
}
return fmt.Sprintf("%s.azurecr.io/aro:%s", d.acrName, version.GitCommit)
}
func (d *dev) DatabaseName() string {

1
pkg/env/env.go поставляемый
Просмотреть файл

@ -53,6 +53,7 @@ type Interface interface {
Zones(vmSize string) ([]string, error)
ACRResourceID() string
ACRName() string
AROOperatorImage() string
E2EStorageAccountName() string
E2EStorageAccountRGName() string
E2EStorageAccountSubID() string

7
pkg/env/prod.go поставляемый
Просмотреть файл

@ -29,6 +29,7 @@ import (
"github.com/Azure/ARO-RP/pkg/util/instancemetadata"
"github.com/Azure/ARO-RP/pkg/util/pem"
"github.com/Azure/ARO-RP/pkg/util/refreshable"
"github.com/Azure/ARO-RP/pkg/util/version"
)
type prod struct {
@ -121,6 +122,8 @@ func newProd(ctx context.Context, log *logrus.Entry, instancemetadata instanceme
return nil, err
}
p.acrName = acrResource.ResourceName
} else {
p.acrName = "arointsvc"
}
return p, nil
@ -158,6 +161,10 @@ func (p *prod) ACRName() string {
return p.acrName
}
func (p *prod) AROOperatorImage() string {
return fmt.Sprintf("%s.azurecr.io/aro:%s", p.acrName, version.GitCommit)
}
func (p *prod) populateCosmosDB(ctx context.Context, rpAuthorizer autorest.Authorizer) error {
databaseaccounts := documentdb.NewDatabaseAccountsClient(p.SubscriptionID(), rpAuthorizer)

4
pkg/env/test.go поставляемый
Просмотреть файл

@ -89,9 +89,9 @@ func (t *Test) SubscriptionID() string {
}
func (t *Test) ACRResourceID() string {
return "/subscriptions/93aeba23-2f76-4307-be82-02921df010cf/resourceGroups/global/providers/Microsoft.ContainerRegistry/registries/arosvc"
return "/subscriptions/93aeba23-2f76-4307-be82-02921df010cf/resourceGroups/global/providers/Microsoft.ContainerRegistry/registries/arointsvc"
}
func (t *Test) ACRName() string {
return "arosvc"
return "arointsvc"
}

Просмотреть файл

@ -59,9 +59,9 @@ func (f *frontend) _getAdminKubernetesObjects(ctx context.Context, r *http.Reque
}
if name != "" {
return f.kubeActionsFactory(log, f.env).Get(ctx, doc.OpenShiftCluster, groupKind, namespace, name)
return f.kubeActionsFactory(log, f.env).Get(doc.OpenShiftCluster, groupKind, namespace, name)
}
return f.kubeActionsFactory(log, f.env).List(ctx, doc.OpenShiftCluster, groupKind, namespace)
return f.kubeActionsFactory(log, f.env).List(doc.OpenShiftCluster, groupKind, namespace)
}
func (f *frontend) deleteAdminKubernetesObjects(w http.ResponseWriter, r *http.Request) {
@ -94,7 +94,7 @@ func (f *frontend) _deleteAdminKubernetesObjects(ctx context.Context, r *http.Re
return err
}
return f.kubeActionsFactory(log, f.env).Delete(ctx, doc.OpenShiftCluster, groupKind, namespace, name)
return f.kubeActionsFactory(log, f.env).Delete(doc.OpenShiftCluster, groupKind, namespace, name)
}
func (f *frontend) postAdminKubernetesObjects(w http.ResponseWriter, r *http.Request) {
@ -138,5 +138,5 @@ func (f *frontend) _postAdminKubernetesObjects(ctx context.Context, r *http.Requ
return err
}
return f.kubeActionsFactory(log, f.env).CreateOrUpdate(ctx, doc.OpenShiftCluster, obj)
return f.kubeActionsFactory(log, f.env).CreateOrUpdate(doc.OpenShiftCluster, obj)
}

Просмотреть файл

@ -93,7 +93,7 @@ func TestAdminKubernetesObjectsGetAndDelete(t *testing.T) {
}
kactions.EXPECT().
Get(gomock.Any(), clusterDoc.OpenShiftCluster, tt.objKind, tt.objNamespace, tt.objName).
Get(clusterDoc.OpenShiftCluster, tt.objKind, tt.objNamespace, tt.objName).
Return([]byte(`{"Kind": "test"}`), nil)
openshiftClusters.EXPECT().Get(gomock.Any(), strings.ToLower(tt.resourceID)).
@ -120,7 +120,7 @@ func TestAdminKubernetesObjectsGetAndDelete(t *testing.T) {
}
kactions.EXPECT().
List(gomock.Any(), clusterDoc.OpenShiftCluster, tt.objKind, tt.objNamespace).
List(clusterDoc.OpenShiftCluster, tt.objKind, tt.objNamespace).
Return([]byte(`{"Kind": "test"}`), nil)
openshiftClusters.EXPECT().Get(gomock.Any(), strings.ToLower(tt.resourceID)).
@ -171,7 +171,7 @@ func TestAdminKubernetesObjectsGetAndDelete(t *testing.T) {
}
kactions.EXPECT().
Delete(gomock.Any(), clusterDoc.OpenShiftCluster, tt.objKind, tt.objNamespace, tt.objName).
Delete(clusterDoc.OpenShiftCluster, tt.objKind, tt.objNamespace, tt.objName).
Return(nil)
openshiftClusters.EXPECT().Get(gomock.Any(), strings.ToLower(tt.resourceID)).
@ -435,7 +435,7 @@ func TestAdminPostKubernetesObjects(t *testing.T) {
},
}
openshiftClusters.EXPECT().Get(gomock.Any(), strings.ToLower(tt.resourceID)).Return(clusterDoc, nil)
kactions.EXPECT().CreateOrUpdate(gomock.Any(), clusterDoc.OpenShiftCluster, tt.objInBody).Return(nil)
kactions.EXPECT().CreateOrUpdate(clusterDoc.OpenShiftCluster, tt.objInBody).Return(nil)
},
wantStatusCode: http.StatusOK,
},

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше