mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 02:33:34 +00:00
rebase: bump k8s.io/kubernetes from 1.26.2 to 1.27.2
Bumps [k8s.io/kubernetes](https://github.com/kubernetes/kubernetes) from 1.26.2 to 1.27.2. - [Release notes](https://github.com/kubernetes/kubernetes/releases) - [Commits](https://github.com/kubernetes/kubernetes/compare/v1.26.2...v1.27.2) --- updated-dependencies: - dependency-name: k8s.io/kubernetes dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
committed by
mergify[bot]
parent
0e79135419
commit
07b05616a0
75
vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/client.go
generated
vendored
75
vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/client.go
generated
vendored
@ -118,6 +118,8 @@ func (cm *connectionManager) closeAll() {
|
||||
// grpcTunnel implements Tunnel
|
||||
type grpcTunnel struct {
|
||||
stream client.ProxyService_ProxyClient
|
||||
sendLock sync.Mutex
|
||||
recvLock sync.Mutex
|
||||
clientConn clientConn
|
||||
pendingDial pendingDialManager
|
||||
conns connectionManager
|
||||
@ -130,6 +132,11 @@ type grpcTunnel struct {
|
||||
// serving.
|
||||
done chan struct{}
|
||||
|
||||
// started is an atomic bool represented as a 0 or 1, and set to true when a single-use tunnel has been started (dialed).
|
||||
// started should only be accessed through atomic methods.
|
||||
// TODO: switch this to an atomic.Bool once the client is exclusively buit with go1.19+
|
||||
started uint32
|
||||
|
||||
// closing is an atomic bool represented as a 0 or 1, and set to true when the tunnel is being closed.
|
||||
// closing should only be accessed through atomic methods.
|
||||
// TODO: switch this to an atomic.Bool once the client is exclusively buit with go1.19+
|
||||
@ -195,6 +202,7 @@ func newUnstartedTunnel(stream client.ProxyService_ProxyClient, c clientConn) *g
|
||||
conns: connectionManager{conns: make(map[int64]*conn)},
|
||||
readTimeoutSeconds: 10,
|
||||
done: make(chan struct{}),
|
||||
started: 0,
|
||||
}
|
||||
s := metrics.ClientConnectionStatusCreated
|
||||
t.prevStatus.Store(s)
|
||||
@ -243,20 +251,17 @@ func (t *grpcTunnel) serve(tunnelCtx context.Context) {
|
||||
}()
|
||||
|
||||
for {
|
||||
pkt, err := t.stream.Recv()
|
||||
pkt, err := t.Recv()
|
||||
if err == io.EOF {
|
||||
return
|
||||
}
|
||||
const segment = commonmetrics.SegmentToClient
|
||||
isClosing := t.isClosing()
|
||||
if err != nil || pkt == nil {
|
||||
if !isClosing {
|
||||
klog.ErrorS(err, "stream read failure")
|
||||
}
|
||||
metrics.Metrics.ObserveStreamErrorNoPacket(segment, err)
|
||||
return
|
||||
}
|
||||
metrics.Metrics.ObservePacket(segment, pkt.Type)
|
||||
if isClosing {
|
||||
return
|
||||
}
|
||||
@ -335,11 +340,23 @@ func (t *grpcTunnel) serve(tunnelCtx context.Context) {
|
||||
|
||||
case client.PacketType_DATA:
|
||||
resp := pkt.GetData()
|
||||
if resp.ConnectID == 0 {
|
||||
klog.ErrorS(nil, "Received packet missing ConnectID", "packetType", "DATA")
|
||||
continue
|
||||
}
|
||||
// TODO: flow control
|
||||
conn, ok := t.conns.get(resp.ConnectID)
|
||||
|
||||
if !ok {
|
||||
klog.V(1).InfoS("Connection not recognized", "connectionID", resp.ConnectID)
|
||||
klog.ErrorS(nil, "Connection not recognized", "connectionID", resp.ConnectID, "packetType", "DATA")
|
||||
t.Send(&client.Packet{
|
||||
Type: client.PacketType_CLOSE_REQ,
|
||||
Payload: &client.Packet_CloseRequest{
|
||||
CloseRequest: &client.CloseRequest{
|
||||
ConnectID: resp.ConnectID,
|
||||
},
|
||||
},
|
||||
})
|
||||
continue
|
||||
}
|
||||
timer := time.NewTimer((time.Duration)(t.readTimeoutSeconds) * time.Second)
|
||||
@ -358,7 +375,7 @@ func (t *grpcTunnel) serve(tunnelCtx context.Context) {
|
||||
conn, ok := t.conns.get(resp.ConnectID)
|
||||
|
||||
if !ok {
|
||||
klog.V(1).InfoS("Connection not recognized", "connectionID", resp.ConnectID)
|
||||
klog.V(1).InfoS("Connection not recognized", "connectionID", resp.ConnectID, "packetType", "CLOSE_RSP")
|
||||
continue
|
||||
}
|
||||
close(conn.readCh)
|
||||
@ -382,6 +399,11 @@ func (t *grpcTunnel) DialContext(requestCtx context.Context, protocol, address s
|
||||
}
|
||||
|
||||
func (t *grpcTunnel) dialContext(requestCtx context.Context, protocol, address string) (net.Conn, error) {
|
||||
prevStarted := atomic.SwapUint32(&t.started, 1)
|
||||
if prevStarted != 0 {
|
||||
return nil, &dialFailure{"single-use dialer already dialed", metrics.DialFailureAlreadyStarted}
|
||||
}
|
||||
|
||||
select {
|
||||
case <-t.done:
|
||||
return nil, errors.New("tunnel is closed")
|
||||
@ -418,18 +440,15 @@ func (t *grpcTunnel) dialContext(requestCtx context.Context, protocol, address s
|
||||
}
|
||||
klog.V(5).InfoS("[tracing] send packet", "type", req.Type)
|
||||
|
||||
const segment = commonmetrics.SegmentFromClient
|
||||
metrics.Metrics.ObservePacket(segment, req.Type)
|
||||
err := t.stream.Send(req)
|
||||
err := t.Send(req)
|
||||
if err != nil {
|
||||
metrics.Metrics.ObserveStreamError(segment, err, req.Type)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
klog.V(5).Infoln("DIAL_REQ sent to proxy server")
|
||||
|
||||
c := &conn{
|
||||
stream: t.stream,
|
||||
tunnel: t,
|
||||
random: random,
|
||||
closeTunnel: t.closeTunnel,
|
||||
}
|
||||
@ -473,10 +492,7 @@ func (t *grpcTunnel) closeDial(dialID int64) {
|
||||
},
|
||||
},
|
||||
}
|
||||
const segment = commonmetrics.SegmentFromClient
|
||||
metrics.Metrics.ObservePacket(segment, req.Type)
|
||||
if err := t.stream.Send(req); err != nil {
|
||||
metrics.Metrics.ObserveStreamError(segment, err, req.Type)
|
||||
if err := t.Send(req); err != nil {
|
||||
klog.V(5).InfoS("Failed to send DIAL_CLS", "err", err, "dialID", dialID)
|
||||
}
|
||||
t.closeTunnel()
|
||||
@ -491,6 +507,35 @@ func (t *grpcTunnel) isClosing() bool {
|
||||
return atomic.LoadUint32(&t.closing) != 0
|
||||
}
|
||||
|
||||
func (t *grpcTunnel) Send(pkt *client.Packet) error {
|
||||
t.sendLock.Lock()
|
||||
defer t.sendLock.Unlock()
|
||||
|
||||
const segment = commonmetrics.SegmentFromClient
|
||||
metrics.Metrics.ObservePacket(segment, pkt.Type)
|
||||
err := t.stream.Send(pkt)
|
||||
if err != nil && err != io.EOF {
|
||||
metrics.Metrics.ObserveStreamError(segment, err, pkt.Type)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *grpcTunnel) Recv() (*client.Packet, error) {
|
||||
t.recvLock.Lock()
|
||||
defer t.recvLock.Unlock()
|
||||
|
||||
const segment = commonmetrics.SegmentToClient
|
||||
pkt, err := t.stream.Recv()
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
metrics.Metrics.ObserveStreamErrorNoPacket(segment, err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
metrics.Metrics.ObservePacket(segment, pkt.Type)
|
||||
return pkt, nil
|
||||
}
|
||||
|
||||
func GetDialFailureReason(err error) (isDialFailure bool, reason metrics.DialFailureReason) {
|
||||
var df *dialFailure
|
||||
if errors.As(err, &df) {
|
||||
|
14
vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/conn.go
generated
vendored
14
vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/conn.go
generated
vendored
@ -24,8 +24,6 @@ import (
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/metrics"
|
||||
commonmetrics "sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/common/metrics"
|
||||
"sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client"
|
||||
)
|
||||
|
||||
@ -38,7 +36,7 @@ var errConnCloseTimeout = errors.New("close timeout")
|
||||
// conn is an implementation of net.Conn, where the data is transported
|
||||
// over an established tunnel defined by a gRPC service ProxyService.
|
||||
type conn struct {
|
||||
stream client.ProxyService_ProxyClient
|
||||
tunnel *grpcTunnel
|
||||
connID int64
|
||||
random int64
|
||||
readCh chan []byte
|
||||
@ -65,11 +63,8 @@ func (c *conn) Write(data []byte) (n int, err error) {
|
||||
|
||||
klog.V(5).InfoS("[tracing] send req", "type", req.Type)
|
||||
|
||||
const segment = commonmetrics.SegmentFromClient
|
||||
metrics.Metrics.ObservePacket(segment, req.Type)
|
||||
err = c.stream.Send(req)
|
||||
err = c.tunnel.Send(req)
|
||||
if err != nil {
|
||||
metrics.Metrics.ObserveStreamError(segment, err, req.Type)
|
||||
return 0, err
|
||||
}
|
||||
return len(data), err
|
||||
@ -153,10 +148,7 @@ func (c *conn) Close() error {
|
||||
|
||||
klog.V(5).InfoS("[tracing] send req", "type", req.Type)
|
||||
|
||||
const segment = commonmetrics.SegmentFromClient
|
||||
metrics.Metrics.ObservePacket(segment, req.Type)
|
||||
if err := c.stream.Send(req); err != nil {
|
||||
metrics.Metrics.ObserveStreamError(segment, err, req.Type)
|
||||
if err := c.tunnel.Send(req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,8 @@ const (
|
||||
// DialFailureTunnelClosed indicates that the client connection was closed before the dial could
|
||||
// complete.
|
||||
DialFailureTunnelClosed DialFailureReason = "tunnelclosed"
|
||||
// DialFailureAlreadyStarted indicates that a single-use tunnel dialer was already used once.
|
||||
DialFailureAlreadyStarted DialFailureReason = "tunnelstarted"
|
||||
)
|
||||
|
||||
type ClientConnectionStatus string
|
||||
|
1306
vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client/client.pb.go
generated
vendored
1306
vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client/client.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
@ -32,11 +32,6 @@ enum PacketType {
|
||||
DIAL_CLS = 5;
|
||||
}
|
||||
|
||||
enum Error {
|
||||
EOF = 0;
|
||||
// ...
|
||||
}
|
||||
|
||||
message Packet {
|
||||
PacketType type = 1;
|
||||
|
||||
|
150
vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client/client_grpc.pb.go
generated
vendored
Normal file
150
vendor/sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client/client_grpc.pb.go
generated
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.12.4
|
||||
// source: konnectivity-client/proto/client/client.proto
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// ProxyServiceClient is the client API for ProxyService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type ProxyServiceClient interface {
|
||||
Proxy(ctx context.Context, opts ...grpc.CallOption) (ProxyService_ProxyClient, error)
|
||||
}
|
||||
|
||||
type proxyServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewProxyServiceClient(cc grpc.ClientConnInterface) ProxyServiceClient {
|
||||
return &proxyServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *proxyServiceClient) Proxy(ctx context.Context, opts ...grpc.CallOption) (ProxyService_ProxyClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &ProxyService_ServiceDesc.Streams[0], "/ProxyService/Proxy", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &proxyServiceProxyClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type ProxyService_ProxyClient interface {
|
||||
Send(*Packet) error
|
||||
Recv() (*Packet, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type proxyServiceProxyClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *proxyServiceProxyClient) Send(m *Packet) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *proxyServiceProxyClient) Recv() (*Packet, error) {
|
||||
m := new(Packet)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// ProxyServiceServer is the server API for ProxyService service.
|
||||
// All implementations should embed UnimplementedProxyServiceServer
|
||||
// for forward compatibility
|
||||
type ProxyServiceServer interface {
|
||||
Proxy(ProxyService_ProxyServer) error
|
||||
}
|
||||
|
||||
// UnimplementedProxyServiceServer should be embedded to have forward compatible implementations.
|
||||
type UnimplementedProxyServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedProxyServiceServer) Proxy(ProxyService_ProxyServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Proxy not implemented")
|
||||
}
|
||||
|
||||
// UnsafeProxyServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to ProxyServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeProxyServiceServer interface {
|
||||
mustEmbedUnimplementedProxyServiceServer()
|
||||
}
|
||||
|
||||
func RegisterProxyServiceServer(s grpc.ServiceRegistrar, srv ProxyServiceServer) {
|
||||
s.RegisterService(&ProxyService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _ProxyService_Proxy_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(ProxyServiceServer).Proxy(&proxyServiceProxyServer{stream})
|
||||
}
|
||||
|
||||
type ProxyService_ProxyServer interface {
|
||||
Send(*Packet) error
|
||||
Recv() (*Packet, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type proxyServiceProxyServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *proxyServiceProxyServer) Send(m *Packet) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *proxyServiceProxyServer) Recv() (*Packet, error) {
|
||||
m := new(Packet)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// ProxyService_ServiceDesc is the grpc.ServiceDesc for ProxyService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var ProxyService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "ProxyService",
|
||||
HandlerType: (*ProxyServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "Proxy",
|
||||
Handler: _ProxyService_Proxy_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "konnectivity-client/proto/client/client.proto",
|
||||
}
|
5
vendor/sigs.k8s.io/json/internal/golang/encoding/json/decode.go
generated
vendored
5
vendor/sigs.k8s.io/json/internal/golang/encoding/json/decode.go
generated
vendored
@ -75,6 +75,8 @@ import (
|
||||
// either be any string type, an integer, implement json.Unmarshaler, or
|
||||
// implement encoding.TextUnmarshaler.
|
||||
//
|
||||
// If the JSON-encoded data contain a syntax error, Unmarshal returns a SyntaxError.
|
||||
//
|
||||
// If a JSON value is not appropriate for a given target type,
|
||||
// or if a JSON number overflows the target type, Unmarshal
|
||||
// skips that field and completes the unmarshaling as best it can.
|
||||
@ -85,14 +87,13 @@ import (
|
||||
//
|
||||
// The JSON null value unmarshals into an interface, map, pointer, or slice
|
||||
// by setting that Go value to nil. Because null is often used in JSON to mean
|
||||
// ``not present,'' unmarshaling a JSON null into any other Go type has no effect
|
||||
// “not present,” unmarshaling a JSON null into any other Go type has no effect
|
||||
// on the value and produces no error.
|
||||
//
|
||||
// When unmarshaling quoted strings, invalid UTF-8 or
|
||||
// invalid UTF-16 surrogate pairs are not treated as an error.
|
||||
// Instead, they are replaced by the Unicode replacement
|
||||
// character U+FFFD.
|
||||
//
|
||||
func Unmarshal(data []byte, v any, opts ...UnmarshalOpt) error {
|
||||
// Check for well-formedness.
|
||||
// Avoids filling out half a data structure
|
||||
|
37
vendor/sigs.k8s.io/json/internal/golang/encoding/json/encode.go
generated
vendored
37
vendor/sigs.k8s.io/json/internal/golang/encoding/json/encode.go
generated
vendored
@ -77,31 +77,31 @@ import (
|
||||
//
|
||||
// Examples of struct field tags and their meanings:
|
||||
//
|
||||
// // Field appears in JSON as key "myName".
|
||||
// Field int `json:"myName"`
|
||||
// // Field appears in JSON as key "myName".
|
||||
// Field int `json:"myName"`
|
||||
//
|
||||
// // Field appears in JSON as key "myName" and
|
||||
// // the field is omitted from the object if its value is empty,
|
||||
// // as defined above.
|
||||
// Field int `json:"myName,omitempty"`
|
||||
// // Field appears in JSON as key "myName" and
|
||||
// // the field is omitted from the object if its value is empty,
|
||||
// // as defined above.
|
||||
// Field int `json:"myName,omitempty"`
|
||||
//
|
||||
// // Field appears in JSON as key "Field" (the default), but
|
||||
// // the field is skipped if empty.
|
||||
// // Note the leading comma.
|
||||
// Field int `json:",omitempty"`
|
||||
// // Field appears in JSON as key "Field" (the default), but
|
||||
// // the field is skipped if empty.
|
||||
// // Note the leading comma.
|
||||
// Field int `json:",omitempty"`
|
||||
//
|
||||
// // Field is ignored by this package.
|
||||
// Field int `json:"-"`
|
||||
// // Field is ignored by this package.
|
||||
// Field int `json:"-"`
|
||||
//
|
||||
// // Field appears in JSON as key "-".
|
||||
// Field int `json:"-,"`
|
||||
// // Field appears in JSON as key "-".
|
||||
// Field int `json:"-,"`
|
||||
//
|
||||
// The "string" option signals that a field is stored as JSON inside a
|
||||
// JSON-encoded string. It applies only to fields of string, floating point,
|
||||
// integer, or boolean types. This extra level of encoding is sometimes used
|
||||
// when communicating with JavaScript programs:
|
||||
//
|
||||
// Int64String int64 `json:",string"`
|
||||
// Int64String int64 `json:",string"`
|
||||
//
|
||||
// The key name will be used if it's a non-empty string consisting of
|
||||
// only Unicode letters, digits, and ASCII punctuation except quotation
|
||||
@ -154,7 +154,6 @@ import (
|
||||
// JSON cannot represent cyclic data structures and Marshal does not
|
||||
// handle them. Passing cyclic structures to Marshal will result in
|
||||
// an error.
|
||||
//
|
||||
func Marshal(v any) ([]byte, error) {
|
||||
e := newEncodeState()
|
||||
|
||||
@ -784,7 +783,7 @@ func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
|
||||
if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
|
||||
// We're a large number of nested ptrEncoder.encode calls deep;
|
||||
// start checking if we've run into a pointer cycle.
|
||||
ptr := v.Pointer()
|
||||
ptr := v.UnsafePointer()
|
||||
if _, ok := e.ptrSeen[ptr]; ok {
|
||||
e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
|
||||
}
|
||||
@ -877,9 +876,9 @@ func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
|
||||
// Here we use a struct to memorize the pointer to the first element of the slice
|
||||
// and its length.
|
||||
ptr := struct {
|
||||
ptr uintptr
|
||||
ptr interface{} // always an unsafe.Pointer, but avoids a dependency on package unsafe
|
||||
len int
|
||||
}{v.Pointer(), v.Len()}
|
||||
}{v.UnsafePointer(), v.Len()}
|
||||
if _, ok := e.ptrSeen[ptr]; ok {
|
||||
e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
|
||||
}
|
||||
|
5
vendor/sigs.k8s.io/json/internal/golang/encoding/json/fold.go
generated
vendored
5
vendor/sigs.k8s.io/json/internal/golang/encoding/json/fold.go
generated
vendored
@ -24,8 +24,9 @@ const (
|
||||
// 4) simpleLetterEqualFold, no specials, no non-letters.
|
||||
//
|
||||
// The letters S and K are special because they map to 3 runes, not just 2:
|
||||
// * S maps to s and to U+017F 'ſ' Latin small letter long s
|
||||
// * k maps to K and to U+212A 'K' Kelvin sign
|
||||
// - S maps to s and to U+017F 'ſ' Latin small letter long s
|
||||
// - k maps to K and to U+212A 'K' Kelvin sign
|
||||
//
|
||||
// See https://play.golang.org/p/tTxjOc0OGo
|
||||
//
|
||||
// The returned function is specialized for matching against s and
|
||||
|
2
vendor/sigs.k8s.io/json/internal/golang/encoding/json/scanner.go
generated
vendored
2
vendor/sigs.k8s.io/json/internal/golang/encoding/json/scanner.go
generated
vendored
@ -27,6 +27,7 @@ func Valid(data []byte) bool {
|
||||
|
||||
// checkValid verifies that data is valid JSON-encoded data.
|
||||
// scan is passed in for use by checkValid to avoid an allocation.
|
||||
// checkValid returns nil or a SyntaxError.
|
||||
func checkValid(data []byte, scan *scanner) error {
|
||||
scan.reset()
|
||||
for _, c := range data {
|
||||
@ -42,6 +43,7 @@ func checkValid(data []byte, scan *scanner) error {
|
||||
}
|
||||
|
||||
// A SyntaxError is a description of a JSON syntax error.
|
||||
// Unmarshal will return a SyntaxError if the JSON can't be parsed.
|
||||
type SyntaxError struct {
|
||||
msg string // description of error
|
||||
Offset int64 // error occurred after reading Offset bytes
|
||||
|
1
vendor/sigs.k8s.io/json/internal/golang/encoding/json/stream.go
generated
vendored
1
vendor/sigs.k8s.io/json/internal/golang/encoding/json/stream.go
generated
vendored
@ -289,7 +289,6 @@ var _ Unmarshaler = (*RawMessage)(nil)
|
||||
// Number, for JSON numbers
|
||||
// string, for JSON string literals
|
||||
// nil, for JSON null
|
||||
//
|
||||
type Token any
|
||||
*/
|
||||
|
||||
|
28
vendor/sigs.k8s.io/json/json.go
generated
vendored
28
vendor/sigs.k8s.io/json/json.go
generated
vendored
@ -34,13 +34,13 @@ type Decoder interface {
|
||||
}
|
||||
|
||||
// NewDecoderCaseSensitivePreserveInts returns a decoder that matches the behavior of encoding/json#NewDecoder, with the following changes:
|
||||
// - When unmarshaling into a struct, JSON keys must case-sensitively match `json` tag names (for tagged struct fields)
|
||||
// or struct field names (for untagged struct fields), or they are treated as unknown fields and discarded.
|
||||
// - When unmarshaling a number into an interface value, it is unmarshaled as an int64 if
|
||||
// the JSON data does not contain a "." character and parses as an integer successfully and
|
||||
// does not overflow int64. Otherwise, the number is unmarshaled as a float64.
|
||||
// - If a syntax error is returned, it will not be of type encoding/json#SyntaxError,
|
||||
// but will be recognizeable by this package's IsSyntaxError() function.
|
||||
// - When unmarshaling into a struct, JSON keys must case-sensitively match `json` tag names (for tagged struct fields)
|
||||
// or struct field names (for untagged struct fields), or they are treated as unknown fields and discarded.
|
||||
// - When unmarshaling a number into an interface value, it is unmarshaled as an int64 if
|
||||
// the JSON data does not contain a "." character and parses as an integer successfully and
|
||||
// does not overflow int64. Otherwise, the number is unmarshaled as a float64.
|
||||
// - If a syntax error is returned, it will not be of type encoding/json#SyntaxError,
|
||||
// but will be recognizeable by this package's IsSyntaxError() function.
|
||||
func NewDecoderCaseSensitivePreserveInts(r io.Reader) Decoder {
|
||||
d := internaljson.NewDecoder(r)
|
||||
d.CaseSensitive()
|
||||
@ -51,13 +51,13 @@ func NewDecoderCaseSensitivePreserveInts(r io.Reader) Decoder {
|
||||
// UnmarshalCaseSensitivePreserveInts parses the JSON-encoded data and stores the result in the value pointed to by v.
|
||||
//
|
||||
// UnmarshalCaseSensitivePreserveInts matches the behavior of encoding/json#Unmarshal, with the following changes:
|
||||
// - When unmarshaling into a struct, JSON keys must case-sensitively match `json` tag names (for tagged struct fields)
|
||||
// or struct field names (for untagged struct fields), or they are treated as unknown fields and discarded.
|
||||
// - When unmarshaling a number into an interface value, it is unmarshaled as an int64 if
|
||||
// the JSON data does not contain a "." character and parses as an integer successfully and
|
||||
// does not overflow int64. Otherwise, the number is unmarshaled as a float64.
|
||||
// - If a syntax error is returned, it will not be of type encoding/json#SyntaxError,
|
||||
// but will be recognizeable by this package's IsSyntaxError() function.
|
||||
// - When unmarshaling into a struct, JSON keys must case-sensitively match `json` tag names (for tagged struct fields)
|
||||
// or struct field names (for untagged struct fields), or they are treated as unknown fields and discarded.
|
||||
// - When unmarshaling a number into an interface value, it is unmarshaled as an int64 if
|
||||
// the JSON data does not contain a "." character and parses as an integer successfully and
|
||||
// does not overflow int64. Otherwise, the number is unmarshaled as a float64.
|
||||
// - If a syntax error is returned, it will not be of type encoding/json#SyntaxError,
|
||||
// but will be recognizeable by this package's IsSyntaxError() function.
|
||||
func UnmarshalCaseSensitivePreserveInts(data []byte, v interface{}) error {
|
||||
return internaljson.Unmarshal(
|
||||
data,
|
||||
|
121
vendor/sigs.k8s.io/structured-merge-diff/v4/merge/conflict.go
generated
vendored
Normal file
121
vendor/sigs.k8s.io/structured-merge-diff/v4/merge/conflict.go
generated
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 merge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
)
|
||||
|
||||
// Conflict is a conflict on a specific field with the current manager of
|
||||
// that field. It does implement the error interface so that it can be
|
||||
// used as an error.
|
||||
type Conflict struct {
|
||||
Manager string
|
||||
Path fieldpath.Path
|
||||
}
|
||||
|
||||
// Conflict is an error.
|
||||
var _ error = Conflict{}
|
||||
|
||||
// Error formats the conflict as an error.
|
||||
func (c Conflict) Error() string {
|
||||
return fmt.Sprintf("conflict with %q: %v", c.Manager, c.Path)
|
||||
}
|
||||
|
||||
// Equals returns true if c == c2
|
||||
func (c Conflict) Equals(c2 Conflict) bool {
|
||||
if c.Manager != c2.Manager {
|
||||
return false
|
||||
}
|
||||
return c.Path.Equals(c2.Path)
|
||||
}
|
||||
|
||||
// Conflicts accumulates multiple conflicts and aggregates them by managers.
|
||||
type Conflicts []Conflict
|
||||
|
||||
var _ error = Conflicts{}
|
||||
|
||||
// Error prints the list of conflicts, grouped by sorted managers.
|
||||
func (conflicts Conflicts) Error() string {
|
||||
if len(conflicts) == 1 {
|
||||
return conflicts[0].Error()
|
||||
}
|
||||
|
||||
m := map[string][]fieldpath.Path{}
|
||||
for _, conflict := range conflicts {
|
||||
m[conflict.Manager] = append(m[conflict.Manager], conflict.Path)
|
||||
}
|
||||
|
||||
managers := []string{}
|
||||
for manager := range m {
|
||||
managers = append(managers, manager)
|
||||
}
|
||||
|
||||
// Print conflicts by sorted managers.
|
||||
sort.Strings(managers)
|
||||
|
||||
messages := []string{}
|
||||
for _, manager := range managers {
|
||||
messages = append(messages, fmt.Sprintf("conflicts with %q:", manager))
|
||||
for _, path := range m[manager] {
|
||||
messages = append(messages, fmt.Sprintf("- %v", path))
|
||||
}
|
||||
}
|
||||
return strings.Join(messages, "\n")
|
||||
}
|
||||
|
||||
// Equals returns true if the lists of conflicts are the same.
|
||||
func (c Conflicts) Equals(c2 Conflicts) bool {
|
||||
if len(c) != len(c2) {
|
||||
return false
|
||||
}
|
||||
for i := range c {
|
||||
if !c[i].Equals(c2[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ToSet aggregates conflicts for all managers into a single Set.
|
||||
func (c Conflicts) ToSet() *fieldpath.Set {
|
||||
set := fieldpath.NewSet()
|
||||
for _, conflict := range []Conflict(c) {
|
||||
set.Insert(conflict.Path)
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
// ConflictsFromManagers creates a list of conflicts given Managers sets.
|
||||
func ConflictsFromManagers(sets fieldpath.ManagedFields) Conflicts {
|
||||
conflicts := []Conflict{}
|
||||
|
||||
for manager, set := range sets {
|
||||
set.Set().Iterate(func(p fieldpath.Path) {
|
||||
conflicts = append(conflicts, Conflict{
|
||||
Manager: manager,
|
||||
Path: p,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return conflicts
|
||||
}
|
356
vendor/sigs.k8s.io/structured-merge-diff/v4/merge/update.go
generated
vendored
Normal file
356
vendor/sigs.k8s.io/structured-merge-diff/v4/merge/update.go
generated
vendored
Normal file
@ -0,0 +1,356 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 merge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/typed"
|
||||
)
|
||||
|
||||
// Converter is an interface to the conversion logic. The converter
|
||||
// needs to be able to convert objects from one version to another.
|
||||
type Converter interface {
|
||||
Convert(object *typed.TypedValue, version fieldpath.APIVersion) (*typed.TypedValue, error)
|
||||
IsMissingVersionError(error) bool
|
||||
}
|
||||
|
||||
// Updater is the object used to compute updated FieldSets and also
|
||||
// merge the object on Apply.
|
||||
type Updater struct {
|
||||
Converter Converter
|
||||
IgnoredFields map[fieldpath.APIVersion]*fieldpath.Set
|
||||
|
||||
enableUnions bool
|
||||
}
|
||||
|
||||
// EnableUnionFeature turns on union handling. It is disabled by default until the
|
||||
// feature is complete.
|
||||
func (s *Updater) EnableUnionFeature() {
|
||||
s.enableUnions = true
|
||||
}
|
||||
|
||||
func (s *Updater) update(oldObject, newObject *typed.TypedValue, version fieldpath.APIVersion, managers fieldpath.ManagedFields, workflow string, force bool) (fieldpath.ManagedFields, *typed.Comparison, error) {
|
||||
conflicts := fieldpath.ManagedFields{}
|
||||
removed := fieldpath.ManagedFields{}
|
||||
compare, err := oldObject.Compare(newObject)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to compare objects: %v", err)
|
||||
}
|
||||
|
||||
versions := map[fieldpath.APIVersion]*typed.Comparison{
|
||||
version: compare.ExcludeFields(s.IgnoredFields[version]),
|
||||
}
|
||||
|
||||
for manager, managerSet := range managers {
|
||||
if manager == workflow {
|
||||
continue
|
||||
}
|
||||
compare, ok := versions[managerSet.APIVersion()]
|
||||
if !ok {
|
||||
var err error
|
||||
versionedOldObject, err := s.Converter.Convert(oldObject, managerSet.APIVersion())
|
||||
if err != nil {
|
||||
if s.Converter.IsMissingVersionError(err) {
|
||||
delete(managers, manager)
|
||||
continue
|
||||
}
|
||||
return nil, nil, fmt.Errorf("failed to convert old object: %v", err)
|
||||
}
|
||||
versionedNewObject, err := s.Converter.Convert(newObject, managerSet.APIVersion())
|
||||
if err != nil {
|
||||
if s.Converter.IsMissingVersionError(err) {
|
||||
delete(managers, manager)
|
||||
continue
|
||||
}
|
||||
return nil, nil, fmt.Errorf("failed to convert new object: %v", err)
|
||||
}
|
||||
compare, err = versionedOldObject.Compare(versionedNewObject)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to compare objects: %v", err)
|
||||
}
|
||||
versions[managerSet.APIVersion()] = compare.ExcludeFields(s.IgnoredFields[managerSet.APIVersion()])
|
||||
}
|
||||
|
||||
conflictSet := managerSet.Set().Intersection(compare.Modified.Union(compare.Added))
|
||||
if !conflictSet.Empty() {
|
||||
conflicts[manager] = fieldpath.NewVersionedSet(conflictSet, managerSet.APIVersion(), false)
|
||||
}
|
||||
|
||||
if !compare.Removed.Empty() {
|
||||
removed[manager] = fieldpath.NewVersionedSet(compare.Removed, managerSet.APIVersion(), false)
|
||||
}
|
||||
}
|
||||
|
||||
if !force && len(conflicts) != 0 {
|
||||
return nil, nil, ConflictsFromManagers(conflicts)
|
||||
}
|
||||
|
||||
for manager, conflictSet := range conflicts {
|
||||
managers[manager] = fieldpath.NewVersionedSet(managers[manager].Set().Difference(conflictSet.Set()), managers[manager].APIVersion(), managers[manager].Applied())
|
||||
}
|
||||
|
||||
for manager, removedSet := range removed {
|
||||
managers[manager] = fieldpath.NewVersionedSet(managers[manager].Set().Difference(removedSet.Set()), managers[manager].APIVersion(), managers[manager].Applied())
|
||||
}
|
||||
|
||||
for manager := range managers {
|
||||
if managers[manager].Set().Empty() {
|
||||
delete(managers, manager)
|
||||
}
|
||||
}
|
||||
|
||||
return managers, compare, nil
|
||||
}
|
||||
|
||||
// Update is the method you should call once you've merged your final
|
||||
// object on CREATE/UPDATE/PATCH verbs. newObject must be the object
|
||||
// that you intend to persist (after applying the patch if this is for a
|
||||
// PATCH call), and liveObject must be the original object (empty if
|
||||
// this is a CREATE call).
|
||||
func (s *Updater) Update(liveObject, newObject *typed.TypedValue, version fieldpath.APIVersion, managers fieldpath.ManagedFields, manager string) (*typed.TypedValue, fieldpath.ManagedFields, error) {
|
||||
var err error
|
||||
managers, err = s.reconcileManagedFieldsWithSchemaChanges(liveObject, managers)
|
||||
if err != nil {
|
||||
return nil, fieldpath.ManagedFields{}, err
|
||||
}
|
||||
if s.enableUnions {
|
||||
newObject, err = liveObject.NormalizeUnions(newObject)
|
||||
if err != nil {
|
||||
return nil, fieldpath.ManagedFields{}, err
|
||||
}
|
||||
}
|
||||
managers, compare, err := s.update(liveObject, newObject, version, managers, manager, true)
|
||||
if err != nil {
|
||||
return nil, fieldpath.ManagedFields{}, err
|
||||
}
|
||||
if _, ok := managers[manager]; !ok {
|
||||
managers[manager] = fieldpath.NewVersionedSet(fieldpath.NewSet(), version, false)
|
||||
}
|
||||
|
||||
ignored := s.IgnoredFields[version]
|
||||
if ignored == nil {
|
||||
ignored = fieldpath.NewSet()
|
||||
}
|
||||
managers[manager] = fieldpath.NewVersionedSet(
|
||||
managers[manager].Set().Union(compare.Modified).Union(compare.Added).Difference(compare.Removed).RecursiveDifference(ignored),
|
||||
version,
|
||||
false,
|
||||
)
|
||||
if managers[manager].Set().Empty() {
|
||||
delete(managers, manager)
|
||||
}
|
||||
return newObject, managers, nil
|
||||
}
|
||||
|
||||
// Apply should be called when Apply is run, given the current object as
|
||||
// well as the configuration that is applied. This will merge the object
|
||||
// and return it. If the object hasn't changed, nil is returned (the
|
||||
// managers can still have changed though).
|
||||
func (s *Updater) Apply(liveObject, configObject *typed.TypedValue, version fieldpath.APIVersion, managers fieldpath.ManagedFields, manager string, force bool) (*typed.TypedValue, fieldpath.ManagedFields, error) {
|
||||
var err error
|
||||
managers, err = s.reconcileManagedFieldsWithSchemaChanges(liveObject, managers)
|
||||
if err != nil {
|
||||
return nil, fieldpath.ManagedFields{}, err
|
||||
}
|
||||
if s.enableUnions {
|
||||
configObject, err = configObject.NormalizeUnionsApply(configObject)
|
||||
if err != nil {
|
||||
return nil, fieldpath.ManagedFields{}, err
|
||||
}
|
||||
}
|
||||
newObject, err := liveObject.Merge(configObject)
|
||||
if err != nil {
|
||||
return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to merge config: %v", err)
|
||||
}
|
||||
if s.enableUnions {
|
||||
newObject, err = configObject.NormalizeUnionsApply(newObject)
|
||||
if err != nil {
|
||||
return nil, fieldpath.ManagedFields{}, err
|
||||
}
|
||||
}
|
||||
lastSet := managers[manager]
|
||||
set, err := configObject.ToFieldSet()
|
||||
if err != nil {
|
||||
return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to get field set: %v", err)
|
||||
}
|
||||
|
||||
ignored := s.IgnoredFields[version]
|
||||
if ignored != nil {
|
||||
set = set.RecursiveDifference(ignored)
|
||||
// TODO: is this correct. If we don't remove from lastSet pruning might remove the fields?
|
||||
if lastSet != nil {
|
||||
lastSet.Set().RecursiveDifference(ignored)
|
||||
}
|
||||
}
|
||||
managers[manager] = fieldpath.NewVersionedSet(set, version, true)
|
||||
newObject, err = s.prune(newObject, managers, manager, lastSet)
|
||||
if err != nil {
|
||||
return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to prune fields: %v", err)
|
||||
}
|
||||
managers, compare, err := s.update(liveObject, newObject, version, managers, manager, force)
|
||||
if err != nil {
|
||||
return nil, fieldpath.ManagedFields{}, err
|
||||
}
|
||||
if compare.IsSame() {
|
||||
newObject = nil
|
||||
}
|
||||
return newObject, managers, nil
|
||||
}
|
||||
|
||||
// prune will remove a field, list or map item, iff:
|
||||
// * applyingManager applied it last time
|
||||
// * applyingManager didn't apply it this time
|
||||
// * no other applier claims to manage it
|
||||
func (s *Updater) prune(merged *typed.TypedValue, managers fieldpath.ManagedFields, applyingManager string, lastSet fieldpath.VersionedSet) (*typed.TypedValue, error) {
|
||||
if lastSet == nil || lastSet.Set().Empty() {
|
||||
return merged, nil
|
||||
}
|
||||
convertedMerged, err := s.Converter.Convert(merged, lastSet.APIVersion())
|
||||
if err != nil {
|
||||
if s.Converter.IsMissingVersionError(err) {
|
||||
return merged, nil
|
||||
}
|
||||
return nil, fmt.Errorf("failed to convert merged object to last applied version: %v", err)
|
||||
}
|
||||
|
||||
sc, tr := convertedMerged.Schema(), convertedMerged.TypeRef()
|
||||
pruned := convertedMerged.RemoveItems(lastSet.Set().EnsureNamedFieldsAreMembers(sc, tr))
|
||||
pruned, err = s.addBackOwnedItems(convertedMerged, pruned, managers, applyingManager)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed add back owned items: %v", err)
|
||||
}
|
||||
pruned, err = s.addBackDanglingItems(convertedMerged, pruned, lastSet)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed add back dangling items: %v", err)
|
||||
}
|
||||
return s.Converter.Convert(pruned, managers[applyingManager].APIVersion())
|
||||
}
|
||||
|
||||
// addBackOwnedItems adds back any fields, list and map items that were removed by prune,
|
||||
// but other appliers or updaters (or the current applier's new config) claim to own.
|
||||
func (s *Updater) addBackOwnedItems(merged, pruned *typed.TypedValue, managedFields fieldpath.ManagedFields, applyingManager string) (*typed.TypedValue, error) {
|
||||
var err error
|
||||
managedAtVersion := map[fieldpath.APIVersion]*fieldpath.Set{}
|
||||
for _, managerSet := range managedFields {
|
||||
if _, ok := managedAtVersion[managerSet.APIVersion()]; !ok {
|
||||
managedAtVersion[managerSet.APIVersion()] = fieldpath.NewSet()
|
||||
}
|
||||
managedAtVersion[managerSet.APIVersion()] = managedAtVersion[managerSet.APIVersion()].Union(managerSet.Set())
|
||||
}
|
||||
// Add back owned items at pruned version first to avoid conversion failure
|
||||
// caused by pruned fields which are required for conversion.
|
||||
prunedVersion := fieldpath.APIVersion(*pruned.TypeRef().NamedType)
|
||||
if managed, ok := managedAtVersion[prunedVersion]; ok {
|
||||
merged, pruned, err = s.addBackOwnedItemsForVersion(merged, pruned, prunedVersion, managed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
delete(managedAtVersion, prunedVersion)
|
||||
}
|
||||
for version, managed := range managedAtVersion {
|
||||
merged, pruned, err = s.addBackOwnedItemsForVersion(merged, pruned, version, managed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return pruned, nil
|
||||
}
|
||||
|
||||
// addBackOwnedItemsForVersion adds back any fields, list and map items that were removed by prune with specific managed field path at a version.
|
||||
// It is an extracted sub-function from addBackOwnedItems for code reuse.
|
||||
func (s *Updater) addBackOwnedItemsForVersion(merged, pruned *typed.TypedValue, version fieldpath.APIVersion, managed *fieldpath.Set) (*typed.TypedValue, *typed.TypedValue, error) {
|
||||
var err error
|
||||
merged, err = s.Converter.Convert(merged, version)
|
||||
if err != nil {
|
||||
if s.Converter.IsMissingVersionError(err) {
|
||||
return merged, pruned, nil
|
||||
}
|
||||
return nil, nil, fmt.Errorf("failed to convert merged object at version %v: %v", version, err)
|
||||
}
|
||||
pruned, err = s.Converter.Convert(pruned, version)
|
||||
if err != nil {
|
||||
if s.Converter.IsMissingVersionError(err) {
|
||||
return merged, pruned, nil
|
||||
}
|
||||
return nil, nil, fmt.Errorf("failed to convert pruned object at version %v: %v", version, err)
|
||||
}
|
||||
mergedSet, err := merged.ToFieldSet()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to create field set from merged object at version %v: %v", version, err)
|
||||
}
|
||||
prunedSet, err := pruned.ToFieldSet()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to create field set from pruned object at version %v: %v", version, err)
|
||||
}
|
||||
sc, tr := merged.Schema(), merged.TypeRef()
|
||||
pruned = merged.RemoveItems(mergedSet.EnsureNamedFieldsAreMembers(sc, tr).Difference(prunedSet.EnsureNamedFieldsAreMembers(sc, tr).Union(managed.EnsureNamedFieldsAreMembers(sc, tr))))
|
||||
return merged, pruned, nil
|
||||
}
|
||||
|
||||
// addBackDanglingItems makes sure that the fields list and map items removed by prune were
|
||||
// previously owned by the currently applying manager. This will add back fields list and map items
|
||||
// that are unowned or that are owned by Updaters and shouldn't be removed.
|
||||
func (s *Updater) addBackDanglingItems(merged, pruned *typed.TypedValue, lastSet fieldpath.VersionedSet) (*typed.TypedValue, error) {
|
||||
convertedPruned, err := s.Converter.Convert(pruned, lastSet.APIVersion())
|
||||
if err != nil {
|
||||
if s.Converter.IsMissingVersionError(err) {
|
||||
return merged, nil
|
||||
}
|
||||
return nil, fmt.Errorf("failed to convert pruned object to last applied version: %v", err)
|
||||
}
|
||||
prunedSet, err := convertedPruned.ToFieldSet()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create field set from pruned object in last applied version: %v", err)
|
||||
}
|
||||
mergedSet, err := merged.ToFieldSet()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create field set from merged object in last applied version: %v", err)
|
||||
}
|
||||
sc, tr := merged.Schema(), merged.TypeRef()
|
||||
prunedSet = prunedSet.EnsureNamedFieldsAreMembers(sc, tr)
|
||||
mergedSet = mergedSet.EnsureNamedFieldsAreMembers(sc, tr)
|
||||
last := lastSet.Set().EnsureNamedFieldsAreMembers(sc, tr)
|
||||
return merged.RemoveItems(mergedSet.Difference(prunedSet).Intersection(last)), nil
|
||||
}
|
||||
|
||||
// reconcileManagedFieldsWithSchemaChanges reconciles the managed fields with any changes to the
|
||||
// object's schema since the managed fields were written.
|
||||
//
|
||||
// Supports:
|
||||
// - changing types from atomic to granular
|
||||
// - changing types from granular to atomic
|
||||
func (s *Updater) reconcileManagedFieldsWithSchemaChanges(liveObject *typed.TypedValue, managers fieldpath.ManagedFields) (fieldpath.ManagedFields, error) {
|
||||
result := fieldpath.ManagedFields{}
|
||||
for manager, versionedSet := range managers {
|
||||
tv, err := s.Converter.Convert(liveObject, versionedSet.APIVersion())
|
||||
if s.Converter.IsMissingVersionError(err) { // okay to skip, obsolete versions will be deleted automatically anyway
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reconciled, err := typed.ReconcileFieldSetWithSchema(versionedSet.Set(), tv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if reconciled != nil {
|
||||
result[manager] = fieldpath.NewVersionedSet(reconciled, versionedSet.APIVersion(), versionedSet.Applied())
|
||||
} else {
|
||||
result[manager] = versionedSet
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
Reference in New Issue
Block a user