github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/uniter/runner/jujuc/resource-get.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package jujuc
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/cmd/v3"
    10  	"github.com/juju/errors"
    11  
    12  	jujucmd "github.com/juju/juju/cmd"
    13  )
    14  
    15  // NewResourceGetCmd creates a new ResourceGetCmd for the given hook context.
    16  func NewResourceGetCmd(ctx Context) (cmd.Command, error) {
    17  	return &ResourceGetCmd{ctx: ctx}, nil
    18  }
    19  
    20  // ResourceGetCmd provides the functionality of the resource-get command.
    21  type ResourceGetCmd struct {
    22  	cmd.CommandBase
    23  	ctx ContextResources
    24  
    25  	resourceName string
    26  }
    27  
    28  // TODO(ericsnow) Also provide an indicator of whether or not
    29  // the resource has changed (in addition to the file path)?
    30  
    31  // Info implements cmd.Command.
    32  func (c ResourceGetCmd) Info() *cmd.Info {
    33  	return jujucmd.Info(&cmd.Info{
    34  		Name:    "resource-get",
    35  		Args:    "<resource name>",
    36  		Purpose: "get the path to the locally cached resource file",
    37  		Doc: `
    38  "resource-get" is used while a hook is running to get the local path
    39  to the file for the identified resource. This file is an fs-local copy,
    40  unique to the unit for which the hook is running. It is downloaded from
    41  the controller, if necessary.
    42  
    43  If "resource-get" for a resource has not been run before (for the unit)
    44  then the resource is downloaded from the controller at the revision
    45  associated with the unit's application. That file is stored in the unit's
    46  local cache. If "resource-get" *has* been run before then each
    47  subsequent run syncs the resource with the controller. This ensures
    48  that the revision of the unit-local copy of the resource matches the
    49  revision of the resource associated with the unit's application.
    50  
    51  Either way, the path provided by "resource-get" references the
    52  up-to-date file for the resource. Note that the resource may get
    53  updated on the controller for the application at any time, meaning the
    54  cached copy *may* be out of date at any time after you call
    55  "resource-get". Consequently, the command should be run at every
    56  point where it is critical that the resource be up to date.
    57  
    58  The "upgrade-charm" hook is useful for keeping your charm's resources
    59  on a unit up to date.  Run "resource-get" there for each of your
    60  charm's resources to do so. The hook fires whenever the the file for
    61  one of the application's resources changes on the controller (in addition
    62  to when the charm itself changes). That means it happens in response
    63  to "juju upgrade-charm" as well as to "juju push-resource".
    64  
    65  Note that the "upgrade-charm" hook does not run when the unit is
    66  started up. So be sure to run "resource-get" for your resources in the
    67  "install" hook (or "config-changed", etc.).
    68  
    69  Note that "resource-get" only provides an FS path to the resource file.
    70  It does not provide any information about the resource (e.g. revision).
    71  `,
    72  	})
    73  }
    74  
    75  // Init implements cmd.Command.
    76  func (c *ResourceGetCmd) Init(args []string) error {
    77  	if len(args) < 1 {
    78  		return errors.Errorf("missing required resource name")
    79  	} else if err := cmd.CheckEmpty(args[1:]); err != nil {
    80  		return errors.Trace(err)
    81  	}
    82  	c.resourceName = args[0]
    83  	return nil
    84  }
    85  
    86  // Run implements cmd.Command.
    87  func (c ResourceGetCmd) Run(ctx *cmd.Context) error {
    88  	filePath, err := c.ctx.DownloadResource(c.resourceName)
    89  	if err != nil {
    90  		return errors.Annotate(err, "could not download resource")
    91  	}
    92  
    93  	if _, err := fmt.Fprintf(ctx.Stdout, filePath); err != nil {
    94  		return errors.Annotate(err, "could not write resource path to stdout")
    95  	}
    96  	return nil
    97  }