1
0
mirror of https://github.com/rancher/os.git synced 2025-08-02 07:24:28 +00:00

Merge pull request #848 from joshwget/show-default-values

`ros config get` shows default values
This commit is contained in:
Darren Shepherd 2016-04-01 09:21:03 -07:00
commit 97e0c01666
12 changed files with 103 additions and 18 deletions

View File

@ -211,7 +211,7 @@ func configGet(c *cli.Context) {
log.WithFields(log.Fields{"err": err}).Fatal("config get: failed to load config")
}
val, err := cfg.Get(arg)
val, err := cfg.GetIgnoreOmitEmpty(arg)
if err != nil {
log.WithFields(log.Fields{"cfg": cfg, "key": arg, "val": val, "err": err}).Fatal("config get: failed to retrieve value")
}

View File

@ -140,6 +140,16 @@ func (c *CloudConfig) Get(key string) (interface{}, error) {
return v, nil
}
func (c *CloudConfig) GetIgnoreOmitEmpty(key string) (interface{}, error) {
data := map[interface{}]interface{}{}
if err := util.ConvertIgnoreOmitEmpty(c, &data); err != nil {
return nil, err
}
v, _ := getOrSetVal(key, data, nil)
return v, nil
}
func (c *CloudConfig) Set(key string, value interface{}) (*CloudConfig, error) {
data := map[interface{}]interface{}{}
if err := util.Convert(c, &data); err != nil {

View File

@ -5,7 +5,8 @@ import:
version: v0.9.0
- package: github.com/cloudfoundry-incubator/candiedyaml
version: 55a459c2d9da2b078f0725e5fb324823b2c71702
version: 01cbc92901719f599b11f3a7e3b1768d7002b0bb
repo: https://github.com/rancher/candiedyaml
- package: github.com/codegangsta/cli
version: v1.2.0

View File

@ -1,6 +1,7 @@
package util
import (
"bytes"
"errors"
"fmt"
"io"
@ -68,6 +69,25 @@ func Convert(from, to interface{}) error {
return yaml.Unmarshal(bytes, to)
}
func ConvertIgnoreOmitEmpty(from, to interface{}) error {
var buffer bytes.Buffer
encoder := yaml.NewEncoder(&buffer)
encoder.IgnoreOmitEmpty = true
if err := encoder.Encode(from); err != nil {
return err
}
decoder := yaml.NewDecoder(&buffer)
if err := decoder.Decode(to); err != nil {
return err
}
return nil
}
func Copy(d interface{}) interface{} {
switch d := d.(type) {
case map[interface{}]interface{}:

View File

@ -25,7 +25,8 @@ func main() {
println("File does not exist:", err.Error())
os.Exit(1)
}
defer file.Close()
document := new(interface{})
decoder := candiedyaml.NewDecoder(file)
err = decoder.Decode(document)
@ -41,7 +42,8 @@ func main() {
println("Failed to open file for writing:", err.Error())
os.Exit(1)
}
defer fileToWrite.Close()
encoder := candiedyaml.NewEncoder(fileToWrite)
err = encoder.Encode(document)

View File

@ -62,6 +62,15 @@ var _ = Describe("Decode", func() {
Expect(err).NotTo(HaveOccurred())
Expect(v).To(Equal(map[interface{}]interface{}{"": ""}))
})
It("Decodes strings starting with a colon", func() {
d := NewDecoder(strings.NewReader(`:colon
`))
var v interface{}
err := d.Decode(&v)
Expect(err).NotTo(HaveOccurred())
Expect(v).To(Equal(":colon"))
})
})
Context("Sequence", func() {

View File

@ -1276,7 +1276,7 @@ func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
for i, w := 0, 0; i < len(value); i += w {
w = width(value[i])
followed_by_whitespace = i+w >= len(value) || is_blankz_at(value, w)
followed_by_whitespace = i+w >= len(value) || is_blankz_at(value, i+w)
if i == 0 {
switch value[i] {

View File

@ -57,6 +57,8 @@ type Encoder struct {
event yaml_event_t
flow bool
err error
IgnoreOmitEmpty bool
}
func Marshal(v interface{}) ([]byte, error) {
@ -174,7 +176,7 @@ func (e *Encoder) emitStruct(tag string, v reflect.Value) {
e.mapping(tag, func() {
for _, f := range fields {
fv := fieldByIndex(v, f.index)
if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) {
if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) && !e.IgnoreOmitEmpty {
continue
}

View File

@ -68,6 +68,14 @@ var _ = Describe("Encode", func() {
})
It("handles strings that contain colons followed by whitespace", func() {
err := enc.Encode("contains: colon")
Expect(err).NotTo(HaveOccurred())
Expect(buf.String()).To(Equal(`'contains: colon'
`))
})
Context("handles ints", func() {
It("handles ints", func() {
err := enc.Encode(13)
@ -303,7 +311,7 @@ int: 123
})
Context("Maps", func() {
It("Decodes simple maps", func() {
It("Encodes simple maps", func() {
err := enc.Encode(&map[string]string{
"name": "Mark McGwire",
"hr": "65",
@ -315,10 +323,27 @@ int: 123
hr: "65"
name: Mark McGwire
`))
})
It("Decodes mix types", func() {
It("sorts by key when strings otherwise by kind", func() {
err := enc.Encode(&map[interface{}]string{
1.2: "float",
8: "integer",
"name": "Mark McGwire",
"hr": "65",
"avg": "0.278",
})
Expect(err).NotTo(HaveOccurred())
Expect(buf.String()).To(Equal(`8: integer
1.2: float
avg: "0.278"
hr: "65"
name: Mark McGwire
`))
})
It("encodes mix types", func() {
err := enc.Encode(&map[string]interface{}{
"name": "Mark McGwire",
"hr": 65,
@ -330,12 +355,11 @@ name: Mark McGwire
hr: 65
name: Mark McGwire
`))
})
})
Context("Sequence of Maps", func() {
It("decodes", func() {
It("encodes", func() {
err := enc.Encode([]map[string]interface{}{
{"name": "Mark McGwire",
"hr": 65,
@ -360,7 +384,7 @@ name: Mark McGwire
})
Context("Maps of Sequence", func() {
It("decodes", func() {
It("encodes", func() {
err := enc.Encode(map[string][]interface{}{
"name": []interface{}{"Mark McGwire", "Sammy Sosa"},
"hr": []interface{}{65, 63},

View File

@ -323,7 +323,7 @@ func resolve_time(val string, v reflect.Value, event yaml_event_t) (string, erro
} else {
matches = timestamp_regexp.FindStringSubmatch(val)
if len(matches) == 0 {
return "", fmt.Errorf("Invalid timestap: '%s' at %s", val, event.start_mark)
return "", fmt.Errorf("Invalid timestamp: '%s' at %s", val, event.start_mark)
}
year, _ := strconv.Atoi(matches[1])

View File

@ -909,7 +909,7 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool {
b == '@' || b == '`') ||
(b == '-' && !is_blank(buf[pos+1])) ||
(parser.flow_level == 0 &&
(buf[pos] == '?' || buf[pos+1] == ':') &&
(buf[pos] == '?' || buf[pos] == ':') &&
!is_blank(buf[pos+1])) {
return yaml_parser_fetch_plain_scalar(parser)
}

View File

@ -306,10 +306,27 @@ func typeByIndex(t reflect.Type, index []int) reflect.Type {
// It implements the methods to sort by string.
type stringValues []reflect.Value
func (sv stringValues) Len() int { return len(sv) }
func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
func (sv stringValues) get(i int) string { return sv[i].String() }
func (sv stringValues) Len() int { return len(sv) }
func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
func (sv stringValues) Less(i, j int) bool {
av, ak := getElem(sv[i])
bv, bk := getElem(sv[j])
if ak == reflect.String && bk == reflect.String {
return av.String() < bv.String()
}
return ak < bk
}
func getElem(v reflect.Value) (reflect.Value, reflect.Kind) {
k := v.Kind()
for k == reflect.Interface || k == reflect.Ptr && !v.IsNil() {
v = v.Elem()
k = v.Kind()
}
return v, k
}
// parseTag splits a struct field's json tag into its name and
// comma-separated options.