github.com/octohelm/wagon@v0.0.0-20240308040401-88662650dc0b/pkg/engine/plan/task/core/image.go (about) 1 package core 2 3 import ( 4 "dagger.io/dagger" 5 "fmt" 6 "github.com/octohelm/wagon/pkg/engine/daggerutil" 7 "golang.org/x/net/context" 8 ) 9 10 func init() { 11 DefaultFactory.Register(&Image{}) 12 } 13 14 type Image struct { 15 Rootfs FS `json:"rootfs"` 16 Config ImageConfig `json:"config"` 17 Platform string `json:"platform,omitempty"` 18 } 19 20 func (img *Image) Type() string { 21 return "oci" 22 } 23 24 func (img *Image) CanExport() bool { 25 return img.Rootfs.CanExport() 26 } 27 28 func (img *Image) ExportTo(ctx context.Context, localPath string) error { 29 return daggerutil.Do(ctx, func(c *dagger.Client) error { 30 rootfs := img.Rootfs.LoadDirectory(c) 31 32 ct := c.Container(dagger.ContainerOpts{ 33 Platform: DefaultPlatform(img.Platform), 34 }).WithRootfs(rootfs) 35 36 ct = img.Config.ApplyTo(ct) 37 38 _, err := ct.Export(ctx, localPath) 39 return err 40 }) 41 } 42 43 type ImageConfig struct { 44 WorkingDir string `json:"workdir" default:""` 45 Env map[string]string `json:"env"` 46 Labels map[string]string `json:"label"` 47 Entrypoint []string `json:"entrypoint"` 48 Cmd []string `json:"cmd"` 49 User string `json:"user" default:""` 50 } 51 52 func (p ImageConfig) ApplyTo(c *dagger.Container) *dagger.Container { 53 for k := range p.Env { 54 c = c.WithEnvVariable(k, p.Env[k]) 55 } 56 57 for k := range p.Labels { 58 c = c.WithLabel(k, p.Labels[k]) 59 } 60 61 if vv := p.User; vv != "" { 62 c = c.WithUser(vv) 63 } 64 65 if vv := p.WorkingDir; vv != "" { 66 c = c.WithWorkdir(vv) 67 } 68 69 if vv := p.Entrypoint; len(vv) != 0 { 70 c = c.WithEntrypoint(vv) 71 } 72 73 if vv := p.Cmd; len(vv) != 0 { 74 c = c.WithDefaultArgs(vv) 75 } 76 77 return c 78 } 79 80 func (p ImageConfig) Merge(config ImageConfig) ImageConfig { 81 final := ImageConfig{} 82 83 final.WorkingDir = p.WorkingDir 84 if config.WorkingDir != "" { 85 final.WorkingDir = config.WorkingDir 86 } 87 88 final.User = p.User 89 if config.WorkingDir != "" { 90 final.User = config.User 91 } 92 93 final.Entrypoint = p.Entrypoint 94 if len(config.Entrypoint) != 0 { 95 final.Entrypoint = config.Entrypoint 96 } 97 98 final.Cmd = p.Cmd 99 if len(config.Cmd) != 0 { 100 final.Cmd = config.Cmd 101 } 102 103 final.Env = mergeMap(p.Env, config.Env) 104 final.Labels = mergeMap(p.Labels, config.Labels) 105 106 return final 107 } 108 109 func (p *ImageConfig) Resolve(ctx context.Context, c *dagger.Client, id dagger.ContainerID) error { 110 ret := struct { 111 Container daggerutil.Container 112 }{} 113 114 err := daggerutil.Query(ctx, c, &ret, fmt.Sprintf(` 115 query { 116 container(id: %q) { 117 id 118 entrypoint 119 defaultArgs 120 workdir 121 user 122 labels { 123 value 124 name 125 } 126 envVariables { 127 value 128 name 129 } 130 rootfs { 131 id 132 } 133 } 134 } 135 `, id)) 136 if err != nil { 137 return err 138 } 139 140 p.WorkingDir = ret.Container.Workdir 141 p.Entrypoint = ret.Container.Entrypoint 142 p.Cmd = ret.Container.DefaultArgs 143 p.User = ret.Container.User 144 145 p.Env = map[string]string{} 146 for _, e := range ret.Container.EnvVariables { 147 p.Env[e.Name] = e.Value 148 } 149 150 p.Labels = map[string]string{} 151 for _, e := range ret.Container.Labels { 152 p.Labels[e.Name] = e.Value 153 } 154 155 return nil 156 } 157 158 func mergeMap[K comparable, V any](a map[K]V, b map[K]V) map[K]V { 159 m := make(map[K]V) 160 161 for k := range a { 162 m[k] = a[k] 163 } 164 165 for k := range b { 166 m[k] = b[k] 167 } 168 169 return m 170 }