зеркало из https://github.com/Azure/ARO-RP.git
Коммит
ebdf715096
|
@ -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 }}
|
||||
|
|
|
@ -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
|
||||
|
|
28
Gopkg.toml
28
Gopkg.toml
|
@ -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"
|
||||
|
|
10
Makefile
10
Makefile
|
@ -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
|
||||
|
|
121
cgmanifest.json
121
cgmanifest.json
|
@ -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)
|
||||
|
|
|
@ -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(©.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)
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -53,6 +53,7 @@ type Interface interface {
|
|||
Zones(vmSize string) ([]string, error)
|
||||
ACRResourceID() string
|
||||
ACRName() string
|
||||
AROOperatorImage() string
|
||||
E2EStorageAccountName() string
|
||||
E2EStorageAccountRGName() string
|
||||
E2EStorageAccountSubID() string
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче