-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.go
130 lines (115 loc) · 3.56 KB
/
main.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
package main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"time"
"github.com/mitchellh/go-homedir"
)
var (
cachePath = flag.String("cache-path", "~/.oci-k8s-cache", "")
expirationThreshold = flag.Duration("expiration-threshold", 30*time.Second, "how long before the expiration should we treat the tokens as expired")
ociPath = flag.String("oci-path", "oci", "path to the oci binary")
clusterID = flag.String("cluster-id", "", "cluster id to pass to the OCI CLI")
region = flag.String("region", "us-ashburn-1", "OCI region to use")
)
type credentials struct {
APIVersion string `json:"apiVersion"`
Kind string `json:"kind"`
Status struct {
Token string `json:"token"`
ExpirationTimestamp time.Time `json:"expirationTimestamp"`
} `json:"status"`
}
func main() {
// hack to support flags at the end of the args
args := os.Args
for i, arg := range args {
if len(arg) > 0 && arg[0] == '-' {
args = args[i:]
break
}
}
if err := flag.CommandLine.Parse(args); err != nil {
panic(err)
}
fullOCIPath, err := exec.LookPath(*ociPath)
if err != nil {
log.Fatalf("failed to look up the path to the OCI binary: %v", err)
return
}
if *clusterID == "" || *region == "" {
log.Fatalf("either clusterID (value: %v) or region (value: %v) are empty", clusterID, region)
return
}
if *cachePath == "" {
log.Fatal("cache path is requried")
return
}
expandedCachePath, err := homedir.Expand(*cachePath)
if err != nil {
log.Fatalf("failed to expand the passed cache path: %v", err)
return
}
if err := os.MkdirAll(expandedCachePath, 0700); err != nil {
log.Fatalf("failed to prepare the directory for the cache: %v", err)
return
}
cachedFilePath := filepath.Join(expandedCachePath, fmt.Sprintf("%s-%s", *region, *clusterID))
cachedFile, err := processCachedFile(cachedFilePath)
if err != nil {
log.Fatalf("failed to process the cached file %s: %v", cachedFilePath, err)
return
}
if cachedFile != nil {
if _, err := os.Stdout.Write(cachedFile); err != nil {
panic(err)
}
return
}
cmd := exec.Command(fullOCIPath, "ce", "cluster", "generate-token", "--cluster-id", *clusterID, "--region", *region)
output, err := cmd.Output()
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
log.Fatalf("failed to run the OCI command, error code %d, stderr:\n%v", exitError.ExitCode(), string(exitError.Stderr))
return
}
log.Fatalf("failed to run the OCI command: %v", err.Error())
return
}
var parsedCredentials credentials
if err := json.Unmarshal(output, &parsedCredentials); err != nil {
log.Fatalf("failed to parse the credentials output: %v", err)
}
if parsedCredentials.Status.ExpirationTimestamp.Before(time.Now().Add(-1 * *expirationThreshold)) {
log.Fatalf("freshly fetched token has an expired timestamp: %v", string(output))
}
if err := ioutil.WriteFile(cachedFilePath, output, 0600); err != nil {
log.Fatalf("failed to write the new cached file %s: %v", cachedFilePath, err)
}
if _, err := os.Stdout.Write(output); err != nil {
panic(err)
}
}
func processCachedFile(path string) ([]byte, error) {
cachedBytes, err := ioutil.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
var parsedCredentials credentials
if err := json.Unmarshal(cachedBytes, &parsedCredentials); err != nil {
return nil, err
}
if parsedCredentials.Status.ExpirationTimestamp.Before(time.Now().Add(-1 * *expirationThreshold)) {
return nil, nil
}
return cachedBytes, nil
}