github.com/blixtra/rkt@v0.8.1-0.20160204105720-ab0d1add1a43/rkt/config/stage1.go (about) 1 // Copyright 2016 The rkt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package config 16 17 import ( 18 "encoding/json" 19 "fmt" 20 "net/url" 21 "path/filepath" 22 "sort" 23 "strings" 24 ) 25 26 type stage1V1JsonParser struct{} 27 28 type stage1V1 struct { 29 Name string `json:"name"` 30 Version string `json:"version"` 31 Location string `json:"location"` 32 } 33 34 var ( 35 allowedSchemes = map[string]struct{}{ 36 "file": struct{}{}, 37 "docker": struct{}{}, 38 "http": struct{}{}, 39 "https": struct{}{}, 40 } 41 ) 42 43 func init() { 44 addParser("stage1", "v1", &stage1V1JsonParser{}) 45 registerSubDir("stage1.d", []string{"stage1"}) 46 } 47 48 func (p *stage1V1JsonParser) parse(config *Config, raw []byte) error { 49 var stage1 stage1V1 50 if err := json.Unmarshal(raw, &stage1); err != nil { 51 return err 52 } 53 if err := p.validateStage1V1(&stage1); err != nil { 54 return fmt.Errorf("invalid stage1 configuration: %v", err) 55 } 56 // At this point either both name and version are specified or 57 // neither. The same goes for data in Config. 58 if stage1.Name != "" { 59 if config.Stage1.Name != "" { 60 return fmt.Errorf("name and version of a default stage1 image are already specified") 61 } 62 config.Stage1.Name = stage1.Name 63 config.Stage1.Version = stage1.Version 64 } 65 if stage1.Location != "" { 66 if config.Stage1.Location != "" { 67 return fmt.Errorf("location of a default stage1 image is already specified") 68 } 69 config.Stage1.Location = stage1.Location 70 } 71 return nil 72 } 73 74 func (p *stage1V1JsonParser) validateStage1V1(stage1 *stage1V1) error { 75 if stage1.Name == "" && stage1.Version != "" { 76 return fmt.Errorf("default stage1 image version specified, but name is missing") 77 } 78 if stage1.Name != "" && stage1.Version == "" { 79 return fmt.Errorf("default stage1 image name specified, but version is missing") 80 } 81 if stage1.Location != "" { 82 if !filepath.IsAbs(stage1.Location) { 83 url, err := url.Parse(stage1.Location) 84 if err != nil { 85 return fmt.Errorf("default stage1 image location is an invalid URL: %v", err) 86 } 87 if url.Scheme == "" { 88 return fmt.Errorf("default stage1 image location is either a relative path or a URL without scheme") 89 } 90 if _, ok := allowedSchemes[url.Scheme]; !ok { 91 schemes := toArray(allowedSchemes) 92 sort.Strings(schemes) 93 return fmt.Errorf("default stage1 image location URL has invalid scheme %q, allowed schemes are %q", url.Scheme, strings.Join(schemes, `", "`)) 94 } 95 } 96 } 97 return nil 98 }