Skip to content

Commit f4d5b45

Browse files
committedJul 18, 2024
fix(upgrade): fix broken upgrade on k8s
Upgrades on k8s were broken duue to the oci image fat manifest format not being supported by Juju.
1 parent b6ba452 commit f4d5b45

15 files changed

+221
-109
lines changed
 

‎apiserver/facades/client/client/client.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/juju/juju/apiserver/facade"
1717
"github.com/juju/juju/cloudconfig/podcfg"
1818
"github.com/juju/juju/controller"
19+
"github.com/juju/juju/core/arch"
1920
"github.com/juju/juju/core/cache"
2021
"github.com/juju/juju/core/leadership"
2122
"github.com/juju/juju/core/multiwatcher"
@@ -327,6 +328,11 @@ func (c *Client) toolVersionsForCAAS(args params.FindToolsParams, streamsVersion
327328
if err != nil {
328329
return result, errors.Trace(err)
329330
}
331+
332+
wantArch := args.Arch
333+
if wantArch == "" {
334+
wantArch = arch.DefaultArchitecture
335+
}
330336
for _, tag := range tags {
331337
number := tag.AgentVersion()
332338
if number.Compare(current) <= 0 {
@@ -351,21 +357,21 @@ func (c *Client) toolVersionsForCAAS(args params.FindToolsParams, streamsVersion
351357
continue
352358
}
353359
}
354-
arch, err := reg.GetArchitecture(imageName, number.String())
360+
arches, err := reg.GetArchitectures(imageName, number.String())
355361
if errors.IsNotFound(err) {
356362
continue
357363
}
358364
if err != nil {
359365
return result, errors.Annotatef(err, "cannot get architecture for %s:%s", imageName, number.String())
360366
}
361-
if args.Arch != "" && arch != args.Arch {
367+
if !set.NewStrings(arches...).Contains(wantArch) {
362368
continue
363369
}
364370
tools := tools.Tools{
365371
Version: version.Binary{
366372
Number: number,
367373
Release: coreos.HostOSTypeName(),
368-
Arch: arch,
374+
Arch: wantArch,
369375
},
370376
}
371377
result.List = append(result.List, &tools)

‎apiserver/facades/client/client/client_test.go

+21-10
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,15 @@ func (s *findToolsSuite) getModelConfig(c *gc.C, agentVersion string) *config.Co
488488
return mCfg
489489
}
490490

491+
func (s *findToolsSuite) TestFindToolsCAASReleasedDefault(c *gc.C) {
492+
s.assertFindToolsCAASReleased(c, "", "amd64")
493+
}
494+
491495
func (s *findToolsSuite) TestFindToolsCAASReleased(c *gc.C) {
496+
s.assertFindToolsCAASReleased(c, "arm64", "arm64")
497+
}
498+
499+
func (s *findToolsSuite) assertFindToolsCAASReleased(c *gc.C, wantArch, expectArch string) {
492500
ctrl := gomock.NewController(c)
493501
defer ctrl.Finish()
494502

@@ -502,6 +510,9 @@ func (s *findToolsSuite) TestFindToolsCAASReleased(c *gc.C) {
502510
{Version: version.MustParseBinary("2.9.9-ubuntu-amd64")},
503511
{Version: version.MustParseBinary("2.9.10-ubuntu-amd64")},
504512
{Version: version.MustParseBinary("2.9.11-ubuntu-amd64")},
513+
{Version: version.MustParseBinary("2.9.9-ubuntu-arm64")},
514+
{Version: version.MustParseBinary("2.9.10-ubuntu-arm64")},
515+
{Version: version.MustParseBinary("2.9.11-ubuntu-arm64")},
505516
}
506517
s.PatchValue(&coreos.HostOS, func() coreos.OSType { return coreos.Ubuntu })
507518

@@ -513,7 +524,7 @@ func (s *findToolsSuite) TestFindToolsCAASReleased(c *gc.C) {
513524
authorizer.EXPECT().HasPermission(permission.WriteAccess, coretesting.ModelTag).Return(nil),
514525

515526
backend.EXPECT().Model().Return(model, nil),
516-
toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{MajorVersion: 2}).
527+
toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{MajorVersion: 2, Arch: wantArch}).
517528
Return(simpleStreams, nil),
518529
model.EXPECT().Type().Return(state.ModelTypeCAAS),
519530
model.EXPECT().Config().Return(s.getModelConfig(c, "2.9.9"), nil),
@@ -536,8 +547,8 @@ func (s *findToolsSuite) TestFindToolsCAASReleased(c *gc.C) {
536547
image.NewImageInfo(version.MustParse("2.9.11")),
537548
image.NewImageInfo(version.MustParse("2.9.12")), // skip: it's not released in simplestream yet.
538549
}, nil),
539-
registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.10").Return("amd64", nil),
540-
registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.11").Return("amd64", nil),
550+
registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.10").Return([]string{"amd64", "arm64"}, nil),
551+
registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.11").Return([]string{"amd64", "arm64"}, nil),
541552
registryProvider.EXPECT().Close().Return(nil),
542553
)
543554

