blob: f042c783028ce22e287762ffc957a53dd2d28919 [file] [log] [blame]
Mohammed Naserdabb1dc2022-09-06 14:45:59 -04001package image_repositories
2
3import (
Mohammed Naseraaba50a2022-09-06 16:15:36 -04004 "context"
Mohammed Naserdabb1dc2022-09-06 14:45:59 -04005 _ "embed"
Mohammed Naseraaba50a2022-09-06 16:15:36 -04006 "encoding/json"
7 "fmt"
Mohammed Naserdabb1dc2022-09-06 14:45:59 -04008 "io"
Mohammed Naseraaba50a2022-09-06 16:15:36 -04009 "net/http"
Mohammed Naserdabb1dc2022-09-06 14:45:59 -040010 "text/template"
11
12 "github.com/go-git/go-billy/v5"
Mohammed Naseraaba50a2022-09-06 16:15:36 -040013 "github.com/google/go-github/v47/github"
Mohammed Naserdabb1dc2022-09-06 14:45:59 -040014)
15
16//go:embed template/Dockerfile
17var dockerfileTemplate string
18
19type Dockerfile struct {
20 BindepImage string
21 BindepImageTag string
22 BuilderImage string
23 BuilderImageTag string
24 RuntimeImage string
25 RuntimeImageTag string
26
27 template *template.Template
28}
29
Mohammed Naseraaba50a2022-09-06 16:15:36 -040030func NewDockerfile(ctx context.Context, ir *ImageRepository) (*Dockerfile, error) {
Mohammed Naserdabb1dc2022-09-06 14:45:59 -040031 tmpl, err := template.New("Dockerfile").Parse(dockerfileTemplate)
32 if err != nil {
33 return nil, err
34 }
35
Mohammed Naseraaba50a2022-09-06 16:15:36 -040036 runtimeImageTag, err := getImageTag(ctx, ir.githubClient, "docker-openstack-runtime", "openstack-runtime-focal")
37 if err != nil {
38 return nil, err
39 }
40
Mohammed Naserdabb1dc2022-09-06 14:45:59 -040041 return &Dockerfile{
42 BindepImage: "quay.io/vexxhost/bindep-loci",
43 BindepImageTag: "latest",
44 BuilderImage: "quay.io/vexxhost/openstack-builder-focal",
45 BuilderImageTag: "latest",
46 RuntimeImage: "quay.io/vexxhost/openstack-runtime-focal",
Mohammed Naseraaba50a2022-09-06 16:15:36 -040047 RuntimeImageTag: runtimeImageTag,
Mohammed Naserdabb1dc2022-09-06 14:45:59 -040048
49 template: tmpl,
50 }, nil
51}
52
Mohammed Naseraaba50a2022-09-06 16:15:36 -040053type quayTagList struct {
54 Tags []quayTag `json:"tags"`
55 Page int `json:"page"`
56 HasAdditional bool `json:"has_additional"`
57}
58
59type quayTag struct {
60 Name string `json:"name"`
61 Reversion bool `json:"reversion"`
62 StartTimestamp int32 `json:"start_ts"`
63 ManifestDigest string `json:"manifest_digest"`
64 IsManifestList bool `json:"is_manifest_list"`
65 Size int `json:"size"`
66 LastModified string `json:"last_modified"`
67}
68
69func getImageTag(ctx context.Context, client *github.Client, repository string, image string) (string, error) {
70 // Grab the latest SHA from the main branch
71 commit, _, err := client.Repositories.GetCommitSHA1(ctx, "vexxhost", repository, "main", "")
72 if err != nil {
73 return "", err
74 }
75
76 // Check if the image exists in Quay.io
77 url := fmt.Sprintf("https://quay.io/api/v1/repository/vexxhost/%s/tag/?specificTag=%s", image, commit)
78 resp, err := http.Get(url)
79 if err != nil {
80 return "", err
81 }
82
83 // Decode the response
84 var quayResponse quayTagList
85 decoder := json.NewDecoder(resp.Body)
86 decoder.DisallowUnknownFields()
87 err = decoder.Decode(&quayResponse)
88 if err != nil {
89 return "", err
90 }
91
92 // Check if the tag exists
93 if len(quayResponse.Tags) == 0 {
94 return "", fmt.Errorf("tag %s does not exist in quay.io/vexxhost/%s", commit, image)
95 }
96
97 return commit, nil
98}
99
Mohammed Naserdabb1dc2022-09-06 14:45:59 -0400100func (d *Dockerfile) Write(wr io.Writer) error {
101 return d.template.Execute(wr, d)
102}
103
104func (d *Dockerfile) WriteFile(fs billy.Filesystem) error {
105 f, err := fs.Create("Dockerfile")
106 if err != nil {
107 return err
108 }
109 defer f.Close()
110
111 return d.Write(f)
112}