@@ -26,13 +26,13 @@ import (
2626 parse2 "github.com/containers/buildah/pkg/parse"
2727 "github.com/moby/buildkit/frontend/dockerfile/shell"
2828 "github.com/pkg/errors"
29- "github.com/sirupsen/logrus"
30-
3129 "github.com/sealerio/sealer/build/kubefile/command"
30+ v1 "github.com/sealerio/sealer/pkg/define/application/v1"
3231 "github.com/sealerio/sealer/pkg/define/application/version"
3332 v12 "github.com/sealerio/sealer/pkg/define/image/v1"
3433 "github.com/sealerio/sealer/pkg/define/options"
3534 "github.com/sealerio/sealer/pkg/imageengine"
35+ "github.com/sirupsen/logrus"
3636)
3737
3838// LegacyContext stores legacy information during the process of parsing.
@@ -58,6 +58,17 @@ type KubefileResult struct {
5858 // LAUNCH ["myapp1","myapp2"]
5959 LaunchedAppNames []string
6060
61+ // GlobalEnv is a set of key value pair.
62+ // set to sealer image some default parameters which is in global level.
63+ // user could overwrite it through v2.ClusterSpec at run stage.
64+ GlobalEnv map [string ]string
65+
66+ // AppEnv is a set of key value pair.
67+ // it is app level, only this app will be aware of its existence,
68+ // it is used to render app files, or as an environment variable for app startup and deletion commands
69+ // it takes precedence over GlobalEnv.
70+ AppEnvMap map [string ]map [string ]string
71+
6172 // Applications structured APP instruction and register it to this map
6273 // APP myapp local://app.yaml
6374 Applications map [string ]version.VersionedApplication
@@ -93,6 +104,8 @@ func (kp *KubefileParser) generateResult(mainNode *Node) (*KubefileResult, error
93104 result = & KubefileResult {
94105 Applications : map [string ]version.VersionedApplication {},
95106 ApplicationConfigs : map [string ]* v12.ApplicationConfig {},
107+ GlobalEnv : map [string ]string {},
108+ AppEnvMap : map [string ]map [string ]string {},
96109 legacyContext : LegacyContext {
97110 files : []string {},
98111 directories : []string {},
@@ -179,6 +192,18 @@ func (kp *KubefileParser) generateResult(mainNode *Node) (*KubefileResult, error
179192 }
180193 }
181194
195+ // register app with all env list.
196+ for appName , appEnv := range result .AppEnvMap {
197+ app := result .Applications [appName ]
198+ result .Applications [appName ] = & v1.Application {
199+ NameVar : app .Name (),
200+ TypeVar : app .Type (),
201+ FilesVar : app .Files (),
202+ VersionVar : app .Version (),
203+ AppEnv : appEnv ,
204+ }
205+ }
206+
182207 return result , nil
183208}
184209
@@ -188,6 +213,12 @@ func (kp *KubefileParser) processOnCmd(result *KubefileResult, node *Node) error
188213 case command .Label , command .Maintainer , command .Add , command .Arg , command .From , command .Run :
189214 result .Dockerfile = mergeLines (result .Dockerfile , node .Original )
190215 return nil
216+ case command .Env :
217+ // update global env to dockerfile at the same, for using it at build stage.
218+ result .Dockerfile = mergeLines (result .Dockerfile , node .Original )
219+ return kp .processGlobalEnv (node , result )
220+ case command .AppEnv :
221+ return kp .processAppEnv (node , result )
191222 case command .App :
192223 _ , err := kp .processApp (node , result )
193224 return err
@@ -304,6 +335,75 @@ func (kp *KubefileParser) processAppCmds(node *Node, result *KubefileResult) err
304335 return nil
305336}
306337
338+ func (kp * KubefileParser ) processAppEnv (node * Node , result * KubefileResult ) error {
339+ var (
340+ appName = ""
341+ envList []string
342+ )
343+
344+ // first node value is the command
345+ for ptr := node .Next ; ptr != nil ; ptr = ptr .Next {
346+ val := ptr .Value
347+ // record the first word to be the app name
348+ if appName == "" {
349+ appName = val
350+ continue
351+ }
352+ envList = append (envList , val )
353+ }
354+
355+ if appName == "" {
356+ return errors .New ("app name should be specified in the APPENV instruction" )
357+ }
358+
359+ if _ , ok := result .Applications [appName ]; ! ok {
360+ return fmt .Errorf ("the specified app name(%s) for `APPENV` should be exist" , appName )
361+ }
362+
363+ tmpEnv := make (map [string ]string )
364+ for _ , elem := range envList {
365+ var kv []string
366+ if kv = strings .SplitN (elem , "=" , 2 ); len (kv ) != 2 {
367+ continue
368+ }
369+ tmpEnv [kv [0 ]] = kv [1 ]
370+ }
371+
372+ appEnv := result .AppEnvMap [appName ]
373+ if appEnv == nil {
374+ appEnv = make (map [string ]string )
375+ }
376+
377+ for k , v := range tmpEnv {
378+ appEnv [k ] = v
379+ }
380+
381+ result .AppEnvMap [appName ] = appEnv
382+ return nil
383+ }
384+
385+ func (kp * KubefileParser ) processGlobalEnv (node * Node , result * KubefileResult ) error {
386+ valueList := strings .SplitN (node .Original , "ENV " , 2 )
387+ if len (valueList ) != 2 {
388+ return fmt .Errorf ("line %d: invalid ENV instruction: %s" , node .StartLine , node .Original )
389+ }
390+ envs := valueList [1 ]
391+
392+ for _ , elem := range strings .Split (envs , " " ) {
393+ if elem == "" {
394+ continue
395+ }
396+
397+ var kv []string
398+ if kv = strings .SplitN (elem , "=" , 2 ); len (kv ) != 2 {
399+ continue
400+ }
401+ result .GlobalEnv [kv [0 ]] = kv [1 ]
402+ }
403+
404+ return nil
405+ }
406+
307407func (kp * KubefileParser ) processCmd (node * Node , result * KubefileResult ) error {
308408 original := node .Original
309409 cmd := strings .Split (original , "CMD " )
0 commit comments