Last active
July 7, 2023 14:02
-
-
Save anthonydahanne/3b8977e04d500936dec7660cf3c354d2 to your computer and use it in GitHub Desktop.
Update release numbers on pivnet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module pivnet/patcher | |
go 1.20 | |
require gopkg.in/yaml.v3 v3.0.1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"encoding/json" | |
"fmt" | |
"gopkg.in/yaml.v3" | |
"io" | |
"log" | |
"net/http" | |
"os" | |
"regexp" | |
) | |
const pivnetApiUrl = "https://network.tanzu.vmware.com/api/v2/" | |
const pivnetProduct = "java-buildpack" | |
const stringToAppend = ".0" | |
const dotpivnetrc = ".pivnetrc" | |
type PivnetConf struct { | |
Profile []map[string]string `yaml:"profiles"` | |
} | |
func main() { | |
pattern := regexp.MustCompile("([\\d]+.[\\d]+.[\\d]+)") | |
dirname, err := os.UserHomeDir() | |
if err != nil { | |
log.Fatal("Impossible to get to user directory", err) | |
} | |
filename := dirname + "/" + dotpivnetrc | |
pivnetConfig, err := readConf(filename) | |
if err != nil { | |
log.Fatal("pivnet configuration was not loaded; please make sure you have it generated using pivnet login") | |
} | |
log.Printf("✅ Successfully loaded pivnet local configuration at %q", filename) | |
accessToken := pivnetConfig.Profile[0]["access_token"] | |
if accessToken == "" { | |
log.Fatal("pivnet configuration does not contain an api_token set; please make sure you have it generated using pivnet login") | |
} | |
log.Printf("✅ Successfully loaded pivnet access_token") | |
allReleasesResponse := map[string]interface{}{} | |
err = retrieveReleases(accessToken, allReleasesResponse) | |
if err != nil { | |
log.Fatal("impossible to retrieve releases from pivnet", err) | |
} | |
var releases = allReleasesResponse["releases"].([]interface{}) | |
log.Printf("✅ Successfully retrieved %d releases for the TanzuNet product named %s", len(releases), pivnetProduct) | |
for _, release := range releases { | |
var currentRelease = release.(map[string]interface{}) | |
id := int(currentRelease["id"].(float64)) | |
version := currentRelease["version"].(string) | |
if pattern.MatchString(version) { | |
log.Printf("⏭️ skipping %s since it already matches the expected version schema, X.Y.Z", version) | |
continue | |
} | |
log.Printf("❓ OK to patch %s version %s (release id %d) into version %s ? y/n", pivnetProduct, version, id, version+stringToAppend) | |
var answer string | |
fmt.Scan(&answer) | |
if answer == "y" { | |
resultResponse := map[string]interface{}{} | |
err := patchRelease(accessToken, currentRelease, id, version, resultResponse) | |
if err != nil { | |
log.Print("impossible to patch this release - moving on.", err) | |
} else { | |
log.Print(resultResponse["message"]) | |
} | |
} else { | |
continue | |
} | |
} | |
} | |
func patchRelease(accessToken string, currentRelease map[string]interface{}, id int, version string, resultResponse map[string]interface{}) error { | |
currentRelease["version"] = version + stringToAppend | |
jsonMarshalledRelease, err := json.Marshal(currentRelease) | |
if err != nil { | |
return err | |
} | |
req, err := http.NewRequest("PUT", pivnetApiUrl+"products/"+pivnetProduct+"/releases/"+fmt.Sprint(id), bytes.NewBuffer(jsonMarshalledRelease)) | |
if err != nil { | |
return err | |
} | |
req.Header.Add("Content-Type", " application/json") | |
req.Header.Add("Accept", " application/json") | |
req.Header.Add("Authorization", "Bearer "+accessToken) | |
client := &http.Client{} | |
resp, err := client.Do(req) | |
if err != nil { | |
return err | |
} | |
defer resp.Body.Close() | |
body, _ := io.ReadAll(resp.Body) | |
postResultBody := string(body) | |
err = json.Unmarshal([]byte(postResultBody), &resultResponse) | |
if err != nil { | |
return err | |
} | |
return nil | |
} | |
func retrieveReleases(accessToken string, allReleases map[string]interface{}) error { | |
req, err := http.NewRequest("GET", pivnetApiUrl+"products/"+pivnetProduct+"/releases", nil) | |
if err != nil { | |
return err | |
} | |
req.Header.Add("Authorization", "Bearer "+accessToken) | |
client := &http.Client{} | |
resp, err := client.Do(req) | |
if err != nil { | |
return err | |
} | |
defer resp.Body.Close() | |
body, _ := io.ReadAll(resp.Body) | |
allReleasesAsString := string(body) | |
if err := json.Unmarshal([]byte(allReleasesAsString), &allReleases); err != nil { | |
return err | |
} | |
return nil | |
} | |
func readConf(filename string) (*PivnetConf, error) { | |
buf, err := os.ReadFile(filename) | |
if err != nil { | |
log.Fatal("Impossible to read "+filename, err) | |
return nil, err | |
} | |
pivnetConfig := &PivnetConf{} | |
err = yaml.Unmarshal(buf, pivnetConfig) | |
if err != nil { | |
return nil, fmt.Errorf("error loading Yaml file %q: %w", filename, err) | |
} | |
return pivnetConfig, err | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
A simple go app to connect to TanzuNet / Pivnet and update the release versions; to match the expected schema X.Y.Z instead of X.Y |
Nice work! 🎉
I made a small addition to skip the already 3-digit versions so it doesn't ask us about those:
func main() {
pattern := regexp.MustCompile("([\\d]+.[\\d]+.[\\d]+)")
and then later, in the loop
version := currentRelease["version"].(string)
if pattern.MatchString(version) {
continue
}
it seems to work, skipping to 4.56 for the first question
@pivotal-david-osullivan thank you! I applied your suggestion and then added a log line to show we skipped
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example output: