From ada0dd78222da413cdc744ab100741ef314d5055 Mon Sep 17 00:00:00 2001 From: Amit Berner Date: Tue, 23 Jan 2024 11:13:35 +0200 Subject: [PATCH 01/35] controllers: pr issue fix fixed ownership of resources and remove finalizer in deletion Signed-off-by: Amit Berner --- ...ler.go => operatorconfigmap_controller.go} | 124 ++++++++---------- main.go | 26 +--- pkg/utils/deployment.go | 40 ------ 3 files changed, 60 insertions(+), 130 deletions(-) rename controllers/{clusterversion_controller.go => operatorconfigmap_controller.go} (82%) delete mode 100644 pkg/utils/deployment.go diff --git a/controllers/clusterversion_controller.go b/controllers/operatorconfigmap_controller.go similarity index 82% rename from controllers/clusterversion_controller.go rename to controllers/operatorconfigmap_controller.go index 076210aa..8dc36008 100644 --- a/controllers/clusterversion_controller.go +++ b/controllers/operatorconfigmap_controller.go @@ -66,16 +66,16 @@ const ( subscriptionLabelValue = "webhook.subscription.ocs.openshift.io" ) -// ClusterVersionReconciler reconciles a ClusterVersion object -type ClusterVersionReconciler struct { +// OperatorConfigMapReconciler reconciles a ClusterVersion object +type OperatorConfigMapReconciler struct { client.Client - OperatorDeployment *appsv1.Deployment - OperatorNamespace string - ConsolePort int32 - Scheme *runtime.Scheme + OperatorNamespace string + ConsolePort int32 + Scheme *runtime.Scheme log logr.Logger ctx context.Context + operatorConfigMap *corev1.ConfigMap consoleDeployment *appsv1.Deployment cephFSDeployment *appsv1.Deployment cephFSDaemonSet *appsv1.DaemonSet @@ -85,7 +85,7 @@ type ClusterVersionReconciler struct { } // SetupWithManager sets up the controller with the Manager. -func (c *ClusterVersionReconciler) SetupWithManager(mgr ctrl.Manager) error { +func (c *OperatorConfigMapReconciler) SetupWithManager(mgr ctrl.Manager) error { clusterVersionPredicates := builder.WithPredicates( predicate.GenerationChangedPredicate{}, ) @@ -99,12 +99,13 @@ func (c *ClusterVersionReconciler) SetupWithManager(mgr ctrl.Manager) error { }, ), ) - // Reconcile the ClusterVersion object when the operator config map is updated - enqueueClusterVersionRequest := handler.EnqueueRequestsFromMapFunc( + // Reconcile the OperatorConfigMap object when the cluster's version object is updated + enqueueConfigMapRequest := handler.EnqueueRequestsFromMapFunc( func(_ context.Context, _ client.Object) []reconcile.Request { return []reconcile.Request{{ NamespacedName: types.NamespacedName{ - Name: clusterVersionName, + Name: operatorConfigMapName, + Namespace: c.OperatorNamespace, }, }} }, @@ -128,24 +129,23 @@ func (c *ClusterVersionReconciler) SetupWithManager(mgr ctrl.Manager) error { ) return ctrl.NewControllerManagedBy(mgr). - For(&configv1.ClusterVersion{}, clusterVersionPredicates). - Watches(&corev1.ConfigMap{}, enqueueClusterVersionRequest, configMapPredicates). - Watches(&extv1.CustomResourceDefinition{}, enqueueClusterVersionRequest, builder.OnlyMetadata). - Watches(&opv1a1.Subscription{}, enqueueClusterVersionRequest, subscriptionPredicates). - Watches(&admrv1.ValidatingWebhookConfiguration{}, enqueueClusterVersionRequest, webhookPredicates). + For(&corev1.ConfigMap{}, configMapPredicates). + Watches(&configv1.ClusterVersion{}, enqueueConfigMapRequest, clusterVersionPredicates). + Watches(&extv1.CustomResourceDefinition{}, enqueueConfigMapRequest, builder.OnlyMetadata). + Watches(&opv1a1.Subscription{}, enqueueConfigMapRequest, subscriptionPredicates). + Watches(&admrv1.ValidatingWebhookConfiguration{}, enqueueConfigMapRequest, webhookPredicates). Complete(c) } //+kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch -//+kubebuilder:rbac:groups=config.openshift.io,resources=clusterversions,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=config.openshift.io,resources=clusterversions/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=config.openshift.io,resources=clusterversions/finalizers,verbs=update +//+kubebuilder:rbac:groups=config.openshift.io,resources=clusterversions,verbs=get;list;watch //+kubebuilder:rbac:groups="apps",resources=deployments,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups="apps",resources=deployments/finalizers,verbs=update //+kubebuilder:rbac:groups="apps",resources=daemonsets,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups="apps",resources=daemonsets/finalizers,verbs=update //+kubebuilder:rbac:groups="storage.k8s.io",resources=csidrivers,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;delete +//+kubebuilder:rbac:groups="",resources=configmaps/finalizers,verbs=update //+kubebuilder:rbac:groups=security.openshift.io,resources=securitycontextconstraints,verbs=get;list;watch;create;patch;update //+kubebuilder:rbac:groups=monitoring.coreos.com,resources=prometheusrules,verbs=get;list;watch;create;update //+kubebuilder:rbac:groups="",resources=services,verbs=get;list;watch;create;update;patch;delete @@ -155,10 +155,18 @@ func (c *ClusterVersionReconciler) SetupWithManager(mgr ctrl.Manager) error { // For more details, check Reconcile and its Result here: // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.8.3/pkg/reconcile -func (c *ClusterVersionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { +func (c *OperatorConfigMapReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { c.ctx = ctx - c.log = log.FromContext(ctx, "ClusterVersion", req) - c.log.Info("Reconciling ClusterVersion") + c.log = log.FromContext(ctx, "OperatorConfigMap", req) + c.log.Info("Reconciling OperatorConfigMap") + + c.operatorConfigMap = &corev1.ConfigMap{} + c.operatorConfigMap.Name = req.Name + c.operatorConfigMap.Namespace = req.Namespace + if err := c.get(c.operatorConfigMap); err != nil { + c.log.Error(err, "failed to get the operator's configMap") + return reconcile.Result{}, err + } if err := c.reconcileSubscriptionValidatingWebhook(); err != nil { c.log.Error(err, "unable to register subscription validating webhook") @@ -179,12 +187,14 @@ func (c *ClusterVersionReconciler) Reconcile(ctx context.Context, req ctrl.Reque c.log.Error(err, "failed to perform precheck for deploying CSI") return ctrl.Result{}, err } else if deployCSI { - instance := configv1.ClusterVersion{} - if err = c.Client.Get(context.TODO(), req.NamespacedName, &instance); err != nil { - return ctrl.Result{}, err + clusterVersion := &configv1.ClusterVersion{} + clusterVersion.Name = clusterVersionName + if err := c.get(clusterVersion); err != nil { + c.log.Error(err, "failed to get the clusterVersion version of the OCP cluster") + return reconcile.Result{}, err } - if err := csi.InitializeSidecars(c.log, instance.Status.Desired.Version); err != nil { + if err := csi.InitializeSidecars(c.log, clusterVersion.Status.Desired.Version); err != nil { c.log.Error(err, "unable to initialize sidecars") return ctrl.Result{}, err } @@ -221,8 +231,8 @@ func (c *ClusterVersionReconciler) Reconcile(ctx context.Context, req ctrl.Reque if err := c.own(monConfigMap); err != nil { return ctrl.Result{}, err } - err = c.create(monConfigMap) - if err != nil && !kerrors.IsAlreadyExists(err) { + + if err := c.create(monConfigMap); err != nil && !kerrors.IsAlreadyExists(err) { c.log.Error(err, "failed to create monitor configmap", "name", monConfigMap.Name) return ctrl.Result{}, err } @@ -242,8 +252,8 @@ func (c *ClusterVersionReconciler) Reconcile(ctx context.Context, req ctrl.Reque if err := c.own(encConfigMap); err != nil { return ctrl.Result{}, err } - err = c.create(encConfigMap) - if err != nil && !kerrors.IsAlreadyExists(err) { + + if err := c.create(encConfigMap); err != nil && !kerrors.IsAlreadyExists(err) { c.log.Error(err, "failed to create monitor configmap", "name", encConfigMap.Name) return ctrl.Result{}, err } @@ -324,35 +334,28 @@ func (c *ClusterVersionReconciler) Reconcile(ctx context.Context, req ctrl.Reque // ownerReference on it as its cluster scoped resource cephfsCSIDriver := templates.CephFSCSIDriver.DeepCopy() cephfsCSIDriver.ObjectMeta.Name = csi.GetCephFSDriverName() - err = csi.CreateCSIDriver(c.ctx, c.Client, cephfsCSIDriver) - if err != nil { + if err := csi.CreateCSIDriver(c.ctx, c.Client, cephfsCSIDriver); err != nil { c.log.Error(err, "unable to create cephfs CSIDriver") return ctrl.Result{}, err } rbdCSIDriver := templates.RbdCSIDriver.DeepCopy() rbdCSIDriver.ObjectMeta.Name = csi.GetRBDDriverName() - err = csi.CreateCSIDriver(c.ctx, c.Client, rbdCSIDriver) - if err != nil { + if err := csi.CreateCSIDriver(c.ctx, c.Client, rbdCSIDriver); err != nil { c.log.Error(err, "unable to create rbd CSIDriver") return ctrl.Result{}, err } prometheusRule := &monitoringv1.PrometheusRule{} - err = k8sYAML.NewYAMLOrJSONDecoder(bytes.NewBufferString(string(pvcPrometheusRules)), 1000).Decode(prometheusRule) - if err != nil { + if err := k8sYAML.NewYAMLOrJSONDecoder(bytes.NewBufferString(string(pvcPrometheusRules)), 1000).Decode(prometheusRule); err != nil { c.log.Error(err, "Unable to retrieve prometheus rules.", "prometheusRule", klog.KRef(prometheusRule.Namespace, prometheusRule.Name)) return ctrl.Result{}, err } - operatorConfig, err := c.getOperatorConfig() - if err != nil { - return ctrl.Result{}, err - } prometheusRule.SetNamespace(c.OperatorNamespace) err = c.createOrUpdate(prometheusRule, func() error { - applyLabels(operatorConfig.Data["OCS_METRICS_LABELS"], &prometheusRule.ObjectMeta) + applyLabels(c.operatorConfigMap.Data["OCS_METRICS_LABELS"], &prometheusRule.ObjectMeta) return c.own(prometheusRule) }) if err != nil { @@ -366,7 +369,7 @@ func (c *ClusterVersionReconciler) Reconcile(ctx context.Context, req ctrl.Reque return ctrl.Result{}, nil } -func (c *ClusterVersionReconciler) createOrUpdate(obj client.Object, f controllerutil.MutateFn) error { +func (c *OperatorConfigMapReconciler) createOrUpdate(obj client.Object, f controllerutil.MutateFn) error { result, err := controllerutil.CreateOrUpdate(c.ctx, c.Client, obj, f) if err != nil { return err @@ -375,11 +378,11 @@ func (c *ClusterVersionReconciler) createOrUpdate(obj client.Object, f controlle return nil } -func (c *ClusterVersionReconciler) own(obj client.Object) error { - return controllerutil.SetControllerReference(c.OperatorDeployment, obj, c.Client.Scheme()) +func (c *OperatorConfigMapReconciler) own(obj client.Object) error { + return controllerutil.SetControllerReference(c.operatorConfigMap, obj, c.Client.Scheme()) } -func (c *ClusterVersionReconciler) create(obj client.Object) error { +func (c *OperatorConfigMapReconciler) create(obj client.Object) error { return c.Client.Create(c.ctx, obj) } @@ -403,16 +406,7 @@ func applyLabels(label string, t *metav1.ObjectMeta) { t.Labels = promLabel } -func (c *ClusterVersionReconciler) getOperatorConfig() (*corev1.ConfigMap, error) { - cm := &corev1.ConfigMap{} - err := c.Client.Get(c.ctx, types.NamespacedName{Name: operatorConfigMapName, Namespace: c.OperatorNamespace}, cm) - if err != nil && !kerrors.IsNotFound(err) { - return nil, err - } - return cm, nil -} - -func (c *ClusterVersionReconciler) ensureConsolePlugin() error { +func (c *OperatorConfigMapReconciler) ensureConsolePlugin() error { c.consoleDeployment = &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: console.DeploymentName, @@ -420,10 +414,7 @@ func (c *ClusterVersionReconciler) ensureConsolePlugin() error { }, } - err := c.Client.Get(c.ctx, types.NamespacedName{ - Name: console.DeploymentName, - Namespace: c.OperatorNamespace, - }, c.consoleDeployment) + err := c.get(c.consoleDeployment) if err != nil { c.log.Error(err, "failed to get the deployment for the console") return err @@ -483,15 +474,8 @@ func (c *ClusterVersionReconciler) ensureConsolePlugin() error { return nil } -func (c *ClusterVersionReconciler) getDeployCSIConfig() (bool, error) { - operatorConfig := &corev1.ConfigMap{} - operatorConfig.Name = operatorConfigMapName - operatorConfig.Namespace = c.OperatorNamespace - if err := c.get(operatorConfig); err != nil { - return false, fmt.Errorf("failed to get operator configmap: %v", err) - } - - data := operatorConfig.Data +func (c *OperatorConfigMapReconciler) getDeployCSIConfig() (bool, error) { + data := c.operatorConfigMap.Data if data == nil { data = map[string]string{} } @@ -526,11 +510,11 @@ func (c *ClusterVersionReconciler) getDeployCSIConfig() (bool, error) { return deployCSI, nil } -func (c *ClusterVersionReconciler) get(obj client.Object, opts ...client.GetOption) error { +func (c *OperatorConfigMapReconciler) get(obj client.Object, opts ...client.GetOption) error { return c.Get(c.ctx, client.ObjectKeyFromObject(obj), obj, opts...) } -func (c *ClusterVersionReconciler) reconcileSubscriptionValidatingWebhook() error { +func (c *OperatorConfigMapReconciler) reconcileSubscriptionValidatingWebhook() error { whConfig := &admrv1.ValidatingWebhookConfiguration{} whConfig.Name = templates.SubscriptionWebhookName @@ -583,7 +567,7 @@ func (c *ClusterVersionReconciler) reconcileSubscriptionValidatingWebhook() erro return nil } -func labelClientOperatorSubscription(c *ClusterVersionReconciler) error { +func labelClientOperatorSubscription(c *OperatorConfigMapReconciler) error { subscriptionList := &opv1a1.SubscriptionList{} err := c.List(c.ctx, subscriptionList, client.InNamespace(c.OperatorNamespace)) if err != nil { diff --git a/main.go b/main.go index 62cf1e2b..816665f0 100644 --- a/main.go +++ b/main.go @@ -17,7 +17,6 @@ limitations under the License. package main import ( - "context" "flag" "os" @@ -124,12 +123,6 @@ func main() { os.Exit(1) } - // apiclient.New() returns a client without cache. - // cache is not initialized before mgr.Start() - // we need this because we need to interact with OperatorCondition - apiClient, err := client.New(mgr.GetConfig(), client.Options{ - Scheme: mgr.GetScheme(), - }) if err != nil { setupLog.Error(err, "Unable to get Client") os.Exit(1) @@ -195,20 +188,13 @@ func main() { os.Exit(1) } - operatorDeployment, err := utils.GetOperatorDeployment(context.TODO(), apiClient) - if err != nil { - setupLog.Error(err, "unable to get operator deployment") - os.Exit(1) - } - - if err = (&controllers.ClusterVersionReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - OperatorDeployment: operatorDeployment, - OperatorNamespace: utils.GetOperatorNamespace(), - ConsolePort: int32(consolePort), + if err = (&controllers.OperatorConfigMapReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + OperatorNamespace: utils.GetOperatorNamespace(), + ConsolePort: int32(consolePort), }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "ClusterVersionReconciler") + setupLog.Error(err, "unable to create controller", "controller", "OperatorConfigMapReconciler") os.Exit(1) } diff --git a/pkg/utils/deployment.go b/pkg/utils/deployment.go deleted file mode 100644 index 37008eec..00000000 --- a/pkg/utils/deployment.go +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright 2022 Red Hat, Inc. - -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 utils - -import ( - "context" - "os" - "strings" - - appsv1 "k8s.io/api/apps/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -// GetOperatorDeployment returns the operator deployment object -func GetOperatorDeployment(ctx context.Context, c client.Client) (*appsv1.Deployment, error) { - deployment := &appsv1.Deployment{} - podNameStrings := strings.Split(os.Getenv(OperatorPodNameEnvVar), "-") - deploymentName := strings.Join(podNameStrings[:len(podNameStrings)-2], "-") - err := c.Get(ctx, types.NamespacedName{Name: deploymentName, Namespace: GetOperatorNamespace()}, deployment) - if err != nil { - return nil, err - } - - return deployment, nil -} From 6c778aeabe6c712b1bc47b08e10ce7b185540038 Mon Sep 17 00:00:00 2001 From: raaizik <132667934+raaizik@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:50:53 +0300 Subject: [PATCH 02/35] godeps: updates ocs-operator dep Signed-off-by: raaizik <132667934+raaizik@users.noreply.github.com> --- go.mod | 34 +- go.sum | 76 +- .../json-patch/v5/internal/json/decode.go | 1385 +++++++++++ .../json-patch/v5/internal/json/encode.go | 1473 ++++++++++++ .../json-patch/v5/internal/json/fold.go | 141 ++ .../json-patch/v5/internal/json/fuzz.go | 42 + .../json-patch/v5/internal/json/indent.go | 143 ++ .../json-patch/v5/internal/json/scanner.go | 610 +++++ .../json-patch/v5/internal/json/stream.go | 515 ++++ .../json-patch/v5/internal/json/tables.go | 218 ++ .../json-patch/v5/internal/json/tags.go | 38 + .../github.com/evanphx/json-patch/v5/merge.go | 58 +- .../github.com/evanphx/json-patch/v5/patch.go | 325 ++- .../golang/protobuf/jsonpb/decode.go | 530 ----- .../golang/protobuf/jsonpb/encode.go | 559 ----- .../github.com/golang/protobuf/jsonpb/json.go | 69 - .../github.com/golang/protobuf/ptypes/any.go | 7 +- vendor/github.com/onsi/gomega/CHANGELOG.md | 38 + vendor/github.com/onsi/gomega/gomega_dsl.go | 2 +- .../onsi/gomega/internal/async_assertion.go | 7 +- vendor/github.com/onsi/gomega/matchers.go | 2 +- .../matchers/be_comparable_to_matcher.go | 4 +- ...rsion-operator_01_clusteroperator.crd.yaml | 167 -- ...01_clusterversion-CustomNoUpgrade.crd.yaml | 780 ------ ...perator_01_clusterversion-Default.crd.yaml | 727 ------ ...usterversion-TechPreviewNoUpgrade.crd.yaml | 780 ------ .../0000_03_config-operator_01_proxy.crd.yaml | 106 - ...rketplace-operator_01_operatorhub.crd.yaml | 109 - ...ator_01_apiserver-CustomNoUpgrade.crd.yaml | 312 --- ...fig-operator_01_apiserver-Default.crd.yaml | 312 --- ...01_apiserver-TechPreviewNoUpgrade.crd.yaml | 312 --- ...01_authentication.crd-CustomNoUpgrade.yaml | 554 ----- ...authentication.crd-Default-Hypershift.yaml | 552 ----- ...tication.crd-Default-Hypershift.yaml-patch | 285 --- ...perator_01_authentication.crd-Default.yaml | 171 -- ...thentication.crd-TechPreviewNoUpgrade.yaml | 555 ----- ...000_10_config-operator_01_console.crd.yaml | 75 - ...g-operator_01_dns-CustomNoUpgrade.crd.yaml | 159 -- ...10_config-operator_01_dns-Default.crd.yaml | 159 -- ...rator_01_dns-TechPreviewNoUpgrade.crd.yaml | 159 -- ...10_config-operator_01_featuregate.crd.yaml | 213 -- .../0000_10_config-operator_01_image.crd.yaml | 162 -- ...ig-operator_01_imagecontentpolicy.crd.yaml | 112 - ...-operator_01_imagedigestmirrorset.crd.yaml | 141 -- ...fig-operator_01_imagetagmirrorset.crd.yaml | 144 -- ...01_infrastructure-CustomNoUpgrade.crd.yaml | 2089 ----------------- ...rastructure-CustomNoUpgrade.crd.yaml-patch | 24 - ...perator_01_infrastructure-Default.crd.yaml | 1761 -------------- ...r_01_infrastructure-Default.crd.yaml-patch | 24 - ...frastructure-TechPreviewNoUpgrade.crd.yaml | 2089 ----------------- ...ucture-TechPreviewNoUpgrade.crd.yaml-patch | 24 - ...000_10_config-operator_01_ingress.crd.yaml | 553 ----- ...erator_01_network-CustomNoUpgrade.crd.yaml | 284 --- ...onfig-operator_01_network-Default.crd.yaml | 284 --- ...r_01_network-TechPreviewNoUpgrade.crd.yaml | 284 --- .../0000_10_config-operator_01_node.crd.yaml | 66 - .../0000_10_config-operator_01_oauth.crd.yaml | 698 ------ ...000_10_config-operator_01_project.crd.yaml | 68 - ...ator_01_scheduler-CustomNoUpgrade.crd.yaml | 130 - ...fig-operator_01_scheduler-Default.crd.yaml | 109 - ...01_scheduler-TechPreviewNoUpgrade.crd.yaml | 130 - ...troller-manager-operator_01_build.crd.yaml | 431 ---- .../config/v1/custom.apiserver.testsuite.yaml | 35 - ...ustom.authentication.single.testsuite.yaml | 284 +++ .../v1/custom.authentication.testsuite.yaml | 2 +- .../v1/custom.clusterversion.testsuite.yaml | 2 +- .../api/config/v1/custom.dns.testsuite.yaml | 104 - .../v1/custom.infrastructure.testsuite.yaml | 2 +- .../config/v1/custom.network.testsuite.yaml | 28 - .../config/v1/custom.scheduler.testsuite.yaml | 2 +- .../github.com/openshift/api/config/v1/doc.go | 1 + .../openshift/api/config/v1/feature_gates.go | 907 +++---- .../config/v1/stable.apiserver.testsuite.yaml | 2 +- ...table.authentication.single.testsuite.yaml | 21 + .../v1/stable.authentication.testsuite.yaml | 2 +- .../api/config/v1/stable.build.testsuite.yaml | 2 +- .../v1/stable.clusteroperator.testsuite.yaml | 2 +- .../v1/stable.clusterversion.testsuite.yaml | 2 +- .../config/v1/stable.console.testsuite.yaml | 2 +- .../api/config/v1/stable.dns.testsuite.yaml | 2 +- .../v1/stable.featuregate.testsuite.yaml | 2 +- ...e.hypershift.authentication.testsuite.yaml | 2 +- .../api/config/v1/stable.image.testsuite.yaml | 2 +- .../stable.imagecontentpolicy.testsuite.yaml | 2 +- ...stable.imagedigestmirrorset.testsuite.yaml | 2 +- .../stable.imagetagmirrorset.testsuite.yaml | 2 +- .../v1/stable.infrastructure.testsuite.yaml | 123 +- .../config/v1/stable.ingress.testsuite.yaml | 2 +- .../config/v1/stable.network.testsuite.yaml | 2 +- .../api/config/v1/stable.node.testsuite.yaml | 2 +- .../api/config/v1/stable.oauth.testsuite.yaml | 2 +- .../v1/stable.operatorhub.testsuite.yaml | 2 +- .../config/v1/stable.project.testsuite.yaml | 2 +- .../api/config/v1/stable.proxy.testsuite.yaml | 2 +- .../config/v1/stable.scheduler.testsuite.yaml | 2 +- .../v1/techpreview.apiserver.testsuite.yaml | 35 - ...eview.authentication.single.testsuite.yaml | 298 +++ .../techpreview.authentication.testsuite.yaml | 2 +- .../techpreview.clusterversion.testsuite.yaml | 2 +- .../config/v1/techpreview.dns.testsuite.yaml | 14 - .../techpreview.infrastructure.testsuite.yaml | 115 +- .../v1/techpreview.network.testsuite.yaml | 28 - .../v1/techpreview.scheduler.testsuite.yaml | 2 +- .../api/config/v1/types_apiserver.go | 5 + .../api/config/v1/types_authentication.go | 16 +- .../openshift/api/config/v1/types_build.go | 6 + .../api/config/v1/types_cluster_operator.go | 12 + .../api/config/v1/types_cluster_version.go | 14 +- .../openshift/api/config/v1/types_console.go | 5 + .../openshift/api/config/v1/types_dns.go | 5 + .../openshift/api/config/v1/types_feature.go | 178 +- .../openshift/api/config/v1/types_image.go | 5 + .../config/v1/types_image_content_policy.go | 5 + .../v1/types_image_digest_mirror_set.go | 5 + .../config/v1/types_image_tag_mirror_set.go | 5 + .../api/config/v1/types_infrastructure.go | 24 +- .../openshift/api/config/v1/types_ingress.go | 5 + .../openshift/api/config/v1/types_network.go | 5 + .../openshift/api/config/v1/types_node.go | 3 + .../openshift/api/config/v1/types_oauth.go | 5 + .../api/config/v1/types_operatorhub.go | 5 + .../openshift/api/config/v1/types_project.go | 5 + .../openshift/api/config/v1/types_proxy.go | 5 + .../api/config/v1/types_scheduling.go | 7 +- .../api/config/v1/types_tlssecurityprofile.go | 55 +- ..._generated.featuregated-crd-manifests.yaml | 491 ++++ .../v1/zz_generated.swagger_doc_generated.go | 8 +- .../v1alpha1/90_consoleplugin.crd.yaml | 374 --- .../stable.consoleplugin.testsuite.yaml | 2 +- .../console/v1alpha1/types_console_plugin.go | 8 + ..._generated.featuregated-crd-manifests.yaml | 24 + ...0000_03_security-openshift_01_scc.crd.yaml | 365 --- .../openshift/api/security/v1/generated.proto | 22 +- ....securitycontextconstraints.testsuite.yaml | 2 +- .../openshift/api/security/v1/types.go | 22 +- ..._generated.featuregated-crd-manifests.yaml | 58 + .../operators/v1alpha1/subscription_types.go | 7 + .../v1alpha1/zz_generated.deepcopy.go | 7 + .../pkg/apis/monitoring/register.go | 8 +- .../apis/monitoring/v1/alertmanager_types.go | 11 +- .../apis/monitoring/v1/podmonitor_types.go | 16 + .../pkg/apis/monitoring/v1/probe_types.go | 15 + .../apis/monitoring/v1/prometheus_types.go | 135 +- .../monitoring/v1/servicemonitor_types.go | 16 + .../pkg/apis/monitoring/v1/types.go | 75 +- .../monitoring/v1/zz_generated.deepcopy.go | 175 +- .../client_golang/prometheus/histogram.go | 56 +- .../client_golang/prometheus/labels.go | 2 + .../prometheus/process_collector_other.go | 4 +- .../prometheus/process_collector_wasip1.go | 26 + .../provider/interfaces/interfaces.go | 2 + .../v4/services/provider/pb/provider.pb.go | 135 +- .../v4/services/provider/pb/storageclient.go | 5 + .../grpc_binarylog_v1/binarylog.pb.go | 6 +- vendor/google.golang.org/grpc/clientconn.go | 26 +- .../grpc/encoding/proto/proto.go | 24 +- .../grpc/internal/binarylog/method_logger.go | 9 +- .../grpc/internal/binarylog/sink.go | 2 +- .../grpc/internal/grpcrand/grpcrand.go | 5 + .../grpc/internal/grpcrand/grpcrand_go1.21.go | 73 + .../grpc/internal/internal.go | 20 +- .../grpc/internal/pretty/pretty.go | 7 +- .../grpc/internal/resolver/unix/unix.go | 4 + .../grpc/internal/status/status.go | 15 +- ...ive_nonunix.go => tcp_keepalive_others.go} | 2 +- .../grpc/internal/tcp_keepalive_windows.go | 54 + .../grpc/internal/transport/controlbuf.go | 5 +- .../grpc/internal/transport/handler_server.go | 2 +- .../grpc/internal/transport/http2_client.go | 18 +- .../grpc/internal/transport/http2_server.go | 36 +- .../grpc/internal/transport/transport.go | 9 +- .../grpc/metadata/metadata.go | 13 +- .../grpc/resolver/resolver.go | 13 + .../grpc/resolver_wrapper.go | 1 + vendor/google.golang.org/grpc/rpc_util.go | 77 +- vendor/google.golang.org/grpc/server.go | 86 +- vendor/google.golang.org/grpc/stream.go | 9 +- vendor/google.golang.org/grpc/trace.go | 26 +- .../google.golang.org/grpc/trace_notrace.go | 52 + .../google.golang.org/grpc/trace_withtrace.go | 39 + vendor/google.golang.org/grpc/version.go | 2 +- vendor/google.golang.org/grpc/vet.sh | 10 +- .../protobuf/protoadapt/convert.go | 31 + .../apis/apiextensions/types_jsonschema.go | 31 + .../pkg/apis/apiextensions/v1/generated.pb.go | 429 ++-- .../pkg/apis/apiextensions/v1/generated.proto | 30 + .../apis/apiextensions/v1/types_jsonschema.go | 31 + .../v1/zz_generated.conversion.go | 2 + .../apiextensions/v1/zz_generated.deepcopy.go | 5 + .../apiextensions/v1beta1/generated.pb.go | 431 ++-- .../apiextensions/v1beta1/generated.proto | 30 + .../apiextensions/v1beta1/types_jsonschema.go | 31 + .../v1beta1/zz_generated.conversion.go | 2 + .../v1beta1/zz_generated.deepcopy.go | 5 + .../apiextensions/zz_generated.deepcopy.go | 5 + .../apiextensions/v1/validationrule.go | 9 + .../apiextensions/v1beta1/validationrule.go | 9 + vendor/modules.txt | 52 +- .../controller-runtime/.golangci.yml | 4 +- .../sigs.k8s.io/controller-runtime/RELEASE.md | 14 +- .../controller-runtime/pkg/cache/cache.go | 18 +- .../pkg/cache/delegating_by_gvk_cache.go | 8 + .../pkg/cache/informer_cache.go | 11 + .../pkg/cache/internal/cache_reader.go | 55 +- .../pkg/cache/internal/informers.go | 57 +- .../pkg/cache/multi_namespace_cache.go | 31 + .../pkg/client/apiutil/apimachinery.go | 21 - .../pkg/client/apiutil/restmapper.go | 87 +- .../controller-runtime/pkg/client/client.go | 18 +- .../controller-runtime/pkg/client/options.go | 5 +- .../controllerutil/controllerutil.go | 94 +- .../controller-runtime/pkg/envtest/crd.go | 23 +- .../controller-runtime/pkg/envtest/webhook.go | 10 +- .../pkg/handler/eventhandler.go | 2 +- .../pkg/internal/field/selector/utils.go | 16 +- .../pkg/internal/syncs/syncs.go | 38 + .../internal/testing/controlplane/kubectl.go | 1 + .../testing/process/procattr_other.go | 28 + .../internal/testing/process/procattr_unix.go | 33 + .../pkg/internal/testing/process/process.go | 4 + .../controller-runtime/pkg/manager/manager.go | 6 +- .../pkg/metrics/workqueue.go | 4 +- .../pkg/reconcile/reconcile.go | 34 +- .../pkg/webhook/admission/defaulter.go | 2 + .../pkg/webhook/admission/http.go | 52 +- .../pkg/webhook/admission/validator.go | 2 + .../pkg/webhook/admission/validator_custom.go | 1 - .../controller-runtime/pkg/webhook/alias.go | 2 + 228 files changed, 9281 insertions(+), 20048 deletions(-) create mode 100644 vendor/github.com/evanphx/json-patch/v5/internal/json/decode.go create mode 100644 vendor/github.com/evanphx/json-patch/v5/internal/json/encode.go create mode 100644 vendor/github.com/evanphx/json-patch/v5/internal/json/fold.go create mode 100644 vendor/github.com/evanphx/json-patch/v5/internal/json/fuzz.go create mode 100644 vendor/github.com/evanphx/json-patch/v5/internal/json/indent.go create mode 100644 vendor/github.com/evanphx/json-patch/v5/internal/json/scanner.go create mode 100644 vendor/github.com/evanphx/json-patch/v5/internal/json/stream.go create mode 100644 vendor/github.com/evanphx/json-patch/v5/internal/json/tables.go create mode 100644 vendor/github.com/evanphx/json-patch/v5/internal/json/tags.go delete mode 100644 vendor/github.com/golang/protobuf/jsonpb/decode.go delete mode 100644 vendor/github.com/golang/protobuf/jsonpb/encode.go delete mode 100644 vendor/github.com/golang/protobuf/jsonpb/json.go delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_00_cluster-version-operator_01_clusteroperator.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_00_cluster-version-operator_01_clusterversion-CustomNoUpgrade.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_00_cluster-version-operator_01_clusterversion-Default.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_00_cluster-version-operator_01_clusterversion-TechPreviewNoUpgrade.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_03_config-operator_01_proxy.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_03_marketplace-operator_01_operatorhub.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_apiserver-CustomNoUpgrade.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_apiserver-Default.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_apiserver-TechPreviewNoUpgrade.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_authentication.crd-CustomNoUpgrade.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_authentication.crd-Default-Hypershift.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_authentication.crd-Default-Hypershift.yaml-patch delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_authentication.crd-Default.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_authentication.crd-TechPreviewNoUpgrade.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_console.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_dns-CustomNoUpgrade.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_dns-Default.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_dns-TechPreviewNoUpgrade.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_featuregate.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_image.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_imagecontentpolicy.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_imagedigestmirrorset.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_imagetagmirrorset.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_infrastructure-CustomNoUpgrade.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_infrastructure-CustomNoUpgrade.crd.yaml-patch delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_infrastructure-Default.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_infrastructure-Default.crd.yaml-patch delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_infrastructure-TechPreviewNoUpgrade.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_infrastructure-TechPreviewNoUpgrade.crd.yaml-patch delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_ingress.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_network-CustomNoUpgrade.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_network-Default.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_network-TechPreviewNoUpgrade.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_node.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_oauth.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_project.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_scheduler-CustomNoUpgrade.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_scheduler-Default.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_scheduler-TechPreviewNoUpgrade.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/0000_10_openshift-controller-manager-operator_01_build.crd.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/custom.apiserver.testsuite.yaml create mode 100644 vendor/github.com/openshift/api/config/v1/custom.authentication.single.testsuite.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/custom.dns.testsuite.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/custom.network.testsuite.yaml create mode 100644 vendor/github.com/openshift/api/config/v1/stable.authentication.single.testsuite.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/techpreview.apiserver.testsuite.yaml create mode 100644 vendor/github.com/openshift/api/config/v1/techpreview.authentication.single.testsuite.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/techpreview.dns.testsuite.yaml delete mode 100644 vendor/github.com/openshift/api/config/v1/techpreview.network.testsuite.yaml create mode 100644 vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml delete mode 100644 vendor/github.com/openshift/api/console/v1alpha1/90_consoleplugin.crd.yaml create mode 100644 vendor/github.com/openshift/api/console/v1alpha1/zz_generated.featuregated-crd-manifests.yaml delete mode 100644 vendor/github.com/openshift/api/security/v1/0000_03_security-openshift_01_scc.crd.yaml create mode 100644 vendor/github.com/openshift/api/security/v1/zz_generated.featuregated-crd-manifests.yaml create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/process_collector_wasip1.go create mode 100644 vendor/google.golang.org/grpc/internal/grpcrand/grpcrand_go1.21.go rename vendor/google.golang.org/grpc/internal/{tcp_keepalive_nonunix.go => tcp_keepalive_others.go} (96%) create mode 100644 vendor/google.golang.org/grpc/internal/tcp_keepalive_windows.go create mode 100644 vendor/google.golang.org/grpc/trace_notrace.go create mode 100644 vendor/google.golang.org/grpc/trace_withtrace.go create mode 100644 vendor/google.golang.org/protobuf/protoadapt/convert.go create mode 100644 vendor/sigs.k8s.io/controller-runtime/pkg/internal/syncs/syncs.go create mode 100644 vendor/sigs.k8s.io/controller-runtime/pkg/internal/testing/process/procattr_other.go create mode 100644 vendor/sigs.k8s.io/controller-runtime/pkg/internal/testing/process/procattr_unix.go diff --git a/go.mod b/go.mod index 68b1cce6..f383e681 100644 --- a/go.mod +++ b/go.mod @@ -13,22 +13,22 @@ require ( github.com/go-logr/logr v1.4.1 github.com/kubernetes-csi/external-snapshotter/client/v6 v6.3.0 github.com/onsi/ginkgo v1.16.5 - github.com/onsi/gomega v1.30.0 - github.com/openshift/api v0.0.0-20240301093301-ce10821dc999 - github.com/operator-framework/api v0.20.0 + github.com/onsi/gomega v1.32.0 + github.com/openshift/api v0.0.0-20240323003854-2252c7adfb79 + github.com/operator-framework/api v0.22.0 github.com/pkg/errors v0.9.1 - github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.70.0 - github.com/red-hat-storage/ocs-operator/v4 v4.0.0-20240325171742-7a2177d09b00 + github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.72.0 + github.com/red-hat-storage/ocs-operator/v4 v4.0.0-20240401090154-4689ec087b5b github.com/stretchr/testify v1.9.0 - google.golang.org/grpc v1.60.0 + google.golang.org/grpc v1.62.1 gopkg.in/yaml.v2 v2.4.0 - k8s.io/api v0.29.2 - k8s.io/apiextensions-apiserver v0.28.4 - k8s.io/apimachinery v0.29.2 - k8s.io/client-go v0.29.2 + k8s.io/api v0.29.3 + k8s.io/apiextensions-apiserver v0.29.2 + k8s.io/apimachinery v0.29.3 + k8s.io/client-go v0.29.3 k8s.io/klog/v2 v2.120.1 - k8s.io/utils v0.0.0-20240102154912-e7106e64919e - sigs.k8s.io/controller-runtime v0.16.3 + k8s.io/utils v0.0.0-20240310230437-4693a0247e57 + sigs.k8s.io/controller-runtime v0.17.2 ) require ( @@ -37,7 +37,7 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.11.3 // indirect - github.com/evanphx/json-patch/v5 v5.7.0 // indirect + github.com/evanphx/json-patch/v5 v5.8.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.20.3 // indirect @@ -45,7 +45,7 @@ require ( github.com/go-openapi/swag v0.22.10 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect @@ -60,7 +60,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect @@ -77,12 +77,12 @@ require ( golang.org/x/time v0.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/component-base v0.28.4 // indirect + k8s.io/component-base v0.29.2 // indirect k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect diff --git a/go.sum b/go.sum index 128a3b21..69129423 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/emicklei/go-restful/v3 v3.11.3 h1:yagOQz/38xJmcNeZJtrUcKjkHRltIaIFXKW github.com/emicklei/go-restful/v3 v3.11.3/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc= -github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/evanphx/json-patch/v5 v5.8.0 h1:lRj6N9Nci7MvzrXuX6HFzU8XjmhPiXPlsKEy1u0KQro= +github.com/evanphx/json-patch/v5 v5.8.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= @@ -44,8 +44,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -95,33 +95,33 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= -github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= +github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8= +github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/openshift/api v0.0.0-20240301093301-ce10821dc999 h1:+S998xHiJApsJZjRAO8wyedU9GfqFd8mtwWly6LqHDo= -github.com/openshift/api v0.0.0-20240301093301-ce10821dc999/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4= -github.com/operator-framework/api v0.20.0 h1:A2YCRhr+6s0k3pRJacnwjh1Ue8BqjIGuQ2jvPg9XCB4= -github.com/operator-framework/api v0.20.0/go.mod h1:rXPOhrQ6mMeXqCmpDgt1ALoar9ZlHL+Iy5qut9R99a4= +github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= +github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= +github.com/openshift/api v0.0.0-20240323003854-2252c7adfb79 h1:ShXEPrqDUU9rUbvoIhOmQI8D6yHQdklMUks9ZVILTNE= +github.com/openshift/api v0.0.0-20240323003854-2252c7adfb79/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4= +github.com/operator-framework/api v0.22.0 h1:UZSn+iaQih4rCReezOnWTTJkMyawwV5iLnIItaOzytY= +github.com/operator-framework/api v0.22.0/go.mod h1:p/7YDbr+n4fmESfZ47yLAV1SvkfE6NU2aX8KhcfI0GA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.70.0 h1:CFTvpkpVP4EXXZuaZuxpikAoma8xVha/IZKMDc9lw+Y= -github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.70.0/go.mod h1:npfc20mPOAu7ViOVnATVMbI7PoXvW99EzgJVqkAomIQ= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.72.0 h1:9h7PxMhT1S8lOdadEKJnBh3ELMdO60XkoDV98grYjuM= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.72.0/go.mod h1:4FiLCL664L4dNGeqZewiiD0NS7hhqi/CxyM4UOq5dfM= +github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= +github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/red-hat-storage/ocs-operator/v4 v4.0.0-20240325171742-7a2177d09b00 h1:XNUvXtgCSvj/dOWKUXOmzX/a7+cCAhdFilxc+MhO0TY= -github.com/red-hat-storage/ocs-operator/v4 v4.0.0-20240325171742-7a2177d09b00/go.mod h1:cE35IBM6w9KQfLbmJBR8b/jhoitTkvjPBb/Yp6QQnKI= +github.com/red-hat-storage/ocs-operator/v4 v4.0.0-20240401090154-4689ec087b5b h1:V+a1aMo2gOAMShZ0iKkchw4KrdZgSL4vNh/gNQee0Ow= +github.com/red-hat-storage/ocs-operator/v4 v4.0.0-20240401090154-4689ec087b5b/go.mod h1:e4AElguwRgtyGEW7JtfJvphjYbcYG4hlpvwDYrQFGi8= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= @@ -137,8 +137,8 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= @@ -213,10 +213,10 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= -google.golang.org/grpc v1.60.0 h1:6FQAR0kM31P6MRdeluor2w2gPaS4SVNrD/DNTxrQ15k= -google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= +google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -244,24 +244,24 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A= -k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0= -k8s.io/apiextensions-apiserver v0.28.4 h1:AZpKY/7wQ8n+ZYDtNHbAJBb+N4AXXJvyZx6ww6yAJvU= -k8s.io/apiextensions-apiserver v0.28.4/go.mod h1:pgQIZ1U8eJSMQcENew/0ShUTlePcSGFq6dxSxf2mwPM= -k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8= -k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= -k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg= -k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA= -k8s.io/component-base v0.28.4 h1:c/iQLWPdUgI90O+T9TeECg8o7N3YJTiuz2sKxILYcYo= -k8s.io/component-base v0.28.4/go.mod h1:m9hR0uvqXDybiGL2nf/3Lf0MerAfQXzkfWhUY58JUbU= +k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= +k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= +k8s.io/apiextensions-apiserver v0.29.2 h1:UK3xB5lOWSnhaCk0RFZ0LUacPZz9RY4wi/yt2Iu+btg= +k8s.io/apiextensions-apiserver v0.29.2/go.mod h1:aLfYjpA5p3OwtqNXQFkhJ56TB+spV8Gc4wfMhUA3/b8= +k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= +k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= +k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= +k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= +k8s.io/component-base v0.29.2 h1:lpiLyuvPA9yV1aQwGLENYyK7n/8t6l3nn3zAtFTJYe8= +k8s.io/component-base v0.29.2/go.mod h1:BfB3SLrefbZXiBfbM+2H1dlat21Uewg/5qtKOl8degM= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ= -k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4= -sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= +k8s.io/utils v0.0.0-20240310230437-4693a0247e57 h1:gbqbevonBh57eILzModw6mrkbwM0gQBEuevE/AaBsHY= +k8s.io/utils v0.0.0-20240310230437-4693a0247e57/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.17.2 h1:FwHwD1CTUemg0pW2otk7/U5/i5m2ymzvOXdbeGOUvw0= +sigs.k8s.io/controller-runtime v0.17.2/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= diff --git a/vendor/github.com/evanphx/json-patch/v5/internal/json/decode.go b/vendor/github.com/evanphx/json-patch/v5/internal/json/decode.go new file mode 100644 index 00000000..e9bb0efe --- /dev/null +++ b/vendor/github.com/evanphx/json-patch/v5/internal/json/decode.go @@ -0,0 +1,1385 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Represents JSON data structure using native Go types: booleans, floats, +// strings, arrays, and maps. + +package json + +import ( + "encoding" + "encoding/base64" + "fmt" + "reflect" + "strconv" + "strings" + "sync" + "unicode" + "unicode/utf16" + "unicode/utf8" +) + +// Unmarshal parses the JSON-encoded data and stores the result +// in the value pointed to by v. If v is nil or not a pointer, +// Unmarshal returns an InvalidUnmarshalError. +// +// Unmarshal uses the inverse of the encodings that +// Marshal uses, allocating maps, slices, and pointers as necessary, +// with the following additional rules: +// +// To unmarshal JSON into a pointer, Unmarshal first handles the case of +// the JSON being the JSON literal null. In that case, Unmarshal sets +// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into +// the value pointed at by the pointer. If the pointer is nil, Unmarshal +// allocates a new value for it to point to. +// +// To unmarshal JSON into a value implementing the Unmarshaler interface, +// Unmarshal calls that value's UnmarshalJSON method, including +// when the input is a JSON null. +// Otherwise, if the value implements encoding.TextUnmarshaler +// and the input is a JSON quoted string, Unmarshal calls that value's +// UnmarshalText method with the unquoted form of the string. +// +// To unmarshal JSON into a struct, Unmarshal matches incoming object +// keys to the keys used by Marshal (either the struct field name or its tag), +// preferring an exact match but also accepting a case-insensitive match. By +// default, object keys which don't have a corresponding struct field are +// ignored (see Decoder.DisallowUnknownFields for an alternative). +// +// To unmarshal JSON into an interface value, +// Unmarshal stores one of these in the interface value: +// +// bool, for JSON booleans +// float64, for JSON numbers +// string, for JSON strings +// []interface{}, for JSON arrays +// map[string]interface{}, for JSON objects +// nil for JSON null +// +// To unmarshal a JSON array into a slice, Unmarshal resets the slice length +// to zero and then appends each element to the slice. +// As a special case, to unmarshal an empty JSON array into a slice, +// Unmarshal replaces the slice with a new empty slice. +// +// To unmarshal a JSON array into a Go array, Unmarshal decodes +// JSON array elements into corresponding Go array elements. +// If the Go array is smaller than the JSON array, +// the additional JSON array elements are discarded. +// If the JSON array is smaller than the Go array, +// the additional Go array elements are set to zero values. +// +// To unmarshal a JSON object into a map, Unmarshal first establishes a map to +// use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal +// reuses the existing map, keeping existing entries. Unmarshal then stores +// key-value pairs from the JSON object into the map. The map's key type must +// 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. +// If no more serious errors are encountered, Unmarshal returns +// an UnmarshalTypeError describing the earliest such error. In any +// case, it's not guaranteed that all the remaining fields following +// the problematic one will be unmarshaled into the target object. +// +// 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 +// 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) error { + // Check for well-formedness. + // Avoids filling out half a data structure + // before discovering a JSON syntax error. + d := ds.Get().(*decodeState) + defer ds.Put(d) + //var d decodeState + d.useNumber = true + err := checkValid(data, &d.scan) + if err != nil { + return err + } + + d.init(data) + return d.unmarshal(v) +} + +var ds = sync.Pool{ + New: func() any { + return new(decodeState) + }, +} + +func UnmarshalWithKeys(data []byte, v any) ([]string, error) { + // Check for well-formedness. + // Avoids filling out half a data structure + // before discovering a JSON syntax error. + + d := ds.Get().(*decodeState) + defer ds.Put(d) + //var d decodeState + d.useNumber = true + err := checkValid(data, &d.scan) + if err != nil { + return nil, err + } + + d.init(data) + err = d.unmarshal(v) + if err != nil { + return nil, err + } + + return d.lastKeys, nil +} + +func UnmarshalValid(data []byte, v any) error { + // Check for well-formedness. + // Avoids filling out half a data structure + // before discovering a JSON syntax error. + d := ds.Get().(*decodeState) + defer ds.Put(d) + //var d decodeState + d.useNumber = true + + d.init(data) + return d.unmarshal(v) +} + +func UnmarshalValidWithKeys(data []byte, v any) ([]string, error) { + // Check for well-formedness. + // Avoids filling out half a data structure + // before discovering a JSON syntax error. + + d := ds.Get().(*decodeState) + defer ds.Put(d) + //var d decodeState + d.useNumber = true + + d.init(data) + err := d.unmarshal(v) + if err != nil { + return nil, err + } + + return d.lastKeys, nil +} + +// Unmarshaler is the interface implemented by types +// that can unmarshal a JSON description of themselves. +// The input can be assumed to be a valid encoding of +// a JSON value. UnmarshalJSON must copy the JSON data +// if it wishes to retain the data after returning. +// +// By convention, to approximate the behavior of Unmarshal itself, +// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op. +type Unmarshaler interface { + UnmarshalJSON([]byte) error +} + +// An UnmarshalTypeError describes a JSON value that was +// not appropriate for a value of a specific Go type. +type UnmarshalTypeError struct { + Value string // description of JSON value - "bool", "array", "number -5" + Type reflect.Type // type of Go value it could not be assigned to + Offset int64 // error occurred after reading Offset bytes + Struct string // name of the struct type containing the field + Field string // the full path from root node to the field +} + +func (e *UnmarshalTypeError) Error() string { + if e.Struct != "" || e.Field != "" { + return "json: cannot unmarshal " + e.Value + " into Go struct field " + e.Struct + "." + e.Field + " of type " + e.Type.String() + } + return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String() +} + +// An UnmarshalFieldError describes a JSON object key that +// led to an unexported (and therefore unwritable) struct field. +// +// Deprecated: No longer used; kept for compatibility. +type UnmarshalFieldError struct { + Key string + Type reflect.Type + Field reflect.StructField +} + +func (e *UnmarshalFieldError) Error() string { + return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String() +} + +// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal. +// (The argument to Unmarshal must be a non-nil pointer.) +type InvalidUnmarshalError struct { + Type reflect.Type +} + +func (e *InvalidUnmarshalError) Error() string { + if e.Type == nil { + return "json: Unmarshal(nil)" + } + + if e.Type.Kind() != reflect.Pointer { + return "json: Unmarshal(non-pointer " + e.Type.String() + ")" + } + return "json: Unmarshal(nil " + e.Type.String() + ")" +} + +func (d *decodeState) unmarshal(v any) error { + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Pointer || rv.IsNil() { + return &InvalidUnmarshalError{reflect.TypeOf(v)} + } + + d.scan.reset() + d.scanWhile(scanSkipSpace) + // We decode rv not rv.Elem because the Unmarshaler interface + // test must be applied at the top level of the value. + err := d.value(rv) + if err != nil { + return d.addErrorContext(err) + } + return d.savedError +} + +// A Number represents a JSON number literal. +type Number string + +// String returns the literal text of the number. +func (n Number) String() string { return string(n) } + +// Float64 returns the number as a float64. +func (n Number) Float64() (float64, error) { + return strconv.ParseFloat(string(n), 64) +} + +// Int64 returns the number as an int64. +func (n Number) Int64() (int64, error) { + return strconv.ParseInt(string(n), 10, 64) +} + +// An errorContext provides context for type errors during decoding. +type errorContext struct { + Struct reflect.Type + FieldStack []string +} + +// decodeState represents the state while decoding a JSON value. +type decodeState struct { + data []byte + off int // next read offset in data + opcode int // last read result + scan scanner + errorContext *errorContext + savedError error + useNumber bool + disallowUnknownFields bool + lastKeys []string +} + +// readIndex returns the position of the last byte read. +func (d *decodeState) readIndex() int { + return d.off - 1 +} + +// phasePanicMsg is used as a panic message when we end up with something that +// shouldn't happen. It can indicate a bug in the JSON decoder, or that +// something is editing the data slice while the decoder executes. +const phasePanicMsg = "JSON decoder out of sync - data changing underfoot?" + +func (d *decodeState) init(data []byte) *decodeState { + d.data = data + d.off = 0 + d.savedError = nil + if d.errorContext != nil { + d.errorContext.Struct = nil + // Reuse the allocated space for the FieldStack slice. + d.errorContext.FieldStack = d.errorContext.FieldStack[:0] + } + return d +} + +// saveError saves the first err it is called with, +// for reporting at the end of the unmarshal. +func (d *decodeState) saveError(err error) { + if d.savedError == nil { + d.savedError = d.addErrorContext(err) + } +} + +// addErrorContext returns a new error enhanced with information from d.errorContext +func (d *decodeState) addErrorContext(err error) error { + if d.errorContext != nil && (d.errorContext.Struct != nil || len(d.errorContext.FieldStack) > 0) { + switch err := err.(type) { + case *UnmarshalTypeError: + err.Struct = d.errorContext.Struct.Name() + err.Field = strings.Join(d.errorContext.FieldStack, ".") + } + } + return err +} + +// skip scans to the end of what was started. +func (d *decodeState) skip() { + s, data, i := &d.scan, d.data, d.off + depth := len(s.parseState) + for { + op := s.step(s, data[i]) + i++ + if len(s.parseState) < depth { + d.off = i + d.opcode = op + return + } + } +} + +// scanNext processes the byte at d.data[d.off]. +func (d *decodeState) scanNext() { + if d.off < len(d.data) { + d.opcode = d.scan.step(&d.scan, d.data[d.off]) + d.off++ + } else { + d.opcode = d.scan.eof() + d.off = len(d.data) + 1 // mark processed EOF with len+1 + } +} + +// scanWhile processes bytes in d.data[d.off:] until it +// receives a scan code not equal to op. +func (d *decodeState) scanWhile(op int) { + s, data, i := &d.scan, d.data, d.off + for i < len(data) { + newOp := s.step(s, data[i]) + i++ + if newOp != op { + d.opcode = newOp + d.off = i + return + } + } + + d.off = len(data) + 1 // mark processed EOF with len+1 + d.opcode = d.scan.eof() +} + +// rescanLiteral is similar to scanWhile(scanContinue), but it specialises the +// common case where we're decoding a literal. The decoder scans the input +// twice, once for syntax errors and to check the length of the value, and the +// second to perform the decoding. +// +// Only in the second step do we use decodeState to tokenize literals, so we +// know there aren't any syntax errors. We can take advantage of that knowledge, +// and scan a literal's bytes much more quickly. +func (d *decodeState) rescanLiteral() { + data, i := d.data, d.off +Switch: + switch data[i-1] { + case '"': // string + for ; i < len(data); i++ { + switch data[i] { + case '\\': + i++ // escaped char + case '"': + i++ // tokenize the closing quote too + break Switch + } + } + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-': // number + for ; i < len(data); i++ { + switch data[i] { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '.', 'e', 'E', '+', '-': + default: + break Switch + } + } + case 't': // true + i += len("rue") + case 'f': // false + i += len("alse") + case 'n': // null + i += len("ull") + } + if i < len(data) { + d.opcode = stateEndValue(&d.scan, data[i]) + } else { + d.opcode = scanEnd + } + d.off = i + 1 +} + +// value consumes a JSON value from d.data[d.off-1:], decoding into v, and +// reads the following byte ahead. If v is invalid, the value is discarded. +// The first byte of the value has been read already. +func (d *decodeState) value(v reflect.Value) error { + switch d.opcode { + default: + panic(phasePanicMsg) + + case scanBeginArray: + if v.IsValid() { + if err := d.array(v); err != nil { + return err + } + } else { + d.skip() + } + d.scanNext() + + case scanBeginObject: + if v.IsValid() { + if err := d.object(v); err != nil { + return err + } + } else { + d.skip() + } + d.scanNext() + + case scanBeginLiteral: + // All bytes inside literal return scanContinue op code. + start := d.readIndex() + d.rescanLiteral() + + if v.IsValid() { + if err := d.literalStore(d.data[start:d.readIndex()], v, false); err != nil { + return err + } + } + } + return nil +} + +type unquotedValue struct{} + +// valueQuoted is like value but decodes a +// quoted string literal or literal null into an interface value. +// If it finds anything other than a quoted string literal or null, +// valueQuoted returns unquotedValue{}. +func (d *decodeState) valueQuoted() any { + switch d.opcode { + default: + panic(phasePanicMsg) + + case scanBeginArray, scanBeginObject: + d.skip() + d.scanNext() + + case scanBeginLiteral: + v := d.literalInterface() + switch v.(type) { + case nil, string: + return v + } + } + return unquotedValue{} +} + +// indirect walks down v allocating pointers as needed, +// until it gets to a non-pointer. +// If it encounters an Unmarshaler, indirect stops and returns that. +// If decodingNull is true, indirect stops at the first settable pointer so it +// can be set to nil. +func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { + // Issue #24153 indicates that it is generally not a guaranteed property + // that you may round-trip a reflect.Value by calling Value.Addr().Elem() + // and expect the value to still be settable for values derived from + // unexported embedded struct fields. + // + // The logic below effectively does this when it first addresses the value + // (to satisfy possible pointer methods) and continues to dereference + // subsequent pointers as necessary. + // + // After the first round-trip, we set v back to the original value to + // preserve the original RW flags contained in reflect.Value. + v0 := v + haveAddr := false + + // If v is a named type and is addressable, + // start with its address, so that if the type has pointer methods, + // we find them. + if v.Kind() != reflect.Pointer && v.Type().Name() != "" && v.CanAddr() { + haveAddr = true + v = v.Addr() + } + for { + // Load value from interface, but only if the result will be + // usefully addressable. + if v.Kind() == reflect.Interface && !v.IsNil() { + e := v.Elem() + if e.Kind() == reflect.Pointer && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Pointer) { + haveAddr = false + v = e + continue + } + } + + if v.Kind() != reflect.Pointer { + break + } + + if decodingNull && v.CanSet() { + break + } + + // Prevent infinite loop if v is an interface pointing to its own address: + // var v interface{} + // v = &v + if v.Elem().Kind() == reflect.Interface && v.Elem().Elem() == v { + v = v.Elem() + break + } + if v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) + } + if v.Type().NumMethod() > 0 && v.CanInterface() { + if u, ok := v.Interface().(Unmarshaler); ok { + return u, nil, reflect.Value{} + } + if !decodingNull { + if u, ok := v.Interface().(encoding.TextUnmarshaler); ok { + return nil, u, reflect.Value{} + } + } + } + + if haveAddr { + v = v0 // restore original value after round-trip Value.Addr().Elem() + haveAddr = false + } else { + v = v.Elem() + } + } + return nil, nil, v +} + +// array consumes an array from d.data[d.off-1:], decoding into v. +// The first byte of the array ('[') has been read already. +func (d *decodeState) array(v reflect.Value) error { + // Check for unmarshaler. + u, ut, pv := indirect(v, false) + if u != nil { + start := d.readIndex() + d.skip() + return u.UnmarshalJSON(d.data[start:d.off]) + } + if ut != nil { + d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)}) + d.skip() + return nil + } + v = pv + + // Check type of target. + switch v.Kind() { + case reflect.Interface: + if v.NumMethod() == 0 { + // Decoding into nil interface? Switch to non-reflect code. + ai := d.arrayInterface() + v.Set(reflect.ValueOf(ai)) + return nil + } + // Otherwise it's invalid. + fallthrough + default: + d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)}) + d.skip() + return nil + case reflect.Array, reflect.Slice: + break + } + + i := 0 + for { + // Look ahead for ] - can only happen on first iteration. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndArray { + break + } + + // Get element of array, growing if necessary. + if v.Kind() == reflect.Slice { + // Grow slice if necessary + if i >= v.Cap() { + newcap := v.Cap() + v.Cap()/2 + if newcap < 4 { + newcap = 4 + } + newv := reflect.MakeSlice(v.Type(), v.Len(), newcap) + reflect.Copy(newv, v) + v.Set(newv) + } + if i >= v.Len() { + v.SetLen(i + 1) + } + } + + if i < v.Len() { + // Decode into element. + if err := d.value(v.Index(i)); err != nil { + return err + } + } else { + // Ran out of fixed array: skip. + if err := d.value(reflect.Value{}); err != nil { + return err + } + } + i++ + + // Next token must be , or ]. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndArray { + break + } + if d.opcode != scanArrayValue { + panic(phasePanicMsg) + } + } + + if i < v.Len() { + if v.Kind() == reflect.Array { + // Array. Zero the rest. + z := reflect.Zero(v.Type().Elem()) + for ; i < v.Len(); i++ { + v.Index(i).Set(z) + } + } else { + v.SetLen(i) + } + } + if i == 0 && v.Kind() == reflect.Slice { + v.Set(reflect.MakeSlice(v.Type(), 0, 0)) + } + return nil +} + +var nullLiteral = []byte("null") +var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() + +// object consumes an object from d.data[d.off-1:], decoding into v. +// The first byte ('{') of the object has been read already. +func (d *decodeState) object(v reflect.Value) error { + // Check for unmarshaler. + u, ut, pv := indirect(v, false) + if u != nil { + start := d.readIndex() + d.skip() + return u.UnmarshalJSON(d.data[start:d.off]) + } + if ut != nil { + d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)}) + d.skip() + return nil + } + v = pv + t := v.Type() + + // Decoding into nil interface? Switch to non-reflect code. + if v.Kind() == reflect.Interface && v.NumMethod() == 0 { + oi := d.objectInterface() + v.Set(reflect.ValueOf(oi)) + return nil + } + + var fields structFields + + // Check type of target: + // struct or + // map[T1]T2 where T1 is string, an integer type, + // or an encoding.TextUnmarshaler + switch v.Kind() { + case reflect.Map: + // Map key must either have string kind, have an integer kind, + // or be an encoding.TextUnmarshaler. + switch t.Key().Kind() { + case reflect.String, + reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + default: + if !reflect.PointerTo(t.Key()).Implements(textUnmarshalerType) { + d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)}) + d.skip() + return nil + } + } + if v.IsNil() { + v.Set(reflect.MakeMap(t)) + } + case reflect.Struct: + fields = cachedTypeFields(t) + // ok + default: + d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)}) + d.skip() + return nil + } + + var mapElem reflect.Value + var origErrorContext errorContext + if d.errorContext != nil { + origErrorContext = *d.errorContext + } + + var keys []string + + for { + // Read opening " of string key or closing }. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndObject { + // closing } - can only happen on first iteration. + break + } + if d.opcode != scanBeginLiteral { + panic(phasePanicMsg) + } + + // Read key. + start := d.readIndex() + d.rescanLiteral() + item := d.data[start:d.readIndex()] + key, ok := unquoteBytes(item) + if !ok { + panic(phasePanicMsg) + } + + keys = append(keys, string(key)) + + // Figure out field corresponding to key. + var subv reflect.Value + destring := false // whether the value is wrapped in a string to be decoded first + + if v.Kind() == reflect.Map { + elemType := t.Elem() + if !mapElem.IsValid() { + mapElem = reflect.New(elemType).Elem() + } else { + mapElem.Set(reflect.Zero(elemType)) + } + subv = mapElem + } else { + var f *field + if i, ok := fields.nameIndex[string(key)]; ok { + // Found an exact name match. + f = &fields.list[i] + } else { + // Fall back to the expensive case-insensitive + // linear search. + for i := range fields.list { + ff := &fields.list[i] + if ff.equalFold(ff.nameBytes, key) { + f = ff + break + } + } + } + if f != nil { + subv = v + destring = f.quoted + for _, i := range f.index { + if subv.Kind() == reflect.Pointer { + if subv.IsNil() { + // If a struct embeds a pointer to an unexported type, + // it is not possible to set a newly allocated value + // since the field is unexported. + // + // See https://golang.org/issue/21357 + if !subv.CanSet() { + d.saveError(fmt.Errorf("json: cannot set embedded pointer to unexported struct: %v", subv.Type().Elem())) + // Invalidate subv to ensure d.value(subv) skips over + // the JSON value without assigning it to subv. + subv = reflect.Value{} + destring = false + break + } + subv.Set(reflect.New(subv.Type().Elem())) + } + subv = subv.Elem() + } + subv = subv.Field(i) + } + if d.errorContext == nil { + d.errorContext = new(errorContext) + } + d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name) + d.errorContext.Struct = t + } else if d.disallowUnknownFields { + d.saveError(fmt.Errorf("json: unknown field %q", key)) + } + } + + // Read : before value. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode != scanObjectKey { + panic(phasePanicMsg) + } + d.scanWhile(scanSkipSpace) + + if destring { + switch qv := d.valueQuoted().(type) { + case nil: + if err := d.literalStore(nullLiteral, subv, false); err != nil { + return err + } + case string: + if err := d.literalStore([]byte(qv), subv, true); err != nil { + return err + } + default: + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type())) + } + } else { + if err := d.value(subv); err != nil { + return err + } + } + + // Write value back to map; + // if using struct, subv points into struct already. + if v.Kind() == reflect.Map { + kt := t.Key() + var kv reflect.Value + switch { + case reflect.PointerTo(kt).Implements(textUnmarshalerType): + kv = reflect.New(kt) + if err := d.literalStore(item, kv, true); err != nil { + return err + } + kv = kv.Elem() + case kt.Kind() == reflect.String: + kv = reflect.ValueOf(key).Convert(kt) + default: + switch kt.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + s := string(key) + n, err := strconv.ParseInt(s, 10, 64) + if err != nil || reflect.Zero(kt).OverflowInt(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)}) + break + } + kv = reflect.ValueOf(n).Convert(kt) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + s := string(key) + n, err := strconv.ParseUint(s, 10, 64) + if err != nil || reflect.Zero(kt).OverflowUint(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)}) + break + } + kv = reflect.ValueOf(n).Convert(kt) + default: + panic("json: Unexpected key type") // should never occur + } + } + if kv.IsValid() { + v.SetMapIndex(kv, subv) + } + } + + // Next token must be , or }. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.errorContext != nil { + // Reset errorContext to its original state. + // Keep the same underlying array for FieldStack, to reuse the + // space and avoid unnecessary allocs. + d.errorContext.FieldStack = d.errorContext.FieldStack[:len(origErrorContext.FieldStack)] + d.errorContext.Struct = origErrorContext.Struct + } + if d.opcode == scanEndObject { + break + } + if d.opcode != scanObjectValue { + panic(phasePanicMsg) + } + } + + if v.Kind() == reflect.Map { + d.lastKeys = keys + } + return nil +} + +// convertNumber converts the number literal s to a float64 or a Number +// depending on the setting of d.useNumber. +func (d *decodeState) convertNumber(s string) (any, error) { + if d.useNumber { + return Number(s), nil + } + f, err := strconv.ParseFloat(s, 64) + if err != nil { + return nil, &UnmarshalTypeError{Value: "number " + s, Type: reflect.TypeOf(0.0), Offset: int64(d.off)} + } + return f, nil +} + +var numberType = reflect.TypeOf(Number("")) + +// literalStore decodes a literal stored in item into v. +// +// fromQuoted indicates whether this literal came from unwrapping a +// string from the ",string" struct tag option. this is used only to +// produce more helpful error messages. +func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) error { + // Check for unmarshaler. + if len(item) == 0 { + //Empty string given + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + return nil + } + isNull := item[0] == 'n' // null + u, ut, pv := indirect(v, isNull) + if u != nil { + return u.UnmarshalJSON(item) + } + if ut != nil { + if item[0] != '"' { + if fromQuoted { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + return nil + } + val := "number" + switch item[0] { + case 'n': + val = "null" + case 't', 'f': + val = "bool" + } + d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())}) + return nil + } + s, ok := unquoteBytes(item) + if !ok { + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + panic(phasePanicMsg) + } + return ut.UnmarshalText(s) + } + + v = pv + + switch c := item[0]; c { + case 'n': // null + // The main parser checks that only true and false can reach here, + // but if this was a quoted string input, it could be anything. + if fromQuoted && string(item) != "null" { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + break + } + switch v.Kind() { + case reflect.Interface, reflect.Pointer, reflect.Map, reflect.Slice: + v.Set(reflect.Zero(v.Type())) + // otherwise, ignore null for primitives/string + } + case 't', 'f': // true, false + value := item[0] == 't' + // The main parser checks that only true and false can reach here, + // but if this was a quoted string input, it could be anything. + if fromQuoted && string(item) != "true" && string(item) != "false" { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + break + } + switch v.Kind() { + default: + if fromQuoted { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + } else { + d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())}) + } + case reflect.Bool: + v.SetBool(value) + case reflect.Interface: + if v.NumMethod() == 0 { + v.Set(reflect.ValueOf(value)) + } else { + d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())}) + } + } + + case '"': // string + s, ok := unquoteBytes(item) + if !ok { + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + panic(phasePanicMsg) + } + switch v.Kind() { + default: + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) + case reflect.Slice: + if v.Type().Elem().Kind() != reflect.Uint8 { + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) + n, err := base64.StdEncoding.Decode(b, s) + if err != nil { + d.saveError(err) + break + } + v.SetBytes(b[:n]) + case reflect.String: + if v.Type() == numberType && !isValidNumber(string(s)) { + return fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item) + } + v.SetString(string(s)) + case reflect.Interface: + if v.NumMethod() == 0 { + v.Set(reflect.ValueOf(string(s))) + } else { + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) + } + } + + default: // number + if c != '-' && (c < '0' || c > '9') { + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + panic(phasePanicMsg) + } + s := string(item) + switch v.Kind() { + default: + if v.Kind() == reflect.String && v.Type() == numberType { + // s must be a valid number, because it's + // already been tokenized. + v.SetString(s) + break + } + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}) + case reflect.Interface: + n, err := d.convertNumber(s) + if err != nil { + d.saveError(err) + break + } + if v.NumMethod() != 0 { + d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.Set(reflect.ValueOf(n)) + + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + n, err := strconv.ParseInt(s, 10, 64) + if err != nil || v.OverflowInt(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.SetInt(n) + + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + n, err := strconv.ParseUint(s, 10, 64) + if err != nil || v.OverflowUint(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.SetUint(n) + + case reflect.Float32, reflect.Float64: + n, err := strconv.ParseFloat(s, v.Type().Bits()) + if err != nil || v.OverflowFloat(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.SetFloat(n) + } + } + return nil +} + +// The xxxInterface routines build up a value to be stored +// in an empty interface. They are not strictly necessary, +// but they avoid the weight of reflection in this common case. + +// valueInterface is like value but returns interface{} +func (d *decodeState) valueInterface() (val any) { + switch d.opcode { + default: + panic(phasePanicMsg) + case scanBeginArray: + val = d.arrayInterface() + d.scanNext() + case scanBeginObject: + val = d.objectInterface() + d.scanNext() + case scanBeginLiteral: + val = d.literalInterface() + } + return +} + +// arrayInterface is like array but returns []interface{}. +func (d *decodeState) arrayInterface() []any { + var v = make([]any, 0) + for { + // Look ahead for ] - can only happen on first iteration. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndArray { + break + } + + v = append(v, d.valueInterface()) + + // Next token must be , or ]. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndArray { + break + } + if d.opcode != scanArrayValue { + panic(phasePanicMsg) + } + } + return v +} + +// objectInterface is like object but returns map[string]interface{}. +func (d *decodeState) objectInterface() map[string]any { + m := make(map[string]any) + for { + // Read opening " of string key or closing }. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndObject { + // closing } - can only happen on first iteration. + break + } + if d.opcode != scanBeginLiteral { + panic(phasePanicMsg) + } + + // Read string key. + start := d.readIndex() + d.rescanLiteral() + item := d.data[start:d.readIndex()] + key, ok := unquote(item) + if !ok { + panic(phasePanicMsg) + } + + // Read : before value. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode != scanObjectKey { + panic(phasePanicMsg) + } + d.scanWhile(scanSkipSpace) + + // Read value. + m[key] = d.valueInterface() + + // Next token must be , or }. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndObject { + break + } + if d.opcode != scanObjectValue { + panic(phasePanicMsg) + } + } + return m +} + +// literalInterface consumes and returns a literal from d.data[d.off-1:] and +// it reads the following byte ahead. The first byte of the literal has been +// read already (that's how the caller knows it's a literal). +func (d *decodeState) literalInterface() any { + // All bytes inside literal return scanContinue op code. + start := d.readIndex() + d.rescanLiteral() + + item := d.data[start:d.readIndex()] + + switch c := item[0]; c { + case 'n': // null + return nil + + case 't', 'f': // true, false + return c == 't' + + case '"': // string + s, ok := unquote(item) + if !ok { + panic(phasePanicMsg) + } + return s + + default: // number + if c != '-' && (c < '0' || c > '9') { + panic(phasePanicMsg) + } + n, err := d.convertNumber(string(item)) + if err != nil { + d.saveError(err) + } + return n + } +} + +// getu4 decodes \uXXXX from the beginning of s, returning the hex value, +// or it returns -1. +func getu4(s []byte) rune { + if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { + return -1 + } + var r rune + for _, c := range s[2:6] { + switch { + case '0' <= c && c <= '9': + c = c - '0' + case 'a' <= c && c <= 'f': + c = c - 'a' + 10 + case 'A' <= c && c <= 'F': + c = c - 'A' + 10 + default: + return -1 + } + r = r*16 + rune(c) + } + return r +} + +// unquote converts a quoted JSON string literal s into an actual string t. +// The rules are different than for Go, so cannot use strconv.Unquote. +func unquote(s []byte) (t string, ok bool) { + s, ok = unquoteBytes(s) + t = string(s) + return +} + +func unquoteBytes(s []byte) (t []byte, ok bool) { + if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { + return + } + s = s[1 : len(s)-1] + + // Check for unusual characters. If there are none, + // then no unquoting is needed, so return a slice of the + // original bytes. + r := 0 + for r < len(s) { + c := s[r] + if c == '\\' || c == '"' || c < ' ' { + break + } + if c < utf8.RuneSelf { + r++ + continue + } + rr, size := utf8.DecodeRune(s[r:]) + if rr == utf8.RuneError && size == 1 { + break + } + r += size + } + if r == len(s) { + return s, true + } + + b := make([]byte, len(s)+2*utf8.UTFMax) + w := copy(b, s[0:r]) + for r < len(s) { + // Out of room? Can only happen if s is full of + // malformed UTF-8 and we're replacing each + // byte with RuneError. + if w >= len(b)-2*utf8.UTFMax { + nb := make([]byte, (len(b)+utf8.UTFMax)*2) + copy(nb, b[0:w]) + b = nb + } + switch c := s[r]; { + case c == '\\': + r++ + if r >= len(s) { + return + } + switch s[r] { + default: + return + case '"', '\\', '/', '\'': + b[w] = s[r] + r++ + w++ + case 'b': + b[w] = '\b' + r++ + w++ + case 'f': + b[w] = '\f' + r++ + w++ + case 'n': + b[w] = '\n' + r++ + w++ + case 'r': + b[w] = '\r' + r++ + w++ + case 't': + b[w] = '\t' + r++ + w++ + case 'u': + r-- + rr := getu4(s[r:]) + if rr < 0 { + return + } + r += 6 + if utf16.IsSurrogate(rr) { + rr1 := getu4(s[r:]) + if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { + // A valid pair; consume. + r += 6 + w += utf8.EncodeRune(b[w:], dec) + break + } + // Invalid surrogate; fall back to replacement rune. + rr = unicode.ReplacementChar + } + w += utf8.EncodeRune(b[w:], rr) + } + + // Quote, control characters are invalid. + case c == '"', c < ' ': + return + + // ASCII + case c < utf8.RuneSelf: + b[w] = c + r++ + w++ + + // Coerce to well-formed UTF-8. + default: + rr, size := utf8.DecodeRune(s[r:]) + r += size + w += utf8.EncodeRune(b[w:], rr) + } + } + return b[0:w], true +} diff --git a/vendor/github.com/evanphx/json-patch/v5/internal/json/encode.go b/vendor/github.com/evanphx/json-patch/v5/internal/json/encode.go new file mode 100644 index 00000000..a1819b16 --- /dev/null +++ b/vendor/github.com/evanphx/json-patch/v5/internal/json/encode.go @@ -0,0 +1,1473 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package json implements encoding and decoding of JSON as defined in +// RFC 7159. The mapping between JSON and Go values is described +// in the documentation for the Marshal and Unmarshal functions. +// +// See "JSON and Go" for an introduction to this package: +// https://golang.org/doc/articles/json_and_go.html +package json + +import ( + "bytes" + "encoding" + "encoding/base64" + "fmt" + "math" + "reflect" + "sort" + "strconv" + "strings" + "sync" + "unicode" + "unicode/utf8" +) + +// Marshal returns the JSON encoding of v. +// +// Marshal traverses the value v recursively. +// If an encountered value implements the Marshaler interface +// and is not a nil pointer, Marshal calls its MarshalJSON method +// to produce JSON. If no MarshalJSON method is present but the +// value implements encoding.TextMarshaler instead, Marshal calls +// its MarshalText method and encodes the result as a JSON string. +// The nil pointer exception is not strictly necessary +// but mimics a similar, necessary exception in the behavior of +// UnmarshalJSON. +// +// Otherwise, Marshal uses the following type-dependent default encodings: +// +// Boolean values encode as JSON booleans. +// +// Floating point, integer, and Number values encode as JSON numbers. +// +// String values encode as JSON strings coerced to valid UTF-8, +// replacing invalid bytes with the Unicode replacement rune. +// So that the JSON will be safe to embed inside HTML