Skip to content

Commit

Permalink
Merge pull request #194 from ninech/set-project-check
Browse files Browse the repository at this point in the history
feat: warn when setting project/org
  • Loading branch information
ctrox authored Dec 5, 2024
2 parents 54c674c + 1dc96f2 commit 834497b
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 57 deletions.
24 changes: 24 additions & 0 deletions api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import (
"github.com/ninech/apis"
infrastructure "github.com/ninech/apis/infrastructure/v1alpha1"
meta "github.com/ninech/apis/meta/v1alpha1"
"github.com/ninech/nctl/api/config"
"github.com/ninech/nctl/api/log"
"github.com/ninech/nctl/internal/format"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -186,6 +188,28 @@ func (c *Client) DeploioRuntimeConfig(ctx context.Context) (*rest.Config, error)
return config, nil
}

func (c *Client) Organization() (string, error) {
cfg, err := config.ReadExtension(c.KubeconfigPath, c.KubeconfigContext)
if err != nil {
if config.IsExtensionNotFoundError(err) {
return "", reloginNeeded(err)
}
return "", err
}

return cfg.Organization, nil
}

// reloginNeeded returns an error which outputs the given err with a message
// saying that a re-login is needed.
func reloginNeeded(err error) error {
return fmt.Errorf(
"%w, please re-login by executing %q",
err,
format.Command().Login(),
)
}

func LoadingRules() (*clientcmd.ClientConfigLoadingRules, error) {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
if _, ok := os.LookupEnv("HOME"); !ok {
Expand Down
11 changes: 0 additions & 11 deletions api/util/authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (

meta "github.com/ninech/apis/meta/v1alpha1"
"github.com/ninech/nctl/api"
"github.com/ninech/nctl/internal/format"
corev1 "k8s.io/api/core/v1"
)

Expand Down Expand Up @@ -43,13 +42,3 @@ func NewBasicAuthFromSecret(ctx context.Context, secret meta.Reference, client *
string(basicAuthSecret.Data[BasicAuthPasswordKey]),
}, nil
}

// ReloginNeeded returns an error which outputs the given err with a message
// saying that a re-login is needed.
func ReloginNeeded(err error) error {
return fmt.Errorf(
"%w, please re-login by executing %q",
err,
format.Command().Login(),
)
}
19 changes: 18 additions & 1 deletion auth/set_org.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package auth

import (
"context"
"fmt"
"slices"

"github.com/ninech/nctl/api"
"github.com/ninech/nctl/api/config"
"github.com/ninech/nctl/internal/format"
)

type SetOrgCmd struct {
Expand All @@ -20,5 +23,19 @@ func (s *SetOrgCmd) Run(ctx context.Context, client *api.Client) error {
return whoamicmd.Run(ctx, client)
}

return config.SetContextOrganization(client.KubeconfigPath, client.KubeconfigContext, s.Organization)
userInfo, err := api.GetUserInfoFromToken(client.Token(ctx))
if err != nil {
return err
}

if err := config.SetContextOrganization(client.KubeconfigPath, client.KubeconfigContext, s.Organization); err != nil {
return err
}

if !slices.Contains(userInfo.Orgs, s.Organization) {
format.PrintWarningf("%s is not in list of available Organizations, you might not have access to all resources.\n", s.Organization)
}

fmt.Println(format.SuccessMessagef("📝", "set active Organization to %s", s.Organization))
return nil
}
31 changes: 30 additions & 1 deletion auth/set_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,44 @@ package auth

import (
"context"
"fmt"

management "github.com/ninech/apis/management/v1alpha1"
"github.com/ninech/nctl/api"
"github.com/ninech/nctl/api/config"
"github.com/ninech/nctl/internal/format"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
)

type SetProjectCmd struct {
Name string `arg:"" predictor:"resource_name" help:"Name of the default project to be used."`
}

func (s *SetProjectCmd) Run(ctx context.Context, client *api.Client) error {
return config.SetContextProject(client.KubeconfigPath, client.KubeconfigContext, s.Name)
org, err := client.Organization()
if err != nil {
return err
}

// we get the project without using the result to be sure it exists and the
// user has access.
if err := client.Get(ctx, types.NamespacedName{Name: s.Name, Namespace: org}, &management.Project{}); err != nil {
if !errors.IsNotFound(err) && !errors.IsForbidden(err) {
return err
}
if errors.IsNotFound(err) {
format.PrintWarningf("did not find Project %s in your Organization %s.\n", s.Name, org)
}
if errors.IsForbidden(err) {
format.PrintWarningf("you are not allowed to get the Project %s, you might not have access to all resources.\n", s.Name)
}
}

if err := config.SetContextProject(client.KubeconfigPath, client.KubeconfigContext, s.Name); err != nil {
return err
}

fmt.Println(format.SuccessMessagef("📝", "set active Project to %s", s.Name))
return nil
}
15 changes: 5 additions & 10 deletions auth/whoami.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"fmt"

"github.com/ninech/nctl/api"
"github.com/ninech/nctl/api/config"
"github.com/ninech/nctl/api/util"
)

