-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathprovider_release.go
149 lines (111 loc) · 3.46 KB
/
provider_release.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"context"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"sort"
"strings"
"github.com/Masterminds/semver"
"github.com/google/go-github/v32/github"
"github.com/pkg/errors"
)
type providerRelease struct {
version *semver.Version
plugins map[string]string
}
func storeFile(path string, content []byte) error {
dir := filepath.Dir(path)
st, err := os.Stat(dir)
if err != nil && !os.IsNotExist(err) {
return errors.Wrapf(err, "while getting stat of %s", dir)
}
if err == nil && !st.IsDir() {
return errors.Errorf("%s is not a directory", dir)
}
if os.IsNotExist(err) {
log.Println("[DEBUG] creating plugin dir", dir)
err = os.MkdirAll(dir, 0700)
if err != nil {
return errors.Wrapf(err, "while creating dir %s", dir)
}
}
err = ioutil.WriteFile(path, content, 0700)
if err != nil {
return errors.Wrapf(err, "while writing to file %s", path)
}
return nil
}
func (p providerRelease) generateShims(dir, pluginName string) error {
for arch, url := range p.plugins {
binaryName := fmt.Sprintf("terraform-provider-%s_v%s", pluginName, p.version.String())
log.Println("[DEBUG] binary name", binaryName)
shimText, err := generateShim(url, pluginName, p.version.String(), binaryName)
pluginDir := filepath.Join(dir, "plugins", arch)
log.Println("[DEBUG] plugin dir", pluginDir)
shimFileName012 := filepath.Join(pluginDir, binaryName)
log.Println("[DEBUG] shim file name for terraform 0.12:", shimFileName012)
err = storeFile(shimFileName012, []byte(shimText))
if err != nil {
return err
}
shimFileName013 := filepath.Join(dir, "plugins", "registry.terraform.io", "hashicorp", pluginName, p.version.String(), arch, binaryName)
log.Println("[DEBUG] shim file name for terraform 0.13:", shimFileName013)
err = storeFile(shimFileName013, []byte(shimText))
if err != nil {
return err
}
}
return nil
}
func repoReleaseToProviderRelease(r *github.RepositoryRelease) (providerRelease, error) {
ver, err := semver.NewVersion(r.GetTagName())
if err != nil {
return providerRelease{}, nil
}
pr := providerRelease{
version: ver,
plugins: make(map[string]string),
}
for _, a := range r.Assets {
matches, arch := matchTerraformProviderAssetName(a.GetName())
// there is no point in generating windows shim, so skip it.
if matches && !strings.Contains(arch, "windows") {
pr.plugins[arch] = a.GetBrowserDownloadURL()
}
}
return pr, nil
}
func findLatestReleaseWithPluginAssets(ctx context.Context, gcl *github.Client, owner, repo string, constraints *semver.Constraints) (providerRelease, error) {
listOptions := &github.ListOptions{
PerPage: 50,
}
providerReleases := []providerRelease{}
for {
releases, response, err := gcl.Repositories.ListReleases(ctx, owner, repo, listOptions)
if err != nil {
return providerRelease{}, errors.Wrap(err, "while listing releases")
}
for _, r := range releases {
pr, err := repoReleaseToProviderRelease(r)
if err == nil && pr.version != nil {
if constraints.Check(pr.version) {
providerReleases = append(providerReleases, pr)
}
}
}
if response.NextPage == 0 {
break
}
listOptions.Page = response.NextPage
}
if len(providerReleases) == 0 {
return providerRelease{}, errors.New("could not find any releases containing terraform provider artifacts")
}
sort.Slice(providerReleases, func(i, j int) bool {
return providerReleases[i].version.Compare(providerReleases[j].version) > 0
})
return providerReleases[0], nil
}