Skip to content

Commit 822271d

Browse files
authored
Add upload results-spreadsheet certsuite sub-command (redhat-best-practices-for-k8s#2389)
* Add upload results-spreadsheet certsuite sub-command * add files to .gitignore; add mnd linter * linting fixes * Avoid using wanted prefix before variables * names modification; seperate getHeaders to two funcs * change sprintf to sprint where needed * add descriptions; name modifications; add a const file * organize conclusion cell insertion loop; fix typos * fix\adjust return values * move credentials and token file to executable dir by default, and add an option for a configured dir for creds
1 parent 316de00 commit 822271d

File tree

10 files changed

+831
-14
lines changed

10 files changed

+831
-14
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ temp/
2525
/all-releases.txt
2626
/latest-release-tag.txt
2727
/release-tag.txt
28+
29+
credentials.json
30+
token.json

cmd/certsuite/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/generate"
1212
"github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/info"
1313
"github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/run"
14+
"github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/upload"
1415
"github.com/redhat-best-practices-for-k8s/certsuite/cmd/certsuite/version"
1516
)
1617

@@ -26,6 +27,7 @@ func newRootCmd() *cobra.Command {
2627
rootCmd.AddCommand(run.NewCommand())
2728
rootCmd.AddCommand(info.NewCommand())
2829
rootCmd.AddCommand(version.NewCommand())
30+
rootCmd.AddCommand(upload.NewCommand())
2931

3032
return &rootCmd
3133
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package resultsspreadsheet
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"net/http"
8+
"os"
9+
10+
"golang.org/x/oauth2"
11+
)
12+
13+
const tokenPermissions = 0o600
14+
15+
// Retrieve a token, saves the token, then returns the generated client.
16+
func getClient(config *oauth2.Config) (*http.Client, error) {
17+
// The file token.json stores the user's access and refresh tokens, and is
18+
// created automatically when the authorization flow completes for the first
19+
// time.
20+
tokFile := "token.json"
21+
tok, err := tokenFromFile(tokFile)
22+
if err != nil {
23+
tok, err = getTokenFromWeb(config)
24+
if err != nil {
25+
return nil, err
26+
}
27+
if err := saveToken(tokFile, tok); err != nil {
28+
return nil, err
29+
}
30+
}
31+
return config.Client(context.Background(), tok), nil
32+
}
33+
34+
// Request a token from the web, then returns the retrieved token.
35+
func getTokenFromWeb(config *oauth2.Config) (*oauth2.Token, error) {
36+
authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
37+
fmt.Printf("Go to the following link in your browser then type the "+
38+
"authorization code: \n%v\n", authURL)
39+
40+
var authCode string
41+
if _, err := fmt.Scan(&authCode); err != nil {
42+
return nil, fmt.Errorf("unable to read authorization code: %v", err)
43+
}
44+
45+
tok, err := config.Exchange(context.TODO(), authCode)
46+
if err != nil {
47+
return nil, fmt.Errorf("unable to retrieve token from web: %v", err)
48+
}
49+
return tok, nil
50+
}
51+
52+
// Retrieves a token from a local file.
53+
func tokenFromFile(file string) (*oauth2.Token, error) {
54+
f, err := os.Open(file)
55+
if err != nil {
56+
return nil, err
57+
}
58+
defer f.Close()
59+
tok := &oauth2.Token{}
60+
err = json.NewDecoder(f).Decode(tok)
61+
return tok, err
62+
}
63+
64+
// Saves a token to a file path.
65+
func saveToken(path string, token *oauth2.Token) error {
66+
fmt.Printf("Saving credential file to: %s\n", path)
67+
f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, tokenPermissions)
68+
if err != nil {
69+
return fmt.Errorf("unable to cache oauth token: %v", err)
70+
}
71+
defer f.Close()
72+
err = json.NewEncoder(f).Encode(token)
73+
if err != nil {
74+
return fmt.Errorf("unable to encode token: %v", err)
75+
}
76+
return nil
77+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package resultsspreadsheet
2+
3+
const (
4+
categoryConclusionsCol = "Category"
5+
workloadVersionConclusionsCol = "Workload Version"
6+
ocpVersionConclusionsCol = "OCP Version"
7+
workloadNameConclusionsCol = "Workload Name"
8+
resultsConclusionsCol = "Results"
9+
workloadNameRawResultsCol = "CNFName"
10+
workloadTypeRawResultsCol = "CNFType"
11+
operatorVersionRawResultsCol = "OperatorVersion"
12+
cellContentLimit = 50000
13+
)
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package resultsspreadsheet
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"net/url"
7+
"strings"
8+
9+
"google.golang.org/api/drive/v3"
10+
"google.golang.org/api/sheets/v4"
11+
)
12+
13+
func createDriveFolder(srv *drive.Service, folderName, parentFolderID string) (*drive.File, error) {
14+
driveFolder := &drive.File{
15+
Name: folderName,
16+
Parents: []string{parentFolderID},
17+
MimeType: "application/vnd.google-apps.folder",
18+
}
19+
20+
// Search for an existing folder with the same name
21+
q := fmt.Sprintf("name = '%s' and mimeType = 'application/vnd.google-apps.folder' and '%s' in parents and trashed = false", folderName, parentFolderID)
22+
call := srv.Files.List().Q(q).Fields("files(id, name)")
23+
24+
files, err := call.Do()
25+
if err != nil {
26+
return nil, fmt.Errorf("unable to list files: %v", err)
27+
}
28+
29+
if len(files.Files) > 0 {
30+
return nil, fmt.Errorf("folder %s already exists in %s folder ID", folderName, parentFolderID)
31+
}
32+
33+
createdFolder, err := srv.Files.Create(driveFolder).Do()
34+
if err != nil {
35+
return nil, fmt.Errorf("unable to create folder: %v", err)
36+
}
37+
38+
return createdFolder, nil
39+
}
40+
41+
func MoveSpreadSheetToFolder(srv *drive.Service, folder *drive.File, spreadsheet *sheets.Spreadsheet) error {
42+
file, err := srv.Files.Get(spreadsheet.SpreadsheetId).Fields("parents").Do()
43+
if err != nil {
44+
log.Fatalf("Unable to get file: %v", err)
45+
}
46+
47+
// Collect the current parent IDs to remove (if needed)
48+
oldParents := append([]string{}, file.Parents...)
49+
50+
updateCall := srv.Files.Update(spreadsheet.SpreadsheetId, nil)
51+
updateCall.AddParents(folder.Id)
52+
53+
// Remove the file from its old parents
54+
if len(oldParents) > 0 {
55+
for _, parent := range oldParents {
56+
updateCall.RemoveParents(parent)
57+
}
58+
}
59+
60+
_, err = updateCall.Do()
61+
if err != nil {
62+
log.Fatalf("Unable change file location: %v", err)
63+
}
64+
65+
return nil
66+
}
67+
68+
func extractFolderIDFromURL(u string) (string, error) {
69+
parsedURL, err := url.Parse(u)
70+
if err != nil {
71+
return "", err
72+
}
73+
74+
pathSegments := strings.Split(parsedURL.Path, "/")
75+
76+
// The folder ID is the last segment in the path
77+
return pathSegments[len(pathSegments)-1], nil
78+
}

0 commit comments

Comments
 (0)