type WhoAmICmd struct {
Expand All @@ -16,11 +14,8 @@ type WhoAmICmd struct {
}

func (s *WhoAmICmd) Run(ctx context.Context, client *api.Client) error {
cfg, err := config.ReadExtension(client.KubeconfigPath, client.KubeconfigContext)
org, err := client.Organization()
if err != nil {
if config.IsExtensionNotFoundError(err) {
return util.ReloginNeeded(err)
}
return err
}

Expand All @@ -29,18 +24,18 @@ func (s *WhoAmICmd) Run(ctx context.Context, client *api.Client) error {
return err
}

printUserInfo(userInfo, cfg)
printUserInfo(userInfo, org)

return nil
}

func printUserInfo(userInfo *api.UserInfo, cfg *config.Extension) {
func printUserInfo(userInfo *api.UserInfo, org string) {
fmt.Printf("You are currently logged in the with the following account: %q\n", userInfo.User)

fmt.Printf("Your current organization: %q\n", cfg.Organization)
fmt.Printf("Your current organization: %q\n", org)

if len(userInfo.Orgs) > 0 {
printAvailableOrgsString(cfg.Organization, userInfo.Orgs)
printAvailableOrgsString(org, userInfo.Orgs)
}
}

Expand Down
11 changes: 3 additions & 8 deletions create/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import (

management "github.com/ninech/apis/management/v1alpha1"
"github.com/ninech/nctl/api"
"github.com/ninech/nctl/api/config"
"github.com/ninech/nctl/api/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand All @@ -18,16 +16,13 @@ type projectCmd struct {
}

func (proj *projectCmd) Run(ctx context.Context, client *api.Client) error {
cfg, err := config.ReadExtension(client.KubeconfigPath, client.KubeconfigContext)
org, err := client.Organization()
if err != nil {
if config.IsExtensionNotFoundError(err) {
return util.ReloginNeeded(err)
}
return err
}

p := newProject(proj.Name, cfg.Organization, proj.DisplayName)
fmt.Printf("Creating new project %s for organization %s\n", p.Name, cfg.Organization)
p := newProject(proj.Name, org, proj.DisplayName)
fmt.Printf("Creating new project %s for organization %s\n", p.Name, org)
c := newCreator(client, p, strings.ToLower(management.ProjectKind))
ctx, cancel := context.WithTimeout(ctx, proj.WaitTimeout)
defer cancel()
Expand Down
13 changes: 4 additions & 9 deletions delete/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (

management "github.com/ninech/apis/management/v1alpha1"
"github.com/ninech/nctl/api"
"github.com/ninech/nctl/api/config"
"github.com/ninech/nctl/api/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand All @@ -19,28 +17,25 @@ func (proj *projectCmd) Run(ctx context.Context, client *api.Client) error {
ctx, cancel := context.WithTimeout(ctx, proj.WaitTimeout)
defer cancel()

cfg, err := config.ReadExtension(client.KubeconfigPath, client.KubeconfigContext)
org, err := client.Organization()
if err != nil {
if config.IsExtensionNotFoundError(err) {
return util.ReloginNeeded(err)
}
return err
}

d := newDeleter(
&management.Project{
ObjectMeta: metav1.ObjectMeta{
Name: proj.Name,
Namespace: cfg.Organization,
Namespace: org,
},
},
management.ProjectKind,
prompt(projectDeletePrompt(cfg.Organization)),
prompt(projectDeletePrompt(org)),
)

// we need to overwrite the namespace as projects are always in the
// main organization namespace
client.Project = cfg.Organization
client.Project = org

if err := d.deleteResource(ctx, client, proj.WaitTimeout, proj.Wait, proj.Force); err != nil {
return fmt.Errorf("error while deleting %s: %w", management.ProjectKind, err)
Expand Down
9 changes: 2 additions & 7 deletions get/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import (
"github.com/gobuffalo/flect"
management "github.com/ninech/apis/management/v1alpha1"
"github.com/ninech/nctl/api"
"github.com/ninech/nctl/api/config"
"github.com/ninech/nctl/api/util"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/conversion"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -256,15 +254,12 @@ func defaultOut(out io.Writer) io.Writer {
// projects returns either all existing projects or only the specific project
// identified by the "onlyName" parameter
func projects(ctx context.Context, client *api.Client, onlyName string) ([]management.Project, error) {
cfg, err := config.ReadExtension(client.KubeconfigPath, client.KubeconfigContext)
org, err := client.Organization()
if err != nil {
if config.IsExtensionNotFoundError(err) {
return nil, util.ReloginNeeded(err)
}
return nil, err
}
opts := []runtimeclient.ListOption{
runtimeclient.InNamespace(cfg.Organization),
runtimeclient.InNamespace(org),
}
if onlyName != "" {
opts = append(opts, runtimeclient.MatchingFields(
Expand Down
5 changes: 2 additions & 3 deletions predictor/predictor.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/gobuffalo/flect"
"github.com/ninech/apis/management/v1alpha1"
"github.com/ninech/nctl/api"
"github.com/ninech/nctl/api/config"
"github.com/posener/complete"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
Expand Down Expand Up @@ -61,11 +60,11 @@ func (r *Resource) Predict(args complete.Args) []string {
ns := r.client.Project
// if we're looking for projects, we need to use the org as the namespace
if u.GetObjectKind().GroupVersionKind().Kind == reflect.TypeOf(v1alpha1.ProjectList{}).Name() {
cfg, err := config.ReadExtension(r.client.KubeconfigPath, r.client.KubeconfigContext)
org, err := r.client.Organization()
if err != nil {
return []string{}
}
ns = cfg.Organization
ns = org
}

if err := r.client.List(ctx, u, client.InNamespace(ns)); err != nil {
Expand Down
9 changes: 2 additions & 7 deletions update/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import (
"github.com/crossplane/crossplane-runtime/pkg/resource"
management "github.com/ninech/apis/management/v1alpha1"
"github.com/ninech/nctl/api"
"github.com/ninech/nctl/api/config"
"github.com/ninech/nctl/api/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand All @@ -18,18 +16,15 @@ type projectCmd struct {
}

func (cmd *projectCmd) Run(ctx context.Context, client *api.Client) error {
cfg, err := config.ReadExtension(client.KubeconfigPath, client.KubeconfigContext)
org, err := client.Organization()
if err != nil {
if config.IsExtensionNotFoundError(err) {
return util.ReloginNeeded(err)
}
return err
}

project := &management.Project{
ObjectMeta: metav1.ObjectMeta{
Name: cmd.Name,
Namespace: cfg.Organization,
Namespace: org,
},
}

Expand Down

0 comments on commit 834497b

Please sign in to comment.