mirror of
https://github.com/portainer/portainer.git
synced 2025-08-04 21:35:23 +02:00
refactor: replace the kubectl
binary with the upstream sdk (#524)
This commit is contained in:
parent
4d4360b86b
commit
bc29419c17
17 changed files with 354 additions and 182 deletions
23
pkg/libkubectl/apply.go
Normal file
23
pkg/libkubectl/apply.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package libkubectl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubectl/pkg/cmd/apply"
|
||||
)
|
||||
|
||||
func (c *Client) Apply(ctx context.Context, manifests []string) (string, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
cmd := apply.NewCmdApply("kubectl", c.factory, c.streams)
|
||||
cmd.SetArgs(manifestFilesToArgs(manifests))
|
||||
cmd.SetOut(buf)
|
||||
|
||||
if err := cmd.ExecuteContext(ctx); err != nil {
|
||||
return "", fmt.Errorf("error applying resources: %w", err)
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
|
@ -41,8 +41,8 @@ func NewClient(libKubectlAccess *ClientAccess, namespace, kubeconfig string, ins
|
|||
// If server and token are provided, they will be used to connect to the cluster
|
||||
// If neither kubeconfigPath or server and token are provided, an error will be returned
|
||||
func generateConfigFlags(token, server, namespace, kubeconfigPath string, insecure bool) (*genericclioptions.ConfigFlags, error) {
|
||||
if kubeconfigPath == "" && (server == "" || token == "") {
|
||||
return nil, errors.New("must provide either a kubeconfig path or a server and token")
|
||||
if kubeconfigPath == "" && server == "" {
|
||||
return nil, errors.New("must provide either a kubeconfig path or a server")
|
||||
}
|
||||
|
||||
configFlags := genericclioptions.NewConfigFlags(true)
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
package libkubectl
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
libKubectlAccess ClientAccess
|
||||
namespace string
|
||||
kubeconfig string
|
||||
insecure bool
|
||||
wantErr bool
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
name: "valid client with token and server",
|
||||
libKubectlAccess: ClientAccess{Token: "test-token", ServerUrl: "https://localhost:6443"},
|
||||
namespace: "default",
|
||||
insecure: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid client with kubeconfig",
|
||||
kubeconfig: "/path/to/kubeconfig",
|
||||
namespace: "test-namespace",
|
||||
insecure: false,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "missing both token/server and kubeconfig",
|
||||
namespace: "default",
|
||||
insecure: false,
|
||||
wantErr: true,
|
||||
errContains: "must provide either a kubeconfig path or a server and token",
|
||||
},
|
||||
{
|
||||
name: "missing token with server",
|
||||
libKubectlAccess: ClientAccess{ServerUrl: "https://localhost:6443"},
|
||||
namespace: "default",
|
||||
insecure: false,
|
||||
wantErr: true,
|
||||
errContains: "must provide either a kubeconfig path or a server and token",
|
||||
},
|
||||
{
|
||||
name: "missing server with token",
|
||||
libKubectlAccess: ClientAccess{Token: "test-token"},
|
||||
namespace: "default",
|
||||
insecure: false,
|
||||
wantErr: true,
|
||||
errContains: "must provide either a kubeconfig path or a server and token",
|
||||
},
|
||||
{
|
||||
name: "empty namespace is valid",
|
||||
libKubectlAccess: ClientAccess{Token: "test-token", ServerUrl: "https://localhost:6443"},
|
||||
namespace: "",
|
||||
insecure: false,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "insecure true with valid credentials",
|
||||
libKubectlAccess: ClientAccess{Token: "test-token", ServerUrl: "https://localhost:6443"},
|
||||
namespace: "default",
|
||||
insecure: true,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
client, err := NewClient(&tt.libKubectlAccess, tt.namespace, tt.kubeconfig, tt.insecure)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("NewClient() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil && tt.errContains != "" {
|
||||
if got := err.Error(); got != tt.errContains {
|
||||
t.Errorf("NewClient() error = %v, want error containing %v", got, tt.errContains)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if !tt.wantErr {
|
||||
if client == nil {
|
||||
t.Error("NewClient() returned nil client when no error was expected")
|
||||
return
|
||||
}
|
||||
|
||||
// Verify client fields are properly initialized
|
||||
if client.factory == nil {
|
||||
t.Error("NewClient() client.factory is nil")
|
||||
}
|
||||
if client.out == nil {
|
||||
t.Error("NewClient() client.out is nil")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
24
pkg/libkubectl/delete.go
Normal file
24
pkg/libkubectl/delete.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package libkubectl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubectl/pkg/cmd/delete"
|
||||
)
|
||||
|
||||
func (c *Client) Delete(ctx context.Context, manifests []string) (string, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
cmd := delete.NewCmdDelete(c.factory, c.streams)
|
||||
cmd.SetArgs(manifestFilesToArgs(manifests))
|
||||
cmd.Flags().Set("ignore-not-found", "true")
|
||||
cmd.SetOut(buf)
|
||||
|
||||
if err := cmd.ExecuteContext(ctx); err != nil {
|
||||
return "", fmt.Errorf("error deleting resources: %w", err)
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
11
pkg/libkubectl/manifest.go
Normal file
11
pkg/libkubectl/manifest.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package libkubectl
|
||||
|
||||
import "strings"
|
||||
|
||||
func manifestFilesToArgs(manifestFiles []string) []string {
|
||||
args := []string{}
|
||||
for _, path := range manifestFiles {
|
||||
args = append(args, "-f", strings.TrimSpace(path))
|
||||
}
|
||||
return args
|
||||
}
|
48
pkg/libkubectl/manifest_test.go
Normal file
48
pkg/libkubectl/manifest_test.go
Normal file
|
@ -0,0 +1,48 @@
|
|||
package libkubectl
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestManifestFilesToArgsHelper(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
manifestFiles []string
|
||||
expectedArgs []string
|
||||
}{
|
||||
{
|
||||
name: "empty list",
|
||||
manifestFiles: []string{},
|
||||
expectedArgs: []string{},
|
||||
},
|
||||
{
|
||||
name: "single manifest",
|
||||
manifestFiles: []string{"manifest.yaml"},
|
||||
expectedArgs: []string{"-f", "manifest.yaml"},
|
||||
},
|
||||
{
|
||||
name: "multiple manifests",
|
||||
manifestFiles: []string{"manifest1.yaml", "manifest2.yaml"},
|
||||
expectedArgs: []string{"-f", "manifest1.yaml", "-f", "manifest2.yaml"},
|
||||
},
|
||||
{
|
||||
name: "manifests with whitespace",
|
||||
manifestFiles: []string{" manifest1.yaml ", " manifest2.yaml"},
|
||||
expectedArgs: []string{"-f", "manifest1.yaml", "-f", "manifest2.yaml"},
|
||||
},
|
||||
{
|
||||
name: "kubernetes resource definitions",
|
||||
manifestFiles: []string{"deployment/nginx", "service/web"},
|
||||
expectedArgs: []string{"-f", "deployment/nginx", "-f", "service/web"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
args := manifestFilesToArgs(tt.manifestFiles)
|
||||
assert.Equal(t, tt.expectedArgs, args)
|
||||
})
|
||||
}
|
||||
}
|
23
pkg/libkubectl/restart.go
Normal file
23
pkg/libkubectl/restart.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package libkubectl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubectl/pkg/cmd/rollout"
|
||||
)
|
||||
|
||||
func (c *Client) RolloutRestart(ctx context.Context, manifests []string) (string, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
cmd := rollout.NewCmdRollout(c.factory, c.streams)
|
||||
cmd.SetArgs(manifestFilesToArgs(manifests))
|
||||
cmd.SetOut(buf)
|
||||
|
||||
if err := cmd.ExecuteContext(ctx); err != nil {
|
||||
return "", fmt.Errorf("error restarting resources: %w", err)
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue