@@ -14,6 +14,7 @@ import (
1414 "time"
1515
1616 "github.com/juju/bundlechanges"
17+ "github.com/juju/cmd"
1718 "github.com/juju/errors"
1819 "github.com/juju/utils"
1920 "gopkg.in/juju/charm.v6-unstable"
@@ -61,7 +62,7 @@ func deployBundle(
6162 bundleConfigFile string ,
6263 channel csparams.Channel ,
6364 apiRoot DeployAPI ,
64- log deploymentLogger ,
65+ ctx * cmd. Context ,
6566 bundleStorage map [string ]map [string ]storage.Constraints ,
6667) (map [* charm.URL ]* macaroon.Macaroon , error ) {
6768
@@ -78,6 +79,10 @@ func deployBundle(
7879 }
7980 var verifyError error
8081 if bundleDir == "" {
82+ // Process includes in the bundle data.
83+ if err := processBundleIncludes (ctx .Dir , data ); err != nil {
84+ return nil , errors .Annotate (err , "unable to process includes" )
85+ }
8186 verifyError = data .Verify (verifyConstraints , verifyStorage )
8287 } else {
8388 // Process includes in the bundle data.
@@ -128,7 +133,7 @@ func deployBundle(
128133 channel : channel ,
129134 api : apiRoot ,
130135 bundleStorage : bundleStorage ,
131- log : log ,
136+ ctx : ctx ,
132137 data : data ,
133138 unitStatus : unitStatus ,
134139 ignoredMachines : make (map [string ]bool , len (data .Applications )),
@@ -211,9 +216,10 @@ type bundleHandler struct {
211216 // in the bundle itself.
212217 bundleStorage map [string ]map [string ]storage.Constraints
213218
214- // log is used to output messages to the user, so that the user can keep
215- // track of the bundle deployment progress.
216- log deploymentLogger
219+ // ctx is the command context, which is used to output messages to the
220+ // user, so that the user can keep track of the bundle deployment
221+ // progress.
222+ ctx * cmd.Context
217223
218224 // data is the original bundle data that we want to deploy.
219225 data * charm.BundleData
@@ -341,6 +347,9 @@ func (h *bundleHandler) addService(
341347 }
342348 resources := make (map [string ]string )
343349 for resName , path := range p .LocalResources {
350+ if ! filepath .IsAbs (path ) {
351+ path = filepath .Clean (filepath .Join (h .bundleDir , path ))
352+ }
344353 resources [resName ] = path
345354 }
346355 for resName , revision := range p .Resources {
@@ -385,7 +394,7 @@ func (h *bundleHandler) addService(
385394
386395 // Deploy the application.
387396 logger .Debugf ("application %s is deploying (charm %s)" , p .Application , ch )
388- h .log .Infof ("Deploying charm %q" , ch )
397+ h .ctx .Infof ("Deploying charm %q" , ch )
389398 if err := api .Deploy (application.DeployArgs {
390399 CharmID : chID ,
391400 Cons : cons ,
@@ -397,7 +406,7 @@ func (h *bundleHandler) addService(
397406 EndpointBindings : p .EndpointBindings ,
398407 }); err == nil {
399408 for resName := range resNames2IDs {
400- h .log .Infof ("added resource %s" , resName )
409+ h .ctx .Infof ("added resource %s" , resName )
401410 }
402411 return nil
403412 } else if ! isErrServiceExists (err ) {
@@ -420,15 +429,15 @@ func (h *bundleHandler) addService(
420429 // by the application Deploy call above.
421430 return errors .Annotatef (err , "cannot update options for application %q" , p .Application )
422431 }
423- h .log .Infof ("configuration updated for application %s" , p .Application )
432+ h .ctx .Infof ("configuration updated for application %s" , p .Application )
424433 }
425434 // Update application constraints.
426435 if p .Constraints != "" {
427436 if err := h .api .SetConstraints (p .Application , cons ); err != nil {
428437 // This should never happen, as the bundle is already verified.
429438 return errors .Annotatef (err , "cannot update constraints for application %q" , p .Application )
430439 }
431- h .log .Infof ("constraints applied for application %s" , p .Application )
440+ h .ctx .Infof ("constraints applied for application %s" , p .Application )
432441 }
433442 return nil
434443}
@@ -465,7 +474,7 @@ func (h *bundleHandler) addMachine(id string, p bundlechanges.AddMachineParams)
465474 default :
466475 msg = strings .Join (notify [:svcLen - 1 ], ", " ) + " and " + notify [svcLen - 1 ]
467476 }
468- h .log .Infof ("avoid creating other machines to host %s units" , msg )
477+ h .ctx .Infof ("avoid creating other machines to host %s units" , msg )
469478 return nil
470479 }
471480 cons , err := constraints .Parse (p .Constraints )
@@ -483,7 +492,7 @@ func (h *bundleHandler) addMachine(id string, p bundlechanges.AddMachineParams)
483492 // placement directives as lxd.
484493 if ct == "lxc" {
485494 if ! h .warnedLXC {
486- h .log .Infof ("Bundle has one or more containers specified as lxc. lxc containers are deprecated in Juju 2.0. lxd containers will be deployed instead." )
495+ h .ctx .Infof ("Bundle has one or more containers specified as lxc. lxc containers are deprecated in Juju 2.0. lxd containers will be deployed instead." )
487496 h .warnedLXC = true
488497 }
489498 ct = string (instance .LXD )
@@ -527,7 +536,7 @@ func (h *bundleHandler) addRelation(id string, p bundlechanges.AddRelationParams
527536 _ , err := h .api .AddRelation ([]string {ep1 , ep2 }, nil )
528537 if err == nil {
529538 // A new relation has been established.
530- h .log .Infof ("Related %q and %q" , ep1 , ep2 )
539+ h .ctx .Infof ("Related %q and %q" , ep1 , ep2 )
531540 return nil
532541 }
533542 if isErrRelationExists (err ) {
@@ -555,7 +564,7 @@ func (h *bundleHandler) addUnit(id string, p bundlechanges.AddUnitParams) error
555564 } else {
556565 msg = fmt .Sprintf ("%d units already present" , num )
557566 }
558- h .log .Infof ("avoid adding new units to application %s: %s" , applicationName , msg )
567+ h .ctx .Infof ("avoid adding new units to application %s: %s" , applicationName , msg )
559568 }
560569 return nil
561570 }
@@ -605,7 +614,7 @@ func (h *bundleHandler) exposeService(id string, p bundlechanges.ExposeParams) e
605614 if err := h .api .Expose (application ); err != nil {
606615 return errors .Annotatef (err , "cannot expose application %s" , application )
607616 }
608- h .log .Infof ("application %s exposed" , application )
617+ h .ctx .Infof ("application %s exposed" , application )
609618 return nil
610619}
611620
@@ -834,7 +843,7 @@ func (h *bundleHandler) upgradeCharm(
834843 return errors .Annotatef (err , "cannot retrieve info for application %q" , applicationName )
835844 }
836845 if existing .String () == id {
837- h .log .Infof ("reusing application %s (charm: %s)" , applicationName , id )
846+ h .ctx .Infof ("reusing application %s (charm: %s)" , applicationName , id )
838847 return nil
839848 }
840849 url , err := charm .ParseURL (id )
@@ -876,9 +885,9 @@ func (h *bundleHandler) upgradeCharm(
876885 if err := h .api .SetCharm (cfg ); err != nil {
877886 return errors .Annotatef (err , "cannot upgrade charm to %q" , id )
878887 }
879- h .log .Infof ("upgraded charm for existing application %s (from %s to %s)" , applicationName , existing , id )
888+ h .ctx .Infof ("upgraded charm for existing application %s (from %s to %s)" , applicationName , existing , id )
880889 for resName := range resNames2IDs {
881- h .log .Infof ("added resource %s" , resName )
890+ h .ctx .Infof ("added resource %s" , resName )
882891 }
883892 return nil
884893}
@@ -902,6 +911,8 @@ func isErrRelationExists(err error) bool {
902911func processBundleIncludes (baseDir string , data * charm.BundleData ) error {
903912
904913 for app , appData := range data .Applications {
914+ // A bundle isn't valid if there are no applications, and applications must
915+ // specify a charm at least, so we know appData must be non-nil.
905916 for key , value := range appData .Options {
906917 result , processed , err := processValue (baseDir , value )
907918 if err != nil {
@@ -923,6 +934,9 @@ func processBundleIncludes(baseDir string, data *charm.BundleData) error {
923934 }
924935
925936 for machine , machineData := range data .Machines {
937+ if machineData == nil {
938+ continue
939+ }
926940 for key , value := range machineData .Annotations {
927941 result , processed , err := processValue (baseDir , value )
928942 if err != nil {
0 commit comments