code.cloudfoundry.org/cli@v7.1.0+incompatible/cf/manifest/manifest_disk_repository.go (about) 1 package manifest 2 3 import ( 4 "fmt" 5 "io" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 10 "code.cloudfoundry.org/cli/cf/errors" 11 . "code.cloudfoundry.org/cli/cf/i18n" 12 "code.cloudfoundry.org/cli/util/generic" 13 "gopkg.in/yaml.v2" 14 ) 15 16 //go:generate counterfeiter . Repository 17 18 type Repository interface { 19 ReadManifest(string) (*Manifest, error) 20 } 21 22 type DiskRepository struct{} 23 24 func NewDiskRepository() (repo Repository) { 25 return DiskRepository{} 26 } 27 28 func (repo DiskRepository) ReadManifest(inputPath string) (*Manifest, error) { 29 m := NewEmptyManifest() 30 manifestPath, err := repo.manifestPath(inputPath) 31 32 if err != nil { 33 return m, fmt.Errorf("%s: %s", T("Error finding manifest"), err.Error()) 34 } 35 36 m.Path = manifestPath 37 38 mapp, err := repo.readAllYAMLFiles(manifestPath) 39 if err != nil { 40 return m, err 41 } 42 43 m.Data = mapp 44 45 return m, nil 46 } 47 48 func (repo DiskRepository) readAllYAMLFiles(path string) (mergedMap generic.Map, err error) { 49 file, err := os.Open(filepath.Clean(path)) 50 if err != nil { 51 return 52 } 53 defer file.Close() 54 55 mapp, err := parseManifest(file) 56 if err != nil { 57 return 58 } 59 60 if !mapp.Has("inherit") { 61 mergedMap = mapp 62 return 63 } 64 65 inheritedPath, ok := mapp.Get("inherit").(string) 66 if !ok { 67 err = errors.New(T("invalid inherit path in manifest")) 68 return 69 } 70 71 if !filepath.IsAbs(inheritedPath) { 72 inheritedPath = filepath.Join(filepath.Dir(path), inheritedPath) 73 } 74 75 inheritedMap, err := repo.readAllYAMLFiles(inheritedPath) 76 if err != nil { 77 return 78 } 79 80 mergedMap = generic.DeepMerge(inheritedMap, mapp) 81 return 82 } 83 84 func parseManifest(file io.Reader) (yamlMap generic.Map, err error) { 85 manifest, err := ioutil.ReadAll(file) 86 if err != nil { 87 return 88 } 89 90 mmap := make(map[interface{}]interface{}) 91 err = yaml.Unmarshal(manifest, &mmap) 92 if err != nil { 93 return 94 } 95 96 if !generic.IsMappable(mmap) || len(mmap) == 0 { 97 err = errors.New(T("Invalid manifest. Expected a map")) 98 return 99 } 100 101 yamlMap = generic.NewMap(mmap) 102 103 return 104 } 105 106 func (repo DiskRepository) manifestPath(userSpecifiedPath string) (string, error) { 107 fileInfo, err := os.Stat(userSpecifiedPath) 108 if err != nil { 109 return "", err 110 } 111 112 if fileInfo.IsDir() { 113 manifestPaths := []string{ 114 filepath.Join(userSpecifiedPath, "manifest.yml"), 115 filepath.Join(userSpecifiedPath, "manifest.yaml"), 116 } 117 var err error 118 for _, manifestPath := range manifestPaths { 119 if _, err = os.Stat(manifestPath); err == nil { 120 return manifestPath, err 121 } 122 } 123 return "", err 124 } 125 return userSpecifiedPath, nil 126 }