@@ -558,12 +569,12 @@ func (s *findToolsSuite) TestFindToolsCAASReleased(c *gc.C) {
558569
},
559570
)
560571
c.Assert(err, jc.ErrorIsNil)
561-
result, err := api.FindTools(params.FindToolsParams{MajorVersion: 2})
572+
result, err := api.FindTools(params.FindToolsParams{MajorVersion: 2, Arch: wantArch})
562573
c.Assert(err, jc.ErrorIsNil)
563574
c.Assert(result, gc.DeepEquals, params.FindToolsResult{
564575
List: []*tools.Tools{
565-
{Version: version.MustParseBinary("2.9.10-ubuntu-amd64")},
566-
{Version: version.MustParseBinary("2.9.11-ubuntu-amd64")},
576+
{Version: version.MustParseBinary("2.9.10-ubuntu-" + expectArch)},
577+
{Version: version.MustParseBinary("2.9.11-ubuntu-" + expectArch)},
567578
},
568579
})
569580
}
@@ -618,10 +629,10 @@ func (s *findToolsSuite) TestFindToolsCAASNonReleased(c *gc.C) {
618629
image.NewImageInfo(version.MustParse("2.9.12")),
619630
image.NewImageInfo(version.MustParse("2.9.13")), // skip: it's not released in simplestream yet.
620631
}, nil),
621-
registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.10.1").Return("amd64", nil),
622-
registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.10").Return("amd64", nil),
623-
registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.11").Return("amd64", nil),
624-
registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.12").Return("", errors.NotFoundf("2.9.12")), // This can only happen on a non-official registry account.
632+
registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.10.1").Return([]string{"amd64", "arm64"}, nil),
633+
registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.10").Return([]string{"amd64", "arm64"}, nil),
634+
registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.11").Return([]string{"amd64", "arm64"}, nil),
635+
registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.12").Return(nil, errors.NotFoundf("2.9.12")), // This can only happen on a non-official registry account.
625636
registryProvider.EXPECT().Close().Return(nil),
626637
)
627638

