Skip to content

Commit f9cc367

Browse files
authored
feat: add login and logout commands (#33)
Add two new commands: `login` and `logout` which allow the user to log in and out of a renku instance.
1 parent b7da849 commit f9cc367

File tree

13 files changed

+4132
-9
lines changed

13 files changed

+4132
-9
lines changed

Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,17 @@ check-format: ## Check that sources are correctly formatted
6868
.PHONY: check-vet
6969
check-vet: ## Check source files with `go vet`
7070
go vet ./...
71+
72+
##@ Code generation
73+
74+
.PHONY: renku-users-apispec
75+
renku-users-apispec: ## Download the "users" API spec
76+
curl -L -o pkg/renkuapi/users/api.spec.yaml https://raw.githubusercontent.com/SwissDataScienceCenter/renku-data-services/refs/heads/main/components/renku_data_services/users/api.spec.yaml
77+
sed -e 's/- default: "general"//g' pkg/renkuapi/users/api.spec.yaml > pkg/renkuapi/users/api.spec.new.yaml
78+
mv pkg/renkuapi/users/api.spec.new.yaml pkg/renkuapi/users/api.spec.yaml
79+
80+
.PHONY: generate
81+
generate: pkg/renkuapi/users/users_gen.go ## Run go generate
82+
83+
pkg/renkuapi/users/users_gen.go: pkg/renkuapi/users/api.spec.yaml
84+
go generate pkg/renkuapi/users/users.go

go.mod

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,33 @@ module github.com/SwissDataScienceCenter/renku-dev-utils
22

33
go 1.24.2
44

5+
tool github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen
6+
57
require (
8+
github.com/getkin/kin-openapi v0.132.0
9+
github.com/golang-jwt/jwt/v5 v5.3.0
10+
github.com/oapi-codegen/runtime v1.1.2
611
github.com/spf13/cobra v1.10.1
12+
github.com/zalando/go-keyring v0.2.6
713
golang.design/x/clipboard v0.7.1
814
k8s.io/api v0.34.1
915
k8s.io/apimachinery v0.34.1
1016
k8s.io/client-go v0.34.1
1117
)
1218

1319
require (
20+
al.essio.dev/pkg/shellescape v1.5.1 // indirect
21+
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
22+
github.com/danieljoos/wincred v1.2.2 // indirect
1423
github.com/davecgh/go-spew v1.1.1 // indirect
24+
github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect
1525
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
1626
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
1727
github.com/go-logr/logr v1.4.2 // indirect
1828
github.com/go-openapi/jsonpointer v0.21.0 // indirect
1929
github.com/go-openapi/jsonreference v0.20.2 // indirect
2030
github.com/go-openapi/swag v0.23.0 // indirect
31+
github.com/godbus/dbus/v5 v5.1.0 // indirect
2132
github.com/gogo/protobuf v1.3.2 // indirect
2233
github.com/google/gnostic-models v0.7.0 // indirect
2334
github.com/google/uuid v1.6.0 // indirect
@@ -27,24 +38,36 @@ require (
2738
github.com/mailru/easyjson v0.7.7 // indirect
2839
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
2940
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
41+
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
3042
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
43+
github.com/oapi-codegen/oapi-codegen/v2 v2.5.0 // indirect
44+
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect
45+
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
46+
github.com/perimeterx/marshmallow v1.1.5 // indirect
3147
github.com/pkg/errors v0.9.1 // indirect
48+
github.com/speakeasy-api/jsonpath v0.6.0 // indirect
49+
github.com/speakeasy-api/openapi-overlay v0.10.2 // indirect
3250
github.com/spf13/pflag v1.0.9 // indirect
51+
github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect
3352
github.com/x448/float16 v0.8.4 // indirect
3453
go.yaml.in/yaml/v2 v2.4.2 // indirect
3554
go.yaml.in/yaml/v3 v3.0.4 // indirect
3655
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect
3756
golang.org/x/image v0.28.0 // indirect
3857
golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f // indirect
39-
golang.org/x/net v0.38.0 // indirect
58+
golang.org/x/mod v0.25.0 // indirect
59+
golang.org/x/net v0.41.0 // indirect
4060
golang.org/x/oauth2 v0.27.0 // indirect
61+
golang.org/x/sync v0.15.0 // indirect
4162
golang.org/x/sys v0.33.0 // indirect
42-
golang.org/x/term v0.30.0 // indirect
63+
golang.org/x/term v0.32.0 // indirect
4364
golang.org/x/text v0.26.0 // indirect
4465
golang.org/x/time v0.9.0 // indirect
66+
golang.org/x/tools v0.34.0 // indirect
4567
google.golang.org/protobuf v1.36.5 // indirect
4668
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
4769
gopkg.in/inf.v0 v0.9.1 // indirect
70+
gopkg.in/yaml.v2 v2.4.0 // indirect
4871
gopkg.in/yaml.v3 v3.0.1 // indirect
4972
k8s.io/klog/v2 v2.130.1 // indirect
5073
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect

go.sum

Lines changed: 136 additions & 4 deletions
Large diffs are not rendered by default.

pkg/cmd/cleanupdeployment.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,10 @@ func askForConfirmation(question string) (response bool, err error) {
138138
return false, err
139139
}
140140
res = strings.ToLower(strings.TrimSpace(res))
141-
if res == "yes" {
141+
switch res {
142+
case "yes":
142143
return true, nil
143-
} else if res == "no" {
144+
case "no":
144145
return false, nil
145146
}
146147
return false, fmt.Errorf("Invalid answer, aborting.")

pkg/cmd/login.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
8+
"github.com/SwissDataScienceCenter/renku-dev-utils/pkg/github"
9+
ns "github.com/SwissDataScienceCenter/renku-dev-utils/pkg/namespace"
10+
"github.com/SwissDataScienceCenter/renku-dev-utils/pkg/renkuapi"
11+
"github.com/SwissDataScienceCenter/renku-dev-utils/pkg/renkuapi/users"
12+
"github.com/spf13/cobra"
13+
)
14+
15+
var loginCmd = &cobra.Command{
16+
Use: "login",
17+
Short: "Log in to a renku instance",
18+
Run: login,
19+
}
20+
21+
func login(cmd *cobra.Command, args []string) {
22+
ctx := context.Background()
23+
24+
url, err := cmd.Flags().GetString("url")
25+
if err != nil {
26+
fmt.Println(err)
27+
os.Exit(1)
28+
}
29+
30+
if url == "" {
31+
namespace, err := cmd.Flags().GetString("namespace")
32+
if err != nil {
33+
fmt.Println(err)
34+
os.Exit(1)
35+
}
36+
if namespace == "" {
37+
cli, err := github.NewGitHubCLI("")
38+
if err != nil {
39+
fmt.Println(err)
40+
os.Exit(1)
41+
}
42+
namespace, err = ns.FindCurrentNamespace(ctx, cli)
43+
if err != nil {
44+
fmt.Println(err)
45+
os.Exit(1)
46+
}
47+
}
48+
49+
deploymentURL, err := ns.GetDeploymentURL(namespace)
50+
if err != nil {
51+
fmt.Println(err)
52+
os.Exit(1)
53+
}
54+
url = deploymentURL.String()
55+
}
56+
57+
fmt.Printf("Renku URL: %s\n", url)
58+
59+
auth, err := renkuapi.NewRenkuApiAuth(url)
60+
if err != nil {
61+
fmt.Println(err)
62+
os.Exit(1)
63+
}
64+
65+
err = auth.Login(ctx)
66+
if err != nil {
67+
fmt.Println(err)
68+
os.Exit(1)
69+
}
70+
71+
ruc, err := users.NewRenkuUsersClient(url, users.WithRequestEditors(users.RequestEditorFn(auth.RequestEditor())))
72+
if err != nil {
73+
fmt.Println(err)
74+
os.Exit(1)
75+
}
76+
77+
userInfo, err := ruc.GetUser(ctx)
78+
if err != nil {
79+
fmt.Println(err)
80+
os.Exit(1)
81+
}
82+
83+
fmt.Println("Logged in as:")
84+
fmt.Printf(" username: %s\n", userInfo.Username)
85+
fmt.Printf(" email: %s\n", *userInfo.Email)
86+
fmt.Printf(" first name: %s\n", *userInfo.FirstName)
87+
fmt.Printf(" last name: %s\n", *userInfo.LastName)
88+
fmt.Printf(" is admin: %t\n", userInfo.IsAdmin)
89+
}
90+
91+
func init() {
92+
loginCmd.Flags().String("url", "", "instance URL")
93+
loginCmd.Flags().StringP("namespace", "n", "", "k8s namespace")
94+
}

pkg/cmd/logout.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
8+
"github.com/SwissDataScienceCenter/renku-dev-utils/pkg/github"
9+
ns "github.com/SwissDataScienceCenter/renku-dev-utils/pkg/namespace"
10+
"github.com/SwissDataScienceCenter/renku-dev-utils/pkg/renkuapi"
11+
"github.com/spf13/cobra"
12+
)
13+
14+
var logoutCmd = &cobra.Command{
15+
Use: "logout",
16+
Short: "Log out of a renku instance",
17+
Run: logout,
18+
}
19+
20+
func logout(cmd *cobra.Command, args []string) {
21+
ctx := context.Background()
22+
23+
logoutAll, err := cmd.Flags().GetBool("all")
24+
if err != nil {
25+
fmt.Println(err)
26+
os.Exit(1)
27+
}
28+
if logoutAll {
29+
err := renkuapi.LogoutAll(ctx)
30+
if err != nil {
31+
fmt.Println(err)
32+
os.Exit(1)
33+
}
34+
return
35+
}
36+
37+
url, err := cmd.Flags().GetString("url")
38+
if err != nil {
39+
fmt.Println(err)
40+
os.Exit(1)
41+
}
42+
43+
if url == "" {
44+
namespace, err := cmd.Flags().GetString("namespace")
45+
if err != nil {
46+
fmt.Println(err)
47+
os.Exit(1)
48+
}
49+
if namespace == "" {
50+
cli, err := github.NewGitHubCLI("")
51+
if err != nil {
52+
fmt.Println(err)
53+
os.Exit(1)
54+
}
55+
namespace, err = ns.FindCurrentNamespace(ctx, cli)
56+
if err != nil {
57+
fmt.Println(err)
58+
os.Exit(1)
59+
}
60+
}
61+
62+
deploymentURL, err := ns.GetDeploymentURL(namespace)
63+
if err != nil {
64+
fmt.Println(err)
65+
os.Exit(1)
66+
}
67+
url = deploymentURL.String()
68+
}
69+
70+
fmt.Printf("Renku URL: %s\n", url)
71+
72+
auth, err := renkuapi.NewRenkuApiAuth(url)
73+
if err != nil {
74+
fmt.Println(err)
75+
os.Exit(1)
76+
}
77+
78+
err = auth.Logout(ctx)
79+
if err != nil {
80+
fmt.Println(err)
81+
os.Exit(1)
82+
}
83+
}
84+
85+
func init() {
86+
logoutCmd.Flags().String("url", "", "instance URL")
87+
logoutCmd.Flags().StringP("namespace", "n", "", "k8s namespace")
88+
logoutCmd.Flags().Bool("all", false, "remove all saved logins")
89+
}

pkg/cmd/root.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ func runRoot(cmd *cobra.Command, args []string) error {
3333
func init() {
3434
rootCmd.AddCommand(cleanupDeploymentCmd)
3535
rootCmd.AddCommand(copyKeycloakAdminPasswordCmd)
36+
rootCmd.AddCommand(loginCmd)
37+
rootCmd.AddCommand(logoutCmd)
3638
rootCmd.AddCommand(makeMeAdminCmd)
3739
rootCmd.AddCommand(namespaceCmd)
3840
rootCmd.AddCommand(openDeploymentCmd)

pkg/keycloak/rest.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ func (client *KeycloakClient) PostForm(ctx context.Context, url string, data url
102102
}
103103

104104
return resp, nil
105-
106105
}
107106

108107
func tryParseResponse(resp *http.Response, result any) error {

0 commit comments

Comments
 (0)