github.com/oam-dev/kubevela@v1.9.11/references/appfile/api/appfile.go (about) 1 /* 2 Copyright 2021 The KubeVela Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package api 18 19 import ( 20 "encoding/json" 21 "errors" 22 "os" 23 "path/filepath" 24 "strings" 25 "time" 26 27 "sigs.k8s.io/yaml" 28 29 "github.com/oam-dev/kubevela/apis/core.oam.dev/common" 30 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" 31 "github.com/oam-dev/kubevela/pkg/builtin" 32 cmdutil "github.com/oam-dev/kubevela/pkg/utils/util" 33 "github.com/oam-dev/kubevela/references/appfile/template" 34 ) 35 36 // error msg used in Appfile 37 var ( 38 ErrImageNotDefined = errors.New("image not defined") 39 ) 40 41 // DefaultAppfilePath defines the default file path that used by `vela up` command 42 const ( 43 DefaultJSONAppfilePath = "./vela.json" 44 DefaultAppfilePath = "./vela.yaml" 45 DefaultUnknowFormatAppfilePath = "./Appfile" 46 ) 47 48 // AppFile defines the spec of KubeVela Appfile 49 type AppFile struct { 50 Name string `json:"name"` 51 CreateTime time.Time `json:"createTime,omitempty"` 52 UpdateTime time.Time `json:"updateTime,omitempty"` 53 Services map[string]Service `json:"services"` 54 Secrets map[string]string `json:"secrets,omitempty"` 55 56 initialized bool 57 } 58 59 // NewAppFile init an empty AppFile struct 60 func NewAppFile() *AppFile { 61 return &AppFile{ 62 Services: make(map[string]Service), 63 Secrets: make(map[string]string), 64 } 65 } 66 67 // Load will load appfile from default path 68 func Load() (*AppFile, error) { 69 if _, err := os.Stat(DefaultAppfilePath); err == nil { 70 return LoadFromFile(DefaultAppfilePath) 71 } 72 if _, err := os.Stat(DefaultJSONAppfilePath); err == nil { 73 return LoadFromFile(DefaultJSONAppfilePath) 74 } 75 return LoadFromFile(DefaultUnknowFormatAppfilePath) 76 } 77 78 // JSONToYaml will convert JSON format appfile to yaml and load the AppFile struct 79 func JSONToYaml(data []byte, appFile *AppFile) (*AppFile, error) { 80 j, e := yaml.JSONToYAML(data) 81 if e != nil { 82 return nil, e 83 } 84 err := yaml.Unmarshal(j, appFile) 85 if err != nil { 86 return nil, err 87 } 88 return appFile, nil 89 } 90 91 // LoadFromFile will read the file and load the AppFile struct 92 func LoadFromFile(filename string) (*AppFile, error) { 93 b, err := os.ReadFile(filepath.Clean(filename)) 94 if err != nil { 95 return nil, err 96 } 97 return LoadFromBytes(b) 98 } 99 100 // LoadFromBytes will load AppFile from bytes 101 func LoadFromBytes(b []byte) (*AppFile, error) { 102 af := NewAppFile() 103 var err error 104 if json.Valid(b) { 105 af, err = JSONToYaml(b, af) 106 } else { 107 err = yaml.Unmarshal(b, af) 108 } 109 if err != nil { 110 return nil, err 111 } 112 return af, nil 113 } 114 115 // ExecuteAppfileTasks will execute built-in tasks(such as image builder, etc.) and generate locally executed application 116 func (app *AppFile) ExecuteAppfileTasks(io cmdutil.IOStreams) error { 117 if app.initialized { 118 return nil 119 } 120 for name, svc := range app.Services { 121 newSvc, err := builtin.RunBuildInTasks(svc, io) 122 if err != nil { 123 return err 124 } 125 app.Services[name] = newSvc 126 } 127 app.initialized = true 128 return nil 129 } 130 131 // ConvertToApplication renders Appfile into Application, Scopes and other K8s Resources. 132 func (app *AppFile) ConvertToApplication(namespace string, io cmdutil.IOStreams, tm template.Manager, silence bool) (*v1beta1.Application, error) { 133 if err := app.ExecuteAppfileTasks(io); err != nil { 134 if strings.Contains(err.Error(), "'image' : not found") { 135 return nil, ErrImageNotDefined 136 } 137 return nil, err 138 } 139 // auxiliaryObjects currently include OAM Scope Custom Resources and ConfigMaps 140 servApp := new(v1beta1.Application) 141 servApp.SetNamespace(namespace) 142 servApp.SetName(app.Name) 143 servApp.Spec.Components = []common.ApplicationComponent{} 144 if !silence { 145 io.Infof("parsing application components") 146 } 147 for serviceName, svc := range app.GetServices() { 148 comp, err := svc.RenderServiceToApplicationComponent(tm, serviceName) 149 if err != nil { 150 return nil, err 151 } 152 servApp.Spec.Components = append(servApp.Spec.Components, comp) 153 } 154 servApp.SetGroupVersionKind(v1beta1.SchemeGroupVersion.WithKind("Application")) 155 return servApp, nil 156 }