Skip to content

Commit

Permalink
Add context unit tests (#1905)
Browse files Browse the repository at this point in the history
* Add context unit tests

Signed-off-by: Javier López Barba <javier@okteto.com>

* Fix tests kubeconfig overwrite

Signed-off-by: Javier López Barba <javier@okteto.com>

* Remove temp files after running tests

Signed-off-by: Javier López Barba <javier@okteto.com>

* Create new function

Signed-off-by: Javier López Barba <javier@okteto.com>

* Create fake package

Signed-off-by: Javier López Barba <javier@okteto.com>

* Refactor ctx unit test

Signed-off-by: Javier López Barba <javier@okteto.com>

* Fix ctx comments

Signed-off-by: Javier López Barba <javier@okteto.com>

* Fix comments

Signed-off-by: Javier López Barba <javier@okteto.com>

* Fix merge conflicts

Signed-off-by: Javier López Barba <javier@okteto.com>

* Fix tests

Signed-off-by: Javier López Barba <javier@okteto.com>
  • Loading branch information
jLopezbarb committed Nov 16, 2021
1 parent 8f7d479 commit e015a1a
Show file tree
Hide file tree
Showing 24 changed files with 989 additions and 139 deletions.
135 changes: 135 additions & 0 deletions cmd/context/context_test.go
@@ -0,0 +1,135 @@
// Copyright 2021 The Okteto Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package context

import (
"encoding/json"
"fmt"
"os"
"testing"

"github.com/okteto/okteto/pkg/config"
"github.com/okteto/okteto/pkg/k8s/kubeconfig"
"github.com/okteto/okteto/pkg/okteto"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)

type kubeconfigFields struct {
Name []string
Namespace []string
CurrentContext string
}

func Test_initFromDeprecatedToken(t *testing.T) {

var tests = []struct {
name string
tokenUrl string
kubeconfigCtx kubeconfigFields
}{
{
name: "token-create-kubeconfig",
tokenUrl: "https://cloud.okteto.com",
kubeconfigCtx: kubeconfigFields{
Name: []string{"test"},
Namespace: []string{"test"},
CurrentContext: "cloud_okteto_com",
},
},
{
name: "token-token-but-not-in-kubeconfig",
tokenUrl: "https://cloud.okteto.com",
kubeconfigCtx: kubeconfigFields{
Name: []string{"cloud_okteto_com"},
Namespace: []string{"test"},
CurrentContext: "test",
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tokenPath, err := createDeprecatedToken(tt.tokenUrl)
if err != nil {
t.Fatal(err)
}
defer os.Remove(tokenPath)

kubepath, err := createKubeconfig(tt.kubeconfigCtx)
if err != nil {
t.Fatal(err)
}
defer os.Remove(kubepath)
okteto.InitContextWithDeprecatedToken()
if okteto.ContextStore().CurrentContext == "" {
t.Fatal("Not initialized")
}
})
}
}

func createDeprecatedToken(url string) (string, error) {
dir, err := os.MkdirTemp("", "")
if err != nil {
return "", err
}
os.Setenv("OKTETO_FOLDER", dir)
token := &okteto.Token{
URL: url,
Buildkit: "buildkit",
Registry: "registry",
ID: "id",
Username: "username",
Token: "token",
MachineID: "machine-id",
}
marshalled, err := json.MarshalIndent(token, "", "\t")
if err != nil {
return "", fmt.Errorf("failed to generate analytics file: %s", err)
}

if err := os.WriteFile(config.GetTokenPathDeprecated(), marshalled, 0600); err != nil {
return "", fmt.Errorf("couldn't save analytics: %s", err)
}
if _, err := os.Stat(config.GetTokenPathDeprecated()); err != nil {
return "", fmt.Errorf("Not created correctly")
}
if err := os.WriteFile(config.GetCertificatePath(), []byte("a"), 0600); err != nil {
return "", fmt.Errorf("couldn't save analytics: %s", err)
}

return config.GetTokenPathDeprecated(), nil
}

func createKubeconfig(kubeconfigFields kubeconfigFields) (string, error) {
dir, err := os.CreateTemp("", "")
if err != nil {
return "", err
}

os.Setenv("KUBECONFIG", dir.Name())

contexts := make(map[string]*clientcmdapi.Context)
for idx := range kubeconfigFields.Name {
contexts[kubeconfigFields.Name[idx]] = &clientcmdapi.Context{Namespace: kubeconfigFields.Namespace[idx]}
}
cfg := &clientcmdapi.Config{
Contexts: contexts,
CurrentContext: kubeconfigFields.CurrentContext,
}
if err := kubeconfig.Write(cfg, dir.Name()); err != nil {
return "", err
}
return dir.Name(), nil
}
86 changes: 81 additions & 5 deletions cmd/context/create.go
Expand Up @@ -16,16 +16,27 @@ package context
import (
"context"
"fmt"
"os"
"strings"

"github.com/okteto/okteto/cmd/utils"
"github.com/okteto/okteto/pkg/analytics"
"github.com/okteto/okteto/pkg/cmd/login"
"github.com/okteto/okteto/pkg/config"
"github.com/okteto/okteto/pkg/errors"
"github.com/okteto/okteto/pkg/k8s/kubeconfig"
"github.com/okteto/okteto/pkg/log"
"github.com/okteto/okteto/pkg/okteto"
"github.com/okteto/okteto/pkg/types"
"github.com/spf13/cobra"
)

type ContextUse struct {
k8sClientProvider okteto.K8sClientProvider
loginController login.LoginInterface
oktetoClientProvider types.OktetoUserClientProvider
}

// Create adds a new cluster to okteto context
func CreateCMD() *cobra.Command {
ctxOptions := &ContextOptions{}
Expand Down Expand Up @@ -60,8 +71,13 @@ If you need to automate authentication or if you don't want to use browser-based
ctxOptions.IsCtxCommand = true
ctxOptions.Show = false
ctxOptions.Save = true
ctxController := ContextUse{
k8sClientProvider: okteto.NewK8sClientProvider(),
loginController: login.NewLoginController(),
oktetoClientProvider: okteto.NewOktetoClientProvider(),
}

err := Run(ctx, ctxOptions)
err := ctxController.UseContext(ctx, ctxOptions)
analytics.TrackContext(err == nil)
return err
},
Expand All @@ -72,7 +88,7 @@ If you need to automate authentication or if you don't want to use browser-based
return cmd
}

