github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/juju/common/flags.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package common
     5  
     6  import (
     7  	"fmt"
     8  	"io/ioutil"
     9  	"strings"
    10  
    11  	"github.com/juju/cmd"
    12  	"github.com/juju/errors"
    13  	"github.com/juju/utils"
    14  	"gopkg.in/yaml.v2"
    15  )
    16  
    17  // ConfigFlag records k=v attributes from command arguments
    18  // and/or specified files containing key values.
    19  type ConfigFlag struct {
    20  	files []string
    21  	attrs map[string]interface{}
    22  }
    23  
    24  // Set implements gnuflag.Value.Set.
    25  func (f *ConfigFlag) Set(s string) error {
    26  	if s == "" {
    27  		return errors.NotValidf("empty string")
    28  	}
    29  	fields := strings.SplitN(s, "=", 2)
    30  	if len(fields) == 1 {
    31  		f.files = append(f.files, fields[0])
    32  		return nil
    33  	}
    34  	var value interface{}
    35  	if err := yaml.Unmarshal([]byte(fields[1]), &value); err != nil {
    36  		return errors.Trace(err)
    37  	}
    38  	if f.attrs == nil {
    39  		f.attrs = make(map[string]interface{})
    40  	}
    41  	f.attrs[fields[0]] = value
    42  	return nil
    43  }
    44  
    45  // ReadAttrs reads attributes from the specified files, and then overlays
    46  // the results with the k=v attributes.
    47  func (f *ConfigFlag) ReadAttrs(ctx *cmd.Context) (map[string]interface{}, error) {
    48  	attrs := make(map[string]interface{})
    49  	for _, f := range f.files {
    50  		path, err := utils.NormalizePath(f)
    51  		if err != nil {
    52  			return nil, errors.Trace(err)
    53  		}
    54  		data, err := ioutil.ReadFile(ctx.AbsPath(path))
    55  		if err != nil {
    56  			return nil, errors.Trace(err)
    57  		}
    58  		if err := yaml.Unmarshal(data, &attrs); err != nil {
    59  			return nil, err
    60  		}
    61  	}
    62  	for k, v := range f.attrs {
    63  		attrs[k] = v
    64  	}
    65  	return attrs, nil
    66  }
    67  
    68  // String implements gnuflag.Value.String.
    69  func (f *ConfigFlag) String() string {
    70  	strs := make([]string, 0, len(f.attrs)+len(f.files))
    71  	for _, f := range f.files {
    72  		strs = append(strs, f)
    73  	}
    74  	for k, v := range f.attrs {
    75  		strs = append(strs, fmt.Sprintf("%s=%v", k, v))
    76  	}
    77  	return strings.Join(strs, " ")
    78  }