github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/agent/uniter/payload.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package uniter
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names/v5"
     9  
    10  	"github.com/juju/juju/api/base"
    11  	api "github.com/juju/juju/api/client/payloads"
    12  	apiservererrors "github.com/juju/juju/apiserver/errors"
    13  	"github.com/juju/juju/core/payloads"
    14  	"github.com/juju/juju/rpc/params"
    15  )
    16  
    17  // PayloadFacadeClient provides methods for interacting with Juju's internal
    18  // RPC API, relative to payloads.
    19  type PayloadFacadeClient struct {
    20  	FacadeCaller
    21  }
    22  
    23  // NewPayloadFacadeClient builds a new payload API client.
    24  func NewPayloadFacadeClient(caller base.APICaller) *PayloadFacadeClient {
    25  	facadeCaller := base.NewFacadeCaller(caller, "PayloadsHookContext")
    26  	return &PayloadFacadeClient{FacadeCaller: facadeCaller}
    27  }
    28  
    29  // Track calls the Track API server method.
    30  func (c PayloadFacadeClient) Track(payloads ...payloads.Payload) ([]payloads.Result, error) {
    31  	args := payloads2TrackArgs(payloads)
    32  
    33  	var rs params.PayloadResults
    34  	if err := c.FacadeCall("Track", &args, &rs); err != nil {
    35  		return nil, errors.Trace(err)
    36  	}
    37  
    38  	return api2results(rs)
    39  }
    40  
    41  // List calls the List API server method.
    42  func (c PayloadFacadeClient) List(fullIDs ...string) ([]payloads.Result, error) {
    43  	var ids []string
    44  	if len(fullIDs) > 0 {
    45  		actual, err := c.lookUp(fullIDs)
    46  		if err != nil {
    47  			return nil, errors.Trace(err)
    48  		}
    49  		ids = actual
    50  	}
    51  	args := ids2Args(ids)
    52  
    53  	var rs params.PayloadResults
    54  	if err := c.FacadeCall("List", &args, &rs); err != nil {
    55  		return nil, errors.Trace(err)
    56  	}
    57  
    58  	return api2results(rs)
    59  }
    60  
    61  // LookUp calls the LookUp API server method.
    62  func (c PayloadFacadeClient) LookUp(fullIDs ...string) ([]payloads.Result, error) {
    63  	if len(fullIDs) == 0 {
    64  		// Unlike List(), LookUp doesn't fall back to looking up all IDs.
    65  		return nil, nil
    66  	}
    67  	args := fullIDs2LookUpArgs(fullIDs)
    68  
    69  	var rs params.PayloadResults
    70  	if err := c.FacadeCall("LookUp", &args, &rs); err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	return api2results(rs)
    75  }
    76  
    77  // SetStatus calls the SetStatus API server method.
    78  func (c PayloadFacadeClient) SetStatus(status string, fullIDs ...string) ([]payloads.Result, error) {
    79  	ids, err := c.lookUp(fullIDs)
    80  	if err != nil {
    81  		return nil, errors.Trace(err)
    82  	}
    83  	args := ids2SetStatusArgs(ids, status)
    84  
    85  	var rs params.PayloadResults
    86  	if err := c.FacadeCall("SetStatus", &args, &rs); err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	return api2results(rs)
    91  }
    92  
    93  // Untrack calls the Untrack API server method.
    94  func (c PayloadFacadeClient) Untrack(fullIDs ...string) ([]payloads.Result, error) {
    95  	ids, err := c.lookUp(fullIDs)
    96  	if err != nil {
    97  		return nil, errors.Trace(err)
    98  	}
    99  	args := ids2Args(ids)
   100  
   101  	var rs params.PayloadResults
   102  	if err := c.FacadeCall("Untrack", &args, &rs); err != nil {
   103  		return nil, err
   104  	}
   105  
   106  	return api2results(rs)
   107  }
   108  
   109  func (c PayloadFacadeClient) lookUp(fullIDs []string) ([]string, error) {
   110  	results, err := c.LookUp(fullIDs...)
   111  	if err != nil {
   112  		return nil, errors.Annotate(err, "while looking up IDs")
   113  	}
   114  
   115  	var ids []string
   116  	for _, result := range results {
   117  		if result.Error != nil {
   118  			// TODO(ericsnow) Do not short-circuit?
   119  			return nil, errors.Annotate(result.Error, "while looking up IDs")
   120  		}
   121  		ids = append(ids, result.ID)
   122  	}
   123  	return ids, nil
   124  }
   125  
   126  func api2results(rs params.PayloadResults) ([]payloads.Result, error) {
   127  	var results []payloads.Result
   128  	for _, r := range rs.Results {
   129  		result, err := api2Result(r)
   130  		if err != nil {
   131  			// This should not happen; we safely control the result.
   132  			return nil, errors.Trace(err)
   133  		}
   134  		results = append(results, result)
   135  	}
   136  	return results, nil
   137  }
   138  
   139  // api2Result converts the API result to a payloads.Result.
   140  func api2Result(r params.PayloadResult) (payloads.Result, error) {
   141  	result := payloads.Result{
   142  		NotFound: r.NotFound,
   143  	}
   144  
   145  	id, err := api.API2ID(r.Tag)
   146  	if err != nil {
   147  		return result, errors.Trace(err)
   148  	}
   149  	result.ID = id
   150  
   151  	if r.Payload != nil {
   152  		pl, err := api.API2Payload(*r.Payload)
   153  		if err != nil {
   154  			return result, errors.Trace(err)
   155  		}
   156  		result.Payload = &pl
   157  	}
   158  
   159  	if r.Error != nil {
   160  		result.Error = apiservererrors.RestoreError(r.Error)
   161  	}
   162  
   163  	return result, nil
   164  }
   165  
   166  // payloads2TrackArgs converts the provided payload info into arguments
   167  // for the Track API endpoint.
   168  func payloads2TrackArgs(payloadInfo []payloads.Payload) params.TrackPayloadArgs {
   169  	var args params.TrackPayloadArgs
   170  	for _, pl := range payloadInfo {
   171  		fullPayload := payloads.FullPayloadInfo{Payload: pl}
   172  		arg := api.Payload2api(fullPayload)
   173  		args.Payloads = append(args.Payloads, arg)
   174  	}
   175  	return args
   176  }
   177  
   178  // fullIDs2LookUpArgs converts the provided payload "full" IDs into arguments
   179  // for the LookUp API endpoint.
   180  func fullIDs2LookUpArgs(fullIDs []string) params.LookUpPayloadArgs {
   181  	var args params.LookUpPayloadArgs
   182  	for _, fullID := range fullIDs {
   183  		name, rawID := payloads.ParseID(fullID)
   184  		args.Args = append(args.Args, params.LookUpPayloadArg{
   185  			Name: name,
   186  			ID:   rawID,
   187  		})
   188  	}
   189  	return args
   190  }
   191  
   192  // ids2SetStatusArgs converts the provided payload IDs into arguments
   193  // for the SetStatus API endpoint.
   194  func ids2SetStatusArgs(ids []string, status string) params.SetPayloadStatusArgs {
   195  	var args params.SetPayloadStatusArgs
   196  	for _, id := range ids {
   197  		arg := params.SetPayloadStatusArg{
   198  			Status: status,
   199  		}
   200  		arg.Tag = names.NewPayloadTag(id).String()
   201  		args.Args = append(args.Args, arg)
   202  	}
   203  	return args
   204  }
   205  
   206  func ids2Args(ids []string) params.Entities {
   207  	var args params.Entities
   208  	for _, id := range ids {
   209  		tag := names.NewPayloadTag(id).String()
   210  		args.Entities = append(args.Entities, params.Entity{
   211  			Tag: tag,
   212  		})
   213  	}
   214  	return args
   215  }