func UseContext(ctx context.Context, ctxOptions *ContextOptions) error {
func (c *ContextUse) UseContext(ctx context.Context, ctxOptions *ContextOptions) error {
created := false

ctxStore := okteto.ContextStore()
Expand All @@ -95,7 +111,7 @@ func UseContext(ctx context.Context, ctxOptions *ContextOptions) error {
Hint: "Please run 'okteto context' to select one context"}
}

transformedCtx := okteto.K8sContextToOktetoUrl(ctx, ctxOptions.Context, ctxOptions.Namespace)
transformedCtx := okteto.K8sContextToOktetoUrl(ctx, ctxOptions.Context, ctxOptions.Namespace, c.k8sClientProvider)
if transformedCtx != ctxOptions.Context {
ctxOptions.Context = transformedCtx
ctxOptions.IsOkteto = true
Expand All @@ -113,11 +129,11 @@ func UseContext(ctx context.Context, ctxOptions *ContextOptions) error {
ctxStore.CurrentContext = ctxOptions.Context

if ctxOptions.IsOkteto {
if err := initOktetoContext(ctx, ctxOptions); err != nil {
if err := c.initOktetoContext(ctx, ctxOptions); err != nil {
return err
}
} else {
if err := initKubernetesContext(ctxOptions); err != nil {
if err := c.initKubernetesContext(ctxOptions); err != nil {
return err
}
}
Expand Down Expand Up @@ -147,3 +163,63 @@ func UseContext(ctx context.Context, ctxOptions *ContextOptions) error {

return nil
}

func (c *ContextUse) initOktetoContext(ctx context.Context, ctxOptions *ContextOptions) error {
user, err := c.loginController.AuthenticateToOktetoCluster(ctx, ctxOptions.Context, ctxOptions.Token)
if err != nil {
return err
}
ctxOptions.Token = user.Token
okteto.Context().Token = user.Token

userContext, err := c.getUserContext(ctx)
if err != nil {
return err
}
if ctxOptions.Namespace == "" {
ctxOptions.Namespace = userContext.User.Namespace
}
okteto.AddOktetoContext(ctxOptions.Context, &userContext.User, ctxOptions.Namespace, userContext.User.Namespace)
cfg := kubeconfig.Get(config.GetKubeconfigPath())
if cfg == nil {
cfg = kubeconfig.Create()
}
okteto.AddOktetoCredentialsToCfg(cfg, &userContext.Credentials, ctxOptions.Namespace, userContext.User.ID, okteto.Context().Name)
okteto.Context().Cfg = cfg
okteto.Context().IsOkteto = true

setSecrets(userContext.Secrets)

os.Setenv("OKTETO_USERNAME", okteto.Context().Username)

return nil
}

func (_ *ContextUse) initKubernetesContext(ctxOptions *ContextOptions) error {
cfg := kubeconfig.Get(config.GetKubeconfigPath())
if cfg == nil {
return fmt.Errorf(errors.ErrKubernetesContextNotFound, ctxOptions.Context, config.GetKubeconfigPath())
}
kubeCtx, ok := cfg.Contexts[ctxOptions.Context]
if !ok {
return fmt.Errorf(errors.ErrKubernetesContextNotFound, ctxOptions.Context, config.GetKubeconfigPath())
}
cfg.CurrentContext = ctxOptions.Context
if ctxOptions.Namespace != "" {
cfg.Contexts[ctxOptions.Context].Namespace = ctxOptions.Namespace
} else {
if cfg.Contexts[ctxOptions.Context].Namespace == "" {
cfg.Contexts[ctxOptions.Context].Namespace = "default"
}
ctxOptions.Namespace = cfg.Contexts[ctxOptions.Context].Namespace
}

okteto.AddKubernetesContext(ctxOptions.Context, ctxOptions.Namespace, ctxOptions.Builder)

kubeCtx.Namespace = okteto.Context().Namespace
cfg.CurrentContext = okteto.Context().Name
okteto.Context().Cfg = cfg
okteto.Context().IsOkteto = false

return nil
}

0 comments on commit e015a1a

Please sign in to comment.