Skip to content

Commit c338f1d

Browse files
chore: print a message that a new version is available (#4895)
1 parent 07b5999 commit c338f1d

File tree

3 files changed

+169
-2
lines changed

3 files changed

+169
-2
lines changed

.goreleaser.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ builds:
1515
- -mod=readonly
1616
- -trimpath
1717
ldflags:
18-
- '-s -w -X main.version={{.Version}} -X main.commit={{.Commit}}'
18+
- '-s -w -X github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud.Version={{.Version}}'
1919
goos:
2020
- freebsd
2121
- windows

huaweicloud/config/upgrade.go

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package config
2+
3+
import (
4+
"bytes"
5+
"crypto/tls"
6+
"encoding/json"
7+
"io"
8+
"log"
9+
"net/http"
10+
"strconv"
11+
"strings"
12+
13+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
14+
)
15+
16+
const (
17+
versionURL = "https://provider.obs.cn-north-4.myhuaweicloud.com/terraform-provider-huaweicloud/version.json"
18+
defaultSummary = "Newer Version Available"
19+
defaultDetail = "The provider version is out of date, please upgrade to the latest version."
20+
)
21+
22+
type VersionConfig struct {
23+
Latest string `json:"latest"`
24+
Version map[string]string `json:"version"`
25+
Warning string `json:"warning"`
26+
Message string `json:"message"`
27+
}
28+
29+
func CheckUpgrade(version string) diag.Diagnostics {
30+
log.Printf("[DEBUG] current version: %s", version)
31+
if version == "" {
32+
return nil
33+
}
34+
35+
defer func() {
36+
if r := recover(); r != nil {
37+
log.Printf("[ERROR] CheckUpgrade recover: %#v", r)
38+
}
39+
}()
40+
41+
body, _, err := httpRequest("GET", versionURL, nil, nil)
42+
if err != nil {
43+
log.Printf("[WARN] failed to query version config : %s", err)
44+
return nil
45+
}
46+
47+
verCfg := &VersionConfig{}
48+
err = json.Unmarshal(body, verCfg)
49+
if err != nil {
50+
log.Printf("[WARN] failed to unmarshal version config : %s", err)
51+
return nil
52+
}
53+
54+
if verCfg.Latest == "" {
55+
log.Printf("[WARN] failed to get latest version")
56+
return nil
57+
}
58+
59+
if compareVersion(version, verCfg.Latest) != -1 {
60+
return nil
61+
}
62+
63+
summary := defaultSummary
64+
if verCfg.Warning != "" {
65+
summary = verCfg.Warning
66+
summary = strings.ReplaceAll(summary, "${latest}", verCfg.Latest)
67+
summary = strings.ReplaceAll(summary, "${version}", version)
68+
}
69+
70+
detail := defaultDetail
71+
if verCfg.Message != "" {
72+
detail = verCfg.Message
73+
detail = strings.ReplaceAll(detail, "${latest}", verCfg.Latest)
74+
detail = strings.ReplaceAll(detail, "${version}", version)
75+
}
76+
return diag.Diagnostics{
77+
diag.Diagnostic{
78+
Severity: diag.Warning,
79+
Summary: summary,
80+
Detail: detail,
81+
},
82+
}
83+
}
84+
85+
// compareVersion compares two version strings and returns:
86+
// ver1 < ver2 -> -1
87+
// ver1 > ver2 -> 1
88+
// ver1 == ver2 -> 0
89+
func compareVersion(ver1, ver2 string) int {
90+
parts1 := strings.Split(ver1, ".")
91+
parts2 := strings.Split(ver2, ".")
92+
93+
if len(parts1) != len(parts2) {
94+
if len(parts1) > len(parts2) {
95+
return 1
96+
}
97+
return -1
98+
}
99+
100+
for i := range parts1 {
101+
num1, _ := strconv.Atoi(parts1[i])
102+
num2, _ := strconv.Atoi(parts2[i])
103+
104+
if num1 < num2 {
105+
return -1
106+
} else if num1 > num2 {
107+
return 1
108+
}
109+
}
110+
111+
return 0
112+
}
113+
114+
func httpRequest(method, requestUrl string, jsonBody any, headers map[string]string) ([]byte, int, error) {
115+
var body io.Reader
116+
var contentType string
117+
if jsonBody != nil {
118+
rendered, err := json.Marshal(jsonBody)
119+
if err != nil {
120+
return nil, 0, err
121+
}
122+
body = bytes.NewReader(rendered)
123+
contentType = "application/json"
124+
}
125+
126+
client := http.Client{
127+
Transport: &LogRoundTripper{
128+
Rt: &http.Transport{
129+
Proxy: http.ProxyFromEnvironment,
130+
TLSClientConfig: &tls.Config{
131+
MinVersion: tls.VersionTLS12,
132+
InsecureSkipVerify: true, //nolint:gosec
133+
},
134+
},
135+
MaxRetries: 3,
136+
},
137+
}
138+
defer client.CloseIdleConnections()
139+
140+
request, err := http.NewRequest(method, requestUrl, body)
141+
if err != nil {
142+
return nil, 0, err
143+
}
144+
145+
if contentType != "" {
146+
request.Header.Set("Content-Type", contentType)
147+
}
148+
for k, v := range headers {
149+
request.Header.Add(k, v)
150+
}
151+
152+
response, err := client.Do(request)
153+
if err != nil {
154+
return nil, 0, err
155+
}
156+
defer func() {
157+
if err := response.Body.Close(); err != nil {
158+
log.Printf("[WARN] failed to close response: %s", err)
159+
}
160+
}()
161+
162+
bodyByte, err := io.ReadAll(response.Body)
163+
164+
return bodyByte, response.StatusCode, err
165+
}

huaweicloud/provider.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ const (
115115
prefixEuropeRegion string = "eu-west-1"
116116
)
117117

118+
var Version string
119+
118120
// Provider returns a schema.Provider for HuaweiCloud.
119121
func Provider() *schema.Provider {
120122
provider := &schema.Provider{
@@ -2056,7 +2058,7 @@ func configureProvider(_ context.Context, d *schema.ResourceData, terraformVersi
20562058
conf.SetServiceEndpoint("cdn", cdnEndpoint)
20572059
}
20582060

2059-
return &conf, nil
2061+
return &conf, config.CheckUpgrade(Version)
20602062
}
20612063

20622064
func flattenProviderEndpoints(d *schema.ResourceData) (map[string]string, error) {

0 commit comments

Comments
 (0)