-
-
Notifications
You must be signed in to change notification settings - Fork 512
/
cmd_license.go
120 lines (111 loc) · 3.59 KB
/
cmd_license.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
package cli
import (
"context"
"fmt"
"io"
"os"
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"github.com/datawire/ambassador/v2/pkg/kates"
"github.com/telepresenceio/telepresence/v2/pkg/client/cli/cliutil"
"github.com/telepresenceio/telepresence/v2/pkg/client/errcat"
)
func LicenseCommand() *cobra.Command {
var flags struct {
id string
outputFile string
licenseFile string
hostDomain string
}
cmd := &cobra.Command{
Use: "license [flags]",
Args: cobra.NoArgs,
Short: "Get License from Ambassador Cloud",
Long: `Get License from Ambassador Cloud. For more information on what
licenses are used for, head to:
https://www.getambassador.io/docs/telepresence/latest/reference/cluster-config/`,
RunE: func(cmd *cobra.Command, args []string) error {
return getCloudLicense(cmd.Context(), cmd.OutOrStdout(),
flags.id, flags.outputFile, flags.licenseFile, flags.hostDomain)
},
}
cmd.Flags().StringVarP(&flags.id, "id", "i", "", "The id associated with your license.")
cmd.Flags().StringVarP(&flags.outputFile, "output-file", "o", "", "The file where you want the license secret to be output to")
cmd.Flags().StringVarP(&flags.licenseFile, "license-file", "f", "", "The file containing your license if you've downloaded it already")
cmd.Flags().StringVarP(&flags.hostDomain, "host-domain", "d", "auth.datawire.io", "The host domain providing your license")
return cmd
}
// getCloudLicense communicates with system a, acquires the jwt formatted license
// given by the id, places it in a secret, and outputs it to stdout or writes it
// to a file given by the user
func getCloudLicense(ctx context.Context, stdout io.Writer, id, outputFile, licenseFile, hostDomain string) error {
if licenseFile == "" && id == "" {
return errcat.User.New("Must use either --id or --license-file flag")
}
var license string
var err error
if licenseFile == "" {
// If we are getting the license from the cloud, we override the hostDomain
// since the function will provide which host the license came from
license, hostDomain, err = cliutil.GetCloudLicense(ctx, outputFile, id)
if err != nil {
return err
}
} else {
contents, err := os.ReadFile(licenseFile)
if err != nil {
return err
}
// We don't want a pesky trailing \n to mess up the jwt
// so we remove one if it exists
license = string(contents)
license = strings.TrimSuffix(license, "\n")
}
writer := stdout
// If a user gives a file, we write to the file instead of stdout
if outputFile != "" {
f, err := os.Create(outputFile)
if err != nil {
return err
}
defer f.Close()
fmt.Fprintf(stdout, "Writing secret to %v", outputFile)
writer = f
}
if err := createSecretFromLicense(ctx, writer, license, hostDomain); err != nil {
return err
}
return nil
}
// Creates the kubernetes secret that can be put in your cluster
// to access licensed features if the cluster is airgapped and
// writes it to the given writer
func createSecretFromLicense(ctx context.Context, writer io.Writer, license, hostDomain string) error {
secret := &kates.Secret{
TypeMeta: kates.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: kates.ObjectMeta{
Namespace: "ambassador",
Name: "systema-license",
},
Data: map[string][]byte{
"license": []byte(license),
"hostDomain": []byte(hostDomain),
},
}
serializer := json.NewSerializerWithOptions(json.DefaultMetaFactory, nil, nil,
json.SerializerOptions{
Yaml: true,
Pretty: true,
Strict: true,
},
)
err := serializer.Encode(secret, writer)
if err != nil {
return err
}
return nil
}