feat(dao/dp): use external patch method to create json patch

mine
Antoine Meausoone 2020-08-12 21:27:31 +02:00
parent c534fbb75e
commit 8cb9da07b1
3 changed files with 90 additions and 11 deletions

View File

@ -4,8 +4,6 @@ import (
"context"
"errors"
"fmt"
"strings"
"github.com/derailed/k9s/internal/client"
"github.com/rs/zerolog/log"
appsv1 "k8s.io/api/apps/v1"
@ -231,16 +229,11 @@ func (d *Deployment) SetImages(ctx context.Context, path string, images map[stri
if !auth {
return fmt.Errorf("user is not authorized to patch a deployment")
}
var nameStrB strings.Builder
var imageStrB strings.Builder
for name, image := range images {
nameStrB.WriteString(fmt.Sprintf(`{"name":"%s"},`, name))
imageStrB.WriteString(fmt.Sprintf(`{"image":"%s","name":"%s"},`, image, name))
jsonPatch, err := SetImageJsonPatch(images)
if err != nil {
return err
}
namesJson := strings.TrimSuffix(nameStrB.String(), ",")
imagesJson := strings.TrimSuffix(imageStrB.String(), ",")
patchJson := `{"spec":{"template":{"spec":{"$setElementOrder/containers":[` + namesJson + `],"containers":[` + imagesJson + `]}}}}`
dial, err := d.Client().Dial()
if err != nil {
return err
@ -249,7 +242,7 @@ func (d *Deployment) SetImages(ctx context.Context, path string, images map[stri
ctx,
n,
types.StrategicMergePatchType,
[]byte(patchJson),
[]byte(jsonPatch),
metav1.PatchOptions{},
)
return err

47
internal/dao/patch.go Normal file
View File

@ -0,0 +1,47 @@
package dao
import "encoding/json"
type JsonPatch struct {
Spec Spec `json:"spec"`
}
type Spec struct {
Template Template `json:"template"`
}
type Template struct {
Spec ImagesSpec `json:"spec"`
}
type ImagesSpec struct {
SetElementOrders []Element `json:"$setElementOrder/containers"`
Containers []Element `json:"containers"`
}
type Element struct {
Image string `json:"image,omitempty"`
Name string `json:"name"`
}
// Build a json patch string to update PodSpec images
func SetImageJsonPatch(images map[string]string) (string, error) {
elementOrders := make([]Element, 0)
containers := make([]Element, 0)
for key, value := range images {
elementOrders = append(elementOrders, Element{Name: key})
containers = append(containers, Element{Name: key, Image: value})
}
jsonPatch := JsonPatch{
Spec: Spec{
Template: Template{
Spec: ImagesSpec{
SetElementOrders: elementOrders,
Containers: containers,
},
},
},
}
bytes, err := json.Marshal(jsonPatch)
return string(bytes), err
}

View File

@ -0,0 +1,39 @@
package dao
import (
"reflect"
"testing"
)
func TestSetImageJsonPatch(t *testing.T) {
type args struct {
images map[string]string
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
name: "simple",
args: args{
images: map[string]string{"nginx": "nginx:latest"},
},
want: "",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := SetImageJsonPatch(tt.args.images)
if (err != nil) != tt.wantErr {
t.Errorf("SetImageJsonPatch() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("SetImageJsonPatch() got = %v, want %v", got, tt.want)
}
})
}
}