‎apiserver/facades/client/modelupgrader/findagents.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/juju/juju/apiserver/common"
1212
"github.com/juju/juju/cloudconfig/podcfg"
1313
"github.com/juju/juju/controller"
14+
"github.com/juju/juju/core/arch"
1415
coreos "github.com/juju/juju/core/os"
1516
"github.com/juju/juju/docker"
1617
envtools "github.com/juju/juju/environs/tools"
@@ -121,6 +122,11 @@ func (m *ModelUpgraderAPI) agentVersionsForCAAS(
121122
if err != nil {
122123
return nil, errors.Trace(err)
123124
}
125+
126+
wantArch := args.Arch
127+
if wantArch == "" {
128+
wantArch = arch.DefaultArchitecture
129+
}
124130
for _, tag := range tags {
125131
number := tag.AgentVersion()
126132
if args.MajorVersion > 0 {
@@ -145,21 +151,21 @@ func (m *ModelUpgraderAPI) agentVersionsForCAAS(
145151
continue
146152
}
147153
}
148-
arch, err := reg.GetArchitecture(imageName, number.String())
154+
arches, err := reg.GetArchitectures(imageName, number.String())
149155
if errors.Is(err, errors.NotFound) {
150156
continue
151157
}
152158
if err != nil {
153159
return nil, errors.Annotatef(err, "cannot get architecture for %s:%s", imageName, number.String())
154160
}
155-
if args.Arch != "" && arch != args.Arch {
161+
if !set.NewStrings(arches...).Contains(wantArch) {
156162
continue
157163
}
158164
tools := coretools.Tools{
159165
Version: version.Binary{
160166
Number: number,
161167
Release: coreos.HostOSTypeName(),
162-
Arch: arch,
168+
Arch: wantArch,
163169
},
164170
}
165171
result = append(result, &tools)

‎apiserver/facades/client/modelupgrader/upgrader_test.go

+28-15
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,15 @@ func (s *modelUpgradeSuite) TestFindToolsIAAS(c *gc.C) {
774774
})
775775
}
776776

777+
func (s *modelUpgradeSuite) TestFindToolsCAASReleasedDefault(c *gc.C) {
778+
s.assertFindToolsCAASReleased(c, "", "amd64")
779+
}
780+
777781
func (s *modelUpgradeSuite) TestFindToolsCAASReleased(c *gc.C) {
782+
s.assertFindToolsCAASReleased(c, "arm64", "arm64")
783+
}
784+
785+
func (s *modelUpgradeSuite) assertFindToolsCAASReleased(c *gc.C, wantArch, expectArch string) {
778786
ctrl, api := s.getModelUpgraderAPI(c)
779787
defer ctrl.Finish()
780788

@@ -786,13 +794,17 @@ func (s *modelUpgradeSuite) TestFindToolsCAASReleased(c *gc.C) {
786794
{Version: version.MustParseBinary("2.9.9-ubuntu-amd64")},
787795
{Version: version.MustParseBinary("2.9.10-ubuntu-amd64")},
788796
{Version: version.MustParseBinary("2.9.11-ubuntu-amd64")},
797+
{Version: version.MustParseBinary("2.9.9-ubuntu-arm64")},
798+
{Version: version.MustParseBinary("2.9.10-ubuntu-arm64")},
799+
{Version: version.MustParseBinary("2.9.11-ubuntu-arm64")},
789800
}
790801
s.PatchValue(&coreos.HostOS, func() coreos.OSType { return coreos.Ubuntu })
791802

792803
gomock.InOrder(
793804
s.toolsFinder.EXPECT().FindAgents(common.FindAgentsParams{
794805
MajorVersion: 2, MinorVersion: 9,
795806
ModelType: state.ModelTypeCAAS,
807+
Arch: wantArch,
796808
}).Return(simpleStreams, nil),
797809
s.registryProvider.EXPECT().Tags("jujud-operator").Return(coretools.Versions{
798810
image.NewImageInfo(version.MustParse("2.9.8")),
@@ -802,20 +814,21 @@ func (s *modelUpgradeSuite) TestFindToolsCAASReleased(c *gc.C) {
802814
image.NewImageInfo(version.MustParse("2.9.11")),
803815
image.NewImageInfo(version.MustParse("2.9.12")), // skip: it's not released in simplestream yet.
804816
}, nil),
805-
s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.9").Return("amd64", nil),
806-
s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.10.1").Return("amd64", nil),
807-
s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.10").Return("amd64", nil),
808-
s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.11").Return("amd64", nil),
817+
s.registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.9").Return([]string{"amd64", "arm64"}, nil),
818+
s.registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.10.1").Return([]string{"amd64", "arm64"}, nil),
819+
s.registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.10").Return([]string{"amd64", "arm64"}, nil),
820+
s.registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.11").Return([]string{"amd64", "arm64"}, nil),
809821
s.registryProvider.EXPECT().Close().Return(nil),
810822
)
811823

812-
result, err := api.FindAgents(common.FindAgentsParams{MajorVersion: 2, MinorVersion: 9, ModelType: state.ModelTypeCAAS})
824+
result, err := api.FindAgents(common.FindAgentsParams{
825+
MajorVersion: 2, MinorVersion: 9, ModelType: state.ModelTypeCAAS, Arch: wantArch})
813826
c.Assert(err, jc.ErrorIsNil)
814827
c.Assert(result, gc.DeepEquals, coretools.Versions{
815-
&coretools.Tools{Version: version.MustParseBinary("2.9.9-ubuntu-amd64")},
816-
&coretools.Tools{Version: version.MustParseBinary("2.9.10.1-ubuntu-amd64")},
817-
&coretools.Tools{Version: version.MustParseBinary("2.9.10-ubuntu-amd64")},
818-
&coretools.Tools{Version: version.MustParseBinary("2.9.11-ubuntu-amd64")},
828+
&coretools.Tools{Version: version.MustParseBinary("2.9.9-ubuntu-" + expectArch)},
829+
&coretools.Tools{Version: version.MustParseBinary("2.9.10.1-ubuntu-" + expectArch)},
830+
&coretools.Tools{Version: version.MustParseBinary("2.9.10-ubuntu-" + expectArch)},
831+
&coretools.Tools{Version: version.MustParseBinary("2.9.11-ubuntu-" + expectArch)},
819832
})
820833
}
821834

@@ -845,7 +858,7 @@ func (s *modelUpgradeSuite) TestFindToolsCAASReleasedExact(c *gc.C) {
845858
image.NewImageInfo(version.MustParse("2.9.11")),
846859
image.NewImageInfo(version.MustParse("2.9.12")),
847860
}, nil),
848-
s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.10").Return("amd64", nil),
861+
s.registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.10").Return([]string{"amd64"}, nil),
849862
s.registryProvider.EXPECT().Close().Return(nil),
850863
)
851864

@@ -887,11 +900,11 @@ func (s *modelUpgradeSuite) TestFindToolsCAASNonReleased(c *gc.C) {
887900
image.NewImageInfo(version.MustParse("2.9.12")),
888901
image.NewImageInfo(version.MustParse("2.9.13")), // skip: it's not released in simplestream yet.
889902
}, nil),
890-
s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.9").Return("amd64", nil),
891-
s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.10.1").Return("amd64", nil),
892-
s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.10").Return("amd64", nil),
893-
s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.11").Return("amd64", nil),
894-
s.registryProvider.EXPECT().GetArchitecture("jujud-operator", "2.9.12").Return("", errors.NotFoundf("2.9.12")), // This can only happen on a non-official registry account.
903+
s.registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.9").Return([]string{"amd64", "arm64"}, nil),
904+
s.registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.10.1").Return([]string{"amd64", "arm64"}, nil),
905+
s.registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.10").Return([]string{"amd64", "arm64"}, nil),
906+
s.registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.11").Return([]string{"amd64", "arm64"}, nil),
907+
s.registryProvider.EXPECT().GetArchitectures("jujud-operator", "2.9.12").Return(nil, errors.NotFoundf("2.9.12")), // This can only happen on a non-official registry account.
895908
s.registryProvider.EXPECT().Close().Return(nil),
896909
)
897910

‎docker/registry/internal/acr.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,16 @@ func normalizeRepoDetailsAzure(repoDetails *docker.ImageRepoDetails) error {
3333
return nil
3434
}
3535

36-
func (c *azureContainerRegistry) String() string {
36+
func (c azureContainerRegistry) String() string {
3737
return "azurecr.io"
3838
}
3939

4040
// Match checks if the repository details matches current provider format.
41-
func (c *azureContainerRegistry) Match() bool {
41+
func (c azureContainerRegistry) Match() bool {
4242
return strings.Contains(c.repoDetails.ServerAddress, "azurecr.io")
4343
}
4444

45-
func (c *azureContainerRegistry) WrapTransport(...TransportWrapper) error {
45+
func (c azureContainerRegistry) WrapTransport(...TransportWrapper) error {
4646
if c.repoDetails.BasicAuthConfig.Empty() {
4747
return errors.NewNotValid(nil, fmt.Sprintf(`username and password are required for registry %q`, c.repoDetails.Repository))
4848
}
@@ -57,9 +57,9 @@ func (c azureContainerRegistry) Tags(imageName string) (versions tools.Versions,
5757
return c.fetchTags(url, &response)
5858
}
5959

60-
// GetArchitecture returns the archtecture of the image for the specified tag.
61-
func (c azureContainerRegistry) GetArchitecture(imageName, tag string) (string, error) {
62-
return getArchitecture(imageName, tag, c)
60+
// GetArchitectures returns the architectures of the image for the specified tag.
61+
func (c azureContainerRegistry) GetArchitectures(imageName, tag string) ([]string, error) {
62+
return getArchitectures(imageName, tag, c)
6363
}
6464

6565
// GetManifests returns the manifests of the image for the specified tag.

‎docker/registry/internal/acr_test.go

+19-2
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,10 @@ func (s *azureContainerRegistrySuite) assertGetManifestsSchemaVersion1(c *gc.C,
294294
func (s *azureContainerRegistrySuite) TestGetManifestsSchemaVersion1(c *gc.C) {
295295
s.assertGetManifestsSchemaVersion1(c,
296296
`
297-
{ "schemaVersion": 1, "name": "jujuqa/jujud-operator", "tag": "2.9.13", "architecture": "amd64"}
297+
{ "schemaVersion": 1, "name": "jujuqa/jujud-operator", "tag": "2.9.13", "architecture": "ppc64le"}
298298
`[1:],
299299
`application/vnd.docker.distribution.manifest.v1+prettyjws`,
300-
&internal.ManifestsResult{Architecture: "amd64"},
300+
&internal.ManifestsResult{Architectures: []string{"ppc64el"}},
301301
)
302302
}
303303

@@ -319,6 +319,23 @@ func (s *azureContainerRegistrySuite) TestGetManifestsSchemaVersion2(c *gc.C) {
319319
)
320320
}
321321

322+
func (s *azureContainerRegistrySuite) TestGetManifestsSchemaVersion2List(c *gc.C) {
323+
s.assertGetManifestsSchemaVersion1(c,
324+
`
325+
{
326+
"schemaVersion": 2,
327+
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
328+
"manifests": [
329+
{"platform": {"architecture": "amd64"}},
330+
{"platform": {"architecture": "ppc64le"}}
331+
]
332+
}
333+
`[1:],
334+
`application/vnd.docker.distribution.manifest.list.v2+prettyjws`,
335+
&internal.ManifestsResult{Architectures: []string{"amd64", "ppc64el"}},
336+
)
337+
}
338+
322339
func (s *azureContainerRegistrySuite) TestGetBlobs(c *gc.C) {
323340
// Use v2 for private repository.
324341
s.isPrivate = true

‎docker/registry/internal/base_client.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,12 @@ func commonURLGetter(version APIVersion, url url.URL, pathTemplate string, args
194194
return url.String()
195195
}
196196

197-
func (c baseClient) url(pathTemplate string, args ...interface{}) string {
197+
func (c *baseClient) url(pathTemplate string, args ...interface{}) string {
198198
return commonURLGetter(c.APIVersion(), *c.baseURL, pathTemplate, args...)
199199
}
200200

201201
// Ping pings the baseClient endpoint.
202-
func (c baseClient) Ping() error {
202+
func (c *baseClient) Ping() error {
203203
url := c.url("/")
204204
logger.Debugf("baseClient ping %q", url)
205205
resp, err := c.client.Get(url)
@@ -209,7 +209,7 @@ func (c baseClient) Ping() error {
209209
return errors.Trace(unwrapNetError(err))
210210
}
211211

212-
func (c baseClient) ImageRepoDetails() (o docker.ImageRepoDetails) {
212+
func (c *baseClient) ImageRepoDetails() (o docker.ImageRepoDetails) {
213213
if c.repoDetails != nil {
214214
return *c.repoDetails
215215
}
@@ -224,7 +224,7 @@ func (c *baseClient) Close() error {
224224
return nil
225225
}
226226

227-
func (c baseClient) getPaginatedJSON(url string, response interface{}) (string, error) {
227+
func (c *baseClient) getPaginatedJSON(url string, response interface{}) (string, error) {
228228
resp, err := c.client.Get(url)
229229
logger.Tracef("getPaginatedJSON for %q, err %v", url, err)
230230
if err != nil {

0 commit comments

Comments
 (0)
fix(upgrade): fix broken upgrade on k8s &middot; JoseFMP/juju@f4d5b45 · GitHub