github.com/octohelm/wagon@v0.0.0-20240308040401-88662650dc0b/pkg/engine/plan/task/container_push.go (about) 1 package task 2 3 import ( 4 "context" 5 "dagger.io/dagger" 6 "encoding/json" 7 8 "github.com/octohelm/wagon/pkg/engine/daggerutil" 9 "github.com/octohelm/wagon/pkg/engine/plan" 10 "github.com/octohelm/wagon/pkg/engine/plan/task/core" 11 "github.com/pkg/errors" 12 ) 13 14 func init() { 15 core.DefaultFactory.Register(&Push{}) 16 } 17 18 type Push struct { 19 Pusher 20 } 21 22 func (Push) OneOf() []any { 23 return []any{ 24 &PushImage{}, 25 &PushManifests{}, 26 } 27 } 28 29 func (p *Push) UnmarshalJSON(bytes []byte) error { 30 ret := struct { 31 Type string `json:"type"` 32 }{} 33 34 if err := json.Unmarshal(bytes, &ret); err != nil { 35 return err 36 } 37 38 if ret.Type == "manifests" { 39 m := &PushManifests{} 40 if err := json.Unmarshal(bytes, m); err != nil { 41 return err 42 } 43 p.Pusher = m 44 } 45 46 m := &PushImage{} 47 if err := json.Unmarshal(bytes, m); err != nil { 48 return err 49 } 50 p.Pusher = m 51 return nil 52 } 53 54 type Pusher interface { 55 Do(ctx context.Context) error 56 } 57 58 type PushImage struct { 59 core.Task 60 61 Dest string `json:"dest"` 62 Type string `json:"type" enum:"image"` 63 64 Input core.FS `json:"input"` 65 Config core.ImageConfig `json:"config"` 66 Platform string `json:"platform,omitempty"` 67 Format string `json:"format,omitempty" enum:"docker,oci" default:"docker"` 68 69 Auth *core.Auth `json:"auth,omitempty"` 70 71 Result string `json:"-" wagon:"generated,name=result"` 72 } 73 74 func (input *PushImage) Do(ctx context.Context) error { 75 return daggerutil.Do(ctx, func(c *dagger.Client) error { 76 id := input.Input.DirectoryID() 77 if id == "" { 78 return errors.Errorf("missing fs") 79 } 80 81 dir := c.LoadDirectoryFromID(id) 82 83 ctr := input.Config.ApplyTo(c.Container(dagger.ContainerOpts{ 84 Platform: dagger.Platform(input.Platform), 85 }).WithRootfs(dir)) 86 87 ct := c.Container() 88 89 ct = plan.RegistryAuthStoreContext.From(ctx).ApplyTo(ctx, ct) 90 if a := input.Auth; a != nil { 91 ct = a.ApplyTo(ctx, ct, input.Dest) 92 } 93 94 // prepare before push 95 _, err := ctr.Rootfs().Entries(ctx) 96 if err != nil { 97 return err 98 } 99 100 ret, err := ct.Publish(ctx, input.Dest, dagger.ContainerPublishOpts{ 101 PlatformVariants: []*dagger.Container{ 102 ctr, 103 }, 104 MediaTypes: Format(input.Format).MediaTypes(), 105 }) 106 if err != nil { 107 return err 108 } 109 input.Result = ret 110 return nil 111 }) 112 113 } 114 115 type PushManifests struct { 116 core.Task 117 118 Dest string `json:"dest"` 119 Type string `json:"type" enum:"manifests"` 120 Format string `json:"format,omitempty" enum:"docker,oci" default:"docker"` 121 122 Inputs map[string]struct { 123 Input core.FS `json:"input"` 124 Config core.ImageConfig `json:"config"` 125 } `json:"inputs"` 126 127 Auth *core.Auth `json:"auth,omitempty"` 128 129 Result string `json:"-" wagon:"generated,name=result"` 130 } 131 132 func (input *PushManifests) Do(ctx context.Context) error { 133 return daggerutil.Do(ctx, func(c *dagger.Client) error { 134 cts := make([]*dagger.Container, 0, len(input.Inputs)) 135 136 for platform := range input.Inputs { 137 img := input.Inputs[platform] 138 id := img.Input.DirectoryID() 139 if id == "" { 140 return errors.Errorf("missing fs for %s", platform) 141 } 142 143 dir := c.LoadDirectoryFromID(id) 144 145 ctr := img.Config.ApplyTo(c.Container(dagger.ContainerOpts{Platform: dagger.Platform(platform)}).WithRootfs(dir)) 146 147 // prepare before push 148 _, err := ctr.Rootfs().Entries(ctx) 149 if err != nil { 150 return err 151 } 152 153 cts = append(cts, ctr) 154 } 155 156 ct := plan.RegistryAuthStoreContext.From(ctx).ApplyTo(ctx, c.Container()) 157 if a := input.Auth; a != nil { 158 ct = a.ApplyTo(ctx, ct, input.Dest) 159 } 160 161 ret, err := ct.Publish(ctx, input.Dest, dagger.ContainerPublishOpts{ 162 PlatformVariants: cts, 163 MediaTypes: Format(input.Format).MediaTypes(), 164 }) 165 if err != nil { 166 return err 167 } 168 input.Result = ret 169 return nil 170 }) 171 } 172 173 type Format string 174 175 func (f Format) MediaTypes() dagger.ImageMediaTypes { 176 if f == "oci" { 177 return dagger.Ocimediatypes 178 } 179 return dagger.Dockermediatypes 180 }