github.com/profzone/eden-framework@v1.0.10/internal/generator/files/dockerfile.go (about)

     1  package files
     2  
     3  import (
     4  	"encoding/json"
     5  	"github.com/profzone/eden-framework/pkg/executil"
     6  	str "github.com/profzone/eden-framework/pkg/strings"
     7  	"reflect"
     8  	"strconv"
     9  	"strings"
    10  )
    11  
    12  type Dockerfile struct {
    13  	From       string            `docker:"FROM" yaml:"from,omitempty"`
    14  	Image      string            `yaml:"image"`
    15  	Label      map[string]string `docker:"LABEL,multi" yaml:"label,omitempty"`
    16  	Run        string            `docker:"RUN,inline" yaml:"run,omitempty"`
    17  	WorkDir    string            `docker:"WORKDIR" yaml:"workdir,omitempty"`
    18  	Env        map[string]string `docker:"ENV,multi" yaml:"env,omitempty"`
    19  	Add        map[string]string `docker:"ADD,join" yaml:"add,omitempty"`
    20  	Expose     []string          `docker:"EXPOSE" yaml:"expose,omitempty"`
    21  	Volume     []string          `docker:"VOLUME,array" yaml:"volume,omitempty"`
    22  	Cmd        []string          `docker:"CMD,array" yaml:"cmd,omitempty"`
    23  	EntryPoint []string          `docker:"ENTRYPOINT,array" yaml:"entrypoint,omitempty"`
    24  }
    25  
    26  func (d *Dockerfile) String() string {
    27  	envVars := executil.EnvVars{}
    28  	envVars.LoadFromEnviron()
    29  	return envVars.Parse(GetDockerfileTemplate(*d))
    30  }
    31  
    32  func (d Dockerfile) AddContent(from string, to string) *Dockerfile {
    33  	if d.Add == nil {
    34  		d.Add = map[string]string{}
    35  	}
    36  	d.Add[from] = to
    37  	return &d
    38  }
    39  
    40  func (d Dockerfile) AddLabel(label string, content string) *Dockerfile {
    41  	if d.Label == nil {
    42  		d.Label = map[string]string{}
    43  	}
    44  	d.Label[label] = content
    45  	return &d
    46  }
    47  
    48  func (d Dockerfile) AddEnv(key string, value string) *Dockerfile {
    49  	if d.Env == nil {
    50  		d.Env = map[string]string{}
    51  	}
    52  	d.Env[key] = value
    53  	return &d
    54  }
    55  
    56  func (d Dockerfile) WithExpose(exposes ...string) *Dockerfile {
    57  	d.Expose = exposes
    58  	return &d
    59  }
    60  
    61  func (d Dockerfile) WithVolume(volumes ...string) *Dockerfile {
    62  	d.Volume = volumes
    63  	return &d
    64  }
    65  
    66  func (d Dockerfile) WithWorkDir(dir string) *Dockerfile {
    67  	d.WorkDir = dir
    68  	return &d
    69  }
    70  
    71  func (d Dockerfile) WithCmd(cmd ...string) *Dockerfile {
    72  	d.Cmd = cmd
    73  	return &d
    74  }
    75  
    76  func GetDockerfileTemplate(d Dockerfile) string {
    77  	dockerfileConfig := make([]string, 0)
    78  
    79  	appendDockerConfig := func(dockerKey string, value string) {
    80  		dockerfileConfig = append(
    81  			dockerfileConfig,
    82  			strings.Join([]string{dockerKey, value}, " "),
    83  		)
    84  	}
    85  
    86  	tpe := reflect.TypeOf(d)
    87  	rv := reflect.Indirect(reflect.ValueOf(d))
    88  
    89  	for i := 0; i < tpe.NumField(); i++ {
    90  		field := tpe.Field(i)
    91  		dockerTag := field.Tag.Get("docker")
    92  		dockerKeys := strings.Split(dockerTag, ",")
    93  		dockerKey := dockerKeys[0]
    94  		dockerFlags := dockerKeys[1:]
    95  
    96  		if len(dockerKey) > 0 {
    97  			value := rv.FieldByName(field.Name)
    98  
    99  			switch field.Type.Kind() {
   100  			case reflect.String:
   101  				if len(value.String()) > 0 {
   102  					inline := str.StringIncludes(dockerFlags, "inline")
   103  					if inline {
   104  						appendDockerConfig(dockerKey, value.String())
   105  					} else {
   106  						appendDockerConfig(dockerKey, mayQuote(value.String()))
   107  					}
   108  				}
   109  			case reflect.Slice:
   110  				jsonArray := str.StringIncludes(dockerFlags, "array")
   111  				slice := make([]string, 0)
   112  				for i := 0; i < value.Len(); i++ {
   113  					slice = append(slice, value.Index(i).String())
   114  				}
   115  				if len(slice) > 0 {
   116  					if jsonArray {
   117  						jsonString, err := json.Marshal(slice)
   118  						if err != nil {
   119  							panic(err)
   120  						}
   121  						appendDockerConfig(
   122  							dockerKey,
   123  							string(jsonString),
   124  						)
   125  					} else {
   126  						appendDockerConfig(
   127  							dockerKey,
   128  							strings.Join(slice, ""),
   129  						)
   130  					}
   131  				}
   132  
   133  			case reflect.Map:
   134  				multi := str.StringIncludes(dockerFlags, "multi")
   135  				join := str.StringIncludes(dockerFlags, "join")
   136  
   137  				if join {
   138  					destMap := map[string][]string{}
   139  					for _, key := range value.MapKeys() {
   140  						dest := value.MapIndex(key).String()
   141  						if destMap[dest] == nil {
   142  							destMap[dest] = []string{}
   143  						}
   144  						destMap[dest] = append(destMap[dest], key.String())
   145  					}
   146  					for dest, src := range destMap {
   147  						appendDockerConfig(
   148  							dockerKey,
   149  							strings.Join(append(src, dest), " "),
   150  						)
   151  					}
   152  				} else if multi {
   153  					keyValues := []string{}
   154  					for _, key := range value.MapKeys() {
   155  						keyValues = append(
   156  							keyValues,
   157  							key.String()+"="+mayQuote(value.MapIndex(key).String()),
   158  						)
   159  					}
   160  					if len(keyValues) > 0 {
   161  						appendDockerConfig(
   162  							dockerKey,
   163  							strings.Join(keyValues, " "),
   164  						)
   165  					}
   166  				} else {
   167  					for _, key := range value.MapKeys() {
   168  						appendDockerConfig(
   169  							dockerKey,
   170  							strings.Join([]string{key.String(), mayQuote(value.MapIndex(key).String())}, " "),
   171  						)
   172  					}
   173  				}
   174  			}
   175  		}
   176  	}
   177  
   178  	return strings.Join(dockerfileConfig, "\n")
   179  }
   180  
   181  func mayQuote(s string) string {
   182  	if s == "" || strings.Index(s, " ") > -1 {
   183  		return strconv.Quote(s)
   184  	}
   185  	return s
   186  }