diff --git a/data/data/coreos/marketplace-rhcos.json b/data/data/coreos/marketplace-rhcos.json new file mode 100644 index 0000000000..5d94bd6b2c --- /dev/null +++ b/data/data/coreos/marketplace-rhcos.json @@ -0,0 +1,116 @@ +{ + "aarch64": { + "azure": { + "no-purchase-plan": { + "hyperVGen2": { + "publisher": "azureopenshift", + "offer": "aro4", + "sku": "419-arm", + "version": "419.6.20250523" + } + } + } + }, + "x86_64": { + "azure": { + "no-purchase-plan": { + "hyperVGen1": { + "publisher": "azureopenshift", + "offer": "aro4", + "sku": "aro_419", + "version": "419.6.20250523" + }, + "hyperVGen2": { + "publisher": "azureopenshift", + "offer": "aro4", + "sku": "419-v2", + "version": "419.6.20250523" + } + }, + "ocp": { + "hyperVGen1": { + "publisher": "redhat", + "offer": "rh-ocp-worker", + "sku": "rh-ocp-worker-gen1", + "version": "4.18.2025031114" + }, + "hyperVGen2": { + "publisher": "redhat", + "offer": "rh-ocp-worker", + "sku": "rh-ocp-worker", + "version": "4.18.2025031114" + } + }, + "opp": { + "hyperVGen1": { + "publisher": "redhat", + "offer": "rh-opp-worker", + "sku": "rh-opp-worker-gen1", + "version": "4.18.2025031114" + }, + "hyperVGen2": { + "publisher": "redhat", + "offer": "rh-opp-worker", + "sku": "rh-opp-worker", + "version": "4.18.2025031114" + } + }, + "oke": { + "hyperVGen1": { + "publisher": "redhat", + "offer": "rh-oke-worker", + "sku": "rh-oke-worker-gen1", + "version": "4.18.2025031114" + }, + "hyperVGen2": { + "publisher": "redhat", + "offer": "rh-oke-worker", + "sku": "rh-oke-worker", + "version": "4.18.2025031114" + } + }, + "ocp-emea": { + "hyperVGen1": { + "publisher": "redhat-limited", + "offer": "rh-ocp-worker", + "sku": "rh-ocp-worker-gen1", + "version": "4.18.2025031114" + }, + "hyperVGen2": { + "publisher": "redhat-limited", + "offer": "rh-ocp-worker", + "sku": "rh-ocp-worker", + "version": "4.18.2025031114" + } + }, + "opp-emea": { + "hyperVGen1": { + "publisher": "redhat-limited", + "offer": "rh-opp-worker", + "sku": "rh-opp-worker-gen1", + "version": "4.18.2025031114" + }, + "hyperVGen2": { + "publisher": "redhat-limited", + "offer": "rh-opp-worker", + "sku": "rh-opp-worker", + "version": "4.18.2025031114" + } + }, + "oke-emea": { + "hyperVGen1": { + "publisher": "redhat-limited", + "offer": "rh-oke-worker", + "sku": "rh-oke-worker-gen1", + "version": "4.18.2025031114" + }, + "hyperVGen2": { + "publisher": "redhat-limited", + "offer": "rh-oke-worker", + "sku": "rh-oke-worker", + "version": "4.18.2025031114" + } + } + } + } +} diff --git a/go.mod b/go.mod index 7495546bf8..1ee1079784 100644 --- a/go.mod +++ b/go.mod @@ -10,8 +10,8 @@ require ( cloud.google.com/go/storage v1.43.0 github.com/AlecAivazis/survey/v2 v2.3.5 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3 v3.0.0-beta.2 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 @@ -52,7 +52,7 @@ require ( github.com/clarketm/json v1.14.1 github.com/containers/image/v5 v5.31.0 github.com/coreos/ignition/v2 v2.20.0 - github.com/coreos/stream-metadata-go v0.1.8 + github.com/coreos/stream-metadata-go v0.4.10-0.20250806142651-4a7d280a6c7b github.com/daixiang0/gci v0.13.4 github.com/digitalocean/go-libvirt v0.0.0-20240220204746-fcabe97a6eed github.com/diskfs/go-diskfs v1.4.0 @@ -117,12 +117,12 @@ require ( github.com/vincent-petithory/dataurl v1.0.0 github.com/vmware/govmomi v0.47.1 go.uber.org/mock v0.5.0 - golang.org/x/crypto v0.36.0 + golang.org/x/crypto v0.38.0 golang.org/x/oauth2 v0.28.0 - golang.org/x/sync v0.12.0 - golang.org/x/sys v0.32.0 - golang.org/x/term v0.30.0 - golang.org/x/text v0.23.0 + golang.org/x/sync v0.14.0 + golang.org/x/sys v0.33.0 + golang.org/x/term v0.32.0 + golang.org/x/text v0.25.0 google.golang.org/api v0.214.0 google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a google.golang.org/grpc v1.71.0 @@ -150,7 +150,10 @@ require ( sigs.k8s.io/yaml v1.4.0 ) -require github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.29.0 +require ( + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0 + github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.29.0 +) require github.com/aws/aws-sdk-go-v2/service/servicequotas v1.31.0 @@ -161,7 +164,7 @@ require ( cloud.google.com/go/compute/metadata v0.6.0 // indirect cloud.google.com/go/iam v1.2.2 // indirect cloud.google.com/go/longrunning v0.6.2 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest/adal v0.9.24 // indirect @@ -169,7 +172,7 @@ require ( github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect github.com/BurntSushi/toml v1.4.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/PaesslerAG/gval v1.0.0 // indirect @@ -304,16 +307,16 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect - go.opentelemetry.io/otel v1.35.0 // indirect - go.opentelemetry.io/otel/metric v1.35.0 // indirect - go.opentelemetry.io/otel/trace v1.35.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect + go.opentelemetry.io/otel v1.36.0 // indirect + go.opentelemetry.io/otel/metric v1.36.0 // indirect + go.opentelemetry.io/otel/trace v1.36.0 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/mod v0.24.0 // indirect - golang.org/x/net v0.38.0 // indirect + golang.org/x/mod v0.24.0 + golang.org/x/net v0.40.0 // indirect golang.org/x/time v0.9.0 // indirect golang.org/x/tools v0.31.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect diff --git a/go.sum b/go.sum index 58a8307f63..b9294167e8 100644 --- a/go.sum +++ b/go.sum @@ -25,16 +25,18 @@ github.com/AlecAivazis/survey/v2 v2.3.5 h1:A8cYupsAZkjaUmhtTYv3sSqc7LO5mp1XDfqe5 github.com/AlecAivazis/survey/v2 v2.3.5/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 h1:F0gBpfdPLGsw+nsgk6aqqkZS1jiixa5WwFe3fk/T3Ys= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2/go.mod h1:SqINnQ9lVVdRlyC8cd1lCI0SdX4n2paeABd2K8ggfnE= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3 v3.0.0-beta.2 h1:qiir/pptnHqp6hV8QwV+IExYIf6cPsXBfUDUXQ27t2Y= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v3 v3.0.0-beta.2/go.mod h1:jVRrRDLCOuif95HDYC23ADTMlvahB7tMdl519m9Iyjc= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0 h1:/Di3vB4sNeQ+7A8efjUVENvyB945Wruvstucqp7ZArg= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0/go.mod h1:gM3K25LQlsET3QR+4V74zxCsFAy0r6xMNN9n80SZn+4= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1 h1:UPeCRD+XY7QlaGQte2EVI2iOcWvUYA2XY8w5T/8v0NQ= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1/go.mod h1:oGV6NlB0cvi1ZbYRR2UN44QHxWFyGk+iylgD0qaMXjA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4= @@ -93,8 +95,8 @@ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUM github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= -github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3 h1:H5xDQaE3XowWfhZRUpnfC+rGZMEVoSiji+b+/HFAPU4= -github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= @@ -260,8 +262,8 @@ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8 github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/ignition/v2 v2.20.0 h1:xQjrxhCbcSKpqrN2hOQavAc1rx0GOf6qh2QCauScwPU= github.com/coreos/ignition/v2 v2.20.0/go.mod h1:l7EpXNWA7jBXmjUMvnVBlrrj+LX2wA/PAyD9kstwFDQ= -github.com/coreos/stream-metadata-go v0.1.8 h1:EbLlLia+Ekuqgh8nF4NNFs0jUqmhUbN4mWd1O8u8TQE= -github.com/coreos/stream-metadata-go v0.1.8/go.mod h1:RTjQyHgO/G37oJ3qnqYK6Z4TPZ5EsaabOtfMjVXmgko= +github.com/coreos/stream-metadata-go v0.4.10-0.20250806142651-4a7d280a6c7b h1:CT6nMx5Ap/K6MT8zMqByrWz+RZV7O6pBGW5LhB/pwvY= +github.com/coreos/stream-metadata-go v0.4.10-0.20250806142651-4a7d280a6c7b/go.mod h1:dTE8UEFgyUcrbdUg7vGT3uIP7S8a1IwUlmWLKlOp8G8= github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687 h1:uSmlDgJGbUB0bwQBcZomBTottKwEDF5fF8UjSwKSzWM= github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687/go.mod h1:Salmysdw7DAVuobBW/LwsKKgpyCPHUhjyJoMJD+ZJiI= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= @@ -615,8 +617,8 @@ github.com/keploy/go-sdk v0.9.0 h1:kpSNcCTDdELsa1gWyhoD9oV57SgSMbG/wq6Cjp4y7cY= github.com/keploy/go-sdk v0.9.0/go.mod h1:vNKXoFd2MaK+Gly/K6XeP1Hs9dP834C74szH+vtBPwg= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= -github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= +github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= +github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= @@ -873,8 +875,8 @@ github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= -github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= +github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= +github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -982,23 +984,23 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= -go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= -go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= -go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= +go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= +go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= +go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= +go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= @@ -1036,8 +1038,8 @@ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo7yrN4mVcnkHDYz5vvs= @@ -1115,8 +1117,8 @@ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= @@ -1136,8 +1138,8 @@ golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1199,8 +1201,8 @@ golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1227,8 +1229,8 @@ golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -1249,8 +1251,8 @@ golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= diff --git a/hack/build-coreos-manifest.go b/hack/build-coreos-manifest.go index e8ed9dec10..6411144b42 100644 --- a/hack/build-coreos-manifest.go +++ b/hack/build-coreos-manifest.go @@ -7,37 +7,31 @@ package main import ( + "encoding/json" "fmt" "os" "path/filepath" "strings" + "github.com/coreos/stream-metadata-go/stream" + "github.com/coreos/stream-metadata-go/stream/rhcos" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/yaml" ) const ( - streamRHCOSJSON = "data/data/coreos/rhcos.json" - streamFCOSJSON = "data/data/coreos/fcos.json" - streamSCOSJSON = "data/data/coreos/scos.json" - fcosTAG = "okd" - scosTAG = "scos" - dest = "bin/manifests/coreos-bootimages.yaml" + streamRHCOSJSON = "data/data/coreos/rhcos.json" + streamFCOSJSON = "data/data/coreos/fcos.json" + streamSCOSJSON = "data/data/coreos/scos.json" + streamMarketplaceRHCOSJSON = "data/data/coreos/marketplace-rhcos.json" + fcosTAG = "okd" + scosTAG = "scos" + dest = "bin/manifests/coreos-bootimages.yaml" ) func run() error { - var streamJSON string - tags, _ := os.LookupEnv("TAGS") - switch { - case strings.Contains(tags, fcosTAG): - streamJSON = streamFCOSJSON - case strings.Contains(tags, scosTAG): - streamJSON = streamSCOSJSON - default: - streamJSON = streamRHCOSJSON - } - bootimages, err := os.ReadFile(streamJSON) + bootimages, err := getBootImages() if err != nil { return err } @@ -79,6 +73,67 @@ func run() error { return nil } +func getBootImages() ([]byte, error) { + var okd bool + var streamJSON string + tags, _ := os.LookupEnv("TAGS") + switch { + case strings.Contains(tags, fcosTAG): + streamJSON = streamFCOSJSON + okd = true + case strings.Contains(tags, scosTAG): + streamJSON = streamSCOSJSON + okd = true + default: + streamJSON = streamRHCOSJSON + } + + bootimages, err := os.ReadFile(streamJSON) + if err != nil { + return nil, err + } + + if okd { + // okd does not yet have marketplace images, so we are done + return bootimages, nil + } + + return mergeMarketplaceStream(bootimages) +} + +type marketplaceStream map[string]*rhcos.Marketplace + +func mergeMarketplaceStream(streamJSON []byte) ([]byte, error) { + mktStream := marketplaceStream{} + mktJSON, err := os.ReadFile(streamMarketplaceRHCOSJSON) + if err != nil { + return nil, fmt.Errorf("failed to open marketplace file: %w", err) + } + if err := json.Unmarshal(mktJSON, &mktStream); err != nil { + return nil, fmt.Errorf("failed to unmarshal market stream: %w", err) + } + + stream := stream.Stream{} + if err := json.Unmarshal(streamJSON, &stream); err != nil { + return nil, fmt.Errorf("failed to unmarshal boot image stream: %w", err) + } + + for name, arch := range stream.Architectures { + if mkt, ok := mktStream[name]; ok { + if arch.RHELCoreOSExtensions == nil { + arch.RHELCoreOSExtensions = &rhcos.Extensions{} + } + arch.RHELCoreOSExtensions.Marketplace = mkt + } + } + + bootImgs, err := json.Marshal(stream) + if err != nil { + return nil, fmt.Errorf("failed to marshal merged boot image stream: %w", err) + } + return bootImgs, nil +} + func main() { if err := run(); err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) diff --git a/hack/rhcos/README.md b/hack/rhcos/README.md new file mode 100644 index 0000000000..0e95203748 --- /dev/null +++ b/hack/rhcos/README.md @@ -0,0 +1,25 @@ +# Populating the RHCOS Stream Marketplace Extension + +This tool is used to reach out to cloud sdks and populate the +data/data/coreos/marketplace-rhcos.json file. That file represents +the mareketplace extension to the rhcos stream and is merged into +the stream. + +To run the program: + +```shell +go run -mod=vendor ./hack/rhcos/populate-marketplace-imagestream.go +``` + +The program will find marketplace images based on the version of the +RHCOS stream. The version can be overriden with the +`STREAM_RELEASE_OVERRIDE` variable. This is useful if you are working +on the main branch, where up-to-date images are not available. For +example, looking up Azure images requires knowing the X.Y version +to populate the offer, so when working on the main branch (4.20), +it is necessary to run the following command to correctly populate +the stream: + +```shell +STREAM_RELEASE_OVERRIDE=4.19 go run -mod=vendor ./hack/rhcos/populate-marketplace-imagestream.go +``` \ No newline at end of file diff --git a/hack/rhcos/populate-marketplace-imagestream.go b/hack/rhcos/populate-marketplace-imagestream.go new file mode 100644 index 0000000000..e3b5e4799a --- /dev/null +++ b/hack/rhcos/populate-marketplace-imagestream.go @@ -0,0 +1,116 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "log" + "os" + "strings" + + "github.com/coreos/stream-metadata-go/stream" + "github.com/coreos/stream-metadata-go/stream/rhcos" + + "github.com/openshift/installer/pkg/rhcos/marketplace/azure" +) + +const ( + streamRHCOSJSON = "data/data/coreos/rhcos.json" + streamMarketplaceRHCOSJSON = "data/data/coreos/marketplace-rhcos.json" + + x86 = "x86_64" + arm64 = "aarch64" +) + +// arch -> marketplace +type marketplaceStream map[string]*rhcos.Marketplace + +func main() { + ctx := context.Background() + stream := marketplaceStream{} + + if err := stream.populate(ctx); err != nil { + log.Fatalln("Failed to populate marketplace stream:", err) + } + + if err := stream.write(); err != nil { + log.Fatalln("Failed to write marketplace stream:", err) + } + log.Printf("Successfully wrote marketplace stream to %s", streamMarketplaceRHCOSJSON) +} + +// populate gathers the marketplace images for each cloud +// and adds them to the marketplace stream data structure. +func (s marketplaceStream) populate(ctx context.Context) error { + clouds := []func(ctx context.Context, arch string) error{ + s.azure, + } + + for _, supportedArch := range []string{arm64, x86} { + s[supportedArch] = &rhcos.Marketplace{} + for _, populateCloud := range clouds { + if err := populateCloud(ctx, supportedArch); err != nil { + return err + } + } + } + return nil +} + +// write serializes the marketplace stream to disk. +func (s marketplaceStream) write() error { + contents, err := json.MarshalIndent(s, "", " ") + if err != nil { + return fmt.Errorf("error marshaling stream: %w", err) + } + + // TODO(padillon): dumb question time, git is still complaining \ No newline at end of file + // what am I doing wrong? + contents = append(contents, []byte("\n")...) + + if err := os.WriteFile(streamMarketplaceRHCOSJSON, contents, 0644); err != nil { + return fmt.Errorf("error writing stream: %w", err) + } + return nil +} + +func (s marketplaceStream) azure(ctx context.Context, arch string) error { + var err error + + s[arch].Azure = &rhcos.AzureMarketplace{} + + rel, err := getReleaseFromStream() + if err != nil { + return fmt.Errorf("failed to get release from rhcos stream: %w", err) + } + + azClient, err := azure.NewStreamClient() + if err != nil { + return fmt.Errorf("failed to initialize azure client: %w", err) + } + + if s[arch].Azure, err = azClient.Populate(ctx, arch, rel); err != nil { + return err + } + + return nil +} + +// getXYFromStream obtains the X.Y version from rhcos.json. +func getReleaseFromStream() (string, error) { + if rel, ok := os.LookupEnv("STREAM_RELEASE_OVERRIDE"); ok { + log.Printf("Found STREAM_RELEASE_OVERRIDE %s", rel) + return rel, nil + } + fileContents, err := os.ReadFile(streamRHCOSJSON) + if err != nil { + return "", err + } + + st := &stream.Stream{} + if err := json.Unmarshal(fileContents, st); err != nil { + return "", fmt.Errorf("failed to unmarshal RHCOS stream: %w", err) + } + + return strings.Split(st.Stream, "-")[1], nil +} diff --git a/pkg/rhcos/builds.go b/pkg/rhcos/builds.go index b0c26c476f..6169b763a4 100644 --- a/pkg/rhcos/builds.go +++ b/pkg/rhcos/builds.go @@ -7,43 +7,69 @@ package rhcos import ( "context" "encoding/json" + "errors" "fmt" "io" + "io/fs" "net/url" "github.com/coreos/stream-metadata-go/stream" - "github.com/pkg/errors" + "github.com/coreos/stream-metadata-go/stream/rhcos" + "github.com/sirupsen/logrus" "github.com/openshift/installer/data" ) +type marketplaceStream map[string]*rhcos.Marketplace + // FetchRawCoreOSStream returns the raw stream metadata for the // bootimages embedded in the installer. func FetchRawCoreOSStream(ctx context.Context) ([]byte, error) { - file, err := data.Assets.Open(getStreamFileName()) + st, err := FetchCoreOSBuild(ctx) if err != nil { - return nil, errors.Wrapf(err, "failed to read embedded CoreOS stream metadata") + return nil, fmt.Errorf("failed to get combined CoreOS build: %w", err) } - defer file.Close() - - body, err := io.ReadAll(file) + rawStream, err := json.Marshal(st) if err != nil { - return nil, errors.Wrap(err, "failed to read CoreOS stream metadata") + return nil, fmt.Errorf("failed to marshal combined CoreOS stream: %w", err) } - return body, nil + return rawStream, nil } // FetchCoreOSBuild returns the pinned version of RHEL/Fedora CoreOS used // by the installer to provision the bootstrap node and control plane currently. // For more information, see e.g. https://github.com/openshift/enhancements/pull/201 func FetchCoreOSBuild(ctx context.Context) (*stream.Stream, error) { - body, err := FetchRawCoreOSStream(ctx) + body, err := fetchRawCoreOSStream(ctx) if err != nil { return nil, err } var st stream.Stream if err := json.Unmarshal(body, &st); err != nil { - return nil, errors.Wrap(err, "failed to parse CoreOS stream metadata") + return nil, fmt.Errorf("failed to parse CoreOS stream metadata: %w", err) + } + + // Merge marketplace json file into stream json file + mktBody, err := fetchRawMarketplaceStream() + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + logrus.Debug("No marketplace json file found: skipping merge.") + return &st, nil + } + return nil, err + } + var mktSt marketplaceStream + if err := json.Unmarshal(mktBody, &mktSt); err != nil { + return nil, fmt.Errorf("failed to parse marketplace stream: %w", err) + } + + for name, arch := range st.Architectures { + if mkt, ok := mktSt[name]; ok { + if arch.RHELCoreOSExtensions == nil { + arch.RHELCoreOSExtensions = &rhcos.Extensions{} + } + arch.RHELCoreOSExtensions.Marketplace = mkt + } } return &st, nil } @@ -87,3 +113,31 @@ func FindArtifactURL(artifacts stream.PlatformArtifacts) (string, error) { } return "", fmt.Errorf("no \"disk\" artifact found") } + +func fetchRawCoreOSStream(ctx context.Context) ([]byte, error) { + file, err := data.Assets.Open(getStreamFileName()) + if err != nil { + return nil, fmt.Errorf("failed to read embedded CoreOS stream metadata: %w", err) + } + defer file.Close() + + body, err := io.ReadAll(file) + if err != nil { + return nil, fmt.Errorf("failed to read CoreOS stream metadata: %w", err) + } + return body, nil +} + +func fetchRawMarketplaceStream() ([]byte, error) { + file, err := data.Assets.Open(getMarketplaceStreamFileName()) + if err != nil { + return nil, err + } + defer file.Close() + + body, err := io.ReadAll(file) + if err != nil { + return nil, err + } + return body, nil +} diff --git a/pkg/rhcos/marketplace/azure/azure.go b/pkg/rhcos/marketplace/azure/azure.go new file mode 100644 index 0000000000..a7f5658247 --- /dev/null +++ b/pkg/rhcos/marketplace/azure/azure.go @@ -0,0 +1,288 @@ +package azure + +import ( + "context" + "fmt" + "strconv" + "strings" + + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute" + "github.com/coreos/stream-metadata-go/stream/rhcos" + "github.com/sirupsen/logrus" + "golang.org/x/mod/semver" + + azuresession "github.com/openshift/installer/pkg/asset/installconfig/azure" + "github.com/openshift/installer/pkg/types/azure" +) + +const ( + // region is an arbitrarily chosen region. Marketplace + // images are published globally, we just need to verify + // the image exists, so we can use any region. + + region = "centralus" + + // image attributes for the NoPurchasePlan image, + // published by ARO. + pubARO = "azureopenshift" + offerARO = "aro4" + + // image attributes for paid marketplace images. + pubRH = "redhat" + pubEMEA = "redhat-limited" + offerOCP = "rh-ocp-worker" + offerOPP = "rh-opp-worker" + offerOKE = "rh-oke-worker" + + // supported architectures. + x86 = "x86_64" + arm64 = "aarch64" +) + +// MarketplaceStream connects to the Azure SDK to populate the RHCOS stream. +type MarketplaceStream struct { + client *armcompute.VirtualMachineImagesClient +} + +type imgsQuery struct { + gen1, gen2 *imgQuery +} + +type imgQuery struct { + publisher, offer, sku, xyVersion string +} + +// NewStreamClient instantiates a MarketplaceStream. +func NewStreamClient() (*MarketplaceStream, error) { + cl, err := getClient() + if err != nil { + return nil, fmt.Errorf("failed to create azure marketplace stream client: %w", err) + } + return &MarketplaceStream{cl}, nil +} + +// Populate finds the marketplace images for a given architecture and release. +func (az *MarketplaceStream) Populate(ctx context.Context, arch, rel string) (*rhcos.AzureMarketplace, error) { + s := &rhcos.AzureMarketplace{} + + var err error + if s.NoPurchasePlan, err = az.noPurchasePlan(ctx, arch, rel); err != nil { + return nil, fmt.Errorf("failed getting Azure non-paid images: %w", err) + } + + if s.OCP, err = az.getImages(ctx, paidImageQuery(pubRH, rel, offerOCP), arch); err != nil { + return nil, fmt.Errorf("failed getting Azure OCP marketplace images: %w", err) + } + + if s.OPP, err = az.getImages(ctx, paidImageQuery(pubRH, rel, offerOPP), arch); err != nil { + return nil, fmt.Errorf("failed getting Azure OPP marketplace images: %w", err) + } + + if s.OKE, err = az.getImages(ctx, paidImageQuery(pubRH, rel, offerOKE), arch); err != nil { + return nil, fmt.Errorf("failed getting Azure OKE marketplace images: %w", err) + } + + if s.OCPEMEA, err = az.getImages(ctx, paidImageQuery(pubEMEA, rel, offerOCP), arch); err != nil { + return nil, fmt.Errorf("failed getting Azure OCP EMEA marketplace images: %w", err) + } + + if s.OPPEMEA, err = az.getImages(ctx, paidImageQuery(pubEMEA, rel, offerOPP), arch); err != nil { + return nil, fmt.Errorf("failed getting Azure OPP EMEA marketplace images: %w", err) + } + + if s.OKEEMEA, err = az.getImages(ctx, paidImageQuery(pubEMEA, rel, offerOKE), arch); err != nil { + return nil, fmt.Errorf("failed getting Azure OKE EMEA marketplace images: %w", err) + } + + return s, nil +} + +func (az *MarketplaceStream) noPurchasePlan(ctx context.Context, arch, release string) (*rhcos.AzureMarketplaceImages, error) { + logrus.Info("Retrieving NoPurchase Plan Images for release: ", release) + gen1SKU, gen2SKU := parseAROSKUs(release, arch) + q := imgsQuery{ + gen1: &imgQuery{ + publisher: pubARO, + offer: offerARO, + sku: gen1SKU, + xyVersion: release, + }, + gen2: &imgQuery{ + publisher: pubARO, + offer: offerARO, + sku: gen2SKU, + xyVersion: release, + }, + } + return az.getImages(ctx, q, arch) +} + +func paidImageQuery(pub, release, offer string) imgsQuery { + return imgsQuery{ + gen1: &imgQuery{ + publisher: pub, + offer: offer, + sku: fmt.Sprintf("%s-gen1", offer), + xyVersion: release, + }, + gen2: &imgQuery{ + publisher: pub, + offer: offer, + sku: offer, + xyVersion: release, + }, + } +} + +func (az *MarketplaceStream) getImages(ctx context.Context, query imgsQuery, arch string) (*rhcos.AzureMarketplaceImages, error) { + imgs := &rhcos.AzureMarketplaceImages{} + if gen1 := query.gen1; gen1 != nil && gen1.sku != "" { + logrus.Infof("Searching for image with publisher: %s, offer %s, sku %s architecture %s in release %s", gen1.publisher, gen1.offer, gen1.sku, arch, gen1.xyVersion) + img, err := az.getImage(ctx, gen1.publisher, gen1.offer, gen1.sku, gen1.xyVersion, arch) + if err != nil { + logrus.Error(err) + } + imgs.Gen1 = img + } + if gen2 := query.gen2; gen2 != nil && gen2.sku != "" { + logrus.Infof("Searching for image with publisher: %s, offer %s, sku %s architecture %s in release %s", gen2.publisher, gen2.offer, gen2.sku, arch, gen2.xyVersion) + img, err := az.getImage(ctx, gen2.publisher, gen2.offer, gen2.sku, gen2.xyVersion, arch) + if err != nil { + logrus.Error(err) + } + imgs.Gen2 = img + } + if imgs.Gen1 == nil && imgs.Gen2 == nil { + return nil, nil + } + return imgs, nil +} + +// getImage finds the latest version matching the x.y version of the release. +func (az *MarketplaceStream) getImage(ctx context.Context, pub, offer, sku, xyVersion, arch string) (*rhcos.AzureMarketplaceImage, error) { + resp, err := az.client.List(ctx, region, pub, offer, sku, nil) + if err != nil { + return nil, fmt.Errorf("failed to list images: %w", err) + } + + if len(resp.VirtualMachineImageResourceArray) == 0 { + logrus.Infof("Found no images for publisher: %s, offer: %s, sku %s for the architecture %s in the release %s", pub, offer, sku, arch, xyVersion) + return nil, nil + } + + var foundVersion string + var greatestSemver string + for _, v := range resp.VirtualMachineImageResourceArray { + v := *v.Name + semVer := convertToSemver(v) + logrus.Infof("Found potential image match, version: %s", v) + + // Ensure that the image is not from a later Y stream, + // e.g. if we are populating a 4.19 stream, we don't want 4.20 images, + // but 4.18 would be ok if 4.19 is not available yet. + if checkIfNewer(semVer, xyVersion) { + logrus.Infof("Skipping version %s as it is released after %s", v, xyVersion) + continue + } + + if semver.Compare(greatestSemver, semVer) < 0 { + greatestSemver = semVer + foundVersion = v + } + } + + // Now that we've found the version, check the architecture and the plan. + img, err := az.client.Get(ctx, region, pub, offer, sku, foundVersion, nil) + if err != nil { + return nil, fmt.Errorf("could not get the image for the found version, urn: %s:%s:%s:%s in region %s: %w", pub, offer, sku, foundVersion, region, err) + } + + // This way of checking architecture is works, + // but may be unnecessary. We would only need to do something + // like this if the URN for different architectures can be the same; + // otherwise we know before generating the query which architecture we are looking for. + azureArch := map[string]armcompute.ArchitectureTypes{ + x86: armcompute.ArchitectureTypesX64, + arm64: armcompute.ArchitectureTypesArm64, + } + + if *img.Properties.Architecture != azureArch[arch] { + return nil, nil + } + + logrus.Infof("Using image %s:%s:%s:%s", pub, offer, sku, foundVersion) + return &rhcos.AzureMarketplaceImage{ + Publisher: pub, + Offer: offer, + SKU: sku, + Version: foundVersion, + }, nil +} + +// parseARO takes the release from coreos stream and +// uses conventions to generate the SKU (gen1 & gen2) and version. +// For instance, with a coreos release of "4.19" +// gen1SKU: "aro_418" +// gen2SKU: "418-v2" +// version: "418.94.20241009" (removes timestamp & build number) +func parseAROSKUs(release, arch string) (string, string) { + xyVersion := strings.ReplaceAll(release, ".", "") + var gen1SKU, gen2SKU string + switch arch { + case x86: + gen1SKU = fmt.Sprintf("aro_%s", xyVersion) + gen2SKU = fmt.Sprintf("%s-v2", xyVersion) + case arm64: + gen1SKU = "" + gen2SKU = fmt.Sprintf("%s-arm", xyVersion) + } + return gen1SKU, gen2SKU +} + +func getClient() (*armcompute.VirtualMachineImagesClient, error) { + ssn, err := azuresession.GetSession(azure.PublicCloud, "") + if err != nil { + return nil, fmt.Errorf("failed to get session: %w", err) + } + + client, err := armcompute.NewVirtualMachineImagesClient(ssn.Credentials.SubscriptionID, ssn.TokenCreds, nil) + if err != nil { + return nil, fmt.Errorf("failed to create client: %w", err) + } + return client, nil +} + +// ARO & the paid marketplace images format their version strings differently. +// This function takes either one, and converts it to a go semantic version string. +// ARO combines xy into what should be the x, and includes the RHEL version in y; e.g. 418.94.20250122. +// Paid marketplace images use a correct semantic version (well, they use a timestamp for z, but good enough): 4.17.2024101109. +func convertToSemver(ver string) string { + // Using RHEL versioning + if major := strings.Split(ver, ".")[0]; major == "9" || major == "10" { + return fmt.Sprintf("v%s", ver) + } + + if segments := strings.Split(ver, "."); len(segments[0]) == 1 { + semV := fmt.Sprintf("v%s", ver) + return semV + } else if len(segments[0]) == 3 { + combinedXY := segments[0] + semV := fmt.Sprintf("v%s", strings.Join([]string{combinedXY[:1], combinedXY[1:], segments[2]}, ".")) + return semV + } + return "" +} + +func checkIfNewer(candidate, release string) bool { + img, err := strconv.Atoi(strings.Split(semver.MajorMinor(candidate), ".")[1]) + if err != nil { + logrus.Infof("Error converting minor version to int with version %s", candidate) + return true + } + rel, err := strconv.Atoi(strings.Split(release, ".")[1]) + if err != nil { + logrus.Infof("Error converting minor version to int with version %s", release) + return true + } + return img > rel +} diff --git a/pkg/rhcos/stream.go b/pkg/rhcos/stream.go index 078b0e8d37..f4c62bab6d 100644 --- a/pkg/rhcos/stream.go +++ b/pkg/rhcos/stream.go @@ -5,3 +5,7 @@ package rhcos func getStreamFileName() string { return "coreos/rhcos.json" } + +func getMarketplaceStreamFileName() string { + return "coreos/marketplace-rhcos.json" +} diff --git a/pkg/rhcos/stream_fcos.go b/pkg/rhcos/stream_fcos.go index 6325fd97a1..37bf6250dd 100644 --- a/pkg/rhcos/stream_fcos.go +++ b/pkg/rhcos/stream_fcos.go @@ -5,3 +5,9 @@ package rhcos func getStreamFileName() string { return "coreos/fcos.json" } + +func getMarketplaceStreamFileName() string { + // There is no need for OKD marketplace images at this time + // so we can skip reading a marketplace stream file. + return "" +} diff --git a/pkg/rhcos/stream_scos.go b/pkg/rhcos/stream_scos.go index 121e971a3d..d5db6b94a6 100644 --- a/pkg/rhcos/stream_scos.go +++ b/pkg/rhcos/stream_scos.go @@ -5,3 +5,10 @@ package rhcos func getStreamFileName() string { return "coreos/scos.json" } + +func getMarketplaceStreamFileName() string { + // There is no current need for scos marketplace images, + // so this file does not currently exist. The calling + // functions will gracefully handle the missing file. + return "coreos/marketplace-scos.json" +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md index cf422304e7..926ed3882c 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md @@ -1,5 +1,19 @@ # Release History +## 1.18.0 (2025-04-03) + +### Features Added + +* Added `AccessToken.RefreshOn` and updated `BearerTokenPolicy` to consider nonzero values of it when deciding whether to request a new token + + +## 1.17.1 (2025-03-20) + +### Other Changes + +* Upgraded to Go 1.23 +* Upgraded dependencies + ## 1.17.0 (2025-01-07) ### Features Added diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go index f2b296b6dc..460170034a 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go @@ -47,8 +47,13 @@ func HasStatusCode(resp *http.Response, statusCodes ...int) bool { // AccessToken represents an Azure service bearer access token with expiry information. // Exported as azcore.AccessToken. type AccessToken struct { - Token string + // Token is the access token + Token string + // ExpiresOn indicates when the token expires ExpiresOn time.Time + // RefreshOn is a suggested time to refresh the token. + // Clients should ignore this value when it's zero. + RefreshOn time.Time } // TokenRequestOptions contain specific parameter that may be used by credentials types when attempting to get a token. diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go index 44ab00d400..85514db3b8 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go @@ -40,5 +40,5 @@ const ( Module = "azcore" // Version is the semantic version (see http://semver.org) of this module. - Version = "v1.17.0" + Version = "v1.18.0" ) diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go index b26db920b0..1950a2e5b3 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_bearer_token.go @@ -51,6 +51,15 @@ func acquire(state acquiringResourceState) (newResource exported.AccessToken, ne return tk, tk.ExpiresOn, nil } +// shouldRefresh determines whether the token should be refreshed. It's a variable so tests can replace it. +var shouldRefresh = func(tk exported.AccessToken, _ acquiringResourceState) bool { + if tk.RefreshOn.IsZero() { + return tk.ExpiresOn.Add(-5 * time.Minute).Before(time.Now()) + } + // no offset in this case because the authority suggested a refresh window--between RefreshOn and ExpiresOn + return tk.RefreshOn.Before(time.Now()) +} + // NewBearerTokenPolicy creates a policy object that authorizes requests with bearer tokens. // cred: an azcore.TokenCredential implementation such as a credential object from azidentity // scopes: the list of permission scopes required for the token. @@ -69,11 +78,14 @@ func NewBearerTokenPolicy(cred exported.TokenCredential, scopes []string, opts * return authNZ(policy.TokenRequestOptions{Scopes: scopes}) } } + mr := temporal.NewResourceWithOptions(acquire, temporal.ResourceOptions[exported.AccessToken, acquiringResourceState]{ + ShouldRefresh: shouldRefresh, + }) return &BearerTokenPolicy{ authzHandler: ah, cred: cred, scopes: scopes, - mainResource: temporal.NewResource(acquire), + mainResource: mr, allowHTTP: opts.InsecureAllowCredentialWithHTTP, } } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md index 11c64eb294..84e7941e4f 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/CHANGELOG.md @@ -1,5 +1,29 @@ # Release History +## 1.10.1 (2025-06-10) + +### Bugs Fixed +- `AzureCLICredential` and `AzureDeveloperCLICredential` could wait indefinitely for subprocess output + +## 1.10.0 (2025-05-14) + +### Features Added +- `DefaultAzureCredential` reads environment variable `AZURE_TOKEN_CREDENTIALS` to enable a subset of its credentials: + - `dev` selects `AzureCLICredential` and `AzureDeveloperCLICredential` + - `prod` selects `EnvironmentCredential`, `WorkloadIdentityCredential` and `ManagedIdentityCredential` + +## 1.9.0 (2025-04-08) + +### Features Added +* `GetToken()` sets `AccessToken.RefreshOn` when the token provider specifies a value + +### Other Changes +* `NewManagedIdentityCredential` logs the configured user-assigned identity, if any +* Deprecated `UsernamePasswordCredential` because it can't support multifactor + authentication (MFA), which Microsoft Entra ID requires for most tenants. See + https://aka.ms/azsdk/identity/mfa for migration guidance. +* Updated dependencies + ## 1.8.2 (2025-02-12) ### Other Changes diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md index 5cc64c08f2..069bc688d5 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/README.md @@ -21,7 +21,7 @@ go get -u github.com/Azure/azure-sdk-for-go/sdk/azidentity ## Prerequisites - an [Azure subscription](https://azure.microsoft.com/free/) -- Go 1.18 +- [Supported](https://aka.ms/azsdk/go/supported-versions) version of Go ### Authenticating during local development @@ -146,7 +146,6 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil) |-|- |[InteractiveBrowserCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#InteractiveBrowserCredential)|Interactively authenticate a user with the default web browser |[DeviceCodeCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DeviceCodeCredential)|Interactively authenticate a user on a device with limited UI -|[UsernamePasswordCredential](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#UsernamePasswordCredential)|Authenticate a user with a username and password ### Authenticating via Development Tools @@ -159,7 +158,7 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil) `DefaultAzureCredential` and `EnvironmentCredential` can be configured with environment variables. Each type of authentication requires values for specific variables: -#### Service principal with secret +### Service principal with secret |variable name|value |-|- @@ -167,7 +166,7 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil) |`AZURE_TENANT_ID`|ID of the application's Microsoft Entra tenant |`AZURE_CLIENT_SECRET`|one of the application's client secrets -#### Service principal with certificate +### Service principal with certificate |variable name|value |-|- @@ -176,16 +175,7 @@ client := armresources.NewResourceGroupsClient("subscription ID", chain, nil) |`AZURE_CLIENT_CERTIFICATE_PATH`|path to a certificate file including private key |`AZURE_CLIENT_CERTIFICATE_PASSWORD`|password of the certificate file, if any -#### Username and password - -|variable name|value -|-|- -|`AZURE_CLIENT_ID`|ID of a Microsoft Entra application -|`AZURE_USERNAME`|a username (usually an email address) -|`AZURE_PASSWORD`|that user's password - -Configuration is attempted in the above order. For example, if values for a -client secret and certificate are both present, the client secret will be used. +Configuration is attempted in the above order. For example, if values for a client secret and certificate are both present, the client secret will be used. ## Token caching diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD index 8fc7c64aa3..da2094e36b 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TOKEN_CACHING.MD @@ -22,11 +22,11 @@ Some credential types support opt-in persistent token caching (see [the below ta Persistent caches are encrypted at rest using a mechanism that depends on the operating system: -| Operating system | Encryption facility | -| ---------------- | ---------------------------------------------- | -| Linux | kernel key retention service (keyctl) | -| macOS | Keychain (requires cgo and native build tools) | -| Windows | Data Protection API (DPAPI) | +| Operating system | Encryption facility | Limitations | +| ---------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Linux | kernel key retention service (keyctl) | Cache data is lost on system shutdown because kernel keys are stored in memory. Depending on kernel compile options, data may also be lost on logout, or storage may be impossible because the key retention service isn't available. | +| macOS | Keychain | Building requires cgo and native build tools. Keychain access requires a graphical session, so persistent caching isn't possible in a headless environment such as an SSH session (macOS as host). | +| Windows | Data Protection API (DPAPI) | No specific limitations. | Persistent caching requires encryption. When the required encryption facility is unuseable, or the application is running on an unsupported OS, the persistent cache constructor returns an error. This doesn't mean that authentication is impossible, only that credentials can't persist authentication data and the application will need to reauthenticate the next time it runs. See the package documentation for examples showing how to configure persistent caching and access cached data for [users][user_example] and [service principals][sp_example]. @@ -50,7 +50,6 @@ The following table indicates the state of in-memory and persistent caching in e | `InteractiveBrowserCredential` | Supported | Supported | | `ManagedIdentityCredential` | Supported | Not Supported | | `OnBehalfOfCredential` | Supported | Not Supported | -| `UsernamePasswordCredential` | Supported | Supported | | `WorkloadIdentityCredential` | Supported | Supported | [sp_example]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#example-package-PersistentServicePrincipalAuthentication diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md index 9c4b1cd71c..91f4f05cc0 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azidentity/TROUBLESHOOTING.md @@ -20,7 +20,6 @@ This troubleshooting guide covers failure investigation techniques, common error - [Azure App Service and Azure Functions managed identity](#azure-app-service-and-azure-functions-managed-identity) - [Azure Kubernetes Service managed identity](#azure-kubernetes-service-managed-identity) - [Azure Virtual Machine managed identity](#azure-virtual-machine-managed-identity) -- [Troubleshoot UsernamePasswordCredential authentication issues](#troubleshoot-usernamepasswordcredential-authentication-issues) - [Troubleshoot WorkloadIdentityCredential authentication issues](#troubleshoot-workloadidentitycredential-authentication-issues) - [Get additional help](#get-additional-help) @@ -111,13 +110,6 @@ azlog.SetEvents(azidentity.EventAuthentication) |AADSTS700027|Client assertion contains an invalid signature.|Ensure the specified certificate has been uploaded to the application registration as described in [Microsoft Entra ID documentation](https://learn.microsoft.com/entra/identity-platform/howto-create-service-principal-portal#option-1-upload-a-certificate).| |AADSTS700016|The specified application wasn't found in the specified tenant.|Ensure the client and tenant IDs provided to the credential constructor are correct for your application registration. For multi-tenant apps, ensure the application has been added to the desired tenant by a tenant admin. To add a new application in the desired tenant, follow the [Microsoft Entra ID instructions](https://learn.microsoft.com/entra/identity-platform/howto-create-service-principal-portal).| - -## Troubleshoot UsernamePasswordCredential authentication issues - -| Error Code | Issue | Mitigation | -|---|---|---| -|AADSTS50126|The provided username or password is invalid.|Ensure the username and password provided to the credential constructor are valid.| - ## Troubleshoot ManagedIdentityCredential authentication issues @@ -181,6 +173,7 @@ curl "$IDENTITY_ENDPOINT?resource=https://management.core.windows.net&api-versio |---|---|---| |Azure CLI not found on path|The Azure CLI isn’t installed or isn't on the application's path.|| |Please run 'az login' to set up account|No account is currently logged into the Azure CLI, or the login has expired.|| +|Subscription "[your subscription]" contains invalid characters. If this is the name of a subscription, use its ID instead|The subscription name contains a character that may not be safe in a command line.|Use the subscription's ID instead of its name. You can get this from the Azure CLI: `az account show --name "[your subscription]" --query "id"` #### Verify the Azure CLI can obtain tokens @@ -226,7 +219,7 @@ azd auth token --output json --scope https://management.core.windows.net/.defaul | Error Message |Description| Mitigation | |---|---|---| -|no client ID/tenant ID/token file specified|Incomplete configuration|In most cases these values are provided via environment variables set by Azure Workload Identity.