pulumi/pkg/encoding/marshal.go
joeduffy 3d74eac67d Make major commands more pleasant
This change eliminates the need to constantly type in the environment
name when performing major commands like configuration, planning, and
deployment.  It's probably due to my age, however, I keep fat-fingering
simple commands in front of investors and I am embarrassed!

In the new model, there is a notion of a "current environment", and
I have modeled it kinda sorta just like Git's notion of "current branch."

By default, the current environment is set when you `init` something.
Otherwise, there is the `coco env select <env>` command to change it.
(Running this command w/out a new <env> will show you the current one.)

The major commands `config`, `plan`, `deploy`, and `destroy` will prefer
to use the current environment, unless it is overridden by using the
--env flag.  All of the `coco env <cmd> <env>` commands still require the
explicit passing of an environment which seems reasonable since they are,
after all, about manipulating environments.

As part of this, I've overhauled the aging workspace settings cruft,
which had fallen into disrepair since the initial prototype.
2017-03-21 19:23:32 -07:00

98 lines
2.4 KiB
Go

// Copyright 2017 Pulumi, Inc. All rights reserved.
package encoding
import (
"encoding/json"
"path/filepath"
"github.com/ghodss/yaml"
)
var JSONExt = ".json"
var YAMLExt = ".yaml"
// Exts contains a list of all the valid marshalable extension types.
var Exts = []string{
JSONExt,
YAMLExt,
// Although ".yml" is not a sanctioned YAML extension, it is used quite broadly; so we will support it.
".yml",
}
// Detect auto-detects a marshaler for the given path.
func Detect(path string) (Marshaler, string) {
ext := filepath.Ext(path)
if ext == "" {
ext = DefaultExt() // default to the first (preferred) marshaler.
}
return Marshalers[ext], ext
}
// Marshalers is a map of extension to a Marshaler object for that extension.
var Marshalers map[string]Marshaler
// Default returns the default marshaler object.
func Default() Marshaler {
return Marshalers[DefaultExt()]
}
// DefaultExt returns the default extension to use.
func DefaultExt() string {
return Exts[0]
}
// Marshaler is a type that knows how to marshal and unmarshal data in one format.
type Marshaler interface {
IsJSONLike() bool
IsYAMLLike() bool
Marshal(v interface{}) ([]byte, error)
Unmarshal(data []byte, v interface{}) error
}
var JSON Marshaler = &jsonMarshaler{}
type jsonMarshaler struct {
}
func (m *jsonMarshaler) IsJSONLike() bool {
return true
}
func (m *jsonMarshaler) IsYAMLLike() bool {
return false
}
func (m *jsonMarshaler) Marshal(v interface{}) ([]byte, error) {
return json.MarshalIndent(v, "", " ")
}
func (m *jsonMarshaler) Unmarshal(data []byte, v interface{}) error {
// TODO: use a "strict" marshaler, so that we can warn on unrecognized keys (avoiding silly mistakes). We should
// set aside an officially sanctioned area in the metadata for extensibility by 3rd parties.
return json.Unmarshal(data, v)
}
var YAML Marshaler = &yamlMarshaler{}
type yamlMarshaler struct {
}
func (m *yamlMarshaler) IsJSONLike() bool {
return false
}
func (m *yamlMarshaler) IsYAMLLike() bool {
return true
}
func (m *yamlMarshaler) Marshal(v interface{}) ([]byte, error) {
return yaml.Marshal(v)
}
func (m *yamlMarshaler) Unmarshal(data []byte, v interface{}) error {
// TODO: use a "strict" marshaler, so that we can warn on unrecognized keys (avoiding silly mistakes). We should
// set aside an officially sanctioned area in the metadata for extensibility by 3rd parties.
return yaml.Unmarshal(data, v)
}