Skip to content

Commit

Permalink
Support bases in bundles
Browse files Browse the repository at this point in the history
This commit backports _some_ of the changes from the PR
juju#15725

However, instead of converting to bases at the edge, we convert to
series at the edge. This is because there are a lot of changes in later
versions that using bases throughout depends on which are not present in
3.1, which would require expensive backports

We also do NOT backport changes to GetChanges and GetChangesMapArgs, as
they are not required to backport this feature. This simplifies the
change significantly
  • Loading branch information
jack-w-shaw committed Aug 21, 2023
1 parent ebd4632 commit d338beb
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 17 deletions.
2 changes: 1 addition & 1 deletion api/common/charms/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ func (c *charmImpl) Revision() int {

func convertCharmManifest(input *params.CharmManifest) (*charm.Manifest, error) {
if input == nil {
return &charm.Manifest{}, nil
return nil, nil
}
res := []charm.Base(nil)
for _, v := range input.Bases {
Expand Down
1 change: 0 additions & 1 deletion api/common/charms/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ func (s *suite) TestApplicationCharmInfo(c *gc.C) {
Name: "foobar",
MinJujuVersion: version.MustParse("2.9.0"),
},
Manifest: &charm.Manifest{},
}
c.Assert(got, gc.DeepEquals, want)
}
1 change: 1 addition & 0 deletions apiserver/facades/client/bundle/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ func (b *BundleAPI) GetChangesMapArgs(args params.BundleChangesParams) (params.B
}
return b.doGetBundleChangesMapArgs(args, vs, func(changes []bundlechanges.Change, results *params.BundleChangesMapArgsResults) error {
results.Changes = make([]*params.BundleChangesMapArgs, len(changes))
results.Errors = make([]string, len(changes))
for i, c := range changes {
args, err := c.Args()
if err != nil {
Expand Down
11 changes: 6 additions & 5 deletions cmd/juju/application/deployer/bundlehandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,12 +339,13 @@ func (h *bundleHandler) resolveCharmsAndEndpoints() error {
}

var base corebase.Base
if spec.Series != "" {
var err error
if spec.Base != "" {
base, err = corebase.ParseBaseFromString(spec.Base)
} else if spec.Series != "" {
base, err = corebase.GetBaseFromSeries(spec.Series)
if err != nil {
return errors.Trace(err)
}
}
if err != nil {
return errors.Trace(err)
}

channel, origin, err := h.constructChannelAndOrigin(ch, base, spec.Channel, cons)
Expand Down
5 changes: 4 additions & 1 deletion core/bundle/changes/changes.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ func FromData(config ChangesConfig) ([]Change, error) {

var addedMachines map[string]*AddMachineChange
if resolver.bundle.Type != kubernetes {
addedMachines = resolver.handleMachines()
addedMachines, err = resolver.handleMachines()
if err != nil {
return nil, errors.Trace(err)
}
}

deployedBundleApps := alreadyDeployedApplicationsFromBundle(model, config.Bundle.Applications)
Expand Down
187 changes: 187 additions & 0 deletions core/bundle/changes/changes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,193 @@ func (s *changesSuite) TestSimpleBundle(c *gc.C) {
s.assertParseData(c, content, expected)
}

func (s *changesSuite) TestSimpleBundleWithBases(c *gc.C) {
content := `
applications:
mediawiki:
charm: ch:mediawiki
base: ubuntu@20.04
num_units: 1
expose: true
options:
debug: false
annotations:
gui-x: "609"
gui-y: "-15"
resources:
data: 3
mysql:
charm: ch:mysql
base: ubuntu@20.04
num_units: 1
resources:
data: "./resources/data.tar"
default-base: ubuntu@22.04
relations:
- - mediawiki:db
- mysql:db
`
expected := []record{{
Id: "addCharm-0",
Method: "addCharm",
Params: bundlechanges.AddCharmParams{
Charm: "ch:mediawiki",
Series: "focal",
},
GUIArgs: []interface{}{"ch:mediawiki", "focal", ""},
Args: map[string]interface{}{
"charm": "ch:mediawiki",
"series": "focal",
},
}, {
Id: "deploy-1",
Method: "deploy",
Params: bundlechanges.AddApplicationParams{
Charm: "$addCharm-0",
Application: "mediawiki",
Series: "focal",
Options: map[string]interface{}{"debug": false},
Resources: map[string]int{"data": 3},
},
GUIArgs: []interface{}{
"$addCharm-0",
"focal",
"mediawiki",
map[string]interface{}{"debug": false},
"",
map[string]string{},
map[string]string{},
map[string]int{"data": 3},
0,
"",
},
Args: map[string]interface{}{
"application": "mediawiki",
"charm": "$addCharm-0",
"options": map[string]interface{}{
"debug": false,
},
"resources": map[string]interface{}{
"data": float64(3),
},
"series": "focal",
},
Requires: []string{"addCharm-0"},
}, {
Id: "expose-2",
Method: "expose",
Params: bundlechanges.ExposeParams{
Application: "$deploy-1",
},
GUIArgs: []interface{}{"$deploy-1", nil},
Args: map[string]interface{}{
"application": "$deploy-1",
},
Requires: []string{"deploy-1"},
}, {
Id: "setAnnotations-3",
Method: "setAnnotations",
Params: bundlechanges.SetAnnotationsParams{
Id: "$deploy-1",
EntityType: bundlechanges.ApplicationType,
Annotations: map[string]string{"gui-x": "609", "gui-y": "-15"},
},
GUIArgs: []interface{}{
"$deploy-1",
"application",
map[string]string{"gui-x": "609", "gui-y": "-15"},
},
Args: map[string]interface{}{
"annotations": map[string]interface{}{
"gui-x": "609",
"gui-y": "-15",
},
"entity-type": "application",
"id": "$deploy-1",
},
Requires: []string{"deploy-1"},
}, {
Id: "addCharm-4",
Method: "addCharm",
Params: bundlechanges.AddCharmParams{
Charm: "ch:mysql",
Series: "focal",
},
GUIArgs: []interface{}{"ch:mysql", "focal", ""},
Args: map[string]interface{}{
"charm": "ch:mysql",
"series": "focal",
},
}, {
Id: "deploy-5",
Method: "deploy",
Params: bundlechanges.AddApplicationParams{
Charm: "$addCharm-4",
Application: "mysql",
Series: "focal",
LocalResources: map[string]string{"data": "./resources/data.tar"},
},
GUIArgs: []interface{}{
"$addCharm-4",
"focal",
"mysql",
map[string]interface{}{},
"",
map[string]string{},
map[string]string{},
map[string]int{},
0,
"",
},
Args: map[string]interface{}{
"application": "mysql",
"charm": "$addCharm-4",
"local-resources": map[string]interface{}{
"data": "./resources/data.tar",
},
"series": "focal",
},
Requires: []string{"addCharm-4"},
}, {
Id: "addRelation-6",
Method: "addRelation",
Params: bundlechanges.AddRelationParams{
Endpoint1: "$deploy-1:db",
Endpoint2: "$deploy-5:db",
},
GUIArgs: []interface{}{"$deploy-1:db", "$deploy-5:db"},
Args: map[string]interface{}{
"endpoint1": "$deploy-1:db",
"endpoint2": "$deploy-5:db",
},
Requires: []string{"deploy-1", "deploy-5"},
}, {
Id: "addUnit-7",
Method: "addUnit",
Params: bundlechanges.AddUnitParams{
Application: "$deploy-1",
},
GUIArgs: []interface{}{"$deploy-1", nil},
Args: map[string]interface{}{
"application": "$deploy-1",
},
Requires: []string{"deploy-1"},
}, {
Id: "addUnit-8",
Method: "addUnit",
Params: bundlechanges.AddUnitParams{
Application: "$deploy-5",
},
GUIArgs: []interface{}{"$deploy-5", nil},
Args: map[string]interface{}{
"application": "$deploy-5",
},
Requires: []string{"deploy-5"},
}}

s.assertParseData(c, content, expected)
}

func (s *changesSuite) TestSimpleBundleWithDevices(c *gc.C) {
content := `
applications:
Expand Down
66 changes: 57 additions & 9 deletions core/bundle/changes/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,16 @@ type resolver struct {
func (r *resolver) handleApplications() (map[string]string, error) {
add := r.changes.add
applications := r.bundle.Applications
defaultSeries := r.bundle.Series

var defaultSeries string
if r.bundle.Series != "" {
defaultSeries = r.bundle.Series
} else if r.bundle.DefaultBase != "" {
var err error
if defaultSeries, err = baseToSeries(r.bundle.DefaultBase); err != nil {
return nil, errors.Trace(err)
}
}
existing := r.model

charms := make(map[string]string, len(applications))
Expand Down Expand Up @@ -405,12 +414,21 @@ func equalStringSlice(a, b []string) bool {

// handleMachines populates the change set with "addMachines" records.
// This function also handles adding machine annotations.
func (r *resolver) handleMachines() map[string]*AddMachineChange {
func (r *resolver) handleMachines() (map[string]*AddMachineChange, error) {
add := r.changes.add
machines := r.bundle.Machines
defaultSeries := r.bundle.Series
existing := r.model

var defaultSeries string
if r.bundle.Series != "" {
defaultSeries = r.bundle.Series
} else if r.bundle.DefaultBase != "" {
var err error
if defaultSeries, err = baseToSeries(r.bundle.DefaultBase); err != nil {
return nil, errors.Trace(err)
}
}

addedMachines := make(map[string]*AddMachineChange, len(machines))
// Iterate over the map using its sorted keys so that results are
// deterministic and easier to test.
Expand All @@ -427,11 +445,15 @@ func (r *resolver) handleMachines() map[string]*AddMachineChange {
if machine == nil {
machine = &charm.MachineSpec{}
}
series := machine.Series
if series == "" {
series = defaultSeries
series := defaultSeries
if machine.Series != "" {
series = machine.Series
} else if machine.Base != "" {
var err error
if series, err = baseToSeries(machine.Base); err != nil {
return nil, errors.Trace(err)
}
}

var id string
var target string
var requires []string
Expand Down Expand Up @@ -469,7 +491,7 @@ func (r *resolver) handleMachines() map[string]*AddMachineChange {
}, requires...))
}
}
return addedMachines
return addedMachines, nil
}

// handleRelations populates the change set with "addRelation" records.
Expand Down Expand Up @@ -1140,11 +1162,22 @@ func (r *resolver) handleUnits(addedApplications map[string]string, addedMachine
machChangeIDs.Add(v.Id())
}

var defaultSeries string
if r.bundle.Series != "" {
defaultSeries = r.bundle.Series
} else if r.bundle.DefaultBase != "" {
var err error
defaultSeries, err = baseToSeries(r.bundle.DefaultBase)
if err != nil {
return errors.Trace(err)
}
}

processor := &unitProcessor{
add: r.changes.add,
existing: r.model,
bundle: r.bundle,
defaultSeries: r.bundle.Series,
defaultSeries: defaultSeries,
logger: r.logger,
addedApplications: addedApplications,
addedMachines: addedMachines,
Expand Down Expand Up @@ -1260,6 +1293,9 @@ func getSeries(application *charm.ApplicationSpec, defaultSeries string) (string
if application.Series != "" {
return application.Series, nil
}
if application.Base != "" {
return baseToSeries(application.Base)
}

// Handle local charm paths.
if charm.IsValidLocalCharmOrBundlePath(application.Charm) {
Expand Down Expand Up @@ -1295,6 +1331,18 @@ func getSeries(application *charm.ApplicationSpec, defaultSeries string) (string
return defaultSeries, nil
}

func baseToSeries(b string) (string, error) {
base, err := corebase.ParseBaseFromString(b)
if err != nil {
return "", errors.Trace(err)
}
series, err := corebase.GetSeriesFromBase(base)
if err != nil {
return "", errors.Trace(err)
}
return series, nil
}

// parseEndpoint creates an endpoint from its string representation.
func parseEndpoint(e string) *endpoint {
parts := strings.SplitN(e, ":", 2)
Expand Down

0 comments on commit d338beb

Please sign in to comment.