github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/core/description/payload.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package description
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/schema"
     9  )
    10  
    11  // Payload represents a charm payload for a unit.
    12  type Payload interface {
    13  	Name() string
    14  	Type() string
    15  	RawID() string
    16  	State() string
    17  	Labels() []string
    18  }
    19  
    20  type payloads struct {
    21  	Version   int        `yaml:"version"`
    22  	Payloads_ []*payload `yaml:"payloads"`
    23  }
    24  
    25  type payload struct {
    26  	Name_   string   `yaml:"name"`
    27  	Type_   string   `yaml:"type"`
    28  	RawID_  string   `yaml:"raw-id"`
    29  	State_  string   `yaml:"state"`
    30  	Labels_ []string `yaml:"labels,omitempty"`
    31  }
    32  
    33  // Name implements Payload.
    34  func (p *payload) Name() string {
    35  	return p.Name_
    36  }
    37  
    38  // Type implements Payload.
    39  func (p *payload) Type() string {
    40  	return p.Type_
    41  }
    42  
    43  // RawID implements Payload.
    44  func (p *payload) RawID() string {
    45  	return p.RawID_
    46  }
    47  
    48  // State implements Payload.
    49  func (p *payload) State() string {
    50  	return p.State_
    51  }
    52  
    53  // Labels implements Payload.
    54  func (p *payload) Labels() []string {
    55  	return p.Labels_
    56  }
    57  
    58  // PayloadArgs is an argument struct used to create a
    59  // new internal payload type that supports the Payload interface.
    60  type PayloadArgs struct {
    61  	Name   string
    62  	Type   string
    63  	RawID  string
    64  	State  string
    65  	Labels []string
    66  }
    67  
    68  func newPayload(args PayloadArgs) *payload {
    69  	return &payload{
    70  		Name_:   args.Name,
    71  		Type_:   args.Type,
    72  		RawID_:  args.RawID,
    73  		State_:  args.State,
    74  		Labels_: args.Labels,
    75  	}
    76  }
    77  
    78  func importPayloads(source map[string]interface{}) ([]*payload, error) {
    79  	checker := versionedChecker("payloads")
    80  	coerced, err := checker.Coerce(source, nil)
    81  	if err != nil {
    82  		return nil, errors.Annotatef(err, "payloads version schema check failed")
    83  	}
    84  	valid := coerced.(map[string]interface{})
    85  
    86  	version := int(valid["version"].(int64))
    87  	importFunc, ok := payloadDeserializationFuncs[version]
    88  	if !ok {
    89  		return nil, errors.NotValidf("version %d", version)
    90  	}
    91  	sourceList := valid["payloads"].([]interface{})
    92  	return importPayloadList(sourceList, importFunc)
    93  }
    94  
    95  func importPayloadList(sourceList []interface{}, importFunc payloadDeserializationFunc) ([]*payload, error) {
    96  	result := make([]*payload, 0, len(sourceList))
    97  	for i, value := range sourceList {
    98  		source, ok := value.(map[string]interface{})
    99  		if !ok {
   100  			return nil, errors.Errorf("unexpected value for payload %d, %T", i, value)
   101  		}
   102  		payload, err := importFunc(source)
   103  		if err != nil {
   104  			return nil, errors.Annotatef(err, "payload %d", i)
   105  		}
   106  		result = append(result, payload)
   107  	}
   108  	return result, nil
   109  }
   110  
   111  type payloadDeserializationFunc func(map[string]interface{}) (*payload, error)
   112  
   113  var payloadDeserializationFuncs = map[int]payloadDeserializationFunc{
   114  	1: importPayloadV1,
   115  }
   116  
   117  func importPayloadV1(source map[string]interface{}) (*payload, error) {
   118  	fields := schema.Fields{
   119  		"name":   schema.String(),
   120  		"type":   schema.String(),
   121  		"raw-id": schema.String(),
   122  		"state":  schema.String(),
   123  		"labels": schema.List(schema.String()),
   124  	}
   125  	// Some values don't have to be there.
   126  	defaults := schema.Defaults{
   127  		"labels": schema.Omit,
   128  	}
   129  	checker := schema.FieldMap(fields, defaults)
   130  
   131  	coerced, err := checker.Coerce(source, nil)
   132  	if err != nil {
   133  		return nil, errors.Annotatef(err, "payload v1 schema check failed")
   134  	}
   135  	valid := coerced.(map[string]interface{})
   136  
   137  	return &payload{
   138  		Name_:   valid["name"].(string),
   139  		Type_:   valid["type"].(string),
   140  		RawID_:  valid["raw-id"].(string),
   141  		State_:  valid["state"].(string),
   142  		Labels_: convertToStringSlice(valid["labels"]),
   143  	}, nil
   144  }