Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

util: Move patch.go into its own package #535

Merged
merged 4 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions neonvm/controllers/virtualmachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import (
"github.com/neondatabase/autoscaling/neonvm/pkg/ipam"

"github.com/neondatabase/autoscaling/pkg/api"
"github.com/neondatabase/autoscaling/pkg/util"
"github.com/neondatabase/autoscaling/pkg/util/patch"
)

const (
Expand Down Expand Up @@ -723,7 +723,7 @@ func (r *VirtualMachineReconciler) doReconcile(ctx context.Context, virtualmachi
func updatePodMetadataIfNecessary(ctx context.Context, c client.Client, vm *vmv1.VirtualMachine, runnerPod *corev1.Pod) error {
log := log.FromContext(ctx)

var patches []util.JSONPatch
var patches []patch.Operation

metaSpecs := []struct {
metaField string
Expand Down Expand Up @@ -756,7 +756,7 @@ func updatePodMetadataIfNecessary(ctx context.Context, c client.Client, vm *vmv1
// Add/update the entries we're expecting to be there
for k, e := range spec.expected {
if a, ok := spec.actual[k]; !ok || e != a {
patches = append(patches, util.JSONPatch{
patches = append(patches, patch.Operation{
// From RFC 6902 (JSON patch):
//
// > The "add" operation performs one of the following functions, depending upon
Expand All @@ -770,8 +770,8 @@ func updatePodMetadataIfNecessary(ctx context.Context, c client.Client, vm *vmv1
// > member's value is replaced.
//
// So: if the value is missing we'll add it. And if it's different, we'll replace it.
Op: util.PatchAdd,
Path: fmt.Sprintf("/metadata/%s/%s", spec.metaField, util.PatchPathEscape(k)),
Op: patch.OpAdd,
Path: fmt.Sprintf("/metadata/%s/%s", spec.metaField, patch.PathEscape(k)),
Value: e,
})
}
Expand All @@ -782,9 +782,9 @@ func updatePodMetadataIfNecessary(ctx context.Context, c client.Client, vm *vmv1
for k := range spec.actual {
if _, expected := spec.expected[k]; !expected && !spec.ignoreExtra[k] {
removed = append(removed, k)
patches = append(patches, util.JSONPatch{
Op: util.PatchRemove,
Path: fmt.Sprintf("/metadata/%s/%s", spec.metaField, util.PatchPathEscape(k)),
patches = append(patches, patch.Operation{
Op: patch.OpRemove,
Path: fmt.Sprintf("/metadata/%s/%s", spec.metaField, patch.PathEscape(k)),
})
}
}
Expand Down
7 changes: 4 additions & 3 deletions pkg/agent/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
"github.com/neondatabase/autoscaling/pkg/agent/schedwatch"
"github.com/neondatabase/autoscaling/pkg/api"
"github.com/neondatabase/autoscaling/pkg/util"
"github.com/neondatabase/autoscaling/pkg/util/patch"
)

// PluginProtocolVersion is the current version of the agent<->scheduler plugin in use by this
Expand Down Expand Up @@ -714,12 +715,12 @@ func (r *Runner) doMetricsRequest(
}

func (r *Runner) doNeonVMRequest(ctx context.Context, target api.Resources) error {
patches := []util.JSONPatch{{
Op: util.PatchReplace,
patches := []patch.Operation{{
Op: patch.OpReplace,
Path: "/spec/guest/cpus/use",
Value: target.VCPU.ToResourceQuantity(),
}, {
Op: util.PatchReplace,
Op: patch.OpReplace,
Path: "/spec/guest/memorySlots/use",
Value: target.Mem,
}}
Expand Down
31 changes: 0 additions & 31 deletions pkg/util/patch.go

This file was deleted.

52 changes: 52 additions & 0 deletions pkg/util/patch/patch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Construction of JSON patches. See https://jsonpatch.com/

package patch

import (
"strings"
)

// OpKind is the kind of operation being performed in a single step
type OpKind string

const (
OpAdd OpKind = "add"
OpRemove OpKind = "remove"
OpReplace OpKind = "replace"
OpMove OpKind = "move"
OpCopy OpKind = "copy"
OpTest OpKind = "test"
)

type JSONPatch = []Operation

// Operation is a single step in the overall JSON patch
type Operation struct {
// Op is the kind of operation being performed in this step. See [OpKind] for more.
Op OpKind `json:"op"`
// Path is a [JSON pointer] to the target location of the operation.
//
// In general, nesting is separated by '/'s, with special characters escaped by '~'.
// [PathEscape] is provided to handle escaping, because it can get a little gnarly.
//
// As an example, if you want to add a field "foo" to the first element of an array,
// you'd use the path `/0/foo`. The jsonpatch website has more details (and clearer examples),
// refer there for more information: https://jsonpatch.com/#json-pointer
//
// [JSON pointer]: https://datatracker.ietf.org/doc/html/rfc6901/
Path string `json:"path"`
// From gives the source location for "copy" or "move" operations.
From string `json:"from,omitempty"`
// Value is the new value to use, for "add", "replace", or "test" operations.
Value any `json:"value,omitempty"`
}

var pathEscaper = strings.NewReplacer("~", "~0", "/", "~1")

// PathEscape escapes a string for use in a segment of the Path field of an Operation
//
// This is useful, for example, when using arbitrary strings as map keys (like Kubernetes labels or
// annotations).
func PathEscape(s string) string {
return pathEscaper.Replace(s)
}
Loading