diff --git a/api/v1alpha1/rollout_types.go b/api/v1alpha1/rollout_types.go index eccf21b..522d0af 100644 --- a/api/v1alpha1/rollout_types.go +++ b/api/v1alpha1/rollout_types.go @@ -1,5 +1,5 @@ /* -Copyright 2022 The Kruise Authors. +Copyright 2022 Kruise Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -253,24 +253,20 @@ type RolloutPhase string const ( // RolloutPhaseInitial indicates a rollout is Initial RolloutPhaseInitial RolloutPhase = "Initial" - // RolloutPhaseVerify indicates a rollout is verifying - RolloutPhaseVerify RolloutPhase = "Verifying" // RolloutPhaseHealthy indicates a rollout is healthy RolloutPhaseHealthy RolloutPhase = "Healthy" // RolloutPhasePreparing indicates a rollout is preparing for next progress. RolloutPhasePreparing RolloutPhase = "Preparing" // RolloutPhaseProgressing indicates a rollout is not yet healthy but still making progress towards a healthy state RolloutPhaseProgressing RolloutPhase = "Progressing" - // RolloutPhaseRollback indicates rollback - RolloutPhaseRollback RolloutPhase = "Rollback" // RolloutPhasePaused indicates a rollout is not yet healthy and will not make progress until unpaused RolloutPhasePaused RolloutPhase = "Paused" // RolloutPhaseFinalizing indicates a rollout is finalizing RolloutPhaseFinalizing RolloutPhase = "Finalizing" - // RolloutPhaseRollingBack indicates a rollout is rolling back - RolloutPhaseRollingBack RolloutPhase = "RollingBack" // RolloutPhaseTerminating indicates a rollout is terminated RolloutPhaseTerminating RolloutPhase = "Terminating" + // RolloutPhaseRollback indicates rollback + RolloutPhaseRollback RolloutPhase = "Rollback" // RolloutPhaseCompleted indicates a rollout is completed RolloutPhaseCompleted RolloutPhase = "Completed" // RolloutPhaseCancelled indicates a rollout is cancelled diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 1e51315..bffc973 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -104,11 +104,7 @@ func (in *BatchReleaseList) DeepCopyObject() runtime.Object { func (in *BatchReleaseSpec) DeepCopyInto(out *BatchReleaseSpec) { *out = *in out.Strategy = in.Strategy -<<<<<<< HEAD in.TargetRef.DeepCopyInto(&out.TargetRef) -======= - out.TargetRef = in.TargetRef ->>>>>>> 33cbc1d (add batchrelease controller) in.ReleasePlan.DeepCopyInto(&out.ReleasePlan) } diff --git a/config/crd/bases/rollouts.kruise.io_batchreleases.yaml b/config/crd/bases/rollouts.kruise.io_batchreleases.yaml index 85c6ac5..44e0d4c 100644 --- a/config/crd/bases/rollouts.kruise.io_batchreleases.yaml +++ b/config/crd/bases/rollouts.kruise.io_batchreleases.yaml @@ -109,6 +109,7 @@ spec: description: TargetRevisionName contains the name of the componentRevisionName that we need to upgrade to. properties: +<<<<<<< HEAD <<<<<<< HEAD type: description: workloadRef, revisionRef default is workloadRef @@ -142,12 +143,38 @@ spec: type: string name: description: Name of the referent +======= + type: + description: workloadRef, revisionRef default is workloadRef +>>>>>>> 42b951e (completed-v1) type: string + workloadRef: + description: WorkloadRef contains enough information to let you + identify a workload for Rollout Batch release of the bypass + properties: + apiVersion: + description: API Version of the referent + type: string + kind: + description: Kind of the referent + type: string + name: + description: Name of the referent + type: string + required: + - apiVersion + - kind + - name + type: object required: +<<<<<<< HEAD - apiVersion - kind - name >>>>>>> 33cbc1d (add batchrelease controller) +======= + - type +>>>>>>> 42b951e (completed-v1) type: object required: - releasePlan @@ -161,11 +188,16 @@ spec: description: Canary describes the state of the canary rollout properties: batchState: +<<<<<<< HEAD <<<<<<< HEAD description: ReleasingBatchState indicates the state of the current batch. ======= >>>>>>> 33cbc1d (add batchrelease controller) +======= + description: ReleasingBatchState indicates the state of the current + batch. +>>>>>>> 42b951e (completed-v1) type: string currentBatch: description: The current batch the rollout is working on/blocked, diff --git a/config/crd/bases/rollouts.kruise.io_rollouts.yaml b/config/crd/bases/rollouts.kruise.io_rollouts.yaml index ad0d220..42eafd2 100644 --- a/config/crd/bases/rollouts.kruise.io_rollouts.yaml +++ b/config/crd/bases/rollouts.kruise.io_rollouts.yaml @@ -37,6 +37,9 @@ spec: description: RolloutSpec defines the desired state of Rollout properties: <<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> 42b951e (completed-v1) objectRef: properties: type: @@ -63,12 +66,16 @@ spec: required: - type type: object +<<<<<<< HEAD ======= >>>>>>> 33cbc1d (add batchrelease controller) +======= +>>>>>>> 42b951e (completed-v1) strategy: description: The deployment strategy to use to replace existing pods with new ones. properties: +<<<<<<< HEAD <<<<<<< HEAD canaryPlan: description: CanaryStrategy defines parameters for a Replica Based @@ -88,6 +95,12 @@ spec: canary version. type: string >>>>>>> 33cbc1d (add batchrelease controller) +======= + canaryPlan: + description: CanaryStrategy defines parameters for a Replica Based + Canary + properties: +>>>>>>> 42b951e (completed-v1) steps: description: Steps define the order of phases to execute the canary deployment @@ -95,6 +108,9 @@ spec: description: CanaryStep defines a step of a canary workload. properties: <<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> 42b951e (completed-v1) canaryReplicas: anyOf: - type: integer @@ -104,8 +120,11 @@ spec: 5) or a percentage of total pods. it is mutually exclusive with the PodList field' x-kubernetes-int-or-string: true +<<<<<<< HEAD ======= >>>>>>> 33cbc1d (add batchrelease controller) +======= +>>>>>>> 42b951e (completed-v1) pause: description: Pause freezes the rollout by setting spec.Paused to true. A Rollout will resume when spec.Paused is @@ -117,11 +136,15 @@ spec: format: int32 type: integer type: object +<<<<<<< HEAD <<<<<<< HEAD weight: ======= setWeight: >>>>>>> 33cbc1d (add batchrelease controller) +======= + weight: +>>>>>>> 42b951e (completed-v1) description: SetWeight sets what percentage of the canary pods should receive format: int32 @@ -133,6 +156,7 @@ spec: meshes supported to enable more fine-grained traffic routing properties: <<<<<<< HEAD +<<<<<<< HEAD ======= alb: description: AlbTrafficRouting configuration for Nginx @@ -158,6 +182,8 @@ spec: - ingress type: object >>>>>>> 33cbc1d (add batchrelease controller) +======= +>>>>>>> 42b951e (completed-v1) nginx: description: Nginx holds Nginx Ingress specific configuration to route traffic @@ -166,6 +192,7 @@ spec: description: Ingress refers to the name of an `Ingress` resource in the same namespace as the `Rollout` type: string +<<<<<<< HEAD <<<<<<< HEAD required: - ingress @@ -208,46 +235,57 @@ spec: type: string type: object type: object +======= +>>>>>>> 42b951e (completed-v1) required: - ingress type: object - type: + service: + description: Service holds the name of a service which + selects pods with stable version and don't select any + pods with canary version. type: string + type: + description: Nginx, Alb, Istio etc. + type: string + required: + - type type: object type: object - type: object - targetRef: - description: TargetRef contains enough information to let you identify - a workload for Rollout - properties: - apiVersion: - description: API Version of the referent - type: string - kind: - description: Kind of the referent - type: string - name: - description: Name of the referent + paused: + description: Paused indicates that the Rollout is paused. Default + value is false + type: boolean + type: + description: canaryPlan, BlueGreenPlan Default value is canaryPlan type: string required: - - apiVersion - - kind - - name + - type type: object required: + - objectRef - strategy +<<<<<<< HEAD - targetRef >>>>>>> 33cbc1d (add batchrelease controller) +======= +>>>>>>> 42b951e (completed-v1) type: object status: description: RolloutStatus defines the observed state of Rollout properties: +<<<<<<< HEAD <<<<<<< HEAD canaryRevision: description: CanaryRevision the hash of the canary pod template type: string ======= >>>>>>> 33cbc1d (add batchrelease controller) +======= + canaryRevision: + description: CanaryRevision the hash of the canary pod template + type: string +>>>>>>> 42b951e (completed-v1) canaryStatus: description: Canary describes the state of the canary rollout properties: @@ -340,11 +378,14 @@ spec: rolled out type: string <<<<<<< HEAD +<<<<<<< HEAD ======= updateRevision: description: UpdateRevision the hash of the current pod template type: string >>>>>>> 33cbc1d (add batchrelease controller) +======= +>>>>>>> 42b951e (completed-v1) type: object type: object served: true diff --git a/go.mod b/go.mod index fe3fde3..fbf851b 100644 --- a/go.mod +++ b/go.mod @@ -8,9 +8,6 @@ require ( github.com/onsi/gomega v1.17.0 github.com/openkruise/kruise-api v1.0.0 gopkg.in/yaml.v2 v2.4.0 - github.com/onsi/ginkgo v1.14.1 - github.com/onsi/gomega v1.10.2 - gopkg.in/yaml.v2 v2.3.0 k8s.io/api v0.20.10 k8s.io/apiextensions-apiserver v0.20.1 k8s.io/apimachinery v0.20.10 diff --git a/go.sum b/go.sum index 4068196..bc2406a 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -<<<<<<< Updated upstream cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -247,9 +246,11 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -300,11 +301,8 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa 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.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -<<<<<<< HEAD github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -======= ->>>>>>> 33cbc1d (add batchrelease controller) github.com/openkruise/kruise-api v1.0.0 h1:ScA0LxRRNBsgbcyLhTzR9B+KpGNWsIMptzzmjTqfYQo= github.com/openkruise/kruise-api v1.0.0/go.mod h1:kxV/UA/vrf/hz3z+kL21c0NOawC6K1ZjaKcJFgiOwsE= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -314,6 +312,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= @@ -372,6 +371,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -392,10 +392,12 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -432,6 +434,7 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -440,6 +443,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -469,10 +473,6 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -<<<<<<< HEAD -======= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= ->>>>>>> 33cbc1d (add batchrelease controller) golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= @@ -586,11 +586,8 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -<<<<<<< HEAD golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a h1:CB3a9Nez8M13wwlr/E2YtwoU+qYHKfC+JrDa45RXXoQ= -======= ->>>>>>> 33cbc1d (add batchrelease controller) golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -659,6 +656,7 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -690,6 +688,7 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8= diff --git a/pkg/controller/batchrelease/batchrelease_controller.go b/pkg/controller/batchrelease/batchrelease_controller.go index fdacce7..2b241ae 100644 --- a/pkg/controller/batchrelease/batchrelease_controller.go +++ b/pkg/controller/batchrelease/batchrelease_controller.go @@ -70,10 +70,10 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error { // Watch for changes to BatchRelease err = c.Watch(&source.Kind{Type: &v1alpha1.BatchRelease{}}, &handler.EnqueueRequestForObject{}, predicate.Funcs{ UpdateFunc: func(e event.UpdateEvent) bool { - old := e.ObjectOld.(*v1alpha1.BatchRelease) - new := e.ObjectNew.(*v1alpha1.BatchRelease) - if old.Generation != new.Generation { - klog.V(3).Infof("Observed updated Spec for BatchRelease: %s/%s", new.Namespace, new.Name) + oldObject := e.ObjectOld.(*v1alpha1.BatchRelease) + newObject := e.ObjectNew.(*v1alpha1.BatchRelease) + if oldObject.Generation != newObject.Generation || newObject.DeletionTimestamp != nil { + klog.V(3).Infof("Observed updated Spec for BatchRelease: %s/%s", newObject.Namespace, newObject.Name) return true } return false diff --git a/pkg/controller/batchrelease/batchrelease_controller_test.go b/pkg/controller/batchrelease/batchrelease_controller_test.go new file mode 100644 index 0000000..0eb18fb --- /dev/null +++ b/pkg/controller/batchrelease/batchrelease_controller_test.go @@ -0,0 +1,998 @@ +package batchrelease + +import ( + "context" + "encoding/json" + "fmt" + "testing" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + apps "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/apimachinery/pkg/util/rand" + apimachineryruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/uuid" + "k8s.io/client-go/tools/record" + "k8s.io/utils/pointer" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + kruiseappsv1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1" + "github.com/openkruise/rollouts/api/v1alpha1" + "github.com/openkruise/rollouts/pkg/controller/batchrelease/workloads" +) + +const TIME_LAYOUT = "2006-01-02 15:04:05" + +var ( + scheme *runtime.Scheme + releaseDeploy = &v1alpha1.BatchRelease{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1alpha1.GroupVersion.String(), + Kind: "BatchRelease", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "release", + Namespace: "application", + UID: uuid.NewUUID(), + }, + Spec: v1alpha1.BatchReleaseSpec{ + TargetRef: v1alpha1.ObjectRef{ + WorkloadRef: &v1alpha1.WorkloadRef{ + APIVersion: "apps/v1", + Kind: "Deployment", + Name: "sample", + }, + }, + ReleasePlan: v1alpha1.ReleasePlan{ + Batches: []v1alpha1.ReleaseBatch{ + { + CanaryReplicas: intstr.FromString("10%"), + PauseSeconds: 100, + }, + { + CanaryReplicas: intstr.FromString("50%"), + PauseSeconds: 100, + }, + { + CanaryReplicas: intstr.FromString("80%"), + PauseSeconds: 100, + }, + }, + }, + }, + } + + stableDeploy = &apps.Deployment{ + TypeMeta: metav1.TypeMeta{ + APIVersion: apps.SchemeGroupVersion.String(), + Kind: "Deployment", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sample", + Namespace: "application", + UID: types.UID("87076677"), + Generation: 2, + Labels: map[string]string{ + "app": "busybox", + apps.DefaultDeploymentUniqueLabelKey: "update-pod-hash", + }, + }, + Spec: apps.DeploymentSpec{ + Replicas: pointer.Int32Ptr(100), + Strategy: apps.DeploymentStrategy{ + Type: apps.RollingUpdateDeploymentStrategyType, + RollingUpdate: &apps.RollingUpdateDeployment{ + MaxSurge: &intstr.IntOrString{Type: intstr.Int, IntVal: int32(1)}, + MaxUnavailable: &intstr.IntOrString{Type: intstr.Int, IntVal: int32(2)}, + }, + }, + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app": "busybox", + }, + }, + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + Containers: containers("v2"), + }, + }, + }, + Status: apps.DeploymentStatus{ + Replicas: 100, + ReadyReplicas: 100, + UpdatedReplicas: 0, + AvailableReplicas: 100, + }, + } +) + +var ( + releaseClone = &v1alpha1.BatchRelease{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1alpha1.GroupVersion.String(), + Kind: "BatchRelease", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "release", + Namespace: "application", + UID: uuid.NewUUID(), + }, + Spec: v1alpha1.BatchReleaseSpec{ + TargetRef: v1alpha1.ObjectRef{ + WorkloadRef: &v1alpha1.WorkloadRef{ + APIVersion: "apps.kruise.io/v1alpha1", + Kind: "CloneSet", + Name: "sample", + }, + }, + ReleasePlan: v1alpha1.ReleasePlan{ + Batches: []v1alpha1.ReleaseBatch{ + { + CanaryReplicas: intstr.FromString("10%"), + PauseSeconds: 100, + }, + { + CanaryReplicas: intstr.FromString("50%"), + PauseSeconds: 100, + }, + { + CanaryReplicas: intstr.FromString("80%"), + PauseSeconds: 100, + }, + }, + }, + }, + } + + stableClone = &kruiseappsv1alpha1.CloneSet{ + TypeMeta: metav1.TypeMeta{ + APIVersion: kruiseappsv1alpha1.SchemeGroupVersion.String(), + Kind: "CloneSet", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sample", + Namespace: "application", + UID: types.UID("87076677"), + Generation: 1, + Labels: map[string]string{ + "app": "busybox", + }, + }, + Spec: kruiseappsv1alpha1.CloneSetSpec{ + Replicas: pointer.Int32Ptr(100), + UpdateStrategy: kruiseappsv1alpha1.CloneSetUpdateStrategy{ + Partition: &intstr.IntOrString{Type: intstr.Int, IntVal: int32(1)}, + MaxSurge: &intstr.IntOrString{Type: intstr.Int, IntVal: int32(2)}, + MaxUnavailable: &intstr.IntOrString{Type: intstr.Int, IntVal: int32(2)}, + }, + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app": "busybox", + }, + }, + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + Containers: containers("v2"), + }, + }, + }, + Status: kruiseappsv1alpha1.CloneSetStatus{ + Replicas: 100, + ReadyReplicas: 100, + UpdatedReplicas: 0, + UpdatedReadyReplicas: 0, + ObservedGeneration: 1, + }, + } +) + +func init() { + scheme = runtime.NewScheme() + apimachineryruntime.Must(apps.AddToScheme(scheme)) + apimachineryruntime.Must(v1alpha1.AddToScheme(scheme)) + apimachineryruntime.Must(kruiseappsv1alpha1.AddToScheme(scheme)) + + controlInfo, _ := json.Marshal(metav1.NewControllerRef(releaseDeploy, releaseDeploy.GroupVersionKind())) + stableDeploy.Annotations = map[string]string{ + workloads.BatchReleaseControlAnnotation: string(controlInfo), + } + stableClone.Annotations = map[string]string{ + workloads.BatchReleaseControlAnnotation: string(controlInfo), + } + + canaryTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate := canaryTemplate.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + stableClone.Status.CurrentRevision = workloads.ComputeHash(stableTemplate, nil) + stableClone.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) +} + +func TestReconcile_CloneSet(t *testing.T) { + RegisterFailHandler(Fail) + + cases := []struct { + Name string + GetRelease func() client.Object + GetCloneSet func() []client.Object + ExpectedBatch int32 + ExpectedPhase v1alpha1.RolloutPhase + ExpectedState v1alpha1.ReleasingBatchStateType + }{ + // Following cases of Linear Transaction on State Machine + { + Name: "IfNeedProgress=false, Input-Phase=Initial, Output-Phase=Healthy", + GetRelease: func() client.Object { + return setPhase(releaseClone, v1alpha1.RolloutPhaseInitial) + }, + GetCloneSet: func() []client.Object { + return []client.Object{ + stableClone.DeepCopy(), + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseHealthy, + }, + { + Name: "IfNeedProgress=false, Input-Phase=Healthy, Output-Phase=Healthy", + GetRelease: func() client.Object { + return setPhase(releaseClone, v1alpha1.RolloutPhaseHealthy) + }, + GetCloneSet: func() []client.Object { + return []client.Object{ + stableClone.DeepCopy(), + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseHealthy, + }, + { + Name: "IfNeedProgress=true, Input-Phase=Healthy, Output-Phase=Preparing", + GetRelease: func() client.Object { + return setPhase(releaseClone, v1alpha1.RolloutPhaseHealthy) + }, + GetCloneSet: func() []client.Object { + stable := getStableWithReady(stableClone, "v2") + canary := getCanaryWithStage(stable, "v2", -1, true) + return []client.Object{ + canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhasePreparing, + }, + { + Name: "Preparing, Input-Phase=Preparing, Output-Phase=Progressing", + GetRelease: func() client.Object { + release := setPhase(releaseClone, v1alpha1.RolloutPhasePreparing) + stableTemplate := stableClone.Spec.Template.DeepCopy() + canaryTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + return release + }, + GetCloneSet: func() []client.Object { + stable := getStableWithReady(stableClone, "v2") + canary := getCanaryWithStage(stable, "v2", -1, true) + return []client.Object{ + canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseProgressing, + }, + { + Name: "Progressing, stage=0, Input-State=Initialize, Output-State=Verify", + GetRelease: func() client.Object { + release := setState(releaseClone, v1alpha1.InitializeBatchState) + stableTemplate := stableClone.Spec.Template.DeepCopy() + canaryTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + return release + }, + GetCloneSet: func() []client.Object { + stable := getStableWithReady(stableClone, "v2") + canary := getCanaryWithStage(stable, "v2", -1, true) + return []client.Object{ + canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseProgressing, + ExpectedState: v1alpha1.VerifyBatchState, + }, + { + Name: "Progressing, stage=0, Input-State=DoCanary, Output-State=Verify", + GetRelease: func() client.Object { + release := setState(releaseClone, v1alpha1.DoCanaryBatchState) + stableTemplate := stableClone.Spec.Template.DeepCopy() + canaryTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + return release + }, + GetCloneSet: func() []client.Object { + stable := getStableWithReady(stableClone, "v2") + canary := getCanaryWithStage(stable, "v2", -1, true) + return []client.Object{ + canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseProgressing, + ExpectedState: v1alpha1.VerifyBatchState, + }, + { + Name: "Progressing, stage=0, Input-State=Verify, Output-State=BatchReady", + GetRelease: func() client.Object { + release := setState(releaseClone, v1alpha1.VerifyBatchState) + stableTemplate := stableClone.Spec.Template.DeepCopy() + canaryTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + return release + }, + GetCloneSet: func() []client.Object { + stable := getStableWithReady(stableClone, "v2") + canary := getCanaryWithStage(stable, "v2", 0, true) + return []client.Object{ + canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseProgressing, + ExpectedState: v1alpha1.ReadyBatchState, + }, + { + Name: "Progressing, stage=0->1, Input-State=BatchReady, Output-State=Initialize", + GetRelease: func() client.Object { + release := setState(releaseClone, v1alpha1.ReadyBatchState) + release.Status.CanaryStatus.LastBatchReadyTime = *getOldTime() + stableTemplate := stableClone.Spec.Template.DeepCopy() + canaryTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + return release + }, + GetCloneSet: func() []client.Object { + stable := getStableWithReady(stableClone, "v2") + canary := getCanaryWithStage(stable, "v2", 0, true) + return []client.Object{ + canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseProgressing, + ExpectedState: v1alpha1.InitializeBatchState, + ExpectedBatch: 1, + }, + { + Name: "Progressing, stage=0->1, Input-State=BatchReady, Output-State=BatchReady", + GetRelease: func() client.Object { + release := setState(releaseClone, v1alpha1.ReadyBatchState) + release.Status.CanaryStatus.LastBatchReadyTime = metav1.Now() + stableTemplate := stableClone.Spec.Template.DeepCopy() + canaryTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + return release + }, + GetCloneSet: func() []client.Object { + stable := getStableWithReady(stableClone, "v2") + canary := getCanaryWithStage(stable, "v2", 0, true) + return []client.Object{ + canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseProgressing, + ExpectedState: v1alpha1.ReadyBatchState, + }, + { + Name: "Special Case: Scaling, Input-State=BatchReady, Output-State=Initialize", + GetRelease: func() client.Object { + release := setState(releaseClone, v1alpha1.ReadyBatchState) + release.Status.CanaryStatus.LastBatchReadyTime = metav1.Now() + stableTemplate := stableClone.Spec.Template.DeepCopy() + canaryTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + return release + }, + GetCloneSet: func() []client.Object { + stable := getStableWithReady(stableClone, "v2").(*kruiseappsv1alpha1.CloneSet) + stable.Spec.Replicas = pointer.Int32Ptr(200) + canary := getCanaryWithStage(stable, "v2", 0, true) + return []client.Object{ + canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseProgressing, + ExpectedState: v1alpha1.InitializeBatchState, + }, + { + Name: `Special Case: RollBack, Input-Phase=Progressing, Output-Phase=Cancelled`, + GetRelease: func() client.Object { + release := setState(releaseClone, v1alpha1.ReadyBatchState) + release.Status.CanaryStatus.LastBatchReadyTime = metav1.Now() + stableTemplate := stableClone.Spec.Template.DeepCopy() + canaryTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + return release + }, + GetCloneSet: func() []client.Object { + stable := getStableWithReady(stableClone, "v1") + canary := getCanaryWithStage(stable, "v1", 0, true).(*kruiseappsv1alpha1.CloneSet) + stableTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canary.Status.CurrentRevision = workloads.ComputeHash(stableTemplate, nil) + canary.Status.UpdateRevision = workloads.ComputeHash(stableTemplate, nil) + return []client.Object{ + canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseCancelled, + ExpectedState: v1alpha1.ReadyBatchState, + }, + { + Name: `Special Case: Deletion, Input-Phase=Progressing, Output-Phase=Terminating`, + GetRelease: func() client.Object { + release := setState(releaseClone, v1alpha1.ReadyBatchState) + release.Status.CanaryStatus.LastBatchReadyTime = metav1.Now() + stableTemplate := stableClone.Spec.Template.DeepCopy() + canaryTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + release.DeletionTimestamp = &metav1.Time{Time: time.Now()} + return release + }, + GetCloneSet: func() []client.Object { + stable := getStableWithReady(stableClone, "v2") + canary := getCanaryWithStage(stable, "v2", 0, true) + return []client.Object{ + canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseTerminating, + ExpectedState: v1alpha1.ReadyBatchState, + }, + { + Name: `Special Case: Cancelled, Input-Phase=Progressing, Output-Phase=Cancelled`, + GetRelease: func() client.Object { + release := setState(releaseClone, v1alpha1.ReadyBatchState) + release.Status.CanaryStatus.LastBatchReadyTime = metav1.Now() + stableTemplate := stableClone.Spec.Template.DeepCopy() + canaryTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + release.Spec.Cancelled = true + return release + }, + GetCloneSet: func() []client.Object { + stable := getStableWithReady(stableClone, "v2") + canary := getCanaryWithStage(stable, "v2", 0, true) + return []client.Object{ + canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseCancelled, + ExpectedState: v1alpha1.ReadyBatchState, + }, + { + Name: `Special Case: Continuous Release, Input-Phase=Progressing, Output-Phase=Initial`, + GetRelease: func() client.Object { + release := setState(releaseClone, v1alpha1.ReadyBatchState) + release.Status.CanaryStatus.LastBatchReadyTime = metav1.Now() + stableTemplate := stableClone.Spec.Template.DeepCopy() + canaryTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + return release + }, + GetCloneSet: func() []client.Object { + stable := getStableWithReady(stableClone, "v3") + canary := getCanaryWithStage(stable, "v3", 0, true).(*kruiseappsv1alpha1.CloneSet) + stableTemplate := stableClone.Spec.Template.DeepCopy() + canaryTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v3") + canary.Status.CurrentRevision = workloads.ComputeHash(stableTemplate, nil) + canary.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + return []client.Object{ + canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseInitial, + }, + } + + for _, cs := range cases { + t.Run(cs.Name, func(t *testing.T) { + release := cs.GetRelease() + clonesets := cs.GetCloneSet() + rec := record.NewFakeRecorder(100) + cli := fake.NewClientBuilder().WithScheme(scheme).WithObjects(release). + WithObjects(clonesets...).Build() + reconciler := &BatchReleaseReconciler{ + Client: cli, + recorder: rec, + Scheme: scheme, + executor: NewReleasePlanExecutor(cli, rec), + } + + key := client.ObjectKeyFromObject(release) + request := reconcile.Request{NamespacedName: key} + result, err := reconciler.Reconcile(context.TODO(), request) + Expect(err).NotTo(HaveOccurred()) + Expect(result.RequeueAfter).Should(BeNumerically(">=", int64(0))) + + newRelease := v1alpha1.BatchRelease{} + Expect(cli.Get(context.TODO(), key, &newRelease)).NotTo(HaveOccurred()) + Expect(newRelease.Status.Phase).Should(Equal(cs.ExpectedPhase)) + Expect(newRelease.Status.CanaryStatus.CurrentBatch).Should(Equal(cs.ExpectedBatch)) + Expect(newRelease.Status.CanaryStatus.ReleasingBatchState).Should(Equal(cs.ExpectedState)) + }) + } +} + +func TestReconcile_Deployment(t *testing.T) { + RegisterFailHandler(Fail) + + cases := []struct { + Name string + GetRelease func() client.Object + GetDeployments func() []client.Object + ExpectedBatch int32 + ExpectedPhase v1alpha1.RolloutPhase + ExpectedState v1alpha1.ReleasingBatchStateType + }{ + // Following cases of Linear Transaction on State Machine + { + Name: "IfNeedProgress=false, Input-Phase=Initial, Output-Phase=Healthy", + GetRelease: func() client.Object { + return setPhase(releaseDeploy, v1alpha1.RolloutPhaseInitial) + }, + GetDeployments: func() []client.Object { + return []client.Object{ + stableDeploy.DeepCopy(), + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseHealthy, + }, + { + Name: "IfNeedProgress=false, Input-Phase=Healthy, Output-Phase=Healthy", + GetRelease: func() client.Object { + return setPhase(releaseDeploy, v1alpha1.RolloutPhaseHealthy) + }, + GetDeployments: func() []client.Object { + return []client.Object{ + stableDeploy.DeepCopy(), + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseHealthy, + }, + { + Name: "IfNeedProgress=true, Input-Phase=Healthy, Output-Phase=Preparing", + GetRelease: func() client.Object { + return setPhase(releaseDeploy, v1alpha1.RolloutPhaseHealthy) + }, + GetDeployments: func() []client.Object { + stable := getStableWithReady(stableDeploy, "v2") + canary := getCanaryWithStage(stable, "v2", -1, true) + return []client.Object{ + stable, canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhasePreparing, + }, + { + Name: "Preparing, Input-Phase=Preparing, Output-Phase=Progressing", + GetRelease: func() client.Object { + return setPhase(releaseDeploy, v1alpha1.RolloutPhasePreparing) + }, + GetDeployments: func() []client.Object { + stable := getStableWithReady(stableDeploy, "v2") + canary := getCanaryWithStage(stable, "v2", -1, true) + return []client.Object{ + stable, canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseProgressing, + }, + { + Name: "Progressing, stage=0, Input-State=Initialize, Output-State=Verify", + GetRelease: func() client.Object { + return setState(releaseDeploy, v1alpha1.InitializeBatchState) + }, + GetDeployments: func() []client.Object { + stable := getStableWithReady(stableDeploy, "v2") + canary := getCanaryWithStage(stable, "v2", -1, true) + return []client.Object{ + stable, canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseProgressing, + ExpectedState: v1alpha1.VerifyBatchState, + }, + { + Name: "Progressing, stage=0, Input-State=DoCanary, Output-State=Verify", + GetRelease: func() client.Object { + return setState(releaseDeploy, v1alpha1.DoCanaryBatchState) + }, + GetDeployments: func() []client.Object { + stable := getStableWithReady(stableDeploy, "v2") + canary := getCanaryWithStage(stable, "v2", -1, true) + return []client.Object{ + stable, canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseProgressing, + ExpectedState: v1alpha1.VerifyBatchState, + }, + { + Name: "Progressing, stage=0, Input-State=Verify, Output-State=BatchReady", + GetRelease: func() client.Object { + return setState(releaseDeploy, v1alpha1.VerifyBatchState) + }, + GetDeployments: func() []client.Object { + stable := getStableWithReady(stableDeploy, "v2") + canary := getCanaryWithStage(stable, "v2", 0, true) + return []client.Object{ + stable, canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseProgressing, + ExpectedState: v1alpha1.ReadyBatchState, + }, + { + Name: "Progressing, stage=0->1, Input-State=BatchReady, Output-State=Initialize", + GetRelease: func() client.Object { + release := setState(releaseDeploy, v1alpha1.ReadyBatchState) + release.Status.CanaryStatus.LastBatchReadyTime = *getOldTime() + return release + }, + GetDeployments: func() []client.Object { + stable := getStableWithReady(stableDeploy, "v2") + canary := getCanaryWithStage(stable, "v2", 0, true) + return []client.Object{ + stable, canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseProgressing, + ExpectedState: v1alpha1.InitializeBatchState, + ExpectedBatch: 1, + }, + { + Name: "Progressing, stage=0->1, Input-State=BatchReady, Output-State=BatchReady", + GetRelease: func() client.Object { + release := setState(releaseDeploy, v1alpha1.ReadyBatchState) + release.Status.CanaryStatus.LastBatchReadyTime = metav1.Now() + return release + }, + GetDeployments: func() []client.Object { + stable := getStableWithReady(stableDeploy, "v2") + canary := getCanaryWithStage(stable, "v2", 0, true) + return []client.Object{ + stable, canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseProgressing, + ExpectedState: v1alpha1.ReadyBatchState, + }, + { + Name: "Special Case: Scaling, Input-State=BatchReady, Output-State=Initialize", + GetRelease: func() client.Object { + release := setState(releaseDeploy, v1alpha1.ReadyBatchState) + release.Status.CanaryStatus.LastBatchReadyTime = metav1.Now() + return release + }, + GetDeployments: func() []client.Object { + stable := getStableWithReady(stableDeploy, "v2").(*apps.Deployment) + stable.Spec.Replicas = pointer.Int32Ptr(200) + canary := getCanaryWithStage(stable, "v2", 0, true) + return []client.Object{ + stable, canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseProgressing, + ExpectedState: v1alpha1.InitializeBatchState, + }, + { + Name: `Special Case: RollBack, Input-Phase=Progressing, Output-Phase=Cancelled`, + GetRelease: func() client.Object { + release := setState(releaseDeploy, v1alpha1.ReadyBatchState) + release.Status.CanaryStatus.LastBatchReadyTime = metav1.Now() + stableTemplate := stableDeploy.Spec.Template.DeepCopy() + canaryTemplate := stableDeploy.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + return release + }, + GetDeployments: func() []client.Object { + stable := getStableWithReady(stableDeploy, "v1") + canary := getCanaryWithStage(stable, "v2", 0, true) + return []client.Object{ + stable, canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseCancelled, + ExpectedState: v1alpha1.ReadyBatchState, + }, + { + Name: `Special Case: Deletion, Input-Phase=Progressing, Output-Phase=Terminating`, + GetRelease: func() client.Object { + release := setState(releaseDeploy, v1alpha1.ReadyBatchState) + release.Status.CanaryStatus.LastBatchReadyTime = metav1.Now() + stableTemplate := stableDeploy.Spec.Template.DeepCopy() + canaryTemplate := stableDeploy.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + release.DeletionTimestamp = &metav1.Time{Time: time.Now()} + return release + }, + GetDeployments: func() []client.Object { + stable := getStableWithReady(stableDeploy, "v2") + canary := getCanaryWithStage(stable, "v2", 0, true) + return []client.Object{ + stable, canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseTerminating, + ExpectedState: v1alpha1.ReadyBatchState, + }, + { + Name: `Special Case: Cancelled, Input-Phase=Progressing, Output-Phase=Cancelled`, + GetRelease: func() client.Object { + release := setState(releaseDeploy, v1alpha1.ReadyBatchState) + release.Status.CanaryStatus.LastBatchReadyTime = metav1.Now() + stableTemplate := stableDeploy.Spec.Template.DeepCopy() + canaryTemplate := stableDeploy.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + release.Spec.Cancelled = true + return release + }, + GetDeployments: func() []client.Object { + stable := getStableWithReady(stableDeploy, "v2") + canary := getCanaryWithStage(stable, "v2", 0, true) + return []client.Object{ + stable, canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseCancelled, + ExpectedState: v1alpha1.ReadyBatchState, + }, + { + Name: `Special Case: Continuous Release, Input-Phase=Progressing, Output-Phase=Initial`, + GetRelease: func() client.Object { + release := setState(releaseDeploy, v1alpha1.ReadyBatchState) + release.Status.CanaryStatus.LastBatchReadyTime = metav1.Now() + stableTemplate := stableDeploy.Spec.Template.DeepCopy() + canaryTemplate := stableDeploy.Spec.Template.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + canaryTemplate.Spec.Containers = containers("v2") + release.Status.StableRevision = workloads.ComputeHash(stableTemplate, nil) + release.Status.UpdateRevision = workloads.ComputeHash(canaryTemplate, nil) + return release + }, + GetDeployments: func() []client.Object { + stable := getStableWithReady(stableDeploy, "v3") + canary := getCanaryWithStage(stable, "v2", 0, true) + return []client.Object{ + stable, canary, + } + }, + ExpectedPhase: v1alpha1.RolloutPhaseInitial, + }, + } + + for _, cs := range cases { + t.Run(cs.Name, func(t *testing.T) { + release := cs.GetRelease() + deployments := cs.GetDeployments() + rec := record.NewFakeRecorder(100) + cli := fake.NewClientBuilder().WithScheme(scheme).WithObjects(release). + WithObjects(deployments...).WithObjects(makeReplicaSets(deployments...)...).Build() + reconciler := &BatchReleaseReconciler{ + Client: cli, + recorder: rec, + Scheme: scheme, + executor: NewReleasePlanExecutor(cli, rec), + } + + key := client.ObjectKeyFromObject(release) + request := reconcile.Request{NamespacedName: key} + result, err := reconciler.Reconcile(context.TODO(), request) + Expect(err).NotTo(HaveOccurred()) + Expect(result.RequeueAfter).Should(BeNumerically(">=", int64(0))) + + newRelease := v1alpha1.BatchRelease{} + Expect(cli.Get(context.TODO(), key, &newRelease)).NotTo(HaveOccurred()) + Expect(newRelease.Status.Phase).Should(Equal(cs.ExpectedPhase)) + Expect(newRelease.Status.CanaryStatus.CurrentBatch).Should(Equal(cs.ExpectedBatch)) + Expect(newRelease.Status.CanaryStatus.ReleasingBatchState).Should(Equal(cs.ExpectedState)) + }) + } +} + +func containers(version string) []corev1.Container { + return []corev1.Container{ + { + Name: "busybox", + Image: fmt.Sprintf("busybox:%v", version), + }, + } +} + +func setPhase(release *v1alpha1.BatchRelease, phase v1alpha1.RolloutPhase) *v1alpha1.BatchRelease { + r := release.DeepCopy() + r.Status.Phase = phase + switch phase { + case v1alpha1.RolloutPhaseInitial, v1alpha1.RolloutPhaseHealthy: + default: + r.Status.ObservedWorkloadReplicas = 100 + r.Status.ObservedReleasePlanHash = hashReleasePlanBatches(&release.Spec.ReleasePlan) + } + return r +} + +func setState(release *v1alpha1.BatchRelease, state v1alpha1.ReleasingBatchStateType) *v1alpha1.BatchRelease { + r := release.DeepCopy() + r.Status.Phase = v1alpha1.RolloutPhaseProgressing + r.Status.CanaryStatus.ReleasingBatchState = state + r.Status.ObservedWorkloadReplicas = 100 + r.Status.ObservedReleasePlanHash = hashReleasePlanBatches(&release.Spec.ReleasePlan) + return r +} + +func getStableWithReady(workload client.Object, version string) client.Object { + switch workload.(type) { + case *apps.Deployment: + deploy := workload.(*apps.Deployment) + d := deploy.DeepCopy() + d.Spec.Paused = true + d.Spec.Template.Spec.Containers = containers(version) + d.Status.ObservedGeneration = deploy.Generation + return d + + case *kruiseappsv1alpha1.CloneSet: + clone := workload.(*kruiseappsv1alpha1.CloneSet) + c := clone.DeepCopy() + c.Spec.UpdateStrategy.Paused = true + c.Spec.UpdateStrategy.Partition = &intstr.IntOrString{Type: intstr.String, StrVal: "100%"} + c.Spec.Template.Spec.Containers = containers(version) + c.Status.ObservedGeneration = clone.Generation + return c + } + return nil +} + +func getCanaryWithStage(workload client.Object, version string, stage int, ready bool) client.Object { + var err error + var stageReplicas int + + switch workload.(type) { + case *apps.Deployment: + deploy := workload.(*apps.Deployment) + + if stage >= 0 { + stageReplicas, err = intstr.GetScaledValueFromIntOrPercent( + &releaseDeploy.Spec.ReleasePlan.Batches[stage].CanaryReplicas, int(*deploy.Spec.Replicas), true) + Expect(err).NotTo(HaveOccurred()) + if !ready { + stageReplicas -= 5 + } + } + + d := deploy.DeepCopy() + d.Name += "-canary-324785678" + d.UID = uuid.NewUUID() + d.Spec.Paused = false + d.Labels[workloads.CanaryDeploymentLabelKey] = string(deploy.UID) + d.Spec.Replicas = pointer.Int32Ptr(int32(stageReplicas)) + d.Spec.Template.Spec.Containers = containers(version) + d.Status.Replicas = int32(stageReplicas) + d.Status.ReadyReplicas = int32(stageReplicas) + d.Status.UpdatedReplicas = int32(stageReplicas) + d.Status.AvailableReplicas = int32(stageReplicas) + d.Status.ObservedGeneration = deploy.Generation + d.OwnerReferences = []metav1.OwnerReference{*metav1.NewControllerRef(releaseDeploy, releaseDeploy.GroupVersionKind())} + controlInfo, _ := json.Marshal(metav1.NewControllerRef(releaseDeploy, releaseDeploy.GroupVersionKind())) + d.Annotations = map[string]string{ + workloads.BatchReleaseControlAnnotation: string(controlInfo), + } + return d + + case *kruiseappsv1alpha1.CloneSet: + clone := workload.(*kruiseappsv1alpha1.CloneSet) + + if stage >= 0 { + stageReplicas, err = intstr.GetScaledValueFromIntOrPercent( + &releaseClone.Spec.ReleasePlan.Batches[stage].CanaryReplicas, int(*clone.Spec.Replicas), true) + Expect(err).NotTo(HaveOccurred()) + if !ready { + stageReplicas -= 5 + } + } + + c := clone + c.Spec.UpdateStrategy.Paused = false + c.Spec.UpdateStrategy.Partition = &intstr.IntOrString{Type: intstr.Int, IntVal: *c.Spec.Replicas - int32(stageReplicas)} + c.Spec.Template.Spec.Containers = containers(version) + c.Status.Replicas = *c.Spec.Replicas + c.Status.UpdatedReplicas = int32(stageReplicas) + c.Status.UpdatedReadyReplicas = int32(stageReplicas) + c.Status.ReadyReplicas = c.Status.Replicas + c.Status.ObservedGeneration = clone.Generation + controlInfo, _ := json.Marshal(metav1.NewControllerRef(releaseClone, releaseClone.GroupVersionKind())) + c.Annotations = map[string]string{ + workloads.BatchReleaseControlAnnotation: string(controlInfo), + } + return c + } + + return nil +} + +func makeReplicaSets(deploys ...client.Object) []client.Object { + var rss []client.Object + for _, d := range deploys { + deploy := d.(*apps.Deployment) + labels := deploy.Spec.Selector.DeepCopy().MatchLabels + labels[apps.DefaultDeploymentUniqueLabelKey] = workloads.ComputeHash(&deploy.Spec.Template, nil) + rss = append(rss, &apps.ReplicaSet{ + TypeMeta: metav1.TypeMeta{ + APIVersion: apps.SchemeGroupVersion.String(), + Kind: "ReplicaSet", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: deploy.Name + rand.String(5), + Namespace: deploy.Namespace, + UID: uuid.NewUUID(), + Labels: labels, + OwnerReferences: []metav1.OwnerReference{ + *metav1.NewControllerRef(deploy, deploy.GroupVersionKind()), + }, + }, + Spec: apps.ReplicaSetSpec{ + Replicas: deploy.Spec.Replicas, + Selector: deploy.Spec.Selector.DeepCopy(), + Template: *deploy.Spec.Template.DeepCopy(), + }, + }) + } + return rss +} + +func getOldTime() *metav1.Time { + time, _ := time.Parse(TIME_LAYOUT, "2018-09-10 00:00:00") + return &metav1.Time{Time: time} +} diff --git a/pkg/controller/batchrelease/batchrelease_event_handler.go b/pkg/controller/batchrelease/batchrelease_event_handler.go index e78667e..5dde5ac 100644 --- a/pkg/controller/batchrelease/batchrelease_event_handler.go +++ b/pkg/controller/batchrelease/batchrelease_event_handler.go @@ -59,7 +59,7 @@ func (w workloadEventHandler) Create(evt event.CreateEvent, q workqueue.RateLimi } func (w workloadEventHandler) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) { - var oldAccessor, newAccessor *workloads.Accessor + var oldAccessor, newAccessor *workloads.WorkloadAccessor var gvk schema.GroupVersionKind switch evt.ObjectNew.(type) { @@ -76,7 +76,7 @@ func (w workloadEventHandler) Update(evt event.UpdateEvent, q workqueue.RateLimi newReplicas = *newClone.Spec.Replicas } - oldAccessor = &workloads.Accessor{ + oldAccessor = &workloads.WorkloadAccessor{ Replicas: &oldReplicas, Paused: oldClone.Spec.UpdateStrategy.Paused, Status: &workloads.Status{ @@ -89,7 +89,7 @@ func (w workloadEventHandler) Update(evt event.UpdateEvent, q workqueue.RateLimi Metadata: &oldClone.ObjectMeta, } - newAccessor = &workloads.Accessor{ + newAccessor = &workloads.WorkloadAccessor{ Replicas: &newReplicas, Paused: newClone.Spec.UpdateStrategy.Paused, Status: &workloads.Status{ @@ -115,7 +115,7 @@ func (w workloadEventHandler) Update(evt event.UpdateEvent, q workqueue.RateLimi newReplicas = *newDeploy.Spec.Replicas } - oldAccessor = &workloads.Accessor{ + oldAccessor = &workloads.WorkloadAccessor{ Replicas: &oldReplicas, Paused: oldDeploy.Spec.Paused, Status: &workloads.Status{ @@ -127,7 +127,7 @@ func (w workloadEventHandler) Update(evt event.UpdateEvent, q workqueue.RateLimi Metadata: &oldDeploy.ObjectMeta, } - newAccessor = &workloads.Accessor{ + newAccessor = &workloads.WorkloadAccessor{ Replicas: &newReplicas, Paused: newDeploy.Spec.Paused, Status: &workloads.Status{ @@ -153,29 +153,17 @@ func (w workloadEventHandler) Update(evt event.UpdateEvent, q workqueue.RateLimi Name: newAccessor.Metadata.Name, } - controllerInfo, controlled := newAccessor.Metadata.Annotations[workloads.BatchReleaseControlAnnotation] - if controlled && len(controllerInfo) > 0 { - br := &metav1.OwnerReference{} - if err := json.Unmarshal([]byte(controllerInfo), br); err == nil { - klog.V(3).Infof("%s (%v) is managed by BatchRelease (%s), append queue", gvk.Kind, workloadNsn, br.Name) - nsn := types.NamespacedName{Namespace: workloadNsn.Namespace, Name: br.Name} - q.Add(reconcile.Request{NamespacedName: nsn}) - return - } - } - - br, err := w.getBatchRelease(workloadNsn, gvk) + brNsn, err := w.getBatchRelease(workloadNsn, gvk, newAccessor.Metadata.Annotations[workloads.BatchReleaseControlAnnotation]) if err != nil { klog.Errorf("unable to get BatchRelease related with %s (%s/%s), err: %v", gvk.Kind, workloadNsn.Namespace, workloadNsn.Name, err) return } - if br != nil { - klog.V(3).Infof("%s (%s/%s) changed generation from %d to %d managed by BatchRelease (%s/%s)", - gvk.Kind, workloadNsn.Namespace, workloadNsn.Name, oldAccessor.Metadata.Generation, newAccessor.Metadata.Generation, br.GetNamespace(), br.GetName()) - nsn := types.NamespacedName{Namespace: br.GetNamespace(), Name: br.GetName()} - q.Add(reconcile.Request{NamespacedName: nsn}) + if len(brNsn.Name) != 0 { + klog.V(3).Infof("%s (%s/%s) changed generation from %d to %d managed by BatchRelease (%v)", + gvk.Kind, workloadNsn.Namespace, workloadNsn.Name, oldAccessor.Metadata.Generation, newAccessor.Metadata.Generation, brNsn) + q.Add(reconcile.Request{NamespacedName: brNsn}) } } } @@ -189,12 +177,15 @@ func (w workloadEventHandler) Generic(evt event.GenericEvent, q workqueue.RateLi func (w *workloadEventHandler) handleWorkload(q workqueue.RateLimitingInterface, obj client.Object, action EventAction) { + var controlInfo string var gvk schema.GroupVersionKind switch obj.(type) { case *kruiseappsv1alpha1.CloneSet: gvk = controllerKruiseKindCS + controlInfo = obj.(*kruiseappsv1alpha1.CloneSet).Annotations[workloads.BatchReleaseControlAnnotation] case *appsv1.Deployment: gvk = controllerKindDep + controlInfo = obj.(*appsv1.Deployment).Annotations[workloads.BatchReleaseControlAnnotation] default: return } @@ -203,78 +194,89 @@ func (w *workloadEventHandler) handleWorkload(q workqueue.RateLimitingInterface, Namespace: obj.GetNamespace(), Name: obj.GetName(), } - ws, err := w.getBatchRelease(workloadNsn, gvk) + brNsn, err := w.getBatchRelease(workloadNsn, gvk, controlInfo) if err != nil { klog.Errorf("unable to get BatchRelease related with %s (%s/%s), err: %v", gvk.Kind, workloadNsn.Namespace, workloadNsn.Name, err) return } - if ws != nil { - klog.V(5).Infof("%s %s (%s/%s) and reconcile BatchRelease (%s/%s)", - action, gvk.Kind, workloadNsn.Namespace, workloadNsn.Namespace, ws.Namespace, ws.Name) - nsn := types.NamespacedName{Namespace: ws.GetNamespace(), Name: ws.GetName()} - q.Add(reconcile.Request{NamespacedName: nsn}) + if len(brNsn.Name) != 0 { + klog.V(5).Infof("%s %s (%s/%s) and reconcile BatchRelease (%v)", + action, gvk.Kind, workloadNsn.Namespace, workloadNsn.Namespace, brNsn) + q.Add(reconcile.Request{NamespacedName: brNsn}) } } -func (w *workloadEventHandler) getBatchRelease(workloadNamespaceName types.NamespacedName, gvk schema.GroupVersionKind) (*v1alpha1.BatchRelease, error) { - bsList := &v1alpha1.BatchReleaseList{} - listOptions := &client.ListOptions{Namespace: workloadNamespaceName.Namespace} - if err := w.List(context.TODO(), bsList, listOptions); err != nil { - klog.Errorf("List BatchRelease failed: %s", err.Error()) - return nil, err - } - - for _, bs := range bsList.Items { - if bs.DeletionTimestamp != nil { - continue - } - - targetRef := bs.Spec.TargetRef - targetGV, err := schema.ParseGroupVersion(targetRef.APIVersion) +func (w *workloadEventHandler) getBatchRelease(workloadNamespaceName types.NamespacedName, gvk schema.GroupVersionKind, controlInfo string) (nsn types.NamespacedName, err error) { + if len(controlInfo) > 0 { + br := &metav1.OwnerReference{} + err = json.Unmarshal([]byte(controlInfo), br) if err != nil { - klog.Errorf("failed to parse targetRef's group version: %s", targetRef.APIVersion) - continue + klog.Errorf("Failed to unmarshal controller info annotations for %v(%v)", gvk, workloadNamespaceName) } - if targetRef.Kind == gvk.Kind && targetGV.Group == gvk.Group && targetRef.Name == workloadNamespaceName.Name { - return &bs, nil + if br.APIVersion == v1alpha1.GroupVersion.String() && br.Kind == "BatchRelease" { + klog.V(3).Infof("%s (%v) is managed by BatchRelease (%s), append queue", gvk.Kind, workloadNamespaceName, br.Name) + nsn = types.NamespacedName{Namespace: workloadNamespaceName.Namespace, Name: br.Name} + return } } - return nil, nil + brList := &v1alpha1.BatchReleaseList{} + listOptions := &client.ListOptions{Namespace: workloadNamespaceName.Namespace} + if err = w.List(context.TODO(), brList, listOptions); err != nil { + klog.Errorf("List BatchRelease failed: %s", err.Error()) + return + } + + for i := range brList.Items { + br := &brList.Items[i] + targetRef := br.Spec.TargetRef + targetGV, err := schema.ParseGroupVersion(targetRef.WorkloadRef.APIVersion) + if err != nil { + klog.Errorf("failed to parse targetRef's group version: %s", targetRef.WorkloadRef.APIVersion) + continue + } + + if targetRef.WorkloadRef.Kind == gvk.Kind && targetGV.Group == gvk.Group && targetRef.WorkloadRef.Name == workloadNamespaceName.Name { + nsn = client.ObjectKeyFromObject(br) + } + } + + return } -func observeGenerationChanged(newOne, oldOne *workloads.Accessor) bool { +func observeGenerationChanged(newOne, oldOne *workloads.WorkloadAccessor) bool { return newOne.Metadata.Generation != oldOne.Metadata.Generation } -func observeLatestGeneration(newOne, oldOne *workloads.Accessor) bool { +func observeLatestGeneration(newOne, oldOne *workloads.WorkloadAccessor) bool { oldNot := oldOne.Metadata.Generation != oldOne.Status.ObservedGeneration newDid := newOne.Metadata.Generation == newOne.Status.ObservedGeneration return oldNot && newDid } -func observeScaleEventDone(newOne, oldOne *workloads.Accessor) bool { +func observeScaleEventDone(newOne, oldOne *workloads.WorkloadAccessor) bool { _, controlled := newOne.Metadata.Annotations[workloads.BatchReleaseControlAnnotation] if !controlled { return false } - oldScaling := oldOne.Replicas != newOne.Replicas || + oldScaling := *oldOne.Replicas != *newOne.Replicas || *oldOne.Replicas != oldOne.Status.Replicas newDone := newOne.Metadata.Generation == newOne.Status.ObservedGeneration && - *oldOne.Replicas == oldOne.Status.Replicas + *newOne.Replicas == newOne.Status.Replicas return oldScaling && newDone } -func observeReplicasChanged(newOne, oldOne *workloads.Accessor) bool { +func observeReplicasChanged(newOne, oldOne *workloads.WorkloadAccessor) bool { _, controlled := newOne.Metadata.Annotations[workloads.BatchReleaseControlAnnotation] if !controlled { return false } - return oldOne.Status.Replicas != newOne.Status.Replicas || + return *oldOne.Replicas != *newOne.Replicas || + oldOne.Status.Replicas != newOne.Status.Replicas || oldOne.Status.ReadyReplicas != newOne.Status.ReadyReplicas || oldOne.Status.UpdatedReplicas != newOne.Status.UpdatedReplicas || oldOne.Status.UpdatedReadyReplicas != newOne.Status.UpdatedReadyReplicas diff --git a/pkg/controller/batchrelease/batchrelease_event_handler_test.go b/pkg/controller/batchrelease/batchrelease_event_handler_test.go new file mode 100644 index 0000000..62faf3d --- /dev/null +++ b/pkg/controller/batchrelease/batchrelease_event_handler_test.go @@ -0,0 +1,238 @@ +package batchrelease + +import ( + "encoding/json" + "fmt" + "github.com/openkruise/rollouts/api/v1alpha1" + "github.com/openkruise/rollouts/pkg/controller/batchrelease/workloads" + apps "k8s.io/api/apps/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/util/workqueue" + "k8s.io/utils/pointer" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/event" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestEventHandler_Update(t *testing.T) { + RegisterFailHandler(Fail) + + cases := []struct { + Name string + GetOldWorkload func() client.Object + GetNewWorkload func() client.Object + ExpectedQueueLen int + }{ + { + Name: "Deployment Batch NotReady -> Ready", + GetOldWorkload: func() client.Object { + return getCanaryWithStage(stableDeploy, "v2", 0, false) + }, + GetNewWorkload: func() client.Object { + return getCanaryWithStage(stableDeploy, "v2", 0, true) + }, + ExpectedQueueLen: 1, + }, + { + Name: "Deployment Generation 1 -> 2", + GetOldWorkload: func() client.Object { + oldObject := getStableWithReady(stableDeploy, "v2") + oldObject.SetGeneration(1) + return oldObject + }, + GetNewWorkload: func() client.Object { + newObject := getStableWithReady(stableDeploy, "v2") + newObject.SetGeneration(2) + return newObject + }, + ExpectedQueueLen: 1, + }, + { + Name: "Deployment watched the latest generation", + GetOldWorkload: func() client.Object { + oldObject := getStableWithReady(stableDeploy, "v2").(*apps.Deployment) + oldObject.SetGeneration(2) + oldObject.Status.ObservedGeneration = 1 + return oldObject + }, + GetNewWorkload: func() client.Object { + newObject := getStableWithReady(stableDeploy, "v2").(*apps.Deployment) + newObject.SetGeneration(2) + newObject.Status.ObservedGeneration = 2 + return newObject + }, + ExpectedQueueLen: 1, + }, + { + Name: "Deployment scaling done", + GetOldWorkload: func() client.Object { + oldObject := getStableWithReady(stableDeploy, "v2").(*apps.Deployment) + oldObject.SetGeneration(2) + oldObject.Status.ObservedGeneration = 2 + oldObject.Spec.Replicas = pointer.Int32Ptr(1000) + return oldObject + }, + GetNewWorkload: func() client.Object { + newObject := getStableWithReady(stableDeploy, "v2").(*apps.Deployment) + newObject.SetGeneration(2) + newObject.Status.ObservedGeneration = 2 + newObject.Spec.Replicas = pointer.Int32Ptr(1000) + newObject.Status.Replicas = 1000 + return newObject + }, + ExpectedQueueLen: 1, + }, + { + Name: "Deployment available pod changed", + GetOldWorkload: func() client.Object { + oldObject := getStableWithReady(stableDeploy, "v2").(*apps.Deployment) + oldObject.SetGeneration(2) + oldObject.Status.ObservedGeneration = 2 + oldObject.Status.AvailableReplicas = 20 + return oldObject + }, + GetNewWorkload: func() client.Object { + newObject := getStableWithReady(stableDeploy, "v2").(*apps.Deployment) + newObject.SetGeneration(2) + newObject.Status.ObservedGeneration = 2 + newObject.Status.AvailableReplicas = 50 + return newObject + }, + ExpectedQueueLen: 1, + }, + } + + for _, cs := range cases { + t.Run(cs.Name, func(t *testing.T) { + oldObject := cs.GetOldWorkload() + newObject := cs.GetNewWorkload() + newSJk := scheme + fmt.Println(newSJk) + cli := fake.NewClientBuilder().WithScheme(scheme).WithObjects(releaseDeploy.DeepCopy()).Build() + handler := workloadEventHandler{Reader: cli} + updateQ := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) + updateEvt := event.UpdateEvent{ + ObjectOld: oldObject, + ObjectNew: newObject, + } + handler.Update(updateEvt, updateQ) + Expect(updateQ.Len()).Should(Equal(cs.ExpectedQueueLen)) + }) + } +} + +func TestEventHandler_Create(t *testing.T) { + RegisterFailHandler(Fail) + + cases := []struct { + Name string + GetNewWorkload func() client.Object + ExpectedQueueLen int + }{ + { + Name: "Deployment with controller info annotation", + GetNewWorkload: func() client.Object { + return getCanaryWithStage(stableDeploy, "v2", 0, true) + }, + ExpectedQueueLen: 1, + }, + { + Name: "Deployment without controller info annotation", + GetNewWorkload: func() client.Object { + object := getStableWithReady(stableDeploy, "v2").(*apps.Deployment) + object.Annotations = nil + return object + }, + ExpectedQueueLen: 1, + }, + { + Name: "Deployment with wrong controller info annotation", + GetNewWorkload: func() client.Object { + object := getStableWithReady(stableDeploy, "v2").(*apps.Deployment) + controlInfo, _ := json.Marshal(&metav1.OwnerReference{ + APIVersion: v1alpha1.GroupVersion.String(), + Kind: "Rollout", + Name: "whatever", + }) + object.SetName("another") + object.Annotations[workloads.BatchReleaseControlAnnotation] = string(controlInfo) + return object + }, + ExpectedQueueLen: 0, + }, + } + + for _, cs := range cases { + t.Run(cs.Name, func(t *testing.T) { + newObject := cs.GetNewWorkload() + cli := fake.NewClientBuilder().WithScheme(scheme).WithObjects(releaseDeploy.DeepCopy()).Build() + handler := workloadEventHandler{Reader: cli} + createQ := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) + createEvt := event.CreateEvent{ + Object: newObject, + } + handler.Create(createEvt, createQ) + Expect(createQ.Len()).Should(Equal(cs.ExpectedQueueLen)) + }) + } +} + +func TestEventHandler_Delete(t *testing.T) { + RegisterFailHandler(Fail) + + cases := []struct { + Name string + GetNewWorkload func() client.Object + ExpectedQueueLen int + }{ + { + Name: "Deployment with controller info annotation", + GetNewWorkload: func() client.Object { + return getCanaryWithStage(stableDeploy, "v2", 0, true) + }, + ExpectedQueueLen: 1, + }, + { + Name: "Deployment without controller info annotation", + GetNewWorkload: func() client.Object { + object := getStableWithReady(stableDeploy, "v2").(*apps.Deployment) + object.Annotations = nil + return object + }, + ExpectedQueueLen: 1, + }, + { + Name: "Deployment with wrong controller info annotation", + GetNewWorkload: func() client.Object { + object := getStableWithReady(stableDeploy, "v2").(*apps.Deployment) + controlInfo, _ := json.Marshal(&metav1.OwnerReference{ + APIVersion: v1alpha1.GroupVersion.String(), + Kind: "Rollout", + Name: "whatever", + }) + object.SetName("another") + object.Annotations[workloads.BatchReleaseControlAnnotation] = string(controlInfo) + return object + }, + ExpectedQueueLen: 0, + }, + } + + for _, cs := range cases { + t.Run(cs.Name, func(t *testing.T) { + newObject := cs.GetNewWorkload() + cli := fake.NewClientBuilder().WithScheme(scheme).WithObjects(releaseDeploy.DeepCopy()).Build() + handler := workloadEventHandler{Reader: cli} + deleteQ := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) + deleteEvt := event.DeleteEvent{ + Object: newObject, + } + handler.Delete(deleteEvt, deleteQ) + Expect(deleteQ.Len()).Should(Equal(cs.ExpectedQueueLen)) + }) + } +} diff --git a/pkg/controller/batchrelease/batchrelease_plan_controller.go b/pkg/controller/batchrelease/batchrelease_plan_executor.go similarity index 89% rename from pkg/controller/batchrelease/batchrelease_plan_controller.go rename to pkg/controller/batchrelease/batchrelease_plan_executor.go index dba4a7f..815ef95 100644 --- a/pkg/controller/batchrelease/batchrelease_plan_controller.go +++ b/pkg/controller/batchrelease/batchrelease_plan_executor.go @@ -52,7 +52,7 @@ func (r *Executor) SetReleaseInfo(release *v1alpha1.BatchRelease) { // Do execute the release plan func (r *Executor) Do() (reconcile.Result, *v1alpha1.BatchReleaseStatus) { klog.V(3).InfoS("Reconcile the release plan", - "target-workload", r.release.Spec.TargetRef.Name) + "target-workload", r.release.Spec.TargetRef.WorkloadRef.Name) klog.V(3).InfoS("release-status:", "release-phase", r.releaseStatus.Phase, @@ -77,34 +77,29 @@ func (r *Executor) executeBatchReleasePlan(workloadController workloads.Workload retryDuration := reconcile.Result{} switch status.Phase { - case v1alpha1.RolloutPhaseHealthy: - r.releaseStatus.Phase = v1alpha1.RolloutPhaseVerify - fallthrough + case v1alpha1.RolloutPhaseInitial: + // if this batchRelease was created but workload doest not exist, + // should keep this phase and do nothing util workload is created. - case v1alpha1.RolloutPhaseVerify: - klog.V(3).Infof("ReleasePlan State Machine into %s state", v1alpha1.RolloutPhaseVerify) + case v1alpha1.RolloutPhaseHealthy: + klog.V(3).Infof("ReleasePlan State Machine into %s state", v1alpha1.RolloutPhaseHealthy) // verify whether the workload is ready to execute the release plan in this state. - verified, err := workloadController.VerifySpec() + needed, err := workloadController.IfNeedToProgress() switch { case err != nil: setCondition(r.releaseStatus, "VerifyWorkloadError", err.Error(), v1.ConditionFalse) - case verified: + case needed: setCondition(r.releaseStatus, "VerifyWorkloadSuccessfully", "", v1.ConditionTrue) - status.Phase = v1alpha1.RolloutPhaseInitial + status.Phase = v1alpha1.RolloutPhasePreparing fallthrough default: retryDuration = reconcile.Result{RequeueAfter: DefaultShortDuration} } - case v1alpha1.RolloutPhaseInitial: - klog.V(3).Infof("ReleasePlan State Machine into %s state", v1alpha1.RolloutPhaseInitial) - r.releaseStatus.Phase = v1alpha1.RolloutPhasePreparing - fallthrough - case v1alpha1.RolloutPhasePreparing: klog.V(3).Infof("ReleasePlan State Machine into %s state", v1alpha1.RolloutPhasePreparing) // prepare and initialize something before progressing in this state. - initialized, err := workloadController.Initialize() + initialized, err := workloadController.Prepare() switch { case err != nil: setCondition(r.releaseStatus, "InitializeError", err.Error(), v1.ConditionFalse) @@ -120,8 +115,7 @@ func (r *Executor) executeBatchReleasePlan(workloadController workloads.Workload klog.V(3).Infof("ReleasePlan State Machine into %s state", v1alpha1.RolloutPhaseProgressing) // progress the release plan in this state. var progressDone bool - progressDone, retryDuration = r.progressBatches(workloadController) - if progressDone { + if progressDone, retryDuration = r.progressBatches(workloadController); progressDone { setCondition(r.releaseStatus, "ProgressSuccessfully", "", v1.ConditionTrue) status.Phase = v1alpha1.RolloutPhaseFinalizing } @@ -132,33 +126,39 @@ func (r *Executor) executeBatchReleasePlan(workloadController workloads.Workload if succeed := workloadController.Finalize(false, false); succeed { cleanupConditions(status) status.Phase = v1alpha1.RolloutPhaseCompleted + } else { + retryDuration = reconcile.Result{RequeueAfter: DefaultShortDuration} } - retryDuration = reconcile.Result{RequeueAfter: DefaultShortDuration} - case v1alpha1.RolloutPhaseRollingBack: - klog.V(3).Infof("ReleasePlan State Machine into %s state", v1alpha1.RolloutPhaseRollingBack) + case v1alpha1.RolloutPhaseRollback: + klog.V(3).Infof("ReleasePlan State Machine into %s state", v1alpha1.RolloutPhaseRollback) // restore the workload in this state - cleanup := metav1.GetControllerOf(r.release) == nil - if succeed := workloadController.Finalize(false, cleanup); succeed { + pause, clean := false, true + if workloads.IsControlledByRollout(r.release) { + pause, clean = true, false + } + if succeed := workloadController.Finalize(pause, clean); succeed { cleanupConditions(status) status.Phase = v1alpha1.RolloutPhaseCancelled + } else { + retryDuration = reconcile.Result{RequeueAfter: DefaultShortDuration} } - retryDuration = reconcile.Result{RequeueAfter: DefaultShortDuration} - - case v1alpha1.RolloutPhaseCompleted: - klog.V(3).Infof("ReleasePlan State Machine into %s state", v1alpha1.RolloutPhaseCompleted) - // this state indicates that the plan is executed successfully, should do nothing in this state. case v1alpha1.RolloutPhaseTerminating: klog.V(3).Infof("ReleasePlan State Machine into %s state", v1alpha1.RolloutPhaseTerminating) - if succeed := workloadController.Finalize(true, true); succeed { + if succeed := workloadController.Finalize(false, true); succeed { if r.release.DeletionTimestamp != nil { setCondition(status, v1alpha1.TerminatingReasonInTerminating, "Release plan was cancelled or deleted", v1.ConditionTrue) } else { status.Phase = v1alpha1.RolloutPhaseCancelled } + } else { + retryDuration = reconcile.Result{RequeueAfter: DefaultShortDuration} } - retryDuration = reconcile.Result{RequeueAfter: DefaultShortDuration} + + case v1alpha1.RolloutPhaseCompleted: + klog.V(3).Infof("ReleasePlan State Machine into %s state", v1alpha1.RolloutPhaseCompleted) + // this state indicates that the plan is executed successfully, should do nothing in this state. case v1alpha1.RolloutPhaseCancelled: klog.V(3).Infof("ReleasePlan State Machine into %s state", v1alpha1.RolloutPhaseCancelled) @@ -231,7 +231,7 @@ func (r *Executor) progressBatches(workloadController workloads.WorkloadControll // GetWorkloadController pick the right workload controller to work on the workload func (r *Executor) GetWorkloadController() (workloads.WorkloadController, error) { - targetRef := r.release.Spec.TargetRef + targetRef := r.release.Spec.TargetRef.WorkloadRef targetKey := types.NamespacedName{ Namespace: r.release.Namespace, Name: targetRef.Name, diff --git a/pkg/controller/batchrelease/batchrelease_special_cases_handler.go b/pkg/controller/batchrelease/batchrelease_special_cases_handler.go index 9b900b6..f9e20d4 100644 --- a/pkg/controller/batchrelease/batchrelease_special_cases_handler.go +++ b/pkg/controller/batchrelease/batchrelease_special_cases_handler.go @@ -1,10 +1,10 @@ package batchrelease import ( - "k8s.io/apimachinery/pkg/api/errors" "time" v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" @@ -15,6 +15,7 @@ import ( const ( Keep = "Keep" + Start = "Start" Restart = "Restart" RollingBack = "RollingBack" Terminating = "Terminating" @@ -32,8 +33,8 @@ func (r *Executor) handleSpecialCases(controller workloads.WorkloadController) ( // Note: must keep the order of the following cases switch { case r.releasePlanTerminating(): - reason = "PlanCancelled" - message = "release plan is cancelled, clean up and stop reconcile" + reason = "PlanTerminating" + message = "release plan is terminating, clean up and stop reconcile" needStopThisRound = false action = Terminating @@ -59,16 +60,20 @@ func (r *Executor) handleSpecialCases(controller workloads.WorkloadController) ( case r.releasePlanUnhealthy(): reason = "PlanStatusUnhealthy" message = "release plan status is unhealthy, try to restart release plan" - needStopThisRound = false + needStopThisRound = true action = Restart case r.releasePlanChanged(): reason = "PlanChanged" message = "release plan was changed, try to recalculate canary status" - needStopThisRound = false + needStopThisRound = true action = Recalculate - case workloadEvent == workloads.WorkloadStableOrRollback: + case r.locatedWorkloadAndStart(err): + needStopThisRound = false + action = Start + + case workloadEvent == workloads.WorkloadRollback: reason = "StableOrRollback" message = "workload is table or rolling back, stop the release plan" needStopThisRound = false @@ -83,7 +88,7 @@ func (r *Executor) handleSpecialCases(controller workloads.WorkloadController) ( case workloadEvent == workloads.WorkloadPodTemplateChanged: reason = "RevisionChanged" message = "workload revision was changed, try to restart release plan" - needStopThisRound = false + needStopThisRound = true action = Restart case workloadEvent == workloads.WorkloadUnHealthy: @@ -140,14 +145,18 @@ func (r *Executor) handleSpecialCases(controller workloads.WorkloadController) ( switch action { case Keep: // keep current status, do nothing - case Restart: - signalRestart(r.releaseStatus) - case Recalculate: - signalRecalculate(r.releaseStatus) + case Start: + signalStart(r.releaseStatus) case RollingBack: signalRollingBack(r.releaseStatus) case Terminating: signalTerminating(r.releaseStatus) + case Restart: + signalRestart(r.releaseStatus) + result = reconcile.Result{RequeueAfter: DefaultShortDuration} + case Recalculate: + signalRecalculate(r.releaseStatus) + result = reconcile.Result{RequeueAfter: DefaultShortDuration} } return needStopThisRound, result @@ -165,8 +174,12 @@ func (r *Executor) releasePlanChanged() bool { return r.isProgressing() && r.releaseStatus.ObservedReleasePlanHash != hashReleasePlanBatches(r.releasePlan) } +func (r *Executor) locatedWorkloadAndStart(err error) bool { + return err == nil && r.releaseStatus.Phase == v1alpha1.RolloutPhaseInitial +} + func (r *Executor) workloadHasGone(err error) bool { - return !r.isTerminating() && errors.IsNotFound(err) + return !r.isTerminating() && r.releaseStatus.Phase != v1alpha1.RolloutPhaseInitial && errors.IsNotFound(err) } func (r *Executor) releasePlanPaused() bool { @@ -178,9 +191,10 @@ func (r *Executor) releasePlanPaused() bool { } func (r *Executor) isTerminating() bool { - return r.release.Spec.Cancelled || - r.release.DeletionTimestamp != nil || - r.release.Status.Phase == v1alpha1.RolloutPhaseTerminating + return r.release.DeletionTimestamp != nil || + r.release.Status.Phase == v1alpha1.RolloutPhaseTerminating || + (r.release.Spec.Cancelled && r.releaseStatus.Phase != v1alpha1.RolloutPhaseCancelled) + } func (r *Executor) isProgressing() bool { diff --git a/pkg/controller/batchrelease/batchrelease_util.go b/pkg/controller/batchrelease/batchrelease_util.go index e2f2ef5..f948758 100644 --- a/pkg/controller/batchrelease/batchrelease_util.go +++ b/pkg/controller/batchrelease/batchrelease_util.go @@ -34,6 +34,10 @@ func initializeStatusIfNeeds(status *v1alpha1.BatchReleaseStatus) { } } +func signalStart(status *v1alpha1.BatchReleaseStatus) { + status.Phase = v1alpha1.RolloutPhaseHealthy +} + func signalRestart(status *v1alpha1.BatchReleaseStatus) { resetStatus(status) } @@ -47,11 +51,11 @@ func signalTerminating(status *v1alpha1.BatchReleaseStatus) { } func signalRollingBack(status *v1alpha1.BatchReleaseStatus) { - status.Phase = v1alpha1.RolloutPhaseRollingBack + status.Phase = v1alpha1.RolloutPhaseRollback } func resetStatus(status *v1alpha1.BatchReleaseStatus) { - status.Phase = v1alpha1.RolloutPhaseHealthy + status.Phase = v1alpha1.RolloutPhaseInitial status.StableRevision = "" status.UpdateRevision = "" status.ObservedReleasePlanHash = "" diff --git a/pkg/controller/batchrelease/workloads/cloneset_control_plan.go b/pkg/controller/batchrelease/workloads/cloneset_control_plan.go index 13cf7c2..532cd74 100644 --- a/pkg/controller/batchrelease/workloads/cloneset_control_plan.go +++ b/pkg/controller/batchrelease/workloads/cloneset_control_plan.go @@ -40,8 +40,8 @@ func NewCloneSetRolloutController(client client.Client, recorder record.EventRec } } -// VerifySpec verifies that the rollout resource is consistent with the rollout spec -func (c *CloneSetRolloutController) VerifySpec() (bool, error) { +// IfNeedToProgress verifies that the workload is ready to execute release plan +func (c *CloneSetRolloutController) IfNeedToProgress() (bool, error) { var verifyErr error defer func() { if verifyErr != nil { @@ -76,8 +76,8 @@ func (c *CloneSetRolloutController) VerifySpec() (bool, error) { return true, nil } -// Initialize makes sure that the source and target CloneSet is under our control -func (c *CloneSetRolloutController) Initialize() (bool, error) { +// Prepare makes sure that the source and target CloneSet is under our control +func (c *CloneSetRolloutController) Prepare() (bool, error) { if err := c.fetchCloneSet(); err != nil { //c.releaseStatus.RolloutRetry(err.Error()) return false, nil @@ -185,16 +185,16 @@ func (c *CloneSetRolloutController) Finalize(pause, cleanup bool) bool { } // WatchWorkload return change type if workload was changed during release -func (c *CloneSetRolloutController) WatchWorkload() (WorkloadChangeEventType, *Accessor, error) { +func (c *CloneSetRolloutController) WatchWorkload() (WorkloadChangeEventType, *WorkloadAccessor, error) { if c.parentController.Spec.Cancelled || c.parentController.DeletionTimestamp != nil || c.releaseStatus.Phase == v1alpha1.RolloutPhaseFinalizing || - c.releaseStatus.Phase == v1alpha1.RolloutPhaseRollingBack || + c.releaseStatus.Phase == v1alpha1.RolloutPhaseRollback || c.releaseStatus.Phase == v1alpha1.RolloutPhaseTerminating { return IgnoreWorkloadEvent, nil, nil } - workloadInfo := &Accessor{} + workloadInfo := &WorkloadAccessor{} err := c.fetchCloneSet() if client.IgnoreNotFound(err) != nil { return "", nil, err @@ -219,15 +219,12 @@ func (c *CloneSetRolloutController) WatchWorkload() (WorkloadChangeEventType, *A } switch c.releaseStatus.Phase { - case v1alpha1.RolloutPhaseHealthy, v1alpha1.RolloutPhaseVerify: - return IgnoreWorkloadEvent, workloadInfo, nil - default: if c.clone.Status.CurrentRevision == c.clone.Status.UpdateRevision && c.parentController.Status.UpdateRevision != c.clone.Status.UpdateRevision { workloadInfo.UpdateRevision = &c.clone.Status.UpdateRevision klog.Warning("CloneSet is stable or is rolling back, release plan should stop") - return WorkloadStableOrRollback, workloadInfo, nil + return WorkloadRollback, workloadInfo, nil } if *c.clone.Spec.Replicas != c.releaseStatus.ObservedWorkloadReplicas { workloadInfo.Replicas = c.clone.Spec.Replicas @@ -244,6 +241,9 @@ func (c *CloneSetRolloutController) WatchWorkload() (WorkloadChangeEventType, *A c.releaseStatus.UpdateRevision, c.clone.Status.UpdateRevision) return WorkloadPodTemplateChanged, workloadInfo, nil } + + case v1alpha1.RolloutPhaseHealthy, v1alpha1.RolloutPhaseInitial: + return IgnoreWorkloadEvent, workloadInfo, nil } return IgnoreWorkloadEvent, workloadInfo, nil diff --git a/pkg/controller/batchrelease/workloads/cloneset_controller.go b/pkg/controller/batchrelease/workloads/cloneset_controller.go index 6772aff..365bafe 100644 --- a/pkg/controller/batchrelease/workloads/cloneset_controller.go +++ b/pkg/controller/batchrelease/workloads/cloneset_controller.go @@ -32,8 +32,8 @@ func (c *cloneSetController) claimCloneSet(clone *kruiseappsv1alpha1.CloneSet) ( ref := &metav1.OwnerReference{} err := json.Unmarshal([]byte(controlInfo), ref) if err == nil && ref.UID == c.parentController.UID { - klog.V(3).Info("CloneSet has been controlled by this BatchRelease, no need to claim again") controlled = true + klog.V(3).Info("CloneSet has been controlled by this BatchRelease, no need to claim again") } else { klog.Error("Failed to parse controller info from cloneset annotation, error: %v, controller info: %+v", err, *ref) } @@ -84,7 +84,7 @@ func (c *cloneSetController) claimCloneSet(clone *kruiseappsv1alpha1.CloneSet) ( } klog.V(3).Info("Claim CloneSet Successfully") - return false, nil + return true, nil } // remove the parent controller from the deployment's owner list @@ -116,6 +116,15 @@ func (c *cloneSetController) releaseCloneSet(clone *kruiseappsv1alpha1.CloneSet, "paused": pause, }, } + + if len(clone.Annotations[StashCloneSetPartition]) > 0 { + restoredPartition := &intstr.IntOrString{} + if err := json.Unmarshal([]byte(clone.Annotations[StashCloneSetPartition]), restoredPartition); err == nil { + updateStrategy := patchSpec["updateStrategy"].(map[string]interface{}) + updateStrategy["partition"] = restoredPartition + } + } + patchSpecByte, _ := json.Marshal(patchSpec) patchByte := fmt.Sprintf(`{"metadata":{"annotations":{"%s":null, "%s":null}},"spec":%s}`, BatchReleaseControlAnnotation, StashCloneSetPartition, string(patchSpecByte)) @@ -126,7 +135,7 @@ func (c *cloneSetController) releaseCloneSet(clone *kruiseappsv1alpha1.CloneSet, } klog.V(3).Info("Release CloneSet Successfully") - return false, nil + return true, nil } // scale the deployment @@ -141,8 +150,8 @@ func (c *cloneSetController) patchCloneSetPartition(clone *kruiseappsv1alpha1.Cl patchByte, _ := json.Marshal(patch) if err := c.client.Patch(context.TODO(), clone, client.RawPatch(types.MergePatchType, patchByte)); err != nil { - c.recorder.Eventf(c.parentController, v1.EventTypeWarning, "PatchPartitionFailed", "Failed to update the CloneSet to the correct target partition %d, error: %v", partition, err) - //c.releaseStatus.RolloutRetry(err.Error()) + c.recorder.Eventf(c.parentController, v1.EventTypeWarning, "PatchPartitionFailed", + "Failed to update the CloneSet to the correct target partition %d, error: %v", partition, err) return err } diff --git a/pkg/controller/batchrelease/workloads/cloneset_controller_test.go b/pkg/controller/batchrelease/workloads/cloneset_controller_test.go new file mode 100644 index 0000000..49dee48 --- /dev/null +++ b/pkg/controller/batchrelease/workloads/cloneset_controller_test.go @@ -0,0 +1,196 @@ +package workloads + +import ( + "context" + "fmt" + "reflect" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + apps "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/intstr" + apimachineryruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/uuid" + "k8s.io/client-go/tools/record" + "k8s.io/utils/pointer" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + kruiseappsv1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1" + "github.com/openkruise/rollouts/api/v1alpha1" +) + +var ( + scheme *runtime.Scheme + releaseClone = &v1alpha1.BatchRelease{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1alpha1.GroupVersion.String(), + Kind: "BatchRelease", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "release", + Namespace: "application", + UID: uuid.NewUUID(), + }, + Spec: v1alpha1.BatchReleaseSpec{ + TargetRef: v1alpha1.ObjectRef{ + WorkloadRef: &v1alpha1.WorkloadRef{ + APIVersion: "apps.kruise.io/v1alpha1", + Kind: "CloneSet", + Name: "sample", + }, + }, + ReleasePlan: v1alpha1.ReleasePlan{ + Batches: []v1alpha1.ReleaseBatch{ + { + CanaryReplicas: intstr.FromString("10%"), + PauseSeconds: 100, + }, + { + CanaryReplicas: intstr.FromString("50%"), + PauseSeconds: 100, + }, + { + CanaryReplicas: intstr.FromString("80%"), + PauseSeconds: 100, + }, + }, + }, + }, + } + + stableClone = &kruiseappsv1alpha1.CloneSet{ + TypeMeta: metav1.TypeMeta{ + APIVersion: kruiseappsv1alpha1.SchemeGroupVersion.String(), + Kind: "CloneSet", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sample", + Namespace: "application", + UID: types.UID("87076677"), + Generation: 1, + Labels: map[string]string{ + "app": "busybox", + }, + }, + Spec: kruiseappsv1alpha1.CloneSetSpec{ + Replicas: pointer.Int32Ptr(100), + UpdateStrategy: kruiseappsv1alpha1.CloneSetUpdateStrategy{ + Partition: &intstr.IntOrString{Type: intstr.Int, IntVal: int32(1)}, + MaxSurge: &intstr.IntOrString{Type: intstr.Int, IntVal: int32(2)}, + MaxUnavailable: &intstr.IntOrString{Type: intstr.Int, IntVal: int32(2)}, + }, + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app": "busybox", + }, + }, + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + Containers: containers("v2"), + }, + }, + }, + Status: kruiseappsv1alpha1.CloneSetStatus{ + Replicas: 100, + ReadyReplicas: 100, + UpdatedReplicas: 0, + UpdatedReadyReplicas: 0, + ObservedGeneration: 1, + }, + } +) + +func init() { + scheme = runtime.NewScheme() + apimachineryruntime.Must(apps.AddToScheme(scheme)) + apimachineryruntime.Must(v1alpha1.AddToScheme(scheme)) + apimachineryruntime.Must(kruiseappsv1alpha1.AddToScheme(scheme)) + + canaryTemplate := stableClone.Spec.Template.DeepCopy() + stableTemplate := canaryTemplate.DeepCopy() + stableTemplate.Spec.Containers = containers("v1") + stableClone.Status.CurrentRevision = ComputeHash(stableTemplate, nil) + stableClone.Status.UpdateRevision = ComputeHash(canaryTemplate, nil) +} + +func TestCloneSetController(t *testing.T) { + RegisterFailHandler(Fail) + + cases := []struct { + Name string + Paused bool + Cleanup bool + }{ + { + Name: "paused=true, cleanup=true", + Paused: true, + Cleanup: true, + }, + { + Name: "paused=true, cleanup=false", + Paused: true, + Cleanup: false, + }, + { + Name: "paused=false cleanup=true", + Paused: false, + Cleanup: true, + }, + { + Name: "paused=false , cleanup=false", + Paused: false, + Cleanup: false, + }, + } + + for _, cs := range cases { + t.Run(cs.Name, func(t *testing.T) { + cli := fake.NewClientBuilder().WithScheme(scheme).WithObjects(releaseClone.DeepCopy(), stableClone.DeepCopy()).Build() + rec := record.NewFakeRecorder(100) + c := cloneSetController{ + workloadController: workloadController{ + client: cli, + recorder: rec, + parentController: releaseClone, + releasePlan: &releaseClone.Spec.ReleasePlan, + releaseStatus: &releaseClone.Status, + }, + targetNamespacedName: client.ObjectKeyFromObject(stableClone), + } + oldObject := &kruiseappsv1alpha1.CloneSet{} + Expect(cli.Get(context.TODO(), c.targetNamespacedName, oldObject)).NotTo(HaveOccurred()) + succeed, err := c.claimCloneSet(oldObject.DeepCopy()) + Expect(succeed).Should(BeTrue()) + Expect(err).NotTo(HaveOccurred()) + + newObject := &kruiseappsv1alpha1.CloneSet{} + Expect(cli.Get(context.TODO(), c.targetNamespacedName, newObject)).NotTo(HaveOccurred()) + succeed, err = c.releaseCloneSet(newObject.DeepCopy(), cs.Paused, cs.Cleanup) + Expect(succeed).Should(BeTrue()) + Expect(err).NotTo(HaveOccurred()) + + newObject = &kruiseappsv1alpha1.CloneSet{} + Expect(cli.Get(context.TODO(), c.targetNamespacedName, newObject)).NotTo(HaveOccurred()) + newObject.Spec.UpdateStrategy.Paused = oldObject.Spec.UpdateStrategy.Paused + Expect(reflect.DeepEqual(oldObject.Spec, newObject.Spec)).Should(BeTrue()) + Expect(reflect.DeepEqual(oldObject.Labels, newObject.Labels)).Should(BeTrue()) + Expect(reflect.DeepEqual(oldObject.Finalizers, newObject.Finalizers)).Should(BeTrue()) + Expect(reflect.DeepEqual(oldObject.Annotations, newObject.Annotations)).Should(BeTrue()) + }) + } +} + +func containers(version string) []corev1.Container { + return []corev1.Container{ + { + Name: "busybox", + Image: fmt.Sprintf("busybox:%v", version), + }, + } +} diff --git a/pkg/controller/batchrelease/workloads/controller.go b/pkg/controller/batchrelease/workloads/controller.go index 09b76b7..4351e97 100644 --- a/pkg/controller/batchrelease/workloads/controller.go +++ b/pkg/controller/batchrelease/workloads/controller.go @@ -12,7 +12,7 @@ type WorkloadChangeEventType string const ( IgnoreWorkloadEvent WorkloadChangeEventType = "workload-not-cared" - WorkloadStableOrRollback WorkloadChangeEventType = "workload-rollback" + WorkloadRollback WorkloadChangeEventType = "workload-rollback" WorkloadPodTemplateChanged WorkloadChangeEventType = "workload-pod-template-changed" WorkloadReplicasChanged WorkloadChangeEventType = "workload-replicas-changed" WorkloadStillReconciling WorkloadChangeEventType = "workload-is-reconciling" @@ -21,14 +21,14 @@ const ( // WorkloadController is the interface that all type of cloneSet controller implements type WorkloadController interface { - // VerifySpec makes sure that the resources can be upgraded according to the rollout plan + // IfNeedToProgress makes sure that the resources can be upgraded according to the rollout plan // it returns if the verification succeeded/failed or should retry - VerifySpec() (bool, error) + IfNeedToProgress() (bool, error) - // Initialize make sure that the resource is ready to be upgraded + // Prepare make sure that the resource is ready to be upgraded // this function is tasked to do any initialization work on the resources // it returns if the initialization succeeded/failed or should retry - Initialize() (bool, error) + Prepare() (bool, error) // RolloutOneBatchPods tries to upgrade pods in the resources following the rollout plan // it will upgrade pods as the rollout plan allows at once @@ -52,7 +52,7 @@ type WorkloadController interface { // WatchWorkload will observe and compare the status recorded in release.status and the real-time // workload status. If workload status is inconsistent with that recorded in release.status, // will return the corresponding WorkloadChangeEventType and info. - WatchWorkload() (WorkloadChangeEventType, *Accessor, error) + WatchWorkload() (WorkloadChangeEventType, *WorkloadAccessor, error) } type Status struct { @@ -63,7 +63,7 @@ type Status struct { ObservedGeneration int64 } -type Accessor struct { +type WorkloadAccessor struct { Replicas *int32 Paused bool Status *Status diff --git a/pkg/controller/batchrelease/workloads/deployment_double_control_plan.go b/pkg/controller/batchrelease/workloads/deployment_double_control_plan.go index d825f62..b81693b 100644 --- a/pkg/controller/batchrelease/workloads/deployment_double_control_plan.go +++ b/pkg/controller/batchrelease/workloads/deployment_double_control_plan.go @@ -3,9 +3,6 @@ package workloads import ( "context" "fmt" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sort" - apps "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -16,6 +13,8 @@ import ( "k8s.io/client-go/tools/record" "k8s.io/klog/v2" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sort" "github.com/openkruise/rollouts/api/v1alpha1" ) @@ -50,8 +49,8 @@ func NewDeploymentRolloutController(client client.Client, recorder record.EventR } } -// VerifySpec verifies that the rollout resource is consistent with the rollout spec -func (c *DeploymentsRolloutController) VerifySpec() (bool, error) { +// IfNeedToProgress verifies that the workload is ready to execute release plan +func (c *DeploymentsRolloutController) IfNeedToProgress() (bool, error) { var verifyErr error defer func() { @@ -90,8 +89,8 @@ func (c *DeploymentsRolloutController) VerifySpec() (bool, error) { return true, nil } -// Initialize makes sure that the source and target Deployment is under our control -func (c *DeploymentsRolloutController) Initialize() (bool, error) { +// Prepare makes sure that the source and target Deployment is under our control +func (c *DeploymentsRolloutController) Prepare() (bool, error) { if err := c.fetchStableDeployment(); err != nil { //c.releaseStatus.RolloutRetry(err.Error()) return false, nil @@ -201,17 +200,17 @@ func (c *DeploymentsRolloutController) Finalize(pause, cleanup bool) bool { } // WatchWorkload return change type if workload was changed during release -func (c *DeploymentsRolloutController) WatchWorkload() (WorkloadChangeEventType, *Accessor, error) { +func (c *DeploymentsRolloutController) WatchWorkload() (WorkloadChangeEventType, *WorkloadAccessor, error) { if c.parentController.Spec.Cancelled || c.parentController.DeletionTimestamp != nil || c.releaseStatus.Phase == v1alpha1.RolloutPhaseFinalizing || - c.releaseStatus.Phase == v1alpha1.RolloutPhaseRollingBack || + c.releaseStatus.Phase == v1alpha1.RolloutPhaseRollback || c.releaseStatus.Phase == v1alpha1.RolloutPhaseTerminating { return IgnoreWorkloadEvent, nil, nil } var err error - workloadInfo := &Accessor{} + workloadInfo := &WorkloadAccessor{} err = c.fetchStableDeployment() if err != nil { return "", nil, err @@ -247,7 +246,7 @@ func (c *DeploymentsRolloutController) WatchWorkload() (WorkloadChangeEventType, var updateRevision string switch c.releaseStatus.Phase { - case v1alpha1.RolloutPhaseHealthy, v1alpha1.RolloutPhaseVerify: + case v1alpha1.RolloutPhaseInitial, v1alpha1.RolloutPhaseHealthy: return IgnoreWorkloadEvent, workloadInfo, nil default: @@ -255,7 +254,7 @@ func (c *DeploymentsRolloutController) WatchWorkload() (WorkloadChangeEventType, return "", workloadInfo, err } else if isRollingBack { workloadInfo.UpdateRevision = &updateRevision - return WorkloadStableOrRollback, workloadInfo, nil + return WorkloadRollback, workloadInfo, nil } if *c.stable.Spec.Replicas != c.releaseStatus.ObservedWorkloadReplicas { workloadInfo.Replicas = c.stable.Spec.Replicas @@ -266,12 +265,8 @@ func (c *DeploymentsRolloutController) WatchWorkload() (WorkloadChangeEventType, fallthrough case v1alpha1.RolloutPhaseCompleted, v1alpha1.RolloutPhaseCancelled: - realStableRevision, err := c.GetPodTemplateHash(c.stable, "stable") - if err != nil { - return "", workloadInfo, err - } - if (c.canary == nil || !EqualIgnoreHash(&c.stable.Spec.Template, &c.canary.Spec.Template)) && - c.releaseStatus.UpdateRevision != realStableRevision { + _, err = c.GetPodTemplateHash(c.stable, Latest) + if (c.canary == nil || !EqualIgnoreHash(&c.stable.Spec.Template, &c.canary.Spec.Template)) && apierrors.IsNotFound(err) { workloadInfo.UpdateRevision = &updateRevision klog.Warning("Deployment updateRevision changed during releasing, should try to restart the release plan") return WorkloadPodTemplateChanged, workloadInfo, nil @@ -374,11 +369,11 @@ func (c *DeploymentsRolloutController) recordDeploymentRevisionAndReplicas() err return claimErr } - c.releaseStatus.StableRevision, err = c.GetPodTemplateHash(c.stable, "stable") + c.releaseStatus.StableRevision, err = c.GetPodTemplateHash(c.stable, Stable) if err != nil { return err } - c.releaseStatus.UpdateRevision, err = c.GetPodTemplateHash(c.canary, "canary") + c.releaseStatus.UpdateRevision, err = c.GetPodTemplateHash(c.canary, Latest) if err != nil { return err } @@ -386,9 +381,16 @@ func (c *DeploymentsRolloutController) recordDeploymentRevisionAndReplicas() err return nil } -func (c *DeploymentsRolloutController) GetPodTemplateHash(deploy *apps.Deployment, kind string) (string, error) { +type PodTemplateHashType string + +const ( + Latest PodTemplateHashType = "Latest" + Stable PodTemplateHashType = "Stable" +) + +func (c *DeploymentsRolloutController) GetPodTemplateHash(deploy *apps.Deployment, kind PodTemplateHashType) (string, error) { switch kind { - case "stable", "canary": + case Latest, Stable: if deploy == nil { return "", fmt.Errorf("workload cannot be found, may be deleted or not be created yet") } @@ -407,18 +409,23 @@ func (c *DeploymentsRolloutController) GetPodTemplateHash(deploy *apps.Deploymen for _, rs := range rss { switch kind { - case "stable": + case Stable: if rs.Spec.Replicas != nil && *rs.Spec.Replicas > 0 { return rs.Labels[apps.DefaultDeploymentUniqueLabelKey], nil } - case "canary": + case Latest: if EqualIgnoreHash(&deploy.Spec.Template, &rs.Spec.Template) { return rs.Labels[apps.DefaultDeploymentUniqueLabelKey], nil } } } - return "", fmt.Errorf("cannot find the suitable replicaset pod template hash, kind: %v", kind) + notFoundErr := apierrors.NewNotFound(schema.GroupResource{ + Group: apps.SchemeGroupVersion.Group, + Resource: fmt.Sprintf("%v-ReplicaSet", kind), + }, c.canaryNamespacedName.Name) + + return "", notFoundErr } func (c *DeploymentsRolloutController) listReplicaSetsFor(deploy *apps.Deployment) ([]*apps.ReplicaSet, error) { diff --git a/pkg/controller/batchrelease/workloads/deployment_double_controller.go b/pkg/controller/batchrelease/workloads/deployment_double_controller.go index 14cde57..b2bc6ca 100644 --- a/pkg/controller/batchrelease/workloads/deployment_double_controller.go +++ b/pkg/controller/batchrelease/workloads/deployment_double_controller.go @@ -5,7 +5,9 @@ import ( "encoding/json" "fmt" "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sort" + "time" apps "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" @@ -18,11 +20,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -const ( - CanaryDeploymentLabelKey = "rollouts.kruise.io/canary-deployment" - CanaryDeploymentFinalizer = "finalizer.rollouts.kruise.io/canary-deployment" -) - // deploymentController is the place to hold fields needed for handle Deployment type of workloads type deploymentController struct { workloadController @@ -33,6 +30,34 @@ type deploymentController struct { // add the parent controller to the owner of the deployment, unpause it and initialize the size // before kicking start the update and start from every pod in the old version func (c *deploymentController) claimDeployment(stableDeploy, canaryDeploy *apps.Deployment) (*apps.Deployment, error) { + var controlled bool + if controlInfo, ok := stableDeploy.Annotations[BatchReleaseControlAnnotation]; ok && controlInfo != "" { + ref := &metav1.OwnerReference{} + err := json.Unmarshal([]byte(controlInfo), ref) + if err == nil && ref.UID == c.parentController.UID { + klog.V(3).Info("CloneSet has been controlled by this BatchRelease, no need to claim again") + controlled = true + } else { + klog.Error("Failed to parse controller info from cloneset annotation, error: %v, controller info: %+v", err, *ref) + } + } + + if !controlled { + controlInfo, _ := json.Marshal(metav1.NewControllerRef(c.parentController, c.parentController.GetObjectKind().GroupVersionKind())) + patchedInfo := map[string]interface{}{ + "metadata": map[string]interface{}{ + "annotations": map[string]string{ + BatchReleaseControlAnnotation: string(controlInfo), + }, + }, + } + patchedBody, _ := json.Marshal(patchedInfo) + if err := c.client.Patch(context.TODO(), stableDeploy, client.RawPatch(types.StrategicMergePatchType, patchedBody)); err != nil { + klog.Error("Failed to patch controller info annotations to stable deployment(%v), error: %v", client.ObjectKeyFromObject(canaryDeploy), err) + return canaryDeploy, err + } + } + if canaryDeploy == nil || !EqualIgnoreHash(&stableDeploy.Spec.Template, &canaryDeploy.Spec.Template) { var err error var collisionCount int32 @@ -51,8 +76,11 @@ func (c *deploymentController) claimDeployment(stableDeploy, canaryDeploy *apps. break } - *c.releaseStatus.CollisionCount = collisionCount + if collisionCount > 0 { + c.releaseStatus.CollisionCount = pointer.Int32Ptr(collisionCount) + } } + return canaryDeploy, nil } @@ -96,18 +124,22 @@ func (c *deploymentController) createCanaryDeployment(stableDeploy *apps.Deploym canaryDeploy.Spec.Replicas = pointer.Int32Ptr(0) canaryDeploy.Spec.Paused = false + canaryKey := client.ObjectKeyFromObject(canaryDeploy) // create canary Deployment err := c.client.Create(context.TODO(), canaryDeploy) if err != nil { - klog.Errorf("Failed to create canary Deployment(%v), error: %v", c.canaryNamespacedName, err) + klog.Errorf("Failed to create canary Deployment(%v), error: %v", canaryKey, err) return nil, err } + canaryDeployInfo, _ := json.Marshal(canaryDeploy) + klog.V(3).Infof("Create canary deployment successfully, details: %+v", canaryDeployInfo) + // fetch the canary Deployment var fetchedCanary *apps.Deployment err = retry.RetryOnConflict(retry.DefaultRetry, func() error { fetchedCanary = &apps.Deployment{} - return c.client.Get(context.TODO(), c.canaryNamespacedName, fetchedCanary) + return c.client.Get(context.TODO(), canaryKey, fetchedCanary) }) return fetchedCanary, err @@ -119,6 +151,15 @@ func (c *deploymentController) releaseDeployment(stableDeploy *apps.Deployment, } var patchErr, deleteErr error + { + patchByte := []byte(fmt.Sprintf(`{"metadata":{"annotations":{"%v":null}},"spec":{"paused":%v}}`, BatchReleaseControlAnnotation, pause)) + patchErr = c.client.Patch(context.TODO(), stableDeploy, client.RawPatch(types.StrategicMergePatchType, patchByte)) + if patchErr != nil { + klog.Error("Error occurred when patching Deployment, error: %v", patchErr) + return false, patchErr + } + } + if cleanup { ds, err := c.listCanaryDeployment(client.InNamespace(stableDeploy.Namespace), client.MatchingLabels(map[string]string{CanaryDeploymentLabelKey: string(stableDeploy.UID)})) @@ -126,33 +167,40 @@ func (c *deploymentController) releaseDeployment(stableDeploy *apps.Deployment, return false, err } - // must delete the older first + // must make sure the older is deleted firstly sort.Slice(ds, func(i, j int) bool { return ds[i].CreationTimestamp.Before(&ds[j].CreationTimestamp) }) + // delete all the canary deployments for _, d := range ds { - finalizers := sets.NewString(d.Finalizers...).Delete(CanaryDeploymentFinalizer).List() - patchErr = PatchFinalizer(c.client, d, finalizers) - if patchErr != nil && !errors.IsNotFound(patchErr) { - klog.Error("Error occurred when patching Deployment, error: %v", patchErr) - return false, patchErr + // clean up finalizers first + if controllerutil.ContainsFinalizer(d, CanaryDeploymentFinalizer) { + finalizers := sets.NewString(d.Finalizers...).Delete(CanaryDeploymentFinalizer).List() + patchErr = PatchFinalizer(c.client, d, finalizers) + if patchErr != nil && !errors.IsNotFound(patchErr) { + klog.Error("Error occurred when patching Deployment, error: %v", patchErr) + return false, patchErr + } + time.Sleep(time.Second) } + // delete the deployment deleteErr = c.client.Delete(context.TODO(), d) if deleteErr != nil && !errors.IsNotFound(deleteErr) { klog.Error("Error occurred when deleting Deployment, error: %v", deleteErr) return false, deleteErr } + time.Sleep(time.Second) } - } - if stableDeploy.Spec.Paused != pause { - patchByte := []byte(fmt.Sprintf(`{"spec":{"paused":%v}}`, pause)) - patchErr = c.client.Patch(context.TODO(), stableDeploy, client.RawPatch(types.StrategicMergePatchType, patchByte)) - if patchErr != nil { - klog.Error("Error occurred when patching Deployment, error: %v", patchErr) - return false, patchErr + // make sure that all canary deployments has been deleted + ds, err = c.listCanaryDeployment(client.InNamespace(stableDeploy.Namespace), + client.MatchingLabels(map[string]string{CanaryDeploymentLabelKey: string(stableDeploy.UID)})) + if err != nil { + return false, err } + + return len(ds) == 0, nil } return true, nil diff --git a/pkg/controller/batchrelease/workloads/deployment_double_controller_test.go b/pkg/controller/batchrelease/workloads/deployment_double_controller_test.go new file mode 100644 index 0000000..6341065 --- /dev/null +++ b/pkg/controller/batchrelease/workloads/deployment_double_controller_test.go @@ -0,0 +1,172 @@ +package workloads + +import ( + "context" + "reflect" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + apps "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/apimachinery/pkg/util/uuid" + "k8s.io/client-go/tools/record" + "k8s.io/utils/pointer" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + "github.com/openkruise/rollouts/api/v1alpha1" +) + +var ( + releaseDeploy = &v1alpha1.BatchRelease{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1alpha1.GroupVersion.String(), + Kind: "BatchRelease", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "release", + Namespace: "application", + UID: uuid.NewUUID(), + }, + Spec: v1alpha1.BatchReleaseSpec{ + TargetRef: v1alpha1.ObjectRef{ + WorkloadRef: &v1alpha1.WorkloadRef{ + APIVersion: "apps/v1", + Kind: "Deployment", + Name: "sample", + }, + }, + ReleasePlan: v1alpha1.ReleasePlan{ + Batches: []v1alpha1.ReleaseBatch{ + { + CanaryReplicas: intstr.FromString("10%"), + PauseSeconds: 100, + }, + { + CanaryReplicas: intstr.FromString("50%"), + PauseSeconds: 100, + }, + { + CanaryReplicas: intstr.FromString("80%"), + PauseSeconds: 100, + }, + }, + }, + }, + } + + stableDeploy = &apps.Deployment{ + TypeMeta: metav1.TypeMeta{ + APIVersion: apps.SchemeGroupVersion.String(), + Kind: "Deployment", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sample", + Namespace: "application", + UID: types.UID("87076677"), + Generation: 2, + Labels: map[string]string{ + "app": "busybox", + apps.DefaultDeploymentUniqueLabelKey: "update-pod-hash", + }, + }, + Spec: apps.DeploymentSpec{ + Replicas: pointer.Int32Ptr(100), + Strategy: apps.DeploymentStrategy{ + Type: apps.RollingUpdateDeploymentStrategyType, + RollingUpdate: &apps.RollingUpdateDeployment{ + MaxSurge: &intstr.IntOrString{Type: intstr.Int, IntVal: int32(1)}, + MaxUnavailable: &intstr.IntOrString{Type: intstr.Int, IntVal: int32(2)}, + }, + }, + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app": "busybox", + }, + }, + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + Containers: containers("v2"), + }, + }, + }, + Status: apps.DeploymentStatus{ + Replicas: 100, + ReadyReplicas: 100, + UpdatedReplicas: 0, + AvailableReplicas: 100, + }, + } +) + +func TestDeploymentController(t *testing.T) { + RegisterFailHandler(Fail) + + cases := []struct { + Name string + Paused bool + Cleanup bool + }{ + { + Name: "paused=true, cleanup=true", + Paused: true, + Cleanup: true, + }, + { + Name: "paused=true, cleanup=false", + Paused: true, + Cleanup: false, + }, + { + Name: "paused=false cleanup=true", + Paused: false, + Cleanup: true, + }, + { + Name: "paused=false , cleanup=false", + Paused: false, + Cleanup: false, + }, + } + + for _, cs := range cases { + t.Run(cs.Name, func(t *testing.T) { + cli := fake.NewClientBuilder().WithScheme(scheme).WithObjects(releaseDeploy.DeepCopy(), stableDeploy.DeepCopy()).Build() + rec := record.NewFakeRecorder(100) + c := deploymentController{ + workloadController: workloadController{ + client: cli, + recorder: rec, + parentController: releaseDeploy, + releasePlan: &releaseDeploy.Spec.ReleasePlan, + releaseStatus: &releaseDeploy.Status, + }, + stableNamespacedName: client.ObjectKeyFromObject(stableDeploy), + canaryNamespacedName: client.ObjectKeyFromObject(stableDeploy), + } + oldObject := &apps.Deployment{} + Expect(cli.Get(context.TODO(), c.stableNamespacedName, oldObject)).NotTo(HaveOccurred()) + canary, err := c.claimDeployment(oldObject.DeepCopy(), nil) + Expect(canary).ShouldNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + + newObject := &apps.Deployment{} + Expect(cli.Get(context.TODO(), c.stableNamespacedName, newObject)).NotTo(HaveOccurred()) + succeed, err := c.releaseDeployment(newObject.DeepCopy(), cs.Paused, cs.Cleanup) + Expect(succeed).Should(BeTrue()) + Expect(err).NotTo(HaveOccurred()) + + newObject = &apps.Deployment{} + Expect(cli.Get(context.TODO(), c.stableNamespacedName, newObject)).NotTo(HaveOccurred()) + newObject.Spec.Paused = oldObject.Spec.Paused + Expect(reflect.DeepEqual(oldObject.Spec, newObject.Spec)).Should(BeTrue()) + Expect(reflect.DeepEqual(oldObject.Labels, newObject.Labels)).Should(BeTrue()) + Expect(reflect.DeepEqual(oldObject.Finalizers, newObject.Finalizers)).Should(BeTrue()) + Expect(reflect.DeepEqual(oldObject.Annotations, newObject.Annotations)).Should(BeTrue()) + }) + } +} diff --git a/pkg/controller/batchrelease/workloads/workloads_utils.go b/pkg/controller/batchrelease/workloads/workloads_utils.go index 1ef27d7..45ba2b7 100644 --- a/pkg/controller/batchrelease/workloads/workloads_utils.go +++ b/pkg/controller/batchrelease/workloads/workloads_utils.go @@ -22,6 +22,9 @@ import ( ) const ( + CanaryDeploymentLabelKey = "rollouts.kruise.io/canary-deployment" + CanaryDeploymentFinalizer = "finalizer.rollouts.kruise.io/batch-release" + // We omit vowels from the set of available characters to reduce the chances // of "bad words" being formed. alphanums = "bcdfghjklmnpqrstvwxz2456789" @@ -114,3 +117,11 @@ func PatchFinalizer(c client.Client, object client.Object, finalizers []string) }) return c.Patch(context.TODO(), object, client.RawPatch(types.MergePatchType, patchByte)) } + +func IsControlledByRollout(release *v1alpha1.BatchRelease) bool { + owner := metav1.GetControllerOf(release) + if owner != nil && owner.APIVersion == v1alpha1.GroupVersion.String() && owner.Kind == "Rollout" { + return true + } + return false +} diff --git a/test/e2e/batchrelease_test.go b/test/e2e/batchrelease_test.go index 199d8fd..f674bd5 100644 --- a/test/e2e/batchrelease_test.go +++ b/test/e2e/batchrelease_test.go @@ -181,7 +181,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &kruiseappsv1alpha1.CloneSet{} Expect(GetObject(cloneset.Namespace, cloneset.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas - }, time.Minute, time.Second).Should(Equal(int32(expectedUpdatedReplicas))) + }, 5*time.Minute, time.Second).Should(Equal(int32(expectedUpdatedReplicas))) time.Sleep(time.Duration(batch.PauseSeconds) * time.Second) } @@ -190,7 +190,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) }) It("V1->V2: Percentage, 50%, Succeeded", func() { @@ -227,7 +227,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &kruiseappsv1alpha1.CloneSet{} Expect(GetObject(cloneset.Namespace, cloneset.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas - }, time.Minute, time.Second).Should(Equal(int32(expectedUpdatedReplicas))) + }, 5*time.Minute, time.Second).Should(Equal(int32(expectedUpdatedReplicas))) time.Sleep(time.Duration(batch.PauseSeconds) * time.Second) } @@ -236,14 +236,14 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) By("Checking all pod were updated when release completed...") Eventually(func() int32 { clone := &kruiseappsv1alpha1.CloneSet{} Expect(GetObject(cloneset.Namespace, cloneset.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas - }, 5*time.Minute, time.Second).Should(Equal(*cloneset.Spec.Replicas)) + }, 15*time.Minute, time.Second).Should(Equal(*cloneset.Spec.Replicas)) }) It("V1->V2(Completed)->V3: Percentage, 100%, Succeeded", func() { @@ -284,7 +284,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &kruiseappsv1alpha1.CloneSet{} Expect(GetObject(cloneset.Namespace, cloneset.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas - }, time.Minute, time.Second).Should(Equal(int32(expectedUpdatedReplicas))) + }, 5*time.Minute, time.Second).Should(Equal(int32(expectedUpdatedReplicas))) time.Sleep(time.Duration(batch.PauseSeconds) * time.Second) } @@ -293,7 +293,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) /************************************************************************************* V1->V2 Succeeded, Start to release V2->V3 @@ -318,7 +318,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &kruiseappsv1alpha1.CloneSet{} Expect(GetObject(cloneset.Namespace, cloneset.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas - }, 20*time.Second, time.Second).Should(Equal(int32(expectedUpdatedReplicas))) + }, 5*time.Minute, time.Second).Should(Equal(int32(expectedUpdatedReplicas))) time.Sleep(time.Duration(batch.PauseSeconds) * time.Second) } @@ -327,7 +327,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) }) It("V1->V2(UnCompleted)->V3: Percentage, 100%, Succeeded", func() { @@ -368,7 +368,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &kruiseappsv1alpha1.CloneSet{} Expect(GetObject(cloneset.Namespace, cloneset.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas - }, time.Minute, time.Second).Should(Equal(int32(expectedUpdatedReplicas))) + }, 5*time.Minute, time.Second).Should(Equal(int32(expectedUpdatedReplicas))) time.Sleep(time.Duration(batch.PauseSeconds) * time.Second) } @@ -400,7 +400,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &kruiseappsv1alpha1.CloneSet{} Expect(GetObject(cloneset.Namespace, cloneset.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas - }, time.Minute, time.Second).Should(Equal(int32(expectedUpdatedReplicas))) + }, 5*time.Minute, time.Second).Should(Equal(int32(expectedUpdatedReplicas))) time.Sleep(time.Duration(batch.PauseSeconds) * time.Second) } @@ -409,7 +409,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) }) It("V1->V2: ScalingUp, Percentage, 100%, Succeeded", func() { @@ -463,14 +463,14 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, 10*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) By("Checking all pod were updated when release completed...") Eventually(func() bool { clone := &kruiseappsv1alpha1.CloneSet{} Expect(GetObject(cloneset.Namespace, cloneset.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas == *clone.Spec.Replicas - }, 10*time.Minute, time.Second).Should(BeTrue()) + }, 15*time.Minute, time.Second).Should(BeTrue()) }) It("V1->V2: ScalingDown, Percentage, 100%, Succeeded", func() { @@ -524,14 +524,14 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, 10*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) By("Checking all pod were updated when release completed...") Eventually(func() bool { clone := &kruiseappsv1alpha1.CloneSet{} Expect(GetObject(cloneset.Namespace, cloneset.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas == *clone.Spec.Replicas - }, 10*time.Minute, time.Second).Should(BeTrue()) + }, 15*time.Minute, time.Second).Should(BeTrue()) }) It("V1->V2: ScalingUp, Number, 100%, Succeeded", func() { @@ -585,14 +585,14 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, 10*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) By("Checking all pod were updated when release completed...") Eventually(func() bool { clone := &kruiseappsv1alpha1.CloneSet{} Expect(GetObject(cloneset.Namespace, cloneset.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas == *clone.Spec.Replicas - }, 10*time.Minute, time.Second).Should(BeTrue()) + }, 15*time.Minute, time.Second).Should(BeTrue()) }) It("V1->V2: ScalingDown, Number, 100%, Succeeded", func() { @@ -647,14 +647,14 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, 10*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) By("Checking all pod were updated when release completed...") Eventually(func() bool { clone := &kruiseappsv1alpha1.CloneSet{} Expect(GetObject(cloneset.Namespace, cloneset.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas == *clone.Spec.Replicas - }, 10*time.Minute, time.Second).Should(BeTrue()) + }, 15*time.Minute, time.Second).Should(BeTrue()) }) It("Rollback V1->V2->V1: Percentage, 100%, Succeeded", func() { @@ -700,14 +700,14 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &kruiseappsv1alpha1.CloneSet{} Expect(GetObject(cloneset.Namespace, cloneset.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas == *clone.Spec.Replicas - }, 10*time.Minute, time.Second).Should(BeTrue()) + }, 15*time.Minute, time.Second).Should(BeTrue()) By("Checking BatchRelease completed status phase...") Eventually(func() rolloutsv1alpha1.RolloutPhase { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, 10*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCancelled)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCancelled)) }) }) @@ -755,7 +755,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, 10*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) }) It("V1->V2: Percentage, 50%, Succeeded", func() { @@ -807,7 +807,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &apps.Deployment{} Expect(GetObject(deployment.Namespace, deployment.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas - }, 10*time.Minute, time.Second).Should(Equal(*deployment.Spec.Replicas)) + }, 15*time.Minute, time.Second).Should(Equal(*deployment.Spec.Replicas)) }) It("V1->V2(Completed)->V3: Percentage, 100%, Succeeded", func() { @@ -856,7 +856,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, 10*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) /************************************************************************************* V1->V2 Succeeded, Start to release V2->V3 @@ -889,7 +889,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, 10*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) }) It("V1->V2(UnCompleted)->V3: Percentage, 100%, Succeeded", func() { @@ -969,7 +969,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, 10*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) }) It("V1->V2: ScalingUp, Percentage, 100%, Succeeded", func() { @@ -1023,14 +1023,14 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, 10*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) By("Checking all pod were updated when release completed...") Eventually(func() int32 { clone := &apps.Deployment{} Expect(GetObject(deployment.Namespace, deployment.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas - }, 10*time.Minute, time.Second).Should(Equal(*deployment.Spec.Replicas)) + }, 15*time.Minute, time.Second).Should(Equal(*deployment.Spec.Replicas)) }) It("V1->V2: ScalingDown, Percentage, 100%, Succeeded", func() { @@ -1084,14 +1084,14 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, 10*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) By("Checking all pod were updated when release completed...") Eventually(func() bool { clone := &apps.Deployment{} Expect(GetObject(deployment.Namespace, deployment.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas == *clone.Spec.Replicas - }, 10*time.Minute, time.Second).Should(BeTrue()) + }, 15*time.Minute, time.Second).Should(BeTrue()) }) It("V1->V2: ScalingUp, Number, 100%, Succeeded", func() { @@ -1144,14 +1144,14 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, 10*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) By("Checking all pod were updated when release completed...") Eventually(func() bool { clone := &apps.Deployment{} Expect(GetObject(deployment.Namespace, deployment.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas == *clone.Spec.Replicas - }, 10*time.Minute, time.Second).Should(BeTrue()) + }, 15*time.Minute, time.Second).Should(BeTrue()) }) It("V1->V2: ScalingDown, Number, 100%, Succeeded", func() { @@ -1205,14 +1205,14 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, 10*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCompleted)) By("Checking all pod were updated when release completed...") Eventually(func() bool { clone := &apps.Deployment{} Expect(GetObject(deployment.Namespace, deployment.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas == *clone.Spec.Replicas - }, 10*time.Minute, time.Second).Should(BeTrue()) + }, 15*time.Minute, time.Second).Should(BeTrue()) }) It("Rollback V1->V2->V1: Percentage, 100%, Succeeded", func() { @@ -1262,14 +1262,14 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &apps.Deployment{} Expect(GetObject(deployment.Namespace, deployment.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas - }, 100*time.Second, time.Second).Should(Equal(*deployment.Spec.Replicas)) + }, 15*time.Minute, time.Second).Should(Equal(*deployment.Spec.Replicas)) By("Checking BatchRelease completed status phase...") Eventually(func() rolloutsv1alpha1.RolloutPhase { clone := &rolloutsv1alpha1.BatchRelease{} Expect(GetObject(release.Namespace, release.Name, clone)).NotTo(HaveOccurred()) return clone.Status.Phase - }, 100*time.Second, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCancelled)) + }, 15*time.Minute, time.Second).Should(Equal(rolloutsv1alpha1.RolloutPhaseCancelled)) }) It("Rollback V1->V2: Delete BatchRelease, Percentage, 100%, Succeeded", func() { @@ -1318,7 +1318,6 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { By("Updating cloneset to V1...") deployment.Spec.Template.Spec.Containers[0].Image = images.GetE2EImage(images.BusyBoxV1) UpdateDeployment(deployment) - // record canary revision --> v2 canaryRevisionV3 := workloads.ComputeHash(&deployment.Spec.Template, deployment.Status.CollisionCount) Expect(canaryRevisionV3).Should(Equal(stableRevisionV1)) @@ -1327,7 +1326,7 @@ var _ = SIGDescribe("Test BatchRelease Controller", func() { clone := &apps.Deployment{} Expect(GetObject(deployment.Namespace, deployment.Name, clone)).NotTo(HaveOccurred()) return clone.Status.UpdatedReplicas - }, 100*time.Second, time.Second).Should(Equal(*deployment.Spec.Replicas)) + }, 15*time.Minute, time.Second).Should(Equal(*deployment.Spec.Replicas)) }) }) }) diff --git a/test/e2e/test_data/batchrelease/cloneset_number_100.yaml b/test/e2e/test_data/batchrelease/cloneset_number_100.yaml index 5633904..f88ac67 100644 --- a/test/e2e/test_data/batchrelease/cloneset_number_100.yaml +++ b/test/e2e/test_data/batchrelease/cloneset_number_100.yaml @@ -4,18 +4,20 @@ metadata: name: release-cloneset-100 spec: targetReference: - apiVersion: apps.kruise.io/v1alpha1 - kind: CloneSet - name: sample + type: workloadRef + workloadRef: + apiVersion: apps.kruise.io/v1alpha1 + kind: CloneSet + name: sample releasePlan: batches: - canaryReplicas: 1 - pauseSeconds: 30 + pauseSeconds: 20 - canaryReplicas: 2 - pauseSeconds: 30 + pauseSeconds: 20 - canaryReplicas: 3 - pauseSeconds: 30 + pauseSeconds: 20 - canaryReplicas: 5 - pauseSeconds: 30 + pauseSeconds: 20 diff --git a/test/e2e/test_data/batchrelease/cloneset_percentage_100.yaml b/test/e2e/test_data/batchrelease/cloneset_percentage_100.yaml index 63edb42..e986b36 100644 --- a/test/e2e/test_data/batchrelease/cloneset_percentage_100.yaml +++ b/test/e2e/test_data/batchrelease/cloneset_percentage_100.yaml @@ -4,18 +4,20 @@ metadata: name: release-cloneset-100 spec: targetReference: - apiVersion: apps.kruise.io/v1alpha1 - kind: CloneSet - name: sample + type: workloadRef + workloadRef: + apiVersion: apps.kruise.io/v1alpha1 + kind: CloneSet + name: sample releasePlan: batches: - canaryReplicas: 20% - pauseSeconds: 30 + pauseSeconds: 20 - canaryReplicas: 40% - pauseSeconds: 30 + pauseSeconds: 20 - canaryReplicas: 60% - pauseSeconds: 30 + pauseSeconds: 20 - canaryReplicas: 100% - pauseSeconds: 30 + pauseSeconds: 10 diff --git a/test/e2e/test_data/batchrelease/cloneset_percentage_50.yaml b/test/e2e/test_data/batchrelease/cloneset_percentage_50.yaml index 50e9752..88da33a 100644 --- a/test/e2e/test_data/batchrelease/cloneset_percentage_50.yaml +++ b/test/e2e/test_data/batchrelease/cloneset_percentage_50.yaml @@ -4,17 +4,19 @@ metadata: name: release-cloneset-50 spec: targetReference: - apiVersion: apps.kruise.io/v1alpha1 - kind: CloneSet - name: sample + type: workloadRef + workloadRef: + apiVersion: apps.kruise.io/v1alpha1 + kind: CloneSet + name: sample releasePlan: batches: - canaryReplicas: 20% pauseSeconds: 30 - canaryReplicas: 40% - pauseSeconds: 30 + pauseSeconds: 60 - canaryReplicas: 50% - pauseSeconds: 100 + pauseSeconds: 30 diff --git a/test/e2e/test_data/batchrelease/deployment_number_100.yaml b/test/e2e/test_data/batchrelease/deployment_number_100.yaml index 6a82669..1155c8f 100644 --- a/test/e2e/test_data/batchrelease/deployment_number_100.yaml +++ b/test/e2e/test_data/batchrelease/deployment_number_100.yaml @@ -4,18 +4,20 @@ metadata: name: release-deployment-number-100 spec: targetReference: - apiVersion: apps/v1 - kind: Deployment - name: sample + type: workloadRef + workloadRef: + apiVersion: apps/v1 + kind: Deployment + name: sample releasePlan: batches: - canaryReplicas: 1 - pauseSeconds: 30 + pauseSeconds: 20 - canaryReplicas: 2 - pauseSeconds: 30 + pauseSeconds: 20 - canaryReplicas: 3 - pauseSeconds: 30 + pauseSeconds: 20 - canaryReplicas: 5 - pauseSeconds: 30 + pauseSeconds: 10 diff --git a/test/e2e/test_data/batchrelease/deployment_percentage_100.yaml b/test/e2e/test_data/batchrelease/deployment_percentage_100.yaml index 6a6125b..314e24e 100644 --- a/test/e2e/test_data/batchrelease/deployment_percentage_100.yaml +++ b/test/e2e/test_data/batchrelease/deployment_percentage_100.yaml @@ -4,16 +4,18 @@ metadata: name: release-deployment-percentage-100 spec: targetReference: - apiVersion: apps/v1 - kind: Deployment - name: sample + type: workloadRef + workloadRef: + apiVersion: apps/v1 + kind: Deployment + name: sample releasePlan: batches: - canaryReplicas: 20% - pauseSeconds: 30 + pauseSeconds: 20 - canaryReplicas: 40% - pauseSeconds: 30 + pauseSeconds: 20 - canaryReplicas: 60% - pauseSeconds: 30 + pauseSeconds: 20 - canaryReplicas: 100% - pauseSeconds: 30 + pauseSeconds: 10 diff --git a/test/e2e/test_data/batchrelease/deployment_percentage_50.yaml b/test/e2e/test_data/batchrelease/deployment_percentage_50.yaml index fd10cfc..6996d97 100644 --- a/test/e2e/test_data/batchrelease/deployment_percentage_50.yaml +++ b/test/e2e/test_data/batchrelease/deployment_percentage_50.yaml @@ -4,17 +4,19 @@ metadata: name: release-deployment-percentage-50 spec: targetReference: - apiVersion: apps/v1 - kind: Deployment - name: sample + type: workloadRef + workloadRef: + apiVersion: apps/v1 + kind: Deployment + name: sample releasePlan: batches: - canaryReplicas: 20% pauseSeconds: 30 - canaryReplicas: 40% - pauseSeconds: 30 + pauseSeconds: 60 - canaryReplicas: 50% - pauseSeconds: 100 + pauseSeconds: 30 diff --git a/vendor/github.com/nxadm/tail/.gitignore b/vendor/github.com/nxadm/tail/.gitignore index 299a669..35d9351 100644 --- a/vendor/github.com/nxadm/tail/.gitignore +++ b/vendor/github.com/nxadm/tail/.gitignore @@ -1,7 +1,3 @@ .idea/ -<<<<<<< HEAD .test/ -examples/_* -======= -.test/ ->>>>>>> 33cbc1d (add batchrelease controller) +examples/_* \ No newline at end of file diff --git a/vendor/github.com/nxadm/tail/.travis.yml b/vendor/github.com/nxadm/tail/.travis.yml deleted file mode 100644 index 95dd3bd..0000000 --- a/vendor/github.com/nxadm/tail/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -language: go - -script: - - go test -race -v ./... - -go: - - "1.9" - - "1.10" - - "1.11" - - "1.12" - - "1.13" - - tip - -matrix: - allow_failures: - - go: tip diff --git a/vendor/github.com/nxadm/tail/CHANGES.md b/vendor/github.com/nxadm/tail/CHANGES.md index 51d1034..224e54b 100644 --- a/vendor/github.com/nxadm/tail/CHANGES.md +++ b/vendor/github.com/nxadm/tail/CHANGES.md @@ -1,4 +1,3 @@ -<<<<<<< HEAD # Version v1.4.7-v1.4.8 * Documentation updates. * Small linter cleanups. @@ -10,9 +9,6 @@ * Add example directories with example and tests for issues. # Version v1.4.4-v1.4.5 -======= -# Version v1.4.4 ->>>>>>> 33cbc1d (add batchrelease controller) * Fix of checksum problem because of forced tag. No changes to the code. diff --git a/vendor/github.com/nxadm/tail/README.md b/vendor/github.com/nxadm/tail/README.md index 897b947..f47939c 100644 --- a/vendor/github.com/nxadm/tail/README.md +++ b/vendor/github.com/nxadm/tail/README.md @@ -1,4 +1,3 @@ -<<<<<<< HEAD ![ci](https://github.com/nxadm/tail/workflows/ci/badge.svg)[![Go Reference](https://pkg.go.dev/badge/github.com/nxadm/tail.svg)](https://pkg.go.dev/github.com/nxadm/tail) # tail functionality in Go @@ -15,50 +14,22 @@ A simple example: // Create a tail t, err := tail.TailFile( "/var/log/nginx.log", tail.Config{Follow: true, ReOpen: true}) -======= -[![Build Status](https://travis-ci.org/nxadm/tail.svg?branch=master)](https://travis-ci.org/nxadm/tail) - -This is repo is forked from the dormant upstream repo at -[hpcloud](https://github.com/hpcloud/tail). This fork adds support for go -modules, updates the dependencies, adds features and fixes bugs. Go 1.9 is -the oldest compiler release supported. - -# Go package for tail-ing files - -A Go package striving to emulate the features of the BSD `tail` program. - -```Go -t, err := tail.TailFile("/var/log/nginx.log", tail.Config{Follow: true}) ->>>>>>> 33cbc1d (add batchrelease controller) if err != nil { panic(err) } -<<<<<<< HEAD // Print the text of each received line -======= ->>>>>>> 33cbc1d (add batchrelease controller) for line := range t.Lines { fmt.Println(line.Text) } ``` -<<<<<<< HEAD See [API documentation](https://pkg.go.dev/github.com/nxadm/tail). -======= -See [API documentation](http://godoc.org/github.com/nxadm/tail). - -## Log rotation - -Tail comes with full support for truncation/move detection as it is -designed to work with log rotation tools. ->>>>>>> 33cbc1d (add batchrelease controller) ## Installing go get github.com/nxadm/tail/... -<<<<<<< HEAD ## History This project is an active, drop-in replacement for the @@ -70,9 +41,4 @@ nxadm/tail continues the development by keeping up to date with the Go toolchain and fixing bugs. ## Examples -Examples, e.g. used to debug an issue, are kept in the [examples directory](/examples). -======= -## Windows support - -This package [needs assistance](https://github.com/nxadm/tail/labels/Windows) for full Windows support. ->>>>>>> 33cbc1d (add batchrelease controller) +Examples, e.g. used to debug an issue, are kept in the [examples directory](/examples). \ No newline at end of file diff --git a/vendor/github.com/nxadm/tail/appveyor.yml b/vendor/github.com/nxadm/tail/appveyor.yml deleted file mode 100644 index e149bc6..0000000 --- a/vendor/github.com/nxadm/tail/appveyor.yml +++ /dev/null @@ -1,11 +0,0 @@ -version: 0.{build} -skip_tags: true -cache: C:\Users\appveyor\AppData\Local\NuGet\Cache -build_script: -- SET GOPATH=c:\workspace -- go test -v -race ./... -test: off -clone_folder: c:\workspace\src\github.com\nxadm\tail -branches: - only: - - master diff --git a/vendor/github.com/nxadm/tail/go.mod b/vendor/github.com/nxadm/tail/go.mod index 825b265..5de9a60 100644 --- a/vendor/github.com/nxadm/tail/go.mod +++ b/vendor/github.com/nxadm/tail/go.mod @@ -3,11 +3,6 @@ module github.com/nxadm/tail go 1.13 require ( -<<<<<<< HEAD github.com/fsnotify/fsnotify v1.4.9 -======= - github.com/fsnotify/fsnotify v1.4.7 - golang.org/x/sys v0.0.0-20190904154756-749cb33beabd // indirect ->>>>>>> 33cbc1d (add batchrelease controller) gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 ) diff --git a/vendor/github.com/nxadm/tail/go.sum b/vendor/github.com/nxadm/tail/go.sum index 33b8fb4..3485dae 100644 --- a/vendor/github.com/nxadm/tail/go.sum +++ b/vendor/github.com/nxadm/tail/go.sum @@ -1,13 +1,6 @@ -<<<<<<< HEAD github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 h1:L2auWcuQIvxz9xSEqzESnV/QN/gNRXNApHi3fYwl2w0= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -======= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= ->>>>>>> 33cbc1d (add batchrelease controller) gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= diff --git a/vendor/github.com/nxadm/tail/tail.go b/vendor/github.com/nxadm/tail/tail.go index a623cd0..37ea441 100644 --- a/vendor/github.com/nxadm/tail/tail.go +++ b/vendor/github.com/nxadm/tail/tail.go @@ -1,4 +1,3 @@ -<<<<<<< HEAD // Copyright (c) 2019 FOSS contributors of https://github.com/nxadm/tail // Copyright (c) 2015 HPE Software Inc. All rights reserved. // Copyright (c) 2013 ActiveState Software Inc. All rights reserved. @@ -8,11 +7,6 @@ //it is designed to work with log rotation tools. The library works on all //operating systems supported by Go, including POSIX systems like Linux and //*BSD, and MS Windows. Go 1.9 is the oldest compiler release supported. -======= -// Copyright (c) 2015 HPE Software Inc. All rights reserved. -// Copyright (c) 2013 ActiveState Software Inc. All rights reserved. - ->>>>>>> 33cbc1d (add batchrelease controller) package tail import ( @@ -34,15 +28,11 @@ import ( ) var ( -<<<<<<< HEAD // ErrStop is returned when the tail of a file has been marked to be stopped. -======= ->>>>>>> 33cbc1d (add batchrelease controller) ErrStop = errors.New("tail should now stop") ) type Line struct { -<<<<<<< HEAD Text string // The contents of the file Num int // The line number SeekInfo SeekInfo // SeekInfo @@ -55,31 +45,14 @@ type Line struct { // release. // // NewLine returns a * pointer to a Line struct. -======= - Text string - Num int - SeekInfo SeekInfo - Time time.Time - Err error // Error from tail -} - -// NewLine returns a Line with present time. ->>>>>>> 33cbc1d (add batchrelease controller) func NewLine(text string, lineNum int) *Line { return &Line{text, lineNum, SeekInfo{}, time.Now(), nil} } -<<<<<<< HEAD // SeekInfo represents arguments to io.Seek. See: https://golang.org/pkg/io/#SectionReader.Seek type SeekInfo struct { Offset int64 Whence int -======= -// SeekInfo represents arguments to `io.Seek` -type SeekInfo struct { - Offset int64 - Whence int // io.Seek* ->>>>>>> 33cbc1d (add batchrelease controller) } type logger interface { @@ -97,48 +70,28 @@ type logger interface { // Config is used to specify how a file must be tailed. type Config struct { // File-specifc -<<<<<<< HEAD Location *SeekInfo // Tail from this location. If nil, start at the beginning of the file ReOpen bool // Reopen recreated files (tail -F) MustExist bool // Fail early if the file does not exist Poll bool // Poll for file changes instead of using the default inotify Pipe bool // The file is a named pipe (mkfifo) -======= - Location *SeekInfo // Seek to this location before tailing - ReOpen bool // Reopen recreated files (tail -F) - MustExist bool // Fail early if the file does not exist - Poll bool // Poll for file changes instead of using inotify - Pipe bool // Is a named pipe (mkfifo) - RateLimiter *ratelimiter.LeakyBucket ->>>>>>> 33cbc1d (add batchrelease controller) // Generic IO Follow bool // Continue looking for new lines (tail -f) MaxLineSize int // If non-zero, split longer lines into multiple lines -<<<<<<< HEAD // Optionally, use a ratelimiter (e.g. created by the ratelimiter/NewLeakyBucket function) RateLimiter *ratelimiter.LeakyBucket // Optionally use a Logger. When nil, the Logger is set to tail.DefaultLogger. // To disable logging, set it to tail.DiscardingLogger -======= - // Logger, when nil, is set to tail.DefaultLogger - // To disable logging: set field to tail.DiscardingLogger ->>>>>>> 33cbc1d (add batchrelease controller) Logger logger } type Tail struct { -<<<<<<< HEAD Filename string // The filename Lines chan *Line // A consumable channel of *Line Config // Tail.Configuration -======= - Filename string - Lines chan *Line - Config ->>>>>>> 33cbc1d (add batchrelease controller) file *os.File reader *bufio.Reader @@ -153,28 +106,17 @@ type Tail struct { } var ( -<<<<<<< HEAD // DefaultLogger logs to os.Stderr and it is used when Config.Logger == nil -======= - // DefaultLogger is used when Config.Logger == nil ->>>>>>> 33cbc1d (add batchrelease controller) DefaultLogger = log.New(os.Stderr, "", log.LstdFlags) // DiscardingLogger can be used to disable logging output DiscardingLogger = log.New(ioutil.Discard, "", 0) ) -<<<<<<< HEAD // TailFile begins tailing the file. And returns a pointer to a Tail struct // and an error. An output stream is made available via the Tail.Lines // channel (e.g. to be looped and printed). To handle errors during tailing, // after finishing reading from the Lines channel, invoke the `Wait` or `Err` // method on the returned *Tail. -======= -// TailFile begins tailing the file. Output stream is made available -// via the `Tail.Lines` channel. To handle errors during tailing, -// invoke the `Wait` or `Err` method after finishing reading from the -// `Lines` channel. ->>>>>>> 33cbc1d (add batchrelease controller) func TailFile(filename string, config Config) (*Tail, error) { if config.ReOpen && !config.Follow { util.Fatal("cannot set ReOpen without Follow.") @@ -210,16 +152,9 @@ func TailFile(filename string, config Config) (*Tail, error) { return t, nil } -<<<<<<< HEAD // Tell returns the file's current position, like stdio's ftell() and an error. // Beware that this value may not be completely accurate because one line from // the chan(tail.Lines) may have been read already. -======= -// Tell returns the file's current position, like stdio's ftell(). -// But this value is not very accurate. -// One line from the chan(tail.Lines) may have been read, -// so it may have lost one line. ->>>>>>> 33cbc1d (add batchrelease controller) func (tail *Tail) Tell() (offset int64, err error) { if tail.file == nil { return @@ -245,12 +180,8 @@ func (tail *Tail) Stop() error { return tail.Wait() } -<<<<<<< HEAD // StopAtEOF stops tailing as soon as the end of the file is reached. The function // returns an error, -======= -// StopAtEOF stops tailing as soon as the end of the file is reached. ->>>>>>> 33cbc1d (add batchrelease controller) func (tail *Tail) StopAtEOF() error { tail.Kill(errStopAtEOF) return tail.Wait() @@ -518,10 +449,7 @@ func (tail *Tail) sendLine(line string) bool { // Cleanup removes inotify watches added by the tail package. This function is // meant to be invoked from a process's exit handler. Linux kernel may not // automatically remove inotify watches after the process exits. -<<<<<<< HEAD // If you plan to re-read a file, don't call Cleanup in between. -======= ->>>>>>> 33cbc1d (add batchrelease controller) func (tail *Tail) Cleanup() { watch.Cleanup(tail.Filename) } diff --git a/vendor/github.com/nxadm/tail/tail_posix.go b/vendor/github.com/nxadm/tail/tail_posix.go index 57c2bfd..23e071d 100644 --- a/vendor/github.com/nxadm/tail/tail_posix.go +++ b/vendor/github.com/nxadm/tail/tail_posix.go @@ -1,7 +1,4 @@ -<<<<<<< HEAD // Copyright (c) 2019 FOSS contributors of https://github.com/nxadm/tail -======= ->>>>>>> 33cbc1d (add batchrelease controller) // +build !windows package tail @@ -10,14 +7,11 @@ import ( "os" ) -<<<<<<< HEAD // Deprecated: this function is only useful internally and, as such, // it will be removed from the API in a future major release. // // OpenFile proxies a os.Open call for a file so it can be correctly tailed // on POSIX and non-POSIX OSes like MS Windows. -======= ->>>>>>> 33cbc1d (add batchrelease controller) func OpenFile(name string) (file *os.File, err error) { return os.Open(name) } diff --git a/vendor/github.com/nxadm/tail/tail_windows.go b/vendor/github.com/nxadm/tail/tail_windows.go index ab76fb3..da0d2f3 100644 --- a/vendor/github.com/nxadm/tail/tail_windows.go +++ b/vendor/github.com/nxadm/tail/tail_windows.go @@ -1,13 +1,9 @@ -<<<<<<< HEAD // Copyright (c) 2019 FOSS contributors of https://github.com/nxadm/tail -======= ->>>>>>> 33cbc1d (add batchrelease controller) // +build windows package tail import ( -<<<<<<< HEAD "os" "github.com/nxadm/tail/winfile" @@ -18,12 +14,6 @@ import ( // // OpenFile proxies a os.Open call for a file so it can be correctly tailed // on POSIX and non-POSIX OSes like MS Windows. -======= - "github.com/nxadm/tail/winfile" - "os" -) - ->>>>>>> 33cbc1d (add batchrelease controller) func OpenFile(name string) (file *os.File, err error) { return winfile.OpenFile(name, os.O_RDONLY, 0) } diff --git a/vendor/github.com/nxadm/tail/util/util.go b/vendor/github.com/nxadm/tail/util/util.go index f3e20df..b64caa2 100644 --- a/vendor/github.com/nxadm/tail/util/util.go +++ b/vendor/github.com/nxadm/tail/util/util.go @@ -1,7 +1,4 @@ -<<<<<<< HEAD // Copyright (c) 2019 FOSS contributors of https://github.com/nxadm/tail -======= ->>>>>>> 33cbc1d (add batchrelease controller) // Copyright (c) 2015 HPE Software Inc. All rights reserved. // Copyright (c) 2013 ActiveState Software Inc. All rights reserved. diff --git a/vendor/github.com/nxadm/tail/watch/filechanges.go b/vendor/github.com/nxadm/tail/watch/filechanges.go index f591b9a..5b65f42 100644 --- a/vendor/github.com/nxadm/tail/watch/filechanges.go +++ b/vendor/github.com/nxadm/tail/watch/filechanges.go @@ -1,7 +1,4 @@ -<<<<<<< HEAD // Copyright (c) 2019 FOSS contributors of https://github.com/nxadm/tail -======= ->>>>>>> 33cbc1d (add batchrelease controller) package watch type FileChanges struct { diff --git a/vendor/github.com/nxadm/tail/watch/inotify.go b/vendor/github.com/nxadm/tail/watch/inotify.go index a31c820..cbd11ad 100644 --- a/vendor/github.com/nxadm/tail/watch/inotify.go +++ b/vendor/github.com/nxadm/tail/watch/inotify.go @@ -1,7 +1,4 @@ -<<<<<<< HEAD // Copyright (c) 2019 FOSS contributors of https://github.com/nxadm/tail -======= ->>>>>>> 33cbc1d (add batchrelease controller) // Copyright (c) 2015 HPE Software Inc. All rights reserved. // Copyright (c) 2013 ActiveState Software Inc. All rights reserved. diff --git a/vendor/github.com/nxadm/tail/watch/inotify_tracker.go b/vendor/github.com/nxadm/tail/watch/inotify_tracker.go index 0470e38..cb9572a 100644 --- a/vendor/github.com/nxadm/tail/watch/inotify_tracker.go +++ b/vendor/github.com/nxadm/tail/watch/inotify_tracker.go @@ -1,7 +1,4 @@ -<<<<<<< HEAD // Copyright (c) 2019 FOSS contributors of https://github.com/nxadm/tail -======= ->>>>>>> 33cbc1d (add batchrelease controller) // Copyright (c) 2015 HPE Software Inc. All rights reserved. // Copyright (c) 2013 ActiveState Software Inc. All rights reserved. diff --git a/vendor/github.com/nxadm/tail/watch/polling.go b/vendor/github.com/nxadm/tail/watch/polling.go index 8099ce9..74e10aa 100644 --- a/vendor/github.com/nxadm/tail/watch/polling.go +++ b/vendor/github.com/nxadm/tail/watch/polling.go @@ -1,7 +1,4 @@ -<<<<<<< HEAD // Copyright (c) 2019 FOSS contributors of https://github.com/nxadm/tail -======= ->>>>>>> 33cbc1d (add batchrelease controller) // Copyright (c) 2015 HPE Software Inc. All rights reserved. // Copyright (c) 2013 ActiveState Software Inc. All rights reserved. diff --git a/vendor/github.com/nxadm/tail/watch/watch.go b/vendor/github.com/nxadm/tail/watch/watch.go index febd7ef..2b51128 100644 --- a/vendor/github.com/nxadm/tail/watch/watch.go +++ b/vendor/github.com/nxadm/tail/watch/watch.go @@ -1,7 +1,4 @@ -<<<<<<< HEAD // Copyright (c) 2019 FOSS contributors of https://github.com/nxadm/tail -======= ->>>>>>> 33cbc1d (add batchrelease controller) // Copyright (c) 2015 HPE Software Inc. All rights reserved. // Copyright (c) 2013 ActiveState Software Inc. All rights reserved. diff --git a/vendor/github.com/nxadm/tail/winfile/winfile.go b/vendor/github.com/nxadm/tail/winfile/winfile.go index 26f54f7..4562ac7 100644 --- a/vendor/github.com/nxadm/tail/winfile/winfile.go +++ b/vendor/github.com/nxadm/tail/winfile/winfile.go @@ -1,7 +1,4 @@ -<<<<<<< HEAD // Copyright (c) 2019 FOSS contributors of https://github.com/nxadm/tail -======= ->>>>>>> 33cbc1d (add batchrelease controller) // +build windows package winfile diff --git a/vendor/github.com/onsi/ginkgo/.travis.yml b/vendor/github.com/onsi/ginkgo/.travis.yml index a20b48e..ea0966d 100644 --- a/vendor/github.com/onsi/ginkgo/.travis.yml +++ b/vendor/github.com/onsi/ginkgo/.travis.yml @@ -1,14 +1,8 @@ language: go go: -<<<<<<< HEAD - tip - 1.16.x - 1.15.x -======= - - 1.13.x - - 1.14.x - - tip ->>>>>>> 33cbc1d (add batchrelease controller) cache: directories: @@ -22,19 +16,9 @@ install: - GO111MODULE="off" go get golang.org/x/tools/cmd/cover - GO111MODULE="off" go get github.com/onsi/gomega - GO111MODULE="off" go install github.com/onsi/ginkgo/ginkgo -<<<<<<< HEAD - export PATH=$GOPATH/bin:$PATH script: - GO111MODULE="on" go mod tidy && git diff --exit-code go.mod go.sum - go vet - ginkgo -r --randomizeAllSpecs --randomizeSuites --race --trace -======= - - export PATH=$PATH:$HOME/gopath/bin - -script: - - GO111MODULE="on" go mod tidy - - diff -u <(echo -n) <(git diff go.mod) - - diff -u <(echo -n) <(git diff go.sum) - - $HOME/gopath/bin/ginkgo -r --randomizeAllSpecs --randomizeSuites --race --trace && go vet ->>>>>>> 33cbc1d (add batchrelease controller) diff --git a/vendor/github.com/onsi/ginkgo/CHANGELOG.md b/vendor/github.com/onsi/ginkgo/CHANGELOG.md index d9f2f32..a26bc53 100644 --- a/vendor/github.com/onsi/ginkgo/CHANGELOG.md +++ b/vendor/github.com/onsi/ginkgo/CHANGELOG.md @@ -1,4 +1,3 @@ -<<<<<<< HEAD ## 1.16.5 Ginkgo 2.0 now has a Release Candidate. 1.16.5 advertises the existence of the RC. @@ -66,8 +65,6 @@ You can silence the RC advertisement by setting an `ACK_GINKG_RC=true` environme - correct handling windows backslash in import path (#721) [97f3d51] - Add additional methods to GinkgoT() to improve compatibility with the testing.TB interface [b5fe44d] -======= ->>>>>>> 33cbc1d (add batchrelease controller) ## 1.14.1 ### Fixes diff --git a/vendor/github.com/onsi/ginkgo/README.md b/vendor/github.com/onsi/ginkgo/README.md index 31a4b6a..a25ca5e 100644 --- a/vendor/github.com/onsi/ginkgo/README.md +++ b/vendor/github.com/onsi/ginkgo/README.md @@ -1,6 +1,5 @@ ![Ginkgo: A Go BDD Testing Framework](https://onsi.github.io/ginkgo/images/ginkgo.png) -<<<<<<< HEAD [![test](https://github.com/onsi/ginkgo/workflows/test/badge.svg?branch=master)](https://github.com/onsi/ginkgo/actions?query=workflow%3Atest+branch%3Amaster) Jump to the [docs](https://onsi.github.io/ginkgo/) | [中文文档](https://ke-chain.github.io/ginkgodoc) to learn more. To start rolling your Ginkgo tests *now* [keep reading](#set-me-up)! @@ -15,14 +14,6 @@ As described in the [changelog](https://github.com/onsi/ginkgo/blob/ver2/docs/MI Please start exploring and using the V2 release! To get started follow the [Using the Release Candidate](https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#using-the-beta) directions in the migration guide. -======= -[![Build Status](https://travis-ci.org/onsi/ginkgo.svg?branch=master)](https://travis-ci.org/onsi/ginkgo) - -Jump to the [docs](https://onsi.github.io/ginkgo/) to learn more. To start rolling your Ginkgo tests *now* [keep reading](#set-me-up)! - -If you have a question, comment, bug report, feature request, etc. please open a GitHub issue, or visit the [Ginkgo Slack channel](https://app.slack.com/client/T029RQSE6/CQQ50BBNW). - ->>>>>>> 33cbc1d (add batchrelease controller) ## TLDR Ginkgo builds on Go's `testing` package, allowing expressive [Behavior-Driven Development](https://en.wikipedia.org/wiki/Behavior-driven_development) ("BDD") style tests. It is typically (and optionally) paired with the [Gomega](https://github.com/onsi/gomega) matcher library. @@ -78,11 +69,8 @@ Describe("the strings package", func() { - [Completions for VSCode](https://github.com/onsi/vscode-ginkgo): just use VSCode's extension installer to install `vscode-ginkgo`. -<<<<<<< HEAD - [Ginkgo tools for VSCode](https://marketplace.visualstudio.com/items?itemName=joselitofilho.ginkgotestexplorer): just use VSCode's extension installer to install `ginkgoTestExplorer`. -======= ->>>>>>> 33cbc1d (add batchrelease controller) - Straightforward support for third-party testing libraries such as [Gomock](https://code.google.com/p/gomock/) and [Testify](https://github.com/stretchr/testify). Check out the [docs](https://onsi.github.io/ginkgo/#third-party-integrations) for details. - A modular architecture that lets you easily: diff --git a/vendor/github.com/onsi/ginkgo/RELEASING.md b/vendor/github.com/onsi/ginkgo/RELEASING.md index 581d633..db3d234 100644 --- a/vendor/github.com/onsi/ginkgo/RELEASING.md +++ b/vendor/github.com/onsi/ginkgo/RELEASING.md @@ -8,17 +8,10 @@ A Ginkgo release is a tagged git sha and a GitHub release. To cut a release: - Fixes (fix version) - Maintenance (which in general should not be mentioned in `CHANGELOG.md` as they have no user impact) 1. Update `VERSION` in `config/config.go` -<<<<<<< HEAD 1. Commit, push, and release: ``` git commit -m "vM.m.p" git push gh release create "vM.m.p" git fetch --tags origin master - ``` -======= -1. Create a commit with the version number as the commit message (e.g. `v1.3.0`) -1. Tag the commit with the version number as the tag name (e.g. `v1.3.0`) -1. Push the commit and tag to GitHub -1. Create a new [GitHub release](https://help.github.com/articles/creating-releases/) with the version number as the tag (e.g. `v1.3.0`). List the key changes in the release notes. ->>>>>>> 33cbc1d (add batchrelease controller) + ``` \ No newline at end of file diff --git a/vendor/github.com/onsi/ginkgo/config/config.go b/vendor/github.com/onsi/ginkgo/config/config.go index c1a50e2..3130c77 100644 --- a/vendor/github.com/onsi/ginkgo/config/config.go +++ b/vendor/github.com/onsi/ginkgo/config/config.go @@ -20,23 +20,14 @@ import ( "fmt" ) -<<<<<<< HEAD const VERSION = "1.16.5" -======= -const VERSION = "1.14.1" ->>>>>>> 33cbc1d (add batchrelease controller) type GinkgoConfigType struct { RandomSeed int64 RandomizeAllSpecs bool RegexScansFilePath bool -<<<<<<< HEAD FocusStrings []string SkipStrings []string -======= - FocusString string - SkipString string ->>>>>>> 33cbc1d (add batchrelease controller) SkipMeasurements bool FailOnPending bool FailFast bool @@ -74,14 +65,11 @@ func processPrefix(prefix string) string { return prefix } -<<<<<<< HEAD type flagFunc func(string) func (f flagFunc) String() string { return "" } func (f flagFunc) Set(s string) error { f(s); return nil } -======= ->>>>>>> 33cbc1d (add batchrelease controller) func Flags(flagSet *flag.FlagSet, prefix string, includeParallelFlags bool) { prefix = processPrefix(prefix) flagSet.Int64Var(&(GinkgoConfig.RandomSeed), prefix+"seed", time.Now().Unix(), "The seed used to randomize the spec suite.") @@ -92,13 +80,8 @@ func Flags(flagSet *flag.FlagSet, prefix string, includeParallelFlags bool) { flagSet.BoolVar(&(GinkgoConfig.DryRun), prefix+"dryRun", false, "If set, ginkgo will walk the test hierarchy without actually running anything. Best paired with -v.") -<<<<<<< HEAD flagSet.Var(flagFunc(flagFocus), prefix+"focus", "If set, ginkgo will only run specs that match this regular expression. Can be specified multiple times, values are ORed.") flagSet.Var(flagFunc(flagSkip), prefix+"skip", "If set, ginkgo will only run specs that do not match this regular expression. Can be specified multiple times, values are ORed.") -======= - flagSet.StringVar(&(GinkgoConfig.FocusString), prefix+"focus", "", "If set, ginkgo will only run specs that match this regular expression.") - flagSet.StringVar(&(GinkgoConfig.SkipString), prefix+"skip", "", "If set, ginkgo will only run specs that do not match this regular expression.") ->>>>>>> 33cbc1d (add batchrelease controller) flagSet.BoolVar(&(GinkgoConfig.RegexScansFilePath), prefix+"regexScansFilePath", false, "If set, ginkgo regex matching also will look at the file path (code location).") @@ -155,21 +138,12 @@ func BuildFlagArgs(prefix string, ginkgo GinkgoConfigType, reporter DefaultRepor result = append(result, fmt.Sprintf("--%sdryRun", prefix)) } -<<<<<<< HEAD for _, s := range ginkgo.FocusStrings { result = append(result, fmt.Sprintf("--%sfocus=%s", prefix, s)) } for _, s := range ginkgo.SkipStrings { result = append(result, fmt.Sprintf("--%sskip=%s", prefix, s)) -======= - if ginkgo.FocusString != "" { - result = append(result, fmt.Sprintf("--%sfocus=%s", prefix, ginkgo.FocusString)) - } - - if ginkgo.SkipString != "" { - result = append(result, fmt.Sprintf("--%sskip=%s", prefix, ginkgo.SkipString)) ->>>>>>> 33cbc1d (add batchrelease controller) } if ginkgo.FlakeAttempts > 1 { @@ -242,7 +216,6 @@ func BuildFlagArgs(prefix string, ginkgo GinkgoConfigType, reporter DefaultRepor return result } -<<<<<<< HEAD // flagFocus implements the -focus flag. func flagFocus(arg string) { @@ -257,5 +230,3 @@ func flagSkip(arg string) { GinkgoConfig.SkipStrings = append(GinkgoConfig.SkipStrings, arg) } } -======= ->>>>>>> 33cbc1d (add batchrelease controller) diff --git a/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go b/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go index ccdaa61..ccd7685 100644 --- a/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go +++ b/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go @@ -17,10 +17,7 @@ import ( "io" "net/http" "os" -<<<<<<< HEAD "reflect" -======= ->>>>>>> 33cbc1d (add batchrelease controller) "strings" "time" @@ -36,11 +33,8 @@ import ( "github.com/onsi/ginkgo/types" ) -<<<<<<< HEAD var deprecationTracker = types.NewDeprecationTracker() -======= ->>>>>>> 33cbc1d (add batchrelease controller) const GINKGO_VERSION = config.VERSION const GINKGO_PANIC = ` Your test failed. @@ -79,7 +73,6 @@ func GinkgoRandomSeed() int64 { return config.GinkgoConfig.RandomSeed } -<<<<<<< HEAD //GinkgoParallelNode is deprecated, use GinkgoParallelProcess instead func GinkgoParallelNode() int { deprecationTracker.TrackDeprecation(types.Deprecations.ParallelNode(), codelocation.New(1)) @@ -89,11 +82,6 @@ func GinkgoParallelNode() int { //GinkgoParallelProcess returns the parallel process number for the current ginkgo process //The process number is 1-indexed func GinkgoParallelProcess() int { -======= -//GinkgoParallelNode returns the parallel node number for the current ginkgo process -//The node number is 1-indexed -func GinkgoParallelNode() int { ->>>>>>> 33cbc1d (add batchrelease controller) return config.GinkgoConfig.ParallelNode } @@ -114,7 +102,6 @@ func GinkgoT(optionalOffset ...int) GinkgoTInterface { if len(optionalOffset) > 0 { offset = optionalOffset[0] } -<<<<<<< HEAD failedFunc := func() bool { return CurrentGinkgoTestDescription().Failed } @@ -122,15 +109,11 @@ func GinkgoT(optionalOffset ...int) GinkgoTInterface { return CurrentGinkgoTestDescription().FullTestText } return testingtproxy.New(GinkgoWriter, Fail, Skip, failedFunc, nameFunc, offset) -======= - return testingtproxy.New(GinkgoWriter, Fail, offset) ->>>>>>> 33cbc1d (add batchrelease controller) } //The interface returned by GinkgoT(). This covers most of the methods //in the testing package's T. type GinkgoTInterface interface { -<<<<<<< HEAD Cleanup(func()) Setenv(key, value string) Error(args ...interface{}) @@ -150,22 +133,6 @@ type GinkgoTInterface interface { Skipf(format string, args ...interface{}) Skipped() bool TempDir() string -======= - Fail() - Error(args ...interface{}) - Errorf(format string, args ...interface{}) - FailNow() - Fatal(args ...interface{}) - Fatalf(format string, args ...interface{}) - Log(args ...interface{}) - Logf(format string, args ...interface{}) - Failed() bool - Parallel() - Skip(args ...interface{}) - Skipf(format string, args ...interface{}) - SkipNow() - Skipped() bool ->>>>>>> 33cbc1d (add batchrelease controller) } //Custom Ginkgo test reporters must implement the Reporter interface. @@ -248,41 +215,27 @@ func RunSpecs(t GinkgoTestingT, description string) bool { if config.DefaultReporterConfig.ReportFile != "" { reportFile := config.DefaultReporterConfig.ReportFile specReporters[0] = reporters.NewJUnitReporter(reportFile) -<<<<<<< HEAD specReporters = append(specReporters, buildDefaultReporter()) } return runSpecsWithCustomReporters(t, description, specReporters) -======= - return RunSpecsWithDefaultAndCustomReporters(t, description, specReporters) - } - return RunSpecsWithCustomReporters(t, description, specReporters) ->>>>>>> 33cbc1d (add batchrelease controller) } //To run your tests with Ginkgo's default reporter and your custom reporter(s), replace //RunSpecs() with this method. func RunSpecsWithDefaultAndCustomReporters(t GinkgoTestingT, description string, specReporters []Reporter) bool { -<<<<<<< HEAD deprecationTracker.TrackDeprecation(types.Deprecations.CustomReporter()) specReporters = append(specReporters, buildDefaultReporter()) return runSpecsWithCustomReporters(t, description, specReporters) -======= - specReporters = append(specReporters, buildDefaultReporter()) - return RunSpecsWithCustomReporters(t, description, specReporters) ->>>>>>> 33cbc1d (add batchrelease controller) } //To run your tests with your custom reporter(s) (and *not* Ginkgo's default reporter), replace //RunSpecs() with this method. Note that parallel tests will not work correctly without the default reporter func RunSpecsWithCustomReporters(t GinkgoTestingT, description string, specReporters []Reporter) bool { -<<<<<<< HEAD deprecationTracker.TrackDeprecation(types.Deprecations.CustomReporter()) return runSpecsWithCustomReporters(t, description, specReporters) } func runSpecsWithCustomReporters(t GinkgoTestingT, description string, specReporters []Reporter) bool { -======= ->>>>>>> 33cbc1d (add batchrelease controller) writer := GinkgoWriter.(*writer.Writer) writer.SetStream(config.DefaultReporterConfig.Verbose) reporters := make([]reporters.Reporter, len(specReporters)) @@ -290,14 +243,11 @@ func runSpecsWithCustomReporters(t GinkgoTestingT, description string, specRepor reporters[i] = reporter } passed, hasFocusedTests := global.Suite.Run(t, description, reporters, writer, config.GinkgoConfig) -<<<<<<< HEAD if deprecationTracker.DidTrackDeprecations() { fmt.Fprintln(colorable.NewColorableStderr(), deprecationTracker.DeprecationsReport()) } -======= ->>>>>>> 33cbc1d (add batchrelease controller) if passed && hasFocusedTests && strings.TrimSpace(os.Getenv("GINKGO_EDITOR_INTEGRATION")) == "" { fmt.Println("PASS | FOCUSED") os.Exit(types.GINKGO_FOCUS_EXIT_CODE) @@ -451,20 +401,14 @@ func XWhen(text string, body func()) bool { //Ginkgo will normally run It blocks synchronously. To perform asynchronous tests, pass a //function that accepts a Done channel. When you do this, you can also provide an optional timeout. func It(text string, body interface{}, timeout ...float64) bool { -<<<<<<< HEAD validateBodyFunc(body, codelocation.New(1)) -======= ->>>>>>> 33cbc1d (add batchrelease controller) global.Suite.PushItNode(text, body, types.FlagTypeNone, codelocation.New(1), parseTimeout(timeout...)) return true } //You can focus individual Its using FIt func FIt(text string, body interface{}, timeout ...float64) bool { -<<<<<<< HEAD validateBodyFunc(body, codelocation.New(1)) -======= ->>>>>>> 33cbc1d (add batchrelease controller) global.Suite.PushItNode(text, body, types.FlagTypeFocused, codelocation.New(1), parseTimeout(timeout...)) return true } @@ -485,20 +429,14 @@ func XIt(text string, _ ...interface{}) bool { //which "It" does not fit into a natural sentence flow. All the same protocols apply for Specify blocks //which apply to It blocks. func Specify(text string, body interface{}, timeout ...float64) bool { -<<<<<<< HEAD validateBodyFunc(body, codelocation.New(1)) -======= ->>>>>>> 33cbc1d (add batchrelease controller) global.Suite.PushItNode(text, body, types.FlagTypeNone, codelocation.New(1), parseTimeout(timeout...)) return true } //You can focus individual Specifys using FSpecify func FSpecify(text string, body interface{}, timeout ...float64) bool { -<<<<<<< HEAD validateBodyFunc(body, codelocation.New(1)) -======= ->>>>>>> 33cbc1d (add batchrelease controller) global.Suite.PushItNode(text, body, types.FlagTypeFocused, codelocation.New(1), parseTimeout(timeout...)) return true } @@ -542,40 +480,28 @@ func By(text string, callbacks ...func()) { //The body function must have the signature: // func(b Benchmarker) func Measure(text string, body interface{}, samples int) bool { -<<<<<<< HEAD deprecationTracker.TrackDeprecation(types.Deprecations.Measure(), codelocation.New(1)) -======= ->>>>>>> 33cbc1d (add batchrelease controller) global.Suite.PushMeasureNode(text, body, types.FlagTypeNone, codelocation.New(1), samples) return true } //You can focus individual Measures using FMeasure func FMeasure(text string, body interface{}, samples int) bool { -<<<<<<< HEAD deprecationTracker.TrackDeprecation(types.Deprecations.Measure(), codelocation.New(1)) -======= ->>>>>>> 33cbc1d (add batchrelease controller) global.Suite.PushMeasureNode(text, body, types.FlagTypeFocused, codelocation.New(1), samples) return true } //You can mark Measurements as pending using PMeasure func PMeasure(text string, _ ...interface{}) bool { -<<<<<<< HEAD deprecationTracker.TrackDeprecation(types.Deprecations.Measure(), codelocation.New(1)) -======= ->>>>>>> 33cbc1d (add batchrelease controller) global.Suite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0) return true } //You can mark Measurements as pending using XMeasure func XMeasure(text string, _ ...interface{}) bool { -<<<<<<< HEAD deprecationTracker.TrackDeprecation(types.Deprecations.Measure(), codelocation.New(1)) -======= ->>>>>>> 33cbc1d (add batchrelease controller) global.Suite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0) return true } @@ -587,10 +513,7 @@ func XMeasure(text string, _ ...interface{}) bool { // //You may only register *one* BeforeSuite handler per test suite. You typically do so in your bootstrap file at the top level. func BeforeSuite(body interface{}, timeout ...float64) bool { -<<<<<<< HEAD validateBodyFunc(body, codelocation.New(1)) -======= ->>>>>>> 33cbc1d (add batchrelease controller) global.Suite.SetBeforeSuiteNode(body, codelocation.New(1), parseTimeout(timeout...)) return true } @@ -604,10 +527,7 @@ func BeforeSuite(body interface{}, timeout ...float64) bool { // //You may only register *one* AfterSuite handler per test suite. You typically do so in your bootstrap file at the top level. func AfterSuite(body interface{}, timeout ...float64) bool { -<<<<<<< HEAD validateBodyFunc(body, codelocation.New(1)) -======= ->>>>>>> 33cbc1d (add batchrelease controller) global.Suite.SetAfterSuiteNode(body, codelocation.New(1), parseTimeout(timeout...)) return true } @@ -695,10 +615,7 @@ func SynchronizedAfterSuite(allNodesBody interface{}, node1Body interface{}, tim //Like It blocks, BeforeEach blocks can be made asynchronous by providing a body function that accepts //a Done channel func BeforeEach(body interface{}, timeout ...float64) bool { -<<<<<<< HEAD validateBodyFunc(body, codelocation.New(1)) -======= ->>>>>>> 33cbc1d (add batchrelease controller) global.Suite.PushBeforeEachNode(body, codelocation.New(1), parseTimeout(timeout...)) return true } @@ -709,10 +626,7 @@ func BeforeEach(body interface{}, timeout ...float64) bool { //Like It blocks, BeforeEach blocks can be made asynchronous by providing a body function that accepts //a Done channel func JustBeforeEach(body interface{}, timeout ...float64) bool { -<<<<<<< HEAD validateBodyFunc(body, codelocation.New(1)) -======= ->>>>>>> 33cbc1d (add batchrelease controller) global.Suite.PushJustBeforeEachNode(body, codelocation.New(1), parseTimeout(timeout...)) return true } @@ -723,10 +637,7 @@ func JustBeforeEach(body interface{}, timeout ...float64) bool { //Like It blocks, JustAfterEach blocks can be made asynchronous by providing a body function that accepts //a Done channel func JustAfterEach(body interface{}, timeout ...float64) bool { -<<<<<<< HEAD validateBodyFunc(body, codelocation.New(1)) -======= ->>>>>>> 33cbc1d (add batchrelease controller) global.Suite.PushJustAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...)) return true } @@ -737,15 +648,11 @@ func JustAfterEach(body interface{}, timeout ...float64) bool { //Like It blocks, AfterEach blocks can be made asynchronous by providing a body function that accepts //a Done channel func AfterEach(body interface{}, timeout ...float64) bool { -<<<<<<< HEAD validateBodyFunc(body, codelocation.New(1)) -======= ->>>>>>> 33cbc1d (add batchrelease controller) global.Suite.PushAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...)) return true } -<<<<<<< HEAD func validateBodyFunc(body interface{}, cl types.CodeLocation) { t := reflect.TypeOf(body) if t.Kind() != reflect.Func { @@ -765,8 +672,6 @@ func validateBodyFunc(body interface{}, cl types.CodeLocation) { } } -======= ->>>>>>> 33cbc1d (add batchrelease controller) func parseTimeout(timeout ...float64) time.Duration { if len(timeout) == 0 { return global.DefaultTimeout diff --git a/vendor/github.com/onsi/ginkgo/go.mod b/vendor/github.com/onsi/ginkgo/go.mod index 27fbcae..1711443 100644 --- a/vendor/github.com/onsi/ginkgo/go.mod +++ b/vendor/github.com/onsi/ginkgo/go.mod @@ -1,6 +1,5 @@ module github.com/onsi/ginkgo -<<<<<<< HEAD go 1.16 require ( @@ -12,14 +11,3 @@ require ( ) retract v1.16.3 // git tag accidentally associated with incorrect git commit -======= -require ( - github.com/fsnotify/fsnotify v1.4.9 // indirect - github.com/nxadm/tail v1.4.4 - github.com/onsi/gomega v1.10.1 - golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 - golang.org/x/text v0.3.2 // indirect -) - -go 1.13 ->>>>>>> 33cbc1d (add batchrelease controller) diff --git a/vendor/github.com/onsi/ginkgo/go.sum b/vendor/github.com/onsi/ginkgo/go.sum index e77f63b..5c5c3c5 100644 --- a/vendor/github.com/onsi/ginkgo/go.sum +++ b/vendor/github.com/onsi/ginkgo/go.sum @@ -1,4 +1,3 @@ -<<<<<<< HEAD github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -7,13 +6,6 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -======= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= ->>>>>>> 33cbc1d (add batchrelease controller) github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -26,7 +18,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -<<<<<<< HEAD github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= @@ -77,41 +68,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -======= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= ->>>>>>> 33cbc1d (add batchrelease controller) 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= @@ -121,18 +77,10 @@ google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyz google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -<<<<<<< HEAD gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -======= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= ->>>>>>> 33cbc1d (add batchrelease controller) gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_darwin.go b/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_darwin.go deleted file mode 100644 index e3d09ea..0000000 --- a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_darwin.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build darwin - -package remote - -import ( - "golang.org/x/sys/unix" -) - -func interceptorDupx(oldfd int, newfd int) { - unix.Dup2(oldfd, newfd) -} diff --git a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_dragonfly.go b/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_dragonfly.go deleted file mode 100644 index 72d3868..0000000 --- a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_dragonfly.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build dragonfly - -package remote - -import ( - "golang.org/x/sys/unix" -) - -func interceptorDupx(oldfd int, newfd int) { - unix.Dup2(oldfd, newfd) -} diff --git a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_freebsd.go b/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_freebsd.go deleted file mode 100644 index 497d548..0000000 --- a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_freebsd.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build freebsd - -package remote - -import ( - "golang.org/x/sys/unix" -) - -func interceptorDupx(oldfd int, newfd int) { - unix.Dup2(oldfd, newfd) -} diff --git a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_linux.go b/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_linux.go deleted file mode 100644 index 29add0d..0000000 --- a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_linux.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build linux -// +build !mips64le - -package remote - -import ( - "golang.org/x/sys/unix" -) - -func interceptorDupx(oldfd int, newfd int) { - unix.Dup2(oldfd, newfd) -} diff --git a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_linux_mips64le.go b/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_linux_mips64le.go deleted file mode 100644 index 09bd062..0000000 --- a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_linux_mips64le.go +++ /dev/null @@ -1,12 +0,0 @@ -// +build linux -// +build mips64le - -package remote - -import ( - "golang.org/x/sys/unix" -) - -func interceptorDupx(oldfd int, newfd int) { - unix.Dup3(oldfd, newfd, 0) -} diff --git a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_netbsd.go b/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_netbsd.go deleted file mode 100644 index 16ad6ae..0000000 --- a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_netbsd.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build netbsd - -package remote - -import ( - "golang.org/x/sys/unix" -) - -func interceptorDupx(oldfd int, newfd int) { - unix.Dup2(oldfd, newfd) -} diff --git a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_openbsd.go b/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_openbsd.go deleted file mode 100644 index 4275f84..0000000 --- a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_openbsd.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build openbsd - -package remote - -import ( - "golang.org/x/sys/unix" -) - -func interceptorDupx(oldfd int, newfd int) { - unix.Dup2(oldfd, newfd) -} diff --git a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_solaris.go b/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_solaris.go deleted file mode 100644 index 882a38a..0000000 --- a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_solaris.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build solaris - -package remote - -import ( - "golang.org/x/sys/unix" -) - -func interceptorDupx(oldfd int, newfd int) { - unix.Dup2(oldfd, newfd) -} diff --git a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_unix.go b/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_unix.go index b43a2a0..774967d 100644 --- a/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_unix.go +++ b/vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_unix.go @@ -8,10 +8,7 @@ import ( "os" "github.com/nxadm/tail" -<<<<<<< HEAD "golang.org/x/sys/unix" -======= ->>>>>>> 33cbc1d (add batchrelease controller) ) func NewOutputInterceptor() OutputInterceptor { @@ -39,15 +36,10 @@ func (interceptor *outputInterceptor) StartInterceptingOutput() error { return err } -<<<<<<< HEAD // This might call Dup3 if the dup2 syscall is not available, e.g. on // linux/arm64 or linux/riscv64 unix.Dup2(int(interceptor.redirectFile.Fd()), 1) unix.Dup2(int(interceptor.redirectFile.Fd()), 2) -======= - interceptorDupx(int(interceptor.redirectFile.Fd()), 1) - interceptorDupx(int(interceptor.redirectFile.Fd()), 2) ->>>>>>> 33cbc1d (add batchrelease controller) if interceptor.streamTarget != nil { interceptor.tailer, _ = tail.TailFile(interceptor.redirectFile.Name(), tail.Config{Follow: true}) diff --git a/vendor/github.com/onsi/ginkgo/internal/spec/specs.go b/vendor/github.com/onsi/ginkgo/internal/spec/specs.go index 92218e2..0a24139 100644 --- a/vendor/github.com/onsi/ginkgo/internal/spec/specs.go +++ b/vendor/github.com/onsi/ginkgo/internal/spec/specs.go @@ -4,10 +4,7 @@ import ( "math/rand" "regexp" "sort" -<<<<<<< HEAD "strings" -======= ->>>>>>> 33cbc1d (add batchrelease controller) ) type Specs struct { @@ -50,19 +47,11 @@ func (e *Specs) Shuffle(r *rand.Rand) { e.names = names } -<<<<<<< HEAD func (e *Specs) ApplyFocus(description string, focus, skip []string) { if len(focus)+len(skip) == 0 { e.applyProgrammaticFocus() } else { e.applyRegExpFocusAndSkip(description, focus, skip) -======= -func (e *Specs) ApplyFocus(description string, focusString string, skipString string) { - if focusString == "" && skipString == "" { - e.applyProgrammaticFocus() - } else { - e.applyRegExpFocusAndSkip(description, focusString, skipString) ->>>>>>> 33cbc1d (add batchrelease controller) } } @@ -102,7 +91,6 @@ func (e *Specs) toMatch(description string, i int) []byte { } } -<<<<<<< HEAD func (e *Specs) applyRegExpFocusAndSkip(description string, focus, skip []string) { var focusFilter, skipFilter *regexp.Regexp if len(focus) > 0 { @@ -110,16 +98,6 @@ func (e *Specs) applyRegExpFocusAndSkip(description string, focus, skip []string } if len(skip) > 0 { skipFilter = regexp.MustCompile(strings.Join(skip, "|")) -======= -func (e *Specs) applyRegExpFocusAndSkip(description string, focusString string, skipString string) { - var focusFilter *regexp.Regexp - if focusString != "" { - focusFilter = regexp.MustCompile(focusString) - } - var skipFilter *regexp.Regexp - if skipString != "" { - skipFilter = regexp.MustCompile(skipString) ->>>>>>> 33cbc1d (add batchrelease controller) } for i, spec := range e.specs { diff --git a/vendor/github.com/onsi/ginkgo/internal/suite/suite.go b/vendor/github.com/onsi/ginkgo/internal/suite/suite.go index 7c83d9e..b4a83c4 100644 --- a/vendor/github.com/onsi/ginkgo/internal/suite/suite.go +++ b/vendor/github.com/onsi/ginkgo/internal/suite/suite.go @@ -97,11 +97,7 @@ func (suite *Suite) generateSpecsIterator(description string, config config.Gink specs.Shuffle(rand.New(rand.NewSource(config.RandomSeed))) } -<<<<<<< HEAD specs.ApplyFocus(description, config.FocusStrings, config.SkipStrings) -======= - specs.ApplyFocus(description, config.FocusString, config.SkipString) ->>>>>>> 33cbc1d (add batchrelease controller) if config.SkipMeasurements { specs.SkipMeasurements() diff --git a/vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go b/vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go index bf0d304..4dcfaf4 100644 --- a/vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go +++ b/vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go @@ -6,42 +6,30 @@ import ( ) type failFunc func(message string, callerSkip ...int) -<<<<<<< HEAD type skipFunc func(message string, callerSkip ...int) type failedFunc func() bool type nameFunc func() string func New(writer io.Writer, fail failFunc, skip skipFunc, failed failedFunc, name nameFunc, offset int) *ginkgoTestingTProxy { -======= - -func New(writer io.Writer, fail failFunc, offset int) *ginkgoTestingTProxy { ->>>>>>> 33cbc1d (add batchrelease controller) return &ginkgoTestingTProxy{ fail: fail, offset: offset, writer: writer, -<<<<<<< HEAD skip: skip, failed: failed, name: name, -======= ->>>>>>> 33cbc1d (add batchrelease controller) } } type ginkgoTestingTProxy struct { fail failFunc -<<<<<<< HEAD skip skipFunc failed failedFunc name nameFunc -======= ->>>>>>> 33cbc1d (add batchrelease controller) offset int writer io.Writer } -<<<<<<< HEAD func (t *ginkgoTestingTProxy) Cleanup(func()) { // No-op } @@ -51,8 +39,6 @@ func (t *ginkgoTestingTProxy) Setenv(kev, value string) { // No-op until Cleanup is implemented } -======= ->>>>>>> 33cbc1d (add batchrelease controller) func (t *ginkgoTestingTProxy) Error(args ...interface{}) { t.fail(fmt.Sprintln(args...), t.offset) } @@ -69,13 +55,10 @@ func (t *ginkgoTestingTProxy) FailNow() { t.fail("failed", t.offset) } -<<<<<<< HEAD func (t *ginkgoTestingTProxy) Failed() bool { return t.failed() } -======= ->>>>>>> 33cbc1d (add batchrelease controller) func (t *ginkgoTestingTProxy) Fatal(args ...interface{}) { t.fail(fmt.Sprintln(args...), t.offset) } @@ -84,13 +67,10 @@ func (t *ginkgoTestingTProxy) Fatalf(format string, args ...interface{}) { t.fail(fmt.Sprintf(format, args...), t.offset) } -<<<<<<< HEAD func (t *ginkgoTestingTProxy) Helper() { // No-op } -======= ->>>>>>> 33cbc1d (add batchrelease controller) func (t *ginkgoTestingTProxy) Log(args ...interface{}) { fmt.Fprintln(t.writer, args...) } @@ -99,7 +79,6 @@ func (t *ginkgoTestingTProxy) Logf(format string, args ...interface{}) { t.Log(fmt.Sprintf(format, args...)) } -<<<<<<< HEAD func (t *ginkgoTestingTProxy) Name() string { return t.name() } @@ -118,34 +97,13 @@ func (t *ginkgoTestingTProxy) SkipNow() { func (t *ginkgoTestingTProxy) Skipf(format string, args ...interface{}) { t.skip(fmt.Sprintf(format, args...), t.offset) -======= -func (t *ginkgoTestingTProxy) Failed() bool { - return false -} - -func (t *ginkgoTestingTProxy) Parallel() { -} - -func (t *ginkgoTestingTProxy) Skip(args ...interface{}) { - fmt.Println(args...) -} - -func (t *ginkgoTestingTProxy) Skipf(format string, args ...interface{}) { - t.Skip(fmt.Sprintf(format, args...)) -} - -func (t *ginkgoTestingTProxy) SkipNow() { ->>>>>>> 33cbc1d (add batchrelease controller) } func (t *ginkgoTestingTProxy) Skipped() bool { return false } -<<<<<<< HEAD func (t *ginkgoTestingTProxy) TempDir() string { // No-op return "" } -======= ->>>>>>> 33cbc1d (add batchrelease controller) diff --git a/vendor/github.com/onsi/ginkgo/reporters/junit_reporter.go b/vendor/github.com/onsi/ginkgo/reporters/junit_reporter.go index 126066f..01ddca6 100644 --- a/vendor/github.com/onsi/ginkgo/reporters/junit_reporter.go +++ b/vendor/github.com/onsi/ginkgo/reporters/junit_reporter.go @@ -33,23 +33,12 @@ type JUnitTestSuite struct { type JUnitTestCase struct { Name string `xml:"name,attr"` ClassName string `xml:"classname,attr"` -<<<<<<< HEAD -======= - PassedMessage *JUnitPassedMessage `xml:"passed,omitempty"` ->>>>>>> 33cbc1d (add batchrelease controller) FailureMessage *JUnitFailureMessage `xml:"failure,omitempty"` Skipped *JUnitSkipped `xml:"skipped,omitempty"` Time float64 `xml:"time,attr"` SystemOut string `xml:"system-out,omitempty"` } -<<<<<<< HEAD -======= -type JUnitPassedMessage struct { - Message string `xml:",chardata"` -} - ->>>>>>> 33cbc1d (add batchrelease controller) type JUnitFailureMessage struct { Type string `xml:"type,attr"` Message string `xml:",chardata"` @@ -120,13 +109,7 @@ func (reporter *JUnitReporter) SpecDidComplete(specSummary *types.SpecSummary) { ClassName: reporter.testSuiteName, } if reporter.ReporterConfig.ReportPassed && specSummary.State == types.SpecStatePassed { -<<<<<<< HEAD testCase.SystemOut = specSummary.CapturedOutput -======= - testCase.PassedMessage = &JUnitPassedMessage{ - Message: specSummary.CapturedOutput, - } ->>>>>>> 33cbc1d (add batchrelease controller) } if specSummary.State == types.SpecStateFailed || specSummary.State == types.SpecStateTimedOut || specSummary.State == types.SpecStatePanicked { testCase.FailureMessage = &JUnitFailureMessage{ diff --git a/vendor/github.com/onsi/gomega/.travis.yml b/vendor/github.com/onsi/gomega/.travis.yml index 8f85f97..6543dc5 100644 --- a/vendor/github.com/onsi/gomega/.travis.yml +++ b/vendor/github.com/onsi/gomega/.travis.yml @@ -1,5 +1,4 @@ language: go -<<<<<<< HEAD arch: - amd64 - ppc64le @@ -8,29 +7,12 @@ go: - gotip - 1.16.x - 1.15.x -======= - -go: - - 1.13.x - - 1.14.x - - gotip ->>>>>>> 33cbc1d (add batchrelease controller) env: - GO111MODULE=on -<<<<<<< HEAD install: skip script: - go mod tidy && git diff --exit-code go.mod go.sum - make test -======= -install: - - go get -v ./... - - go build ./... - - go get github.com/onsi/ginkgo - - go install github.com/onsi/ginkgo/ginkgo - -script: make test ->>>>>>> 33cbc1d (add batchrelease controller) diff --git a/vendor/github.com/onsi/gomega/CHANGELOG.md b/vendor/github.com/onsi/gomega/CHANGELOG.md index 2c9b287..65c6c1d 100644 --- a/vendor/github.com/onsi/gomega/CHANGELOG.md +++ b/vendor/github.com/onsi/gomega/CHANGELOG.md @@ -1,4 +1,3 @@ -<<<<<<< HEAD ## 1.17.0 ### Features @@ -97,8 +96,6 @@ In addition, 1.15.0 cleans up some of Gomega's internals. Most users shouldn't ### Fixes - updates golang/x/net to fix vulnerability detected by snyk (#394) [c479356] -======= ->>>>>>> 33cbc1d (add batchrelease controller) ## 1.10.2 ### Fixes diff --git a/vendor/github.com/onsi/gomega/Makefile b/vendor/github.com/onsi/gomega/Makefile index f658320..1c6d107 100644 --- a/vendor/github.com/onsi/gomega/Makefile +++ b/vendor/github.com/onsi/gomega/Makefile @@ -1,4 +1,3 @@ -<<<<<<< HEAD ###### Help ################################################################### .DEFAULT_GOAL = help @@ -32,11 +31,3 @@ docker_test: ## Run tests in a container via docker-compose version: ## Display the version of Go @@go version -======= -test: - [ -z "`gofmt -s -w -l -e .`" ] - go vet - ginkgo -p -r --randomizeAllSpecs --failOnPending --randomizeSuites --race - -.PHONY: test ->>>>>>> 33cbc1d (add batchrelease controller) diff --git a/vendor/github.com/onsi/gomega/README.md b/vendor/github.com/onsi/gomega/README.md index 97d1cc7..d45a8c4 100644 --- a/vendor/github.com/onsi/gomega/README.md +++ b/vendor/github.com/onsi/gomega/README.md @@ -1,10 +1,6 @@ ![Gomega: Ginkgo's Preferred Matcher Library](http://onsi.github.io/gomega/images/gomega.png) -<<<<<<< HEAD [![test](https://github.com/onsi/gomega/actions/workflows/test.yml/badge.svg)](https://github.com/onsi/gomega/actions/workflows/test.yml) -======= -[![Build Status](https://travis-ci.org/onsi/gomega.svg?branch=master)](https://travis-ci.org/onsi/gomega) ->>>>>>> 33cbc1d (add batchrelease controller) Jump straight to the [docs](http://onsi.github.io/gomega/) to learn about Gomega, including a list of [all available matchers](http://onsi.github.io/gomega/#provided-matchers). diff --git a/vendor/github.com/onsi/gomega/format/format.go b/vendor/github.com/onsi/gomega/format/format.go index c621c02..6e78c39 100644 --- a/vendor/github.com/onsi/gomega/format/format.go +++ b/vendor/github.com/onsi/gomega/format/format.go @@ -7,10 +7,7 @@ Gomega's format package pretty-prints objects. It explores input objects recurs package format import ( -<<<<<<< HEAD "context" -======= ->>>>>>> 33cbc1d (add batchrelease controller) "fmt" "reflect" "strconv" @@ -21,13 +18,10 @@ import ( // Use MaxDepth to set the maximum recursion depth when printing deeply nested objects var MaxDepth = uint(10) -<<<<<<< HEAD // MaxLength of the string representation of an object. // If MaxLength is set to 0, the Object will not be truncated. var MaxLength = 4000 -======= ->>>>>>> 33cbc1d (add batchrelease controller) /* By default, all objects (even those that implement fmt.Stringer and fmt.GoStringer) are recursively inspected to generate output. @@ -55,20 +49,7 @@ var TruncateThreshold uint = 50 // after the first diff location in a truncated string assertion error message. var CharactersAroundMismatchToInclude uint = 5 -<<<<<<< HEAD var contextType = reflect.TypeOf((*context.Context)(nil)).Elem() -======= -// Ctx interface defined here to keep backwards compatibility with go < 1.7 -// It matches the context.Context interface -type Ctx interface { - Deadline() (deadline time.Time, ok bool) - Done() <-chan struct{} - Err() error - Value(key interface{}) interface{} -} - -var contextType = reflect.TypeOf((*Ctx)(nil)).Elem() ->>>>>>> 33cbc1d (add batchrelease controller) var timeType = reflect.TypeOf(time.Time{}) //The default indentation string emitted by the format package @@ -76,7 +57,6 @@ var Indent = " " var longFormThreshold = 20 -<<<<<<< HEAD // GomegaStringer allows for custom formating of objects for gomega. type GomegaStringer interface { // GomegaString will be used to custom format an object. @@ -85,8 +65,6 @@ type GomegaStringer interface { GomegaString() string } -======= ->>>>>>> 33cbc1d (add batchrelease controller) /* Generates a formatted matcher success/failure message of the form: @@ -131,7 +109,6 @@ func MessageWithDiff(actual, message, expected string) string { tabLength := 4 spaceFromMessageToActual := tabLength + len(": ") - len(message) -<<<<<<< HEAD paddingCount := spaceFromMessageToActual + spacesBeforeFormattedMismatch if paddingCount < 0 { @@ -139,9 +116,6 @@ func MessageWithDiff(actual, message, expected string) string { } padding := strings.Repeat(" ", paddingCount) + "|" -======= - padding := strings.Repeat(" ", spaceFromMessageToActual+spacesBeforeFormattedMismatch) + "|" ->>>>>>> 33cbc1d (add batchrelease controller) return Message(formattedActual, message+padding, formattedExpected) } @@ -197,7 +171,6 @@ func findFirstMismatch(a, b string) int { return 0 } -<<<<<<< HEAD const truncateHelpText = ` Gomega truncated this representation as it exceeds 'format.MaxLength'. Consider having the object provide a custom 'GomegaStringer' representation @@ -225,8 +198,6 @@ func truncateLongStrings(s string) string { return s } -======= ->>>>>>> 33cbc1d (add batchrelease controller) /* Pretty prints the passed in object at the passed in indentation level. @@ -241,11 +212,7 @@ Set PrintContextObjects to true to print the content of objects implementing con func Object(object interface{}, indentation uint) string { indent := strings.Repeat(Indent, int(indentation)) value := reflect.ValueOf(object) -<<<<<<< HEAD return fmt.Sprintf("%s<%s>: %s", indent, formatType(value), formatValue(value, indentation)) -======= - return fmt.Sprintf("%s<%s>: %s", indent, formatType(object), formatValue(value, indentation)) ->>>>>>> 33cbc1d (add batchrelease controller) } /* @@ -265,7 +232,6 @@ func IndentString(s string, indentation uint) string { return result } -<<<<<<< HEAD func formatType(v reflect.Value) string { switch v.Kind() { case reflect.Invalid: @@ -280,27 +246,6 @@ func formatType(v reflect.Value) string { return fmt.Sprintf("%s | len:%d", v.Type(), v.Len()) default: return fmt.Sprintf("%s", v.Type()) -======= -func formatType(object interface{}) string { - t := reflect.TypeOf(object) - if t == nil { - return "nil" - } - switch t.Kind() { - case reflect.Chan: - v := reflect.ValueOf(object) - return fmt.Sprintf("%T | len:%d, cap:%d", object, v.Len(), v.Cap()) - case reflect.Ptr: - return fmt.Sprintf("%T | %p", object, object) - case reflect.Slice: - v := reflect.ValueOf(object) - return fmt.Sprintf("%T | len:%d, cap:%d", object, v.Len(), v.Cap()) - case reflect.Map: - v := reflect.ValueOf(object) - return fmt.Sprintf("%T | len:%d", object, v.Len()) - default: - return fmt.Sprintf("%T", object) ->>>>>>> 33cbc1d (add batchrelease controller) } } @@ -313,7 +258,6 @@ func formatValue(value reflect.Value, indentation uint) string { return "nil" } -<<<<<<< HEAD if value.CanInterface() { obj := value.Interface() @@ -329,16 +273,6 @@ func formatValue(value reflect.Value, indentation uint) string { return truncateLongStrings(x.GoString()) case fmt.Stringer: return truncateLongStrings(x.String()) -======= - if UseStringerRepresentation { - if value.CanInterface() { - obj := value.Interface() - switch x := obj.(type) { - case fmt.GoStringer: - return x.GoString() - case fmt.Stringer: - return x.String() ->>>>>>> 33cbc1d (add batchrelease controller) } } } @@ -369,7 +303,6 @@ func formatValue(value reflect.Value, indentation uint) string { case reflect.Ptr: return formatValue(value.Elem(), indentation) case reflect.Slice: -<<<<<<< HEAD return truncateLongStrings(formatSlice(value, indentation)) case reflect.String: return truncateLongStrings(formatString(value.String(), indentation)) @@ -377,21 +310,11 @@ func formatValue(value reflect.Value, indentation uint) string { return truncateLongStrings(formatSlice(value, indentation)) case reflect.Map: return truncateLongStrings(formatMap(value, indentation)) -======= - return formatSlice(value, indentation) - case reflect.String: - return formatString(value.String(), indentation) - case reflect.Array: - return formatSlice(value, indentation) - case reflect.Map: - return formatMap(value, indentation) ->>>>>>> 33cbc1d (add batchrelease controller) case reflect.Struct: if value.Type() == timeType && value.CanInterface() { t, _ := value.Interface().(time.Time) return t.Format(time.RFC3339Nano) } -<<<<<<< HEAD return truncateLongStrings(formatStruct(value, indentation)) case reflect.Interface: return formatInterface(value, indentation) @@ -400,16 +323,6 @@ func formatValue(value reflect.Value, indentation uint) string { return truncateLongStrings(fmt.Sprintf("%#v", value.Interface())) } return truncateLongStrings(fmt.Sprintf("%#v", value)) -======= - return formatStruct(value, indentation) - case reflect.Interface: - return formatValue(value.Elem(), indentation) - default: - if value.CanInterface() { - return fmt.Sprintf("%#v", value.Interface()) - } - return fmt.Sprintf("%#v", value) ->>>>>>> 33cbc1d (add batchrelease controller) } } @@ -499,13 +412,10 @@ func formatStruct(v reflect.Value, indentation uint) string { return fmt.Sprintf("{%s}", strings.Join(result, ", ")) } -<<<<<<< HEAD func formatInterface(v reflect.Value, indentation uint) string { return fmt.Sprintf("<%s>%s", formatType(v.Elem()), formatValue(v.Elem(), indentation)) } -======= ->>>>>>> 33cbc1d (add batchrelease controller) func isNilValue(a reflect.Value) bool { switch a.Kind() { case reflect.Invalid: diff --git a/vendor/github.com/onsi/gomega/go.mod b/vendor/github.com/onsi/gomega/go.mod index c3b346a..7fea4ac 100644 --- a/vendor/github.com/onsi/gomega/go.mod +++ b/vendor/github.com/onsi/gomega/go.mod @@ -1,6 +1,5 @@ module github.com/onsi/gomega -<<<<<<< HEAD go 1.16 require ( @@ -8,12 +7,4 @@ require ( github.com/onsi/ginkgo v1.16.4 golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 gopkg.in/yaml.v2 v2.4.0 -======= -require ( - github.com/golang/protobuf v1.4.2 - github.com/onsi/ginkgo v1.12.1 - golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 - golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 - gopkg.in/yaml.v2 v2.3.0 ->>>>>>> 33cbc1d (add batchrelease controller) ) diff --git a/vendor/github.com/onsi/gomega/go.sum b/vendor/github.com/onsi/gomega/go.sum index 8357dc2..56f1b44 100644 --- a/vendor/github.com/onsi/gomega/go.sum +++ b/vendor/github.com/onsi/gomega/go.sum @@ -1,4 +1,3 @@ -<<<<<<< HEAD github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -7,18 +6,12 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -======= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= ->>>>>>> 33cbc1d (add batchrelease controller) github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -<<<<<<< HEAD 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 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= @@ -91,71 +84,23 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -======= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= ->>>>>>> 33cbc1d (add batchrelease controller) 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= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -<<<<<<< HEAD google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -======= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= ->>>>>>> 33cbc1d (add batchrelease controller) gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -<<<<<<< HEAD gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -======= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= ->>>>>>> 33cbc1d (add batchrelease controller) diff --git a/vendor/github.com/onsi/gomega/gomega_dsl.go b/vendor/github.com/onsi/gomega/gomega_dsl.go index 20934ee..f5156fd 100644 --- a/vendor/github.com/onsi/gomega/gomega_dsl.go +++ b/vendor/github.com/onsi/gomega/gomega_dsl.go @@ -14,7 +14,6 @@ Gomega is MIT-Licensed package gomega import ( -<<<<<<< HEAD "errors" "fmt" "time" @@ -26,27 +25,11 @@ import ( const GOMEGA_VERSION = "1.17.0" const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler. -======= - "fmt" - "reflect" - "time" - - "github.com/onsi/gomega/internal/assertion" - "github.com/onsi/gomega/internal/asyncassertion" - "github.com/onsi/gomega/internal/testingtsupport" - "github.com/onsi/gomega/types" -) - -const GOMEGA_VERSION = "1.10.2" - -const nilFailHandlerPanic = `You are trying to make an assertion, but Gomega's fail handler is nil. ->>>>>>> 33cbc1d (add batchrelease controller) If you're using Ginkgo then you probably forgot to put your assertion in an It(). Alternatively, you may have forgotten to register a fail handler with RegisterFailHandler() or RegisterTestingT(). Depending on your vendoring solution you may be inadvertently importing gomega and subpackages (e.g. ghhtp, gexec,...) from different locations. ` -<<<<<<< HEAD // Gomega describes the essential Gomega DSL. This interface allows libraries // to abstract between the standard package-level function implementations // and alternatives like *WithT. @@ -119,81 +102,16 @@ func RegisterFailHandlerWithT(_ types.GomegaTestingT, fail types.GomegaFailHandl // Testing.T tests. It is now deprecated and you should use NewWithT() instead to get a fresh instance of Gomega for each test. func RegisterTestingT(t types.GomegaTestingT) { Default.(*internal.Gomega).ConfigureWithT(t) -======= -var globalFailWrapper *types.GomegaFailWrapper - -var defaultEventuallyTimeout = time.Second -var defaultEventuallyPollingInterval = 10 * time.Millisecond -var defaultConsistentlyDuration = 100 * time.Millisecond -var defaultConsistentlyPollingInterval = 10 * time.Millisecond - -// RegisterFailHandler connects Ginkgo to Gomega. When a matcher fails -// the fail handler passed into RegisterFailHandler is called. -func RegisterFailHandler(handler types.GomegaFailHandler) { - RegisterFailHandlerWithT(testingtsupport.EmptyTWithHelper{}, handler) -} - -// RegisterFailHandlerWithT ensures that the given types.TWithHelper and fail handler -// are used globally. -func RegisterFailHandlerWithT(t types.TWithHelper, handler types.GomegaFailHandler) { - if handler == nil { - globalFailWrapper = nil - return - } - - globalFailWrapper = &types.GomegaFailWrapper{ - Fail: handler, - TWithHelper: t, - } -} - -// RegisterTestingT connects Gomega to Golang's XUnit style -// Testing.T tests. It is now deprecated and you should use NewWithT() instead. -// -// Legacy Documentation: -// -// You'll need to call this at the top of each XUnit style test: -// -// func TestFarmHasCow(t *testing.T) { -// RegisterTestingT(t) -// -// f := farm.New([]string{"Cow", "Horse"}) -// Expect(f.HasCow()).To(BeTrue(), "Farm should have cow") -// } -// -// Note that this *testing.T is registered *globally* by Gomega (this is why you don't have to -// pass `t` down to the matcher itself). This means that you cannot run the XUnit style tests -// in parallel as the global fail handler cannot point to more than one testing.T at a time. -// -// NewWithT() does not have this limitation -// -// (As an aside: Ginkgo gets around this limitation by running parallel tests in different *processes*). -func RegisterTestingT(t types.GomegaTestingT) { - tWithHelper, hasHelper := t.(types.TWithHelper) - if !hasHelper { - RegisterFailHandler(testingtsupport.BuildTestingTGomegaFailWrapper(t).Fail) - return - } - RegisterFailHandlerWithT(tWithHelper, testingtsupport.BuildTestingTGomegaFailWrapper(t).Fail) ->>>>>>> 33cbc1d (add batchrelease controller) } // InterceptGomegaFailures runs a given callback and returns an array of // failure messages generated by any Gomega assertions within the callback. -<<<<<<< HEAD // Exeuction continues after the first failure allowing users to collect all failures // in the callback. -======= -// -// This is accomplished by temporarily replacing the *global* fail handler -// with a fail handler that simply annotates failures. The original fail handler -// is reset when InterceptGomegaFailures returns. ->>>>>>> 33cbc1d (add batchrelease controller) // // This is most useful when testing custom matchers, but can also be used to check // on a value using a Gomega assertion without causing a test failure. func InterceptGomegaFailures(f func()) []string { -<<<<<<< HEAD originalHandler := Default.(*internal.Gomega).Fail failures := []string{} Default.(*internal.Gomega).Fail = func(message string, callerSkip ...int) { @@ -238,18 +156,6 @@ func ensureDefaultGomegaIsConfigured() { } } -======= - originalHandler := globalFailWrapper.Fail - failures := []string{} - RegisterFailHandler(func(message string, callerSkip ...int) { - failures = append(failures, message) - }) - f() - RegisterFailHandler(originalHandler) - return failures -} - ->>>>>>> 33cbc1d (add batchrelease controller) // Ω wraps an actual value allowing assertions to be made on it: // Ω("foo").Should(Equal("foo")) // @@ -268,12 +174,8 @@ func ensureDefaultGomegaIsConfigured() { // // Ω and Expect are identical func Ω(actual interface{}, extra ...interface{}) Assertion { -<<<<<<< HEAD ensureDefaultGomegaIsConfigured() return Default.Ω(actual, extra...) -======= - return ExpectWithOffset(0, actual, extra...) ->>>>>>> 33cbc1d (add batchrelease controller) } // Expect wraps an actual value allowing assertions to be made on it: @@ -294,30 +196,21 @@ func Ω(actual interface{}, extra ...interface{}) Assertion { // // Expect and Ω are identical func Expect(actual interface{}, extra ...interface{}) Assertion { -<<<<<<< HEAD ensureDefaultGomegaIsConfigured() return Default.Expect(actual, extra...) -======= - return ExpectWithOffset(0, actual, extra...) ->>>>>>> 33cbc1d (add batchrelease controller) } // ExpectWithOffset wraps an actual value allowing assertions to be made on it: // ExpectWithOffset(1, "foo").To(Equal("foo")) // // Unlike `Expect` and `Ω`, `ExpectWithOffset` takes an additional integer argument -<<<<<<< HEAD // that is used to modify the call-stack offset when computing line numbers. It is // the same as `Expect(...).WithOffset`. -======= -// that is used to modify the call-stack offset when computing line numbers. ->>>>>>> 33cbc1d (add batchrelease controller) // // This is most useful in helper functions that make assertions. If you want Gomega's // error message to refer to the calling line in the test (as opposed to the line in the helper function) // set the first argument of `ExpectWithOffset` appropriately. func ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) Assertion { -<<<<<<< HEAD ensureDefaultGomegaIsConfigured() return Default.ExpectWithOffset(offset, actual, extra...) } @@ -415,58 +308,11 @@ the same as `Eventually(...).WithTimeout` or `Eventually(...).WithTimeout(...).W func Eventually(actual interface{}, intervals ...interface{}) AsyncAssertion { ensureDefaultGomegaIsConfigured() return Default.Eventually(actual, intervals...) -======= - if globalFailWrapper == nil { - panic(nilFailHandlerPanic) - } - return assertion.New(actual, globalFailWrapper, offset, extra...) -} - -// Eventually wraps an actual value allowing assertions to be made on it. -// The assertion is tried periodically until it passes or a timeout occurs. -// -// Both the timeout and polling interval are configurable as optional arguments: -// The first optional argument is the timeout -// The second optional argument is the polling interval -// -// Both intervals can either be specified as time.Duration, parsable duration strings or as floats/integers. In the -// last case they are interpreted as seconds. -// -// If Eventually is passed an actual that is a function taking no arguments and returning at least one value, -// then Eventually will call the function periodically and try the matcher against the function's first return value. -// -// Example: -// -// Eventually(func() int { -// return thingImPolling.Count() -// }).Should(BeNumerically(">=", 17)) -// -// Note that this example could be rewritten: -// -// Eventually(thingImPolling.Count).Should(BeNumerically(">=", 17)) -// -// If the function returns more than one value, then Eventually will pass the first value to the matcher and -// assert that all other values are nil/zero. -// This allows you to pass Eventually a function that returns a value and an error - a common pattern in Go. -// -// For example, consider a method that returns a value and an error: -// func FetchFromDB() (string, error) -// -// Then -// Eventually(FetchFromDB).Should(Equal("hasselhoff")) -// -// Will pass only if the the returned error is nil and the returned string passes the matcher. -// -// Eventually's default timeout is 1 second, and its default polling interval is 10ms -func Eventually(actual interface{}, intervals ...interface{}) AsyncAssertion { - return EventuallyWithOffset(0, actual, intervals...) ->>>>>>> 33cbc1d (add batchrelease controller) } // EventuallyWithOffset operates like Eventually but takes an additional // initial argument to indicate an offset in the call stack. This is useful when building helper // functions that contain matchers. To learn more, read about `ExpectWithOffset`. -<<<<<<< HEAD // // `EventuallyWithOffset` is the same as `Eventually(...).WithOffset`. // @@ -496,111 +342,37 @@ This will block for 200 milliseconds and repeatedly check the channel and ensure func Consistently(actual interface{}, intervals ...interface{}) AsyncAssertion { ensureDefaultGomegaIsConfigured() return Default.Consistently(actual, intervals...) -======= -func EventuallyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion { - if globalFailWrapper == nil { - panic(nilFailHandlerPanic) - } - timeoutInterval := defaultEventuallyTimeout - pollingInterval := defaultEventuallyPollingInterval - if len(intervals) > 0 { - timeoutInterval = toDuration(intervals[0]) - } - if len(intervals) > 1 { - pollingInterval = toDuration(intervals[1]) - } - return asyncassertion.New(asyncassertion.AsyncAssertionTypeEventually, actual, globalFailWrapper, timeoutInterval, pollingInterval, offset) -} - -// Consistently wraps an actual value allowing assertions to be made on it. -// The assertion is tried periodically and is required to pass for a period of time. -// -// Both the total time and polling interval are configurable as optional arguments: -// The first optional argument is the duration that Consistently will run for -// The second optional argument is the polling interval -// -// Both intervals can either be specified as time.Duration, parsable duration strings or as floats/integers. In the -// last case they are interpreted as seconds. -// -// If Consistently is passed an actual that is a function taking no arguments and returning at least one value, -// then Consistently will call the function periodically and try the matcher against the function's first return value. -// -// If the function returns more than one value, then Consistently will pass the first value to the matcher and -// assert that all other values are nil/zero. -// This allows you to pass Consistently a function that returns a value and an error - a common pattern in Go. -// -// Consistently is useful in cases where you want to assert that something *does not happen* over a period of time. -// For example, you want to assert that a goroutine does *not* send data down a channel. In this case, you could: -// -// Consistently(channel).ShouldNot(Receive()) -// -// Consistently's default duration is 100ms, and its default polling interval is 10ms -func Consistently(actual interface{}, intervals ...interface{}) AsyncAssertion { - return ConsistentlyWithOffset(0, actual, intervals...) ->>>>>>> 33cbc1d (add batchrelease controller) } // ConsistentlyWithOffset operates like Consistently but takes an additional // initial argument to indicate an offset in the call stack. This is useful when building helper // functions that contain matchers. To learn more, read about `ExpectWithOffset`. -<<<<<<< HEAD // // `ConsistentlyWithOffset` is the same as `Consistently(...).WithOffset` and // optional `WithTimeout` and `WithPolling`. func ConsistentlyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion { ensureDefaultGomegaIsConfigured() return Default.ConsistentlyWithOffset(offset, actual, intervals...) -======= -func ConsistentlyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion { - if globalFailWrapper == nil { - panic(nilFailHandlerPanic) - } - timeoutInterval := defaultConsistentlyDuration - pollingInterval := defaultConsistentlyPollingInterval - if len(intervals) > 0 { - timeoutInterval = toDuration(intervals[0]) - } - if len(intervals) > 1 { - pollingInterval = toDuration(intervals[1]) - } - return asyncassertion.New(asyncassertion.AsyncAssertionTypeConsistently, actual, globalFailWrapper, timeoutInterval, pollingInterval, offset) ->>>>>>> 33cbc1d (add batchrelease controller) } // SetDefaultEventuallyTimeout sets the default timeout duration for Eventually. Eventually will repeatedly poll your condition until it succeeds, or until this timeout elapses. func SetDefaultEventuallyTimeout(t time.Duration) { -<<<<<<< HEAD Default.SetDefaultEventuallyTimeout(t) -======= - defaultEventuallyTimeout = t ->>>>>>> 33cbc1d (add batchrelease controller) } // SetDefaultEventuallyPollingInterval sets the default polling interval for Eventually. func SetDefaultEventuallyPollingInterval(t time.Duration) { -<<<<<<< HEAD Default.SetDefaultEventuallyPollingInterval(t) -======= - defaultEventuallyPollingInterval = t ->>>>>>> 33cbc1d (add batchrelease controller) } // SetDefaultConsistentlyDuration sets the default duration for Consistently. Consistently will verify that your condition is satisfied for this long. func SetDefaultConsistentlyDuration(t time.Duration) { -<<<<<<< HEAD Default.SetDefaultConsistentlyDuration(t) -======= - defaultConsistentlyDuration = t ->>>>>>> 33cbc1d (add batchrelease controller) } // SetDefaultConsistentlyPollingInterval sets the default polling interval for Consistently. func SetDefaultConsistentlyPollingInterval(t time.Duration) { -<<<<<<< HEAD Default.SetDefaultConsistentlyPollingInterval(t) -======= - defaultConsistentlyPollingInterval = t ->>>>>>> 33cbc1d (add batchrelease controller) } // AsyncAssertion is returned by Eventually and Consistently and polls the actual value passed into Eventually against @@ -618,20 +390,10 @@ func SetDefaultConsistentlyPollingInterval(t time.Duration) { // // Eventually(myChannel).Should(Receive(), "Something should have come down the pipe.") // Consistently(myChannel).ShouldNot(Receive(), func() string { return "Nothing should have come down the pipe." }) -<<<<<<< HEAD type AsyncAssertion = types.AsyncAssertion // GomegaAsyncAssertion is deprecated in favor of AsyncAssertion, which does not stutter. type GomegaAsyncAssertion = types.AsyncAssertion -======= -type AsyncAssertion interface { - Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool - ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool -} - -// GomegaAsyncAssertion is deprecated in favor of AsyncAssertion, which does not stutter. -type GomegaAsyncAssertion = AsyncAssertion ->>>>>>> 33cbc1d (add batchrelease controller) // Assertion is returned by Ω and Expect and compares the actual value to the matcher // passed to the Should/ShouldNot and To/ToNot/NotTo methods. @@ -650,7 +412,6 @@ type GomegaAsyncAssertion = AsyncAssertion // Example: // // Ω(farm.HasCow()).Should(BeTrue(), "Farm %v should have a cow", farm) -<<<<<<< HEAD type Assertion = types.Assertion // GomegaAssertion is deprecated in favor of Assertion, which does not stutter. @@ -658,151 +419,3 @@ type GomegaAssertion = types.Assertion // OmegaMatcher is deprecated in favor of the better-named and better-organized types.GomegaMatcher but sticks around to support existing code that uses it type OmegaMatcher = types.GomegaMatcher -======= -type Assertion interface { - Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool - ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool - - To(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool - ToNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool - NotTo(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool -} - -// GomegaAssertion is deprecated in favor of Assertion, which does not stutter. -type GomegaAssertion = Assertion - -// OmegaMatcher is deprecated in favor of the better-named and better-organized types.GomegaMatcher but sticks around to support existing code that uses it -type OmegaMatcher types.GomegaMatcher - -// WithT wraps a *testing.T and provides `Expect`, `Eventually`, and `Consistently` methods. This allows you to leverage -// Gomega's rich ecosystem of matchers in standard `testing` test suites. -// -// Use `NewWithT` to instantiate a `WithT` -type WithT struct { - t types.GomegaTestingT -} - -// GomegaWithT is deprecated in favor of gomega.WithT, which does not stutter. -type GomegaWithT = WithT - -// NewWithT takes a *testing.T and returngs a `gomega.WithT` allowing you to use `Expect`, `Eventually`, and `Consistently` along with -// Gomega's rich ecosystem of matchers in standard `testing` test suits. -// -// func TestFarmHasCow(t *testing.T) { -// g := gomega.NewWithT(t) -// -// f := farm.New([]string{"Cow", "Horse"}) -// g.Expect(f.HasCow()).To(BeTrue(), "Farm should have cow") -// } -func NewWithT(t types.GomegaTestingT) *WithT { - return &WithT{ - t: t, - } -} - -// NewGomegaWithT is deprecated in favor of gomega.NewWithT, which does not stutter. -func NewGomegaWithT(t types.GomegaTestingT) *GomegaWithT { - return NewWithT(t) -} - -// ExpectWithOffset is used to make assertions. See documentation for ExpectWithOffset. -func (g *WithT) ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) Assertion { - return assertion.New(actual, testingtsupport.BuildTestingTGomegaFailWrapper(g.t), offset, extra...) -} - -// EventuallyWithOffset is used to make asynchronous assertions. See documentation for EventuallyWithOffset. -func (g *WithT) EventuallyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion { - timeoutInterval := defaultEventuallyTimeout - pollingInterval := defaultEventuallyPollingInterval - if len(intervals) > 0 { - timeoutInterval = toDuration(intervals[0]) - } - if len(intervals) > 1 { - pollingInterval = toDuration(intervals[1]) - } - return asyncassertion.New(asyncassertion.AsyncAssertionTypeEventually, actual, testingtsupport.BuildTestingTGomegaFailWrapper(g.t), timeoutInterval, pollingInterval, offset) -} - -// ConsistentlyWithOffset is used to make asynchronous assertions. See documentation for ConsistentlyWithOffset. -func (g *WithT) ConsistentlyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion { - timeoutInterval := defaultConsistentlyDuration - pollingInterval := defaultConsistentlyPollingInterval - if len(intervals) > 0 { - timeoutInterval = toDuration(intervals[0]) - } - if len(intervals) > 1 { - pollingInterval = toDuration(intervals[1]) - } - return asyncassertion.New(asyncassertion.AsyncAssertionTypeConsistently, actual, testingtsupport.BuildTestingTGomegaFailWrapper(g.t), timeoutInterval, pollingInterval, offset) -} - -// Expect is used to make assertions. See documentation for Expect. -func (g *WithT) Expect(actual interface{}, extra ...interface{}) Assertion { - return g.ExpectWithOffset(0, actual, extra...) -} - -// Eventually is used to make asynchronous assertions. See documentation for Eventually. -func (g *WithT) Eventually(actual interface{}, intervals ...interface{}) AsyncAssertion { - return g.EventuallyWithOffset(0, actual, intervals...) -} - -// Consistently is used to make asynchronous assertions. See documentation for Consistently. -func (g *WithT) Consistently(actual interface{}, intervals ...interface{}) AsyncAssertion { - return g.ConsistentlyWithOffset(0, actual, intervals...) -} - -func toDuration(input interface{}) time.Duration { - duration, ok := input.(time.Duration) - if ok { - return duration - } - - value := reflect.ValueOf(input) - kind := reflect.TypeOf(input).Kind() - - if reflect.Int <= kind && kind <= reflect.Int64 { - return time.Duration(value.Int()) * time.Second - } else if reflect.Uint <= kind && kind <= reflect.Uint64 { - return time.Duration(value.Uint()) * time.Second - } else if reflect.Float32 <= kind && kind <= reflect.Float64 { - return time.Duration(value.Float() * float64(time.Second)) - } else if reflect.String == kind { - duration, err := time.ParseDuration(value.String()) - if err != nil { - panic(fmt.Sprintf("%#v is not a valid parsable duration string.", input)) - } - return duration - } - - panic(fmt.Sprintf("%v is not a valid interval. Must be time.Duration, parsable duration string or a number.", input)) -} - -// Gomega describes the essential Gomega DSL. This interface allows libraries -// to abstract between the standard package-level function implementations -// and alternatives like *WithT. -type Gomega interface { - Expect(actual interface{}, extra ...interface{}) Assertion - Eventually(actual interface{}, intervals ...interface{}) AsyncAssertion - Consistently(actual interface{}, intervals ...interface{}) AsyncAssertion -} - -type globalFailHandlerGomega struct{} - -// DefaultGomega supplies the standard package-level implementation -var Default Gomega = globalFailHandlerGomega{} - -// Expect is used to make assertions. See documentation for Expect. -func (globalFailHandlerGomega) Expect(actual interface{}, extra ...interface{}) Assertion { - return Expect(actual, extra...) -} - -// Eventually is used to make asynchronous assertions. See documentation for Eventually. -func (globalFailHandlerGomega) Eventually(actual interface{}, extra ...interface{}) AsyncAssertion { - return Eventually(actual, extra...) -} - -// Consistently is used to make asynchronous assertions. See documentation for Consistently. -func (globalFailHandlerGomega) Consistently(actual interface{}, extra ...interface{}) AsyncAssertion { - return Consistently(actual, extra...) -} ->>>>>>> 33cbc1d (add batchrelease controller) diff --git a/vendor/github.com/onsi/gomega/internal/assertion/assertion.go b/vendor/github.com/onsi/gomega/internal/assertion/assertion.go deleted file mode 100644 index a248298..0000000 --- a/vendor/github.com/onsi/gomega/internal/assertion/assertion.go +++ /dev/null @@ -1,109 +0,0 @@ -package assertion - -import ( - "fmt" - "reflect" - - "github.com/onsi/gomega/types" -) - -type Assertion struct { - actualInput interface{} - failWrapper *types.GomegaFailWrapper - offset int - extra []interface{} -} - -func New(actualInput interface{}, failWrapper *types.GomegaFailWrapper, offset int, extra ...interface{}) *Assertion { - return &Assertion{ - actualInput: actualInput, - failWrapper: failWrapper, - offset: offset, - extra: extra, - } -} - -func (assertion *Assertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { - assertion.failWrapper.TWithHelper.Helper() - return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, true, optionalDescription...) -} - -func (assertion *Assertion) ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { - assertion.failWrapper.TWithHelper.Helper() - return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...) -} - -func (assertion *Assertion) To(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { - assertion.failWrapper.TWithHelper.Helper() - return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, true, optionalDescription...) -} - -func (assertion *Assertion) ToNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { - assertion.failWrapper.TWithHelper.Helper() - return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...) -} - -func (assertion *Assertion) NotTo(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { - assertion.failWrapper.TWithHelper.Helper() - return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...) -} - -func (assertion *Assertion) buildDescription(optionalDescription ...interface{}) string { - switch len(optionalDescription) { - case 0: - return "" - case 1: - if describe, ok := optionalDescription[0].(func() string); ok { - return describe() + "\n" - } - } - return fmt.Sprintf(optionalDescription[0].(string), optionalDescription[1:]...) + "\n" -} - -func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool, optionalDescription ...interface{}) bool { - matches, err := matcher.Match(assertion.actualInput) - assertion.failWrapper.TWithHelper.Helper() - if err != nil { - description := assertion.buildDescription(optionalDescription...) - assertion.failWrapper.Fail(description+err.Error(), 2+assertion.offset) - return false - } - if matches != desiredMatch { - var message string - if desiredMatch { - message = matcher.FailureMessage(assertion.actualInput) - } else { - message = matcher.NegatedFailureMessage(assertion.actualInput) - } - description := assertion.buildDescription(optionalDescription...) - assertion.failWrapper.Fail(description+message, 2+assertion.offset) - return false - } - - return true -} - -func (assertion *Assertion) vetExtras(optionalDescription ...interface{}) bool { - success, message := vetExtras(assertion.extra) - if success { - return true - } - - description := assertion.buildDescription(optionalDescription...) - assertion.failWrapper.TWithHelper.Helper() - assertion.failWrapper.Fail(description+message, 2+assertion.offset) - return false -} - -func vetExtras(extras []interface{}) (bool, string) { - for i, extra := range extras { - if extra != nil { - zeroValue := reflect.Zero(reflect.TypeOf(extra)).Interface() - if !reflect.DeepEqual(zeroValue, extra) { - message := fmt.Sprintf("Unexpected non-nil/non-zero extra argument at index %d:\n\t<%T>: %#v", i+1, extra, extra) - return false, message - } - } - } - return true, "" -} diff --git a/vendor/github.com/onsi/gomega/internal/asyncassertion/async_assertion.go b/vendor/github.com/onsi/gomega/internal/asyncassertion/async_assertion.go deleted file mode 100644 index 5204836..0000000 --- a/vendor/github.com/onsi/gomega/internal/asyncassertion/async_assertion.go +++ /dev/null @@ -1,198 +0,0 @@ -// untested sections: 2 - -package asyncassertion - -import ( - "errors" - "fmt" - "reflect" - "time" - - "github.com/onsi/gomega/internal/oraclematcher" - "github.com/onsi/gomega/types" -) - -type AsyncAssertionType uint - -const ( - AsyncAssertionTypeEventually AsyncAssertionType = iota - AsyncAssertionTypeConsistently -) - -type AsyncAssertion struct { - asyncType AsyncAssertionType - actualInput interface{} - timeoutInterval time.Duration - pollingInterval time.Duration - failWrapper *types.GomegaFailWrapper - offset int -} - -func New(asyncType AsyncAssertionType, actualInput interface{}, failWrapper *types.GomegaFailWrapper, timeoutInterval time.Duration, pollingInterval time.Duration, offset int) *AsyncAssertion { - actualType := reflect.TypeOf(actualInput) - if actualType.Kind() == reflect.Func { - if actualType.NumIn() != 0 || actualType.NumOut() == 0 { - panic("Expected a function with no arguments and one or more return values.") - } - } - - return &AsyncAssertion{ - asyncType: asyncType, - actualInput: actualInput, - failWrapper: failWrapper, - timeoutInterval: timeoutInterval, - pollingInterval: pollingInterval, - offset: offset, - } -} - -func (assertion *AsyncAssertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { - assertion.failWrapper.TWithHelper.Helper() - return assertion.match(matcher, true, optionalDescription...) -} - -func (assertion *AsyncAssertion) ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { - assertion.failWrapper.TWithHelper.Helper() - return assertion.match(matcher, false, optionalDescription...) -} - -func (assertion *AsyncAssertion) buildDescription(optionalDescription ...interface{}) string { - switch len(optionalDescription) { - case 0: - return "" - case 1: - if describe, ok := optionalDescription[0].(func() string); ok { - return describe() + "\n" - } - } - return fmt.Sprintf(optionalDescription[0].(string), optionalDescription[1:]...) + "\n" -} - -func (assertion *AsyncAssertion) actualInputIsAFunction() bool { - actualType := reflect.TypeOf(assertion.actualInput) - return actualType.Kind() == reflect.Func && actualType.NumIn() == 0 && actualType.NumOut() > 0 -} - -func (assertion *AsyncAssertion) pollActual() (interface{}, error) { - if assertion.actualInputIsAFunction() { - values := reflect.ValueOf(assertion.actualInput).Call([]reflect.Value{}) - - extras := []interface{}{} - for _, value := range values[1:] { - extras = append(extras, value.Interface()) - } - - success, message := vetExtras(extras) - - if !success { - return nil, errors.New(message) - } - - return values[0].Interface(), nil - } - - return assertion.actualInput, nil -} - -func (assertion *AsyncAssertion) matcherMayChange(matcher types.GomegaMatcher, value interface{}) bool { - if assertion.actualInputIsAFunction() { - return true - } - - return oraclematcher.MatchMayChangeInTheFuture(matcher, value) -} - -func (assertion *AsyncAssertion) match(matcher types.GomegaMatcher, desiredMatch bool, optionalDescription ...interface{}) bool { - timer := time.Now() - timeout := time.After(assertion.timeoutInterval) - - var matches bool - var err error - mayChange := true - value, err := assertion.pollActual() - if err == nil { - mayChange = assertion.matcherMayChange(matcher, value) - matches, err = matcher.Match(value) - } - - assertion.failWrapper.TWithHelper.Helper() - - fail := func(preamble string) { - errMsg := "" - message := "" - if err != nil { - errMsg = "Error: " + err.Error() - } else { - if desiredMatch { - message = matcher.FailureMessage(value) - } else { - message = matcher.NegatedFailureMessage(value) - } - } - assertion.failWrapper.TWithHelper.Helper() - description := assertion.buildDescription(optionalDescription...) - assertion.failWrapper.Fail(fmt.Sprintf("%s after %.3fs.\n%s%s%s", preamble, time.Since(timer).Seconds(), description, message, errMsg), 3+assertion.offset) - } - - if assertion.asyncType == AsyncAssertionTypeEventually { - for { - if err == nil && matches == desiredMatch { - return true - } - - if !mayChange { - fail("No future change is possible. Bailing out early") - return false - } - - select { - case <-time.After(assertion.pollingInterval): - value, err = assertion.pollActual() - if err == nil { - mayChange = assertion.matcherMayChange(matcher, value) - matches, err = matcher.Match(value) - } - case <-timeout: - fail("Timed out") - return false - } - } - } else if assertion.asyncType == AsyncAssertionTypeConsistently { - for { - if !(err == nil && matches == desiredMatch) { - fail("Failed") - return false - } - - if !mayChange { - return true - } - - select { - case <-time.After(assertion.pollingInterval): - value, err = assertion.pollActual() - if err == nil { - mayChange = assertion.matcherMayChange(matcher, value) - matches, err = matcher.Match(value) - } - case <-timeout: - return true - } - } - } - - return false -} - -func vetExtras(extras []interface{}) (bool, string) { - for i, extra := range extras { - if extra != nil { - zeroValue := reflect.Zero(reflect.TypeOf(extra)).Interface() - if !reflect.DeepEqual(zeroValue, extra) { - message := fmt.Sprintf("Unexpected non-nil/non-zero extra argument at index %d:\n\t<%T>: %#v", i+1, extra, extra) - return false, message - } - } - } - return true, "" -} diff --git a/vendor/github.com/onsi/gomega/internal/oraclematcher/oracle_matcher.go b/vendor/github.com/onsi/gomega/internal/oraclematcher/oracle_matcher.go deleted file mode 100644 index 66cad88..0000000 --- a/vendor/github.com/onsi/gomega/internal/oraclematcher/oracle_matcher.go +++ /dev/null @@ -1,25 +0,0 @@ -package oraclematcher - -import "github.com/onsi/gomega/types" - -/* -GomegaMatchers that also match the OracleMatcher interface can convey information about -whether or not their result will change upon future attempts. - -This allows `Eventually` and `Consistently` to short circuit if success becomes impossible. - -For example, a process' exit code can never change. So, gexec's Exit matcher returns `true` -for `MatchMayChangeInTheFuture` until the process exits, at which point it returns `false` forevermore. -*/ -type OracleMatcher interface { - MatchMayChangeInTheFuture(actual interface{}) bool -} - -func MatchMayChangeInTheFuture(matcher types.GomegaMatcher, value interface{}) bool { - oracleMatcher, ok := matcher.(OracleMatcher) - if !ok { - return true - } - - return oracleMatcher.MatchMayChangeInTheFuture(value) -} diff --git a/vendor/github.com/onsi/gomega/internal/testingtsupport/testing_t_support.go b/vendor/github.com/onsi/gomega/internal/testingtsupport/testing_t_support.go deleted file mode 100644 index bb27032..0000000 --- a/vendor/github.com/onsi/gomega/internal/testingtsupport/testing_t_support.go +++ /dev/null @@ -1,60 +0,0 @@ -package testingtsupport - -import ( - "regexp" - "runtime/debug" - "strings" - - "github.com/onsi/gomega/types" -) - -var StackTracePruneRE = regexp.MustCompile(`\/gomega\/|\/ginkgo\/|\/pkg\/testing\/|\/pkg\/runtime\/`) - -type EmptyTWithHelper struct{} - -func (e EmptyTWithHelper) Helper() {} - -type gomegaTestingT interface { - Fatalf(format string, args ...interface{}) -} - -func BuildTestingTGomegaFailWrapper(t gomegaTestingT) *types.GomegaFailWrapper { - tWithHelper, hasHelper := t.(types.TWithHelper) - if !hasHelper { - tWithHelper = EmptyTWithHelper{} - } - - fail := func(message string, callerSkip ...int) { - if hasHelper { - tWithHelper.Helper() - t.Fatalf("\n%s", message) - } else { - skip := 2 - if len(callerSkip) > 0 { - skip += callerSkip[0] - } - stackTrace := pruneStack(string(debug.Stack()), skip) - t.Fatalf("\n%s\n%s\n", stackTrace, message) - } - } - - return &types.GomegaFailWrapper{ - Fail: fail, - TWithHelper: tWithHelper, - } -} - -func pruneStack(fullStackTrace string, skip int) string { - stack := strings.Split(fullStackTrace, "\n")[1:] - if len(stack) > 2*skip { - stack = stack[2*skip:] - } - prunedStack := []string{} - for i := 0; i < len(stack)/2; i++ { - if !StackTracePruneRE.Match([]byte(stack[i*2])) { - prunedStack = append(prunedStack, stack[i*2]) - prunedStack = append(prunedStack, stack[i*2+1]) - } - } - return strings.Join(prunedStack, "\n") -} diff --git a/vendor/github.com/onsi/gomega/matchers.go b/vendor/github.com/onsi/gomega/matchers.go index ebeff14..e4aacc9 100644 --- a/vendor/github.com/onsi/gomega/matchers.go +++ b/vendor/github.com/onsi/gomega/matchers.go @@ -342,7 +342,6 @@ func HaveKeyWithValue(key interface{}, value interface{}) types.GomegaMatcher { } } -<<<<<<< HEAD //HaveField succeeds if actual is a struct and the value at the passed in field //matches the passed in matcher. By default HaveField used Equal() to perform the match, //however a matcher can be passed in in stead. @@ -371,8 +370,6 @@ func HaveField(field string, expected interface{}) types.GomegaMatcher { } } -======= ->>>>>>> 33cbc1d (add batchrelease controller) //BeNumerically performs numerical assertions in a type-agnostic way. //Actual and expected should be numbers, though the specific type of //number is irrelevant (float32, float64, uint8, etc...). @@ -454,7 +451,6 @@ func BeADirectory() types.GomegaMatcher { //Expected must be either an int or a string. // Expect(resp).Should(HaveHTTPStatus(http.StatusOK)) // asserts that resp.StatusCode == 200 // Expect(resp).Should(HaveHTTPStatus("404 Not Found")) // asserts that resp.Status == "404 Not Found" -<<<<<<< HEAD // Expect(resp).Should(HaveHTTPStatus(http.StatusOK, http.StatusNoContent)) // asserts that resp.StatusCode == 200 || resp.StatusCode == 204 func HaveHTTPStatus(expected ...interface{}) types.GomegaMatcher { return &matchers.HaveHTTPStatusMatcher{Expected: expected} @@ -478,12 +474,6 @@ func HaveHTTPBody(expected interface{}) types.GomegaMatcher { return &matchers.HaveHTTPBodyMatcher{Expected: expected} } -======= -func HaveHTTPStatus(expected interface{}) types.GomegaMatcher { - return &matchers.HaveHTTPStatusMatcher{Expected: expected} -} - ->>>>>>> 33cbc1d (add batchrelease controller) //And succeeds only if all of the given matchers succeed. //The matchers are tried in order, and will fail-fast if one doesn't succeed. // Expect("hi").To(And(HaveLen(2), Equal("hi")) @@ -523,7 +513,6 @@ func Not(matcher types.GomegaMatcher) types.GomegaMatcher { } //WithTransform applies the `transform` to the actual value and matches it against `matcher`. -<<<<<<< HEAD //The given transform must be either a function of one parameter that returns one value or a // function of one parameter that returns two values, where the second value must be of the // error type. @@ -533,17 +522,10 @@ func Not(matcher types.GomegaMatcher) types.GomegaMatcher { // var failingplus1 = func(i int) (int, error) { return 42, "this does not compute" } // Expect(1).To(WithTransform(failingplus1, Equal(2))) // -======= -//The given transform must be a function of one parameter that returns one value. -// var plus1 = func(i int) int { return i + 1 } -// Expect(1).To(WithTransform(plus1, Equal(2)) -// ->>>>>>> 33cbc1d (add batchrelease controller) //And(), Or(), Not() and WithTransform() allow matchers to be composed into complex expressions. func WithTransform(transform interface{}, matcher types.GomegaMatcher) types.GomegaMatcher { return matchers.NewWithTransformMatcher(transform, matcher) } -<<<<<<< HEAD //Satisfy matches the actual value against the `predicate` function. //The given predicate must be a function of one paramter that returns bool. @@ -552,5 +534,3 @@ func WithTransform(transform interface{}, matcher types.GomegaMatcher) types.Gom func Satisfy(predicate interface{}) types.GomegaMatcher { return matchers.NewSatisfyMatcher(predicate) } -======= ->>>>>>> 33cbc1d (add batchrelease controller) diff --git a/vendor/github.com/onsi/gomega/matchers/and.go b/vendor/github.com/onsi/gomega/matchers/and.go index 4d84a12..6bd826a 100644 --- a/vendor/github.com/onsi/gomega/matchers/and.go +++ b/vendor/github.com/onsi/gomega/matchers/and.go @@ -4,10 +4,6 @@ import ( "fmt" "github.com/onsi/gomega/format" -<<<<<<< HEAD -======= - "github.com/onsi/gomega/internal/oraclematcher" ->>>>>>> 33cbc1d (add batchrelease controller) "github.com/onsi/gomega/types" ) @@ -55,20 +51,12 @@ func (m *AndMatcher) MatchMayChangeInTheFuture(actual interface{}) bool { if m.firstFailedMatcher == nil { // so all matchers succeeded.. Any one of them changing would change the result. for _, matcher := range m.Matchers { -<<<<<<< HEAD if types.MatchMayChangeInTheFuture(matcher, actual) { -======= - if oraclematcher.MatchMayChangeInTheFuture(matcher, actual) { ->>>>>>> 33cbc1d (add batchrelease controller) return true } } return false // none of were going to change } // one of the matchers failed.. it must be able to change in order to affect the result -<<<<<<< HEAD return types.MatchMayChangeInTheFuture(m.firstFailedMatcher, actual) -======= - return oraclematcher.MatchMayChangeInTheFuture(m.firstFailedMatcher, actual) ->>>>>>> 33cbc1d (add batchrelease controller) } diff --git a/vendor/github.com/onsi/gomega/matchers/be_element_of_matcher.go b/vendor/github.com/onsi/gomega/matchers/be_element_of_matcher.go index 8c496c9..9ee75a5 100644 --- a/vendor/github.com/onsi/gomega/matchers/be_element_of_matcher.go +++ b/vendor/github.com/onsi/gomega/matchers/be_element_of_matcher.go @@ -18,29 +18,9 @@ func (matcher *BeElementOfMatcher) Match(actual interface{}) (success bool, err return false, fmt.Errorf("BeElement matcher expects actual to be typed") } -<<<<<<< HEAD var lastError error for _, m := range flatten(matcher.Elements) { matcher := &EqualMatcher{Expected: m} -======= - length := len(matcher.Elements) - valueAt := func(i int) interface{} { - return matcher.Elements[i] - } - // Special handling of a single element of type Array or Slice - if length == 1 && isArrayOrSlice(valueAt(0)) { - element := valueAt(0) - value := reflect.ValueOf(element) - length = value.Len() - valueAt = func(i int) interface{} { - return value.Index(i).Interface() - } - } - - var lastError error - for i := 0; i < length; i++ { - matcher := &EqualMatcher{Expected: valueAt(i)} ->>>>>>> 33cbc1d (add batchrelease controller) success, err := matcher.Match(actual) if err != nil { lastError = err @@ -55,17 +35,9 @@ func (matcher *BeElementOfMatcher) Match(actual interface{}) (success bool, err } func (matcher *BeElementOfMatcher) FailureMessage(actual interface{}) (message string) { -<<<<<<< HEAD return format.Message(actual, "to be an element of", presentable(matcher.Elements)) } func (matcher *BeElementOfMatcher) NegatedFailureMessage(actual interface{}) (message string) { return format.Message(actual, "not to be an element of", presentable(matcher.Elements)) -======= - return format.Message(actual, "to be an element of", matcher.Elements) -} - -func (matcher *BeElementOfMatcher) NegatedFailureMessage(actual interface{}) (message string) { - return format.Message(actual, "not to be an element of", matcher.Elements) ->>>>>>> 33cbc1d (add batchrelease controller) } diff --git a/vendor/github.com/onsi/gomega/matchers/be_numerically_matcher.go b/vendor/github.com/onsi/gomega/matchers/be_numerically_matcher.go index f467f4b..100735d 100644 --- a/vendor/github.com/onsi/gomega/matchers/be_numerically_matcher.go +++ b/vendor/github.com/onsi/gomega/matchers/be_numerically_matcher.go @@ -45,11 +45,7 @@ func (matcher *BeNumericallyMatcher) Match(actual interface{}) (success bool, er return false, fmt.Errorf("Expected a number. Got:\n%s", format.Object(matcher.CompareTo[0], 1)) } if len(matcher.CompareTo) == 2 && !isNumber(matcher.CompareTo[1]) { -<<<<<<< HEAD return false, fmt.Errorf("Expected a number. Got:\n%s", format.Object(matcher.CompareTo[1], 1)) -======= - return false, fmt.Errorf("Expected a number. Got:\n%s", format.Object(matcher.CompareTo[0], 1)) ->>>>>>> 33cbc1d (add batchrelease controller) } switch matcher.Comparator { diff --git a/vendor/github.com/onsi/gomega/matchers/consist_of.go b/vendor/github.com/onsi/gomega/matchers/consist_of.go index 8e23e1a..e8ef0de 100644 --- a/vendor/github.com/onsi/gomega/matchers/consist_of.go +++ b/vendor/github.com/onsi/gomega/matchers/consist_of.go @@ -57,7 +57,6 @@ func equalMatchersToElements(matchers []interface{}) (elements []interface{}) { return } -<<<<<<< HEAD func flatten(elems []interface{}) []interface{} { if len(elems) != 1 || !isArrayOrSlice(elems[0]) { return elems @@ -73,19 +72,6 @@ func flatten(elems []interface{}) []interface{} { func matchers(expectedElems []interface{}) (matchers []interface{}) { for _, e := range flatten(expectedElems) { -======= -func matchers(expectedElems []interface{}) (matchers []interface{}) { - elems := expectedElems - if len(expectedElems) == 1 && isArrayOrSlice(expectedElems[0]) { - elems = []interface{}{} - value := reflect.ValueOf(expectedElems[0]) - for i := 0; i < value.Len(); i++ { - elems = append(elems, value.Index(i).Interface()) - } - } - - for _, e := range elems { ->>>>>>> 33cbc1d (add batchrelease controller) matcher, isMatcher := e.(omegaMatcher) if !isMatcher { matcher = &EqualMatcher{Expected: e} @@ -95,7 +81,6 @@ func matchers(expectedElems []interface{}) (matchers []interface{}) { return } -<<<<<<< HEAD func presentable(elems []interface{}) interface{} { elems = flatten(elems) @@ -119,8 +104,6 @@ func presentable(elems []interface{}) interface{} { return ss.Interface() } -======= ->>>>>>> 33cbc1d (add batchrelease controller) func valuesOf(actual interface{}) []interface{} { value := reflect.ValueOf(actual) values := []interface{}{} @@ -139,19 +122,11 @@ func valuesOf(actual interface{}) []interface{} { } func (matcher *ConsistOfMatcher) FailureMessage(actual interface{}) (message string) { -<<<<<<< HEAD message = format.Message(actual, "to consist of", presentable(matcher.Elements)) message = appendMissingElements(message, matcher.missingElements) if len(matcher.extraElements) > 0 { message = fmt.Sprintf("%s\nthe extra elements were\n%s", message, format.Object(presentable(matcher.extraElements), 1)) -======= - message = format.Message(actual, "to consist of", matcher.Elements) - message = appendMissingElements(message, matcher.missingElements) - if len(matcher.extraElements) > 0 { - message = fmt.Sprintf("%s\nthe extra elements were\n%s", message, - format.Object(matcher.extraElements, 1)) ->>>>>>> 33cbc1d (add batchrelease controller) } return } @@ -161,17 +136,9 @@ func appendMissingElements(message string, missingElements []interface{}) string return message } return fmt.Sprintf("%s\nthe missing elements were\n%s", message, -<<<<<<< HEAD format.Object(presentable(missingElements), 1)) } func (matcher *ConsistOfMatcher) NegatedFailureMessage(actual interface{}) (message string) { return format.Message(actual, "not to consist of", presentable(matcher.Elements)) -======= - format.Object(missingElements, 1)) -} - -func (matcher *ConsistOfMatcher) NegatedFailureMessage(actual interface{}) (message string) { - return format.Message(actual, "not to consist of", matcher.Elements) ->>>>>>> 33cbc1d (add batchrelease controller) } diff --git a/vendor/github.com/onsi/gomega/matchers/contain_elements_matcher.go b/vendor/github.com/onsi/gomega/matchers/contain_elements_matcher.go index a7bb465..946cd8b 100644 --- a/vendor/github.com/onsi/gomega/matchers/contain_elements_matcher.go +++ b/vendor/github.com/onsi/gomega/matchers/contain_elements_matcher.go @@ -35,18 +35,10 @@ func (matcher *ContainElementsMatcher) Match(actual interface{}) (success bool, } func (matcher *ContainElementsMatcher) FailureMessage(actual interface{}) (message string) { -<<<<<<< HEAD message = format.Message(actual, "to contain elements", presentable(matcher.Elements)) -======= - message = format.Message(actual, "to contain elements", matcher.Elements) ->>>>>>> 33cbc1d (add batchrelease controller) return appendMissingElements(message, matcher.missingElements) } func (matcher *ContainElementsMatcher) NegatedFailureMessage(actual interface{}) (message string) { -<<<<<<< HEAD return format.Message(actual, "not to contain elements", presentable(matcher.Elements)) -======= - return format.Message(actual, "not to contain elements", matcher.Elements) ->>>>>>> 33cbc1d (add batchrelease controller) } diff --git a/vendor/github.com/onsi/gomega/matchers/have_http_status_matcher.go b/vendor/github.com/onsi/gomega/matchers/have_http_status_matcher.go index e3f2b9d..85f7764 100644 --- a/vendor/github.com/onsi/gomega/matchers/have_http_status_matcher.go +++ b/vendor/github.com/onsi/gomega/matchers/have_http_status_matcher.go @@ -2,26 +2,17 @@ package matchers import ( "fmt" -<<<<<<< HEAD "io" "net/http" "net/http/httptest" "reflect" "strings" -======= - "net/http" - "net/http/httptest" ->>>>>>> 33cbc1d (add batchrelease controller) "github.com/onsi/gomega/format" ) type HaveHTTPStatusMatcher struct { -<<<<<<< HEAD Expected []interface{} -======= - Expected interface{} ->>>>>>> 33cbc1d (add batchrelease controller) } func (matcher *HaveHTTPStatusMatcher) Match(actual interface{}) (success bool, err error) { @@ -35,7 +26,6 @@ func (matcher *HaveHTTPStatusMatcher) Match(actual interface{}) (success bool, e return false, fmt.Errorf("HaveHTTPStatus matcher expects *http.Response or *httptest.ResponseRecorder. Got:\n%s", format.Object(actual, 1)) } -<<<<<<< HEAD if len(matcher.Expected) == 0 { return false, fmt.Errorf("HaveHTTPStatus matcher must be passed an int or a string. Got nothing") } @@ -103,22 +93,4 @@ func formatHttpResponse(input interface{}) string { s.WriteString(fmt.Sprintf("%s}", format.Indent)) return s.String() -======= - switch e := matcher.Expected.(type) { - case int: - return resp.StatusCode == e, nil - case string: - return resp.Status == e, nil - } - - return false, fmt.Errorf("HaveHTTPStatus matcher must be passed an int or a string. Got:\n%s", format.Object(matcher.Expected, 1)) -} - -func (matcher *HaveHTTPStatusMatcher) FailureMessage(actual interface{}) (message string) { - return format.Message(actual, "to have HTTP status", matcher.Expected) -} - -func (matcher *HaveHTTPStatusMatcher) NegatedFailureMessage(actual interface{}) (message string) { - return format.Message(actual, "not to have HTTP status", matcher.Expected) ->>>>>>> 33cbc1d (add batchrelease controller) } diff --git a/vendor/github.com/onsi/gomega/matchers/match_error_matcher.go b/vendor/github.com/onsi/gomega/matchers/match_error_matcher.go index 3a20da0..c8993a8 100644 --- a/vendor/github.com/onsi/gomega/matchers/match_error_matcher.go +++ b/vendor/github.com/onsi/gomega/matchers/match_error_matcher.go @@ -1,18 +1,11 @@ package matchers import ( -<<<<<<< HEAD "errors" -======= ->>>>>>> 33cbc1d (add batchrelease controller) "fmt" "reflect" "github.com/onsi/gomega/format" -<<<<<<< HEAD -======= - "golang.org/x/xerrors" ->>>>>>> 33cbc1d (add batchrelease controller) ) type MatchErrorMatcher struct { @@ -32,11 +25,7 @@ func (matcher *MatchErrorMatcher) Match(actual interface{}) (success bool, err e expected := matcher.Expected if isError(expected) { -<<<<<<< HEAD return reflect.DeepEqual(actualErr, expected) || errors.Is(actualErr, expected.(error)), nil -======= - return reflect.DeepEqual(actualErr, expected) || xerrors.Is(actualErr, expected.(error)), nil ->>>>>>> 33cbc1d (add batchrelease controller) } if isString(expected) { diff --git a/vendor/github.com/onsi/gomega/matchers/not.go b/vendor/github.com/onsi/gomega/matchers/not.go index ad5ad8e..78b7191 100644 --- a/vendor/github.com/onsi/gomega/matchers/not.go +++ b/vendor/github.com/onsi/gomega/matchers/not.go @@ -1,10 +1,6 @@ package matchers import ( -<<<<<<< HEAD -======= - "github.com/onsi/gomega/internal/oraclematcher" ->>>>>>> 33cbc1d (add batchrelease controller) "github.com/onsi/gomega/types" ) @@ -29,9 +25,5 @@ func (m *NotMatcher) NegatedFailureMessage(actual interface{}) (message string) } func (m *NotMatcher) MatchMayChangeInTheFuture(actual interface{}) bool { -<<<<<<< HEAD return types.MatchMayChangeInTheFuture(m.Matcher, actual) // just return m.Matcher's value -======= - return oraclematcher.MatchMayChangeInTheFuture(m.Matcher, actual) // just return m.Matcher's value ->>>>>>> 33cbc1d (add batchrelease controller) } diff --git a/vendor/github.com/onsi/gomega/matchers/or.go b/vendor/github.com/onsi/gomega/matchers/or.go index a62977b..841ae26 100644 --- a/vendor/github.com/onsi/gomega/matchers/or.go +++ b/vendor/github.com/onsi/gomega/matchers/or.go @@ -4,10 +4,6 @@ import ( "fmt" "github.com/onsi/gomega/format" -<<<<<<< HEAD -======= - "github.com/onsi/gomega/internal/oraclematcher" ->>>>>>> 33cbc1d (add batchrelease controller) "github.com/onsi/gomega/types" ) @@ -57,19 +53,11 @@ func (m *OrMatcher) MatchMayChangeInTheFuture(actual interface{}) bool { if m.firstSuccessfulMatcher != nil { // one of the matchers succeeded.. it must be able to change in order to affect the result -<<<<<<< HEAD return types.MatchMayChangeInTheFuture(m.firstSuccessfulMatcher, actual) } else { // so all matchers failed.. Any one of them changing would change the result. for _, matcher := range m.Matchers { if types.MatchMayChangeInTheFuture(matcher, actual) { -======= - return oraclematcher.MatchMayChangeInTheFuture(m.firstSuccessfulMatcher, actual) - } else { - // so all matchers failed.. Any one of them changing would change the result. - for _, matcher := range m.Matchers { - if oraclematcher.MatchMayChangeInTheFuture(matcher, actual) { ->>>>>>> 33cbc1d (add batchrelease controller) return true } } diff --git a/vendor/github.com/onsi/gomega/matchers/with_transform.go b/vendor/github.com/onsi/gomega/matchers/with_transform.go index df2b106..6f743b1 100644 --- a/vendor/github.com/onsi/gomega/matchers/with_transform.go +++ b/vendor/github.com/onsi/gomega/matchers/with_transform.go @@ -4,20 +4,12 @@ import ( "fmt" "reflect" -<<<<<<< HEAD -======= - "github.com/onsi/gomega/internal/oraclematcher" ->>>>>>> 33cbc1d (add batchrelease controller) "github.com/onsi/gomega/types" ) type WithTransformMatcher struct { // input -<<<<<<< HEAD Transform interface{} // must be a function of one parameter that returns one value and an optional error -======= - Transform interface{} // must be a function of one parameter that returns one value ->>>>>>> 33cbc1d (add batchrelease controller) Matcher types.GomegaMatcher // cached value @@ -27,12 +19,9 @@ type WithTransformMatcher struct { transformedValue interface{} } -<<<<<<< HEAD // reflect.Type for error var errorT = reflect.TypeOf((*error)(nil)).Elem() -======= ->>>>>>> 33cbc1d (add batchrelease controller) func NewWithTransformMatcher(transform interface{}, matcher types.GomegaMatcher) *WithTransformMatcher { if transform == nil { panic("transform function cannot be nil") @@ -41,15 +30,10 @@ func NewWithTransformMatcher(transform interface{}, matcher types.GomegaMatcher) if txType.NumIn() != 1 { panic("transform function must have 1 argument") } -<<<<<<< HEAD if numout := txType.NumOut(); numout != 1 { if numout != 2 || !txType.Out(1).AssignableTo(errorT) { panic("transform function must either have 1 return value, or 1 return value plus 1 error value") } -======= - if txType.NumOut() != 1 { - panic("transform function must have 1 return value") ->>>>>>> 33cbc1d (add batchrelease controller) } return &WithTransformMatcher{ @@ -60,7 +44,6 @@ func NewWithTransformMatcher(transform interface{}, matcher types.GomegaMatcher) } func (m *WithTransformMatcher) Match(actual interface{}) (bool, error) { -<<<<<<< HEAD // prepare a parameter to pass to the Transform function var param reflect.Value if actual != nil && reflect.TypeOf(actual).AssignableTo(m.transformArgType) { @@ -74,26 +57,16 @@ func (m *WithTransformMatcher) Match(actual interface{}) (bool, error) { } else { return false, fmt.Errorf("Transform function expects '%s' but we have '%T'", m.transformArgType, actual) -======= - // return error if actual's type is incompatible with Transform function's argument type - actualType := reflect.TypeOf(actual) - if !actualType.AssignableTo(m.transformArgType) { - return false, fmt.Errorf("Transform function expects '%s' but we have '%s'", m.transformArgType, actualType) ->>>>>>> 33cbc1d (add batchrelease controller) } // call the Transform function with `actual` fn := reflect.ValueOf(m.Transform) -<<<<<<< HEAD result := fn.Call([]reflect.Value{param}) if len(result) == 2 { if !result[1].IsNil() { return false, fmt.Errorf("Transform function failed: %s", result[1].Interface().(error).Error()) } } -======= - result := fn.Call([]reflect.Value{reflect.ValueOf(actual)}) ->>>>>>> 33cbc1d (add batchrelease controller) m.transformedValue = result[0].Interface() // expect exactly one value return m.Matcher.Match(m.transformedValue) @@ -113,9 +86,5 @@ func (m *WithTransformMatcher) MatchMayChangeInTheFuture(_ interface{}) bool { // Querying the next matcher is fine if the transformer always will return the same value. // But if the transformer is non-deterministic and returns a different value each time, then there // is no point in querying the next matcher, since it can only comment on the last transformed value. -<<<<<<< HEAD return types.MatchMayChangeInTheFuture(m.Matcher, m.transformedValue) -======= - return oraclematcher.MatchMayChangeInTheFuture(m.Matcher, m.transformedValue) ->>>>>>> 33cbc1d (add batchrelease controller) } diff --git a/vendor/github.com/onsi/gomega/types/types.go b/vendor/github.com/onsi/gomega/types/types.go index e0cbc6a..c315ef0 100644 --- a/vendor/github.com/onsi/gomega/types/types.go +++ b/vendor/github.com/onsi/gomega/types/types.go @@ -1,6 +1,5 @@ package types -<<<<<<< HEAD import ( "time" ) @@ -31,24 +30,6 @@ type Gomega interface { SetDefaultConsistentlyPollingInterval(time.Duration) } -======= -type TWithHelper interface { - Helper() -} - -type GomegaFailHandler func(message string, callerSkip ...int) - -type GomegaFailWrapper struct { - Fail GomegaFailHandler - TWithHelper TWithHelper -} - -//A simple *testing.T interface wrapper -type GomegaTestingT interface { - Fatalf(format string, args ...interface{}) -} - ->>>>>>> 33cbc1d (add batchrelease controller) //All Gomega matchers must implement the GomegaMatcher interface // //For details on writing custom matchers, check out: http://onsi.github.io/gomega/#adding-your-own-matchers @@ -57,7 +38,6 @@ type GomegaMatcher interface { FailureMessage(actual interface{}) (message string) NegatedFailureMessage(actual interface{}) (message string) } -<<<<<<< HEAD /* GomegaMatchers that also match the OracleMatcher interface can convey information about @@ -105,5 +85,3 @@ type Assertion interface { Error() Assertion } -======= ->>>>>>> 33cbc1d (add batchrelease controller) diff --git a/vendor/golang.org/x/text/encoding/simplifiedchinese/hzgb2312.go b/vendor/golang.org/x/text/encoding/simplifiedchinese/hzgb2312.go index b30319b..e15b7bf 100644 --- a/vendor/golang.org/x/text/encoding/simplifiedchinese/hzgb2312.go +++ b/vendor/golang.org/x/text/encoding/simplifiedchinese/hzgb2312.go @@ -57,11 +57,7 @@ loop: err = transform.ErrShortSrc break loop } -<<<<<<< HEAD r, size = utf8.RuneError, 1 -======= - r = utf8.RuneError ->>>>>>> 33cbc1d (add batchrelease controller) goto write } size = 2 diff --git a/vendor/golang.org/x/text/internal/language/language.go b/vendor/golang.org/x/text/internal/language/language.go index b19e6b2..f41aedc 100644 --- a/vendor/golang.org/x/text/internal/language/language.go +++ b/vendor/golang.org/x/text/internal/language/language.go @@ -303,7 +303,6 @@ func (t Tag) Extensions() []string { // are of the allowed values defined for the Unicode locale extension ('u') in // https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers. // TypeForKey will traverse the inheritance chain to get the correct value. -<<<<<<< HEAD // // If there are multiple types associated with a key, only the first will be // returned. If there is no type associated with a key, it returns the empty @@ -315,11 +314,6 @@ func (t Tag) TypeForKey(key string) string { s = s[:p] } return s -======= -func (t Tag) TypeForKey(key string) string { - if start, end, _ := t.findTypeForKey(key); end != start { - return t.str[start:end] ->>>>>>> 33cbc1d (add batchrelease controller) } return "" } @@ -343,7 +337,6 @@ func (t Tag) SetTypeForKey(key, value string) (Tag, error) { // Remove the setting if value is "". if value == "" { -<<<<<<< HEAD start, sep, end, _ := t.findTypeForKey(key) if start != sep { // Remove a possible empty extension. @@ -351,15 +344,6 @@ func (t Tag) SetTypeForKey(key, value string) (Tag, error) { case t.str[start-2] != '-': // has previous elements. case end == len(t.str), // end of string end+2 < len(t.str) && t.str[end+2] == '-': // end of extension -======= - start, end, _ := t.findTypeForKey(key) - if start != end { - // Remove key tag and leading '-'. - start -= 4 - - // Remove a possible empty extension. - if (end == len(t.str) || t.str[end+2] == '-') && t.str[start-2] == '-' { ->>>>>>> 33cbc1d (add batchrelease controller) start -= 2 } if start == int(t.pVariant) && end == len(t.str) { @@ -405,7 +389,6 @@ func (t Tag) SetTypeForKey(key, value string) (Tag, error) { t.str = string(buf[:uStart+len(b)]) } else { s := t.str -<<<<<<< HEAD start, sep, end, hasExt := t.findTypeForKey(key) if start == sep { if hasExt { @@ -414,16 +397,6 @@ func (t Tag) SetTypeForKey(key, value string) (Tag, error) { t.str = fmt.Sprintf("%s-%s%s", s[:sep], b, s[end:]) } else { t.str = fmt.Sprintf("%s-%s%s", s[:start+3], value, s[end:]) -======= - start, end, hasExt := t.findTypeForKey(key) - if start == end { - if hasExt { - b = b[2:] - } - t.str = fmt.Sprintf("%s-%s%s", s[:start], b, s[end:]) - } else { - t.str = fmt.Sprintf("%s%s%s", s[:start], value, s[end:]) ->>>>>>> 33cbc1d (add batchrelease controller) } } return t, nil @@ -434,17 +407,10 @@ func (t Tag) SetTypeForKey(key, value string) (Tag, error) { // wasn't found. The hasExt return value reports whether an -u extension was present. // Note: the extensions are typically very small and are likely to contain // only one key-type pair. -<<<<<<< HEAD func (t Tag) findTypeForKey(key string) (start, sep, end int, hasExt bool) { p := int(t.pExt) if len(key) != 2 || p == len(t.str) || p == 0 { return p, p, p, false -======= -func (t Tag) findTypeForKey(key string) (start, end int, hasExt bool) { - p := int(t.pExt) - if len(key) != 2 || p == len(t.str) || p == 0 { - return p, p, false ->>>>>>> 33cbc1d (add batchrelease controller) } s := t.str @@ -452,17 +418,10 @@ func (t Tag) findTypeForKey(key string) (start, end int, hasExt bool) { for p++; s[p] != 'u'; p++ { if s[p] > 'u' { p-- -<<<<<<< HEAD return p, p, p, false } if p = nextExtension(s, p); p == len(s) { return len(s), len(s), len(s), false -======= - return p, p, false - } - if p = nextExtension(s, p); p == len(s) { - return len(s), len(s), false ->>>>>>> 33cbc1d (add batchrelease controller) } } // Proceed to the hyphen following the extension name. @@ -473,7 +432,6 @@ func (t Tag) findTypeForKey(key string) (start, end int, hasExt bool) { // Iterate over keys until we get the end of a section. for { -<<<<<<< HEAD end = p for p++; p < len(s) && s[p] != '-'; p++ { } @@ -496,42 +454,6 @@ func (t Tag) findTypeForKey(key string) (start, end int, hasExt bool) { } start = end sep = p -======= - // p points to the hyphen preceding the current token. - if p3 := p + 3; s[p3] == '-' { - // Found a key. - // Check whether we just processed the key that was requested. - if curKey == key { - return start, p, true - } - // Set to the next key and continue scanning type tokens. - curKey = s[p+1 : p3] - if curKey > key { - return p, p, true - } - // Start of the type token sequence. - start = p + 4 - // A type is at least 3 characters long. - p += 7 // 4 + 3 - } else { - // Attribute or type, which is at least 3 characters long. - p += 4 - } - // p points past the third character of a type or attribute. - max := p + 5 // maximum length of token plus hyphen. - if len(s) < max { - max = len(s) - } - for ; p < max && s[p] != '-'; p++ { - } - // Bail if we have exhausted all tokens or if the next token starts - // a new extension. - if p == len(s) || s[p+2] == '-' { - if curKey == key { - return start, p, true - } - return p, p, true ->>>>>>> 33cbc1d (add batchrelease controller) } } } diff --git a/vendor/golang.org/x/text/internal/language/parse.go b/vendor/golang.org/x/text/internal/language/parse.go index e796d76..c696fd0 100644 --- a/vendor/golang.org/x/text/internal/language/parse.go +++ b/vendor/golang.org/x/text/internal/language/parse.go @@ -133,7 +133,6 @@ func (s *scanner) resizeRange(oldStart, oldEnd, newSize int) { s.start = oldStart if end := oldStart + newSize; end != oldEnd { diff := end - oldEnd -<<<<<<< HEAD var b []byte if n := len(s.b) + diff; n > cap(s.b) { b = make([]byte, n) @@ -143,16 +142,6 @@ func (s *scanner) resizeRange(oldStart, oldEnd, newSize int) { } copy(b[end:], s.b[oldEnd:]) s.b = b -======= - if end < cap(s.b) { - b := make([]byte, len(s.b)+diff) - copy(b, s.b[:oldStart]) - copy(b[end:], s.b[oldEnd:]) - s.b = b - } else { - s.b = append(s.b[end:], s.b[oldEnd:]...) - } ->>>>>>> 33cbc1d (add batchrelease controller) s.next = end + (s.next - s.end) s.end = end } @@ -494,11 +483,7 @@ func parseExtensions(scan *scanner) int { func parseExtension(scan *scanner) int { start, end := scan.start, scan.end switch scan.token[0] { -<<<<<<< HEAD case 'u': // https://www.ietf.org/rfc/rfc6067.txt -======= - case 'u': ->>>>>>> 33cbc1d (add batchrelease controller) attrStart := end scan.scan() for last := []byte{}; len(scan.token) > 2; scan.scan() { @@ -518,7 +503,6 @@ func parseExtension(scan *scanner) int { last = scan.token end = scan.end } -<<<<<<< HEAD // Scan key-type sequences. A key is of length 2 and may be followed // by 0 or more "type" subtags from 3 to the maximum of 8 letters. var last, key []byte @@ -530,38 +514,18 @@ func parseExtension(scan *scanner) int { } // TODO: check key value validity if bytes.Compare(key, last) != 1 || scan.err != nil { -======= - var last, key []byte - for attrEnd := end; len(scan.token) == 2; last = key { - key = scan.token - keyEnd := scan.end - end = scan.acceptMinSize(3) - // TODO: check key value validity - if keyEnd == end || bytes.Compare(key, last) != 1 { ->>>>>>> 33cbc1d (add batchrelease controller) // We have an invalid key or the keys are not sorted. // Start scanning keys from scratch and reorder. p := attrEnd + 1 scan.next = p keys := [][]byte{} for scan.scan(); len(scan.token) == 2; { -<<<<<<< HEAD keyStart := scan.start end = scan.end for scan.scan(); end < scan.end && len(scan.token) > 2; scan.scan() { end = scan.end } keys = append(keys, scan.b[keyStart:end]) -======= - keyStart, keyEnd := scan.start, scan.end - end = scan.acceptMinSize(3) - if keyEnd != end { - keys = append(keys, scan.b[keyStart:end]) - } else { - scan.setError(ErrSyntax) - end = keyStart - } ->>>>>>> 33cbc1d (add batchrelease controller) } sort.Stable(bytesSort{keys, 2}) if n := len(keys); n > 0 { @@ -585,11 +549,7 @@ func parseExtension(scan *scanner) int { break } } -<<<<<<< HEAD case 't': // https://www.ietf.org/rfc/rfc6497.txt -======= - case 't': ->>>>>>> 33cbc1d (add batchrelease controller) scan.scan() if n := len(scan.token); n >= 2 && n <= 3 && isAlpha(scan.token[1]) { _, end = parseTag(scan) diff --git a/vendor/golang.org/x/text/language/go1_1.go b/vendor/golang.org/x/text/language/go1_1.go index cabb449..c743558 100644 --- a/vendor/golang.org/x/text/language/go1_1.go +++ b/vendor/golang.org/x/text/language/go1_1.go @@ -2,10 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -<<<<<<< HEAD //go:build !go1.2 -======= ->>>>>>> 33cbc1d (add batchrelease controller) // +build !go1.2 package language diff --git a/vendor/golang.org/x/text/language/go1_2.go b/vendor/golang.org/x/text/language/go1_2.go index 641efd7..77aaaa2 100644 --- a/vendor/golang.org/x/text/language/go1_2.go +++ b/vendor/golang.org/x/text/language/go1_2.go @@ -2,10 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -<<<<<<< HEAD //go:build go1.2 -======= ->>>>>>> 33cbc1d (add batchrelease controller) // +build go1.2 package language diff --git a/vendor/golang.org/x/text/language/language.go b/vendor/golang.org/x/text/language/language.go index 83ed66a..289b3a3 100644 --- a/vendor/golang.org/x/text/language/language.go +++ b/vendor/golang.org/x/text/language/language.go @@ -412,13 +412,10 @@ func (t Tag) Extensions() []Extension { // are of the allowed values defined for the Unicode locale extension ('u') in // https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers. // TypeForKey will traverse the inheritance chain to get the correct value. -<<<<<<< HEAD // // If there are multiple types associated with a key, only the first will be // returned. If there is no type associated with a key, it returns the empty // string. -======= ->>>>>>> 33cbc1d (add batchrelease controller) func (t Tag) TypeForKey(key string) string { if !compact.Tag(t).MayHaveExtensions() { if key != "rg" && key != "va" { diff --git a/vendor/golang.org/x/text/language/tables.go b/vendor/golang.org/x/text/language/tables.go index fd247b4..96b57f6 100644 --- a/vendor/golang.org/x/text/language/tables.go +++ b/vendor/golang.org/x/text/language/tables.go @@ -47,11 +47,7 @@ const ( _Zzzz = 251 ) -<<<<<<< HEAD var regionToGroups = []uint8{ // 358 elements -======= -var regionToGroups = []uint8{ // 357 elements ->>>>>>> 33cbc1d (add batchrelease controller) // Entry 0 - 3F 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, @@ -102,13 +98,8 @@ var regionToGroups = []uint8{ // 357 elements 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -<<<<<<< HEAD 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, } // Size: 382 bytes -======= - 0x00, 0x00, 0x00, 0x00, 0x00, -} // Size: 381 bytes ->>>>>>> 33cbc1d (add batchrelease controller) var paradigmLocales = [][3]uint16{ // 3 elements 0: [3]uint16{0x139, 0x0, 0x7b}, @@ -304,8 +295,4 @@ var matchRegion = []regionIntelligibility{ // 15 elements 14: {lang: 0x529, script: 0x3c, group: 0x80, distance: 0x5}, } // Size: 114 bytes -<<<<<<< HEAD // Total table size 1472 bytes (1KiB); checksum: F86C669 -======= -// Total table size 1471 bytes (1KiB); checksum: 4CB1CD46 ->>>>>>> 33cbc1d (add batchrelease controller) diff --git a/vendor/golang.org/x/xerrors/LICENSE b/vendor/golang.org/x/xerrors/LICENSE deleted file mode 100644 index e4a47e1..0000000 --- a/vendor/golang.org/x/xerrors/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2019 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/xerrors/PATENTS b/vendor/golang.org/x/xerrors/PATENTS deleted file mode 100644 index 7330990..0000000 --- a/vendor/golang.org/x/xerrors/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/xerrors/README b/vendor/golang.org/x/xerrors/README deleted file mode 100644 index aac7867..0000000 --- a/vendor/golang.org/x/xerrors/README +++ /dev/null @@ -1,2 +0,0 @@ -This repository holds the transition packages for the new Go 1.13 error values. -See golang.org/design/29934-error-values. diff --git a/vendor/golang.org/x/xerrors/adaptor.go b/vendor/golang.org/x/xerrors/adaptor.go deleted file mode 100644 index 4317f24..0000000 --- a/vendor/golang.org/x/xerrors/adaptor.go +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2018 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 xerrors - -import ( - "bytes" - "fmt" - "io" - "reflect" - "strconv" -) - -// FormatError calls the FormatError method of f with an errors.Printer -// configured according to s and verb, and writes the result to s. -func FormatError(f Formatter, s fmt.State, verb rune) { - // Assuming this function is only called from the Format method, and given - // that FormatError takes precedence over Format, it cannot be called from - // any package that supports errors.Formatter. It is therefore safe to - // disregard that State may be a specific printer implementation and use one - // of our choice instead. - - // limitations: does not support printing error as Go struct. - - var ( - sep = " " // separator before next error - p = &state{State: s} - direct = true - ) - - var err error = f - - switch verb { - // Note that this switch must match the preference order - // for ordinary string printing (%#v before %+v, and so on). - - case 'v': - if s.Flag('#') { - if stringer, ok := err.(fmt.GoStringer); ok { - io.WriteString(&p.buf, stringer.GoString()) - goto exit - } - // proceed as if it were %v - } else if s.Flag('+') { - p.printDetail = true - sep = "\n - " - } - case 's': - case 'q', 'x', 'X': - // Use an intermediate buffer in the rare cases that precision, - // truncation, or one of the alternative verbs (q, x, and X) are - // specified. - direct = false - - default: - p.buf.WriteString("%!") - p.buf.WriteRune(verb) - p.buf.WriteByte('(') - switch { - case err != nil: - p.buf.WriteString(reflect.TypeOf(f).String()) - default: - p.buf.WriteString("") - } - p.buf.WriteByte(')') - io.Copy(s, &p.buf) - return - } - -loop: - for { - switch v := err.(type) { - case Formatter: - err = v.FormatError((*printer)(p)) - case fmt.Formatter: - v.Format(p, 'v') - break loop - default: - io.WriteString(&p.buf, v.Error()) - break loop - } - if err == nil { - break - } - if p.needColon || !p.printDetail { - p.buf.WriteByte(':') - p.needColon = false - } - p.buf.WriteString(sep) - p.inDetail = false - p.needNewline = false - } - -exit: - width, okW := s.Width() - prec, okP := s.Precision() - - if !direct || (okW && width > 0) || okP { - // Construct format string from State s. - format := []byte{'%'} - if s.Flag('-') { - format = append(format, '-') - } - if s.Flag('+') { - format = append(format, '+') - } - if s.Flag(' ') { - format = append(format, ' ') - } - if okW { - format = strconv.AppendInt(format, int64(width), 10) - } - if okP { - format = append(format, '.') - format = strconv.AppendInt(format, int64(prec), 10) - } - format = append(format, string(verb)...) - fmt.Fprintf(s, string(format), p.buf.String()) - } else { - io.Copy(s, &p.buf) - } -} - -var detailSep = []byte("\n ") - -// state tracks error printing state. It implements fmt.State. -type state struct { - fmt.State - buf bytes.Buffer - - printDetail bool - inDetail bool - needColon bool - needNewline bool -} - -func (s *state) Write(b []byte) (n int, err error) { - if s.printDetail { - if len(b) == 0 { - return 0, nil - } - if s.inDetail && s.needColon { - s.needNewline = true - if b[0] == '\n' { - b = b[1:] - } - } - k := 0 - for i, c := range b { - if s.needNewline { - if s.inDetail && s.needColon { - s.buf.WriteByte(':') - s.needColon = false - } - s.buf.Write(detailSep) - s.needNewline = false - } - if c == '\n' { - s.buf.Write(b[k:i]) - k = i + 1 - s.needNewline = true - } - } - s.buf.Write(b[k:]) - if !s.inDetail { - s.needColon = true - } - } else if !s.inDetail { - s.buf.Write(b) - } - return len(b), nil -} - -// printer wraps a state to implement an xerrors.Printer. -type printer state - -func (s *printer) Print(args ...interface{}) { - if !s.inDetail || s.printDetail { - fmt.Fprint((*state)(s), args...) - } -} - -func (s *printer) Printf(format string, args ...interface{}) { - if !s.inDetail || s.printDetail { - fmt.Fprintf((*state)(s), format, args...) - } -} - -func (s *printer) Detail() bool { - s.inDetail = true - return s.printDetail -} diff --git a/vendor/golang.org/x/xerrors/codereview.cfg b/vendor/golang.org/x/xerrors/codereview.cfg deleted file mode 100644 index 3f8b14b..0000000 --- a/vendor/golang.org/x/xerrors/codereview.cfg +++ /dev/null @@ -1 +0,0 @@ -issuerepo: golang/go diff --git a/vendor/golang.org/x/xerrors/doc.go b/vendor/golang.org/x/xerrors/doc.go deleted file mode 100644 index eef99d9..0000000 --- a/vendor/golang.org/x/xerrors/doc.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2019 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 xerrors implements functions to manipulate errors. -// -// This package is based on the Go 2 proposal for error values: -// https://golang.org/design/29934-error-values -// -// These functions were incorporated into the standard library's errors package -// in Go 1.13: -// - Is -// - As -// - Unwrap -// -// Also, Errorf's %w verb was incorporated into fmt.Errorf. -// -// Use this package to get equivalent behavior in all supported Go versions. -// -// No other features of this package were included in Go 1.13, and at present -// there are no plans to include any of them. -package xerrors // import "golang.org/x/xerrors" diff --git a/vendor/golang.org/x/xerrors/errors.go b/vendor/golang.org/x/xerrors/errors.go deleted file mode 100644 index e88d377..0000000 --- a/vendor/golang.org/x/xerrors/errors.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2011 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 xerrors - -import "fmt" - -// errorString is a trivial implementation of error. -type errorString struct { - s string - frame Frame -} - -// New returns an error that formats as the given text. -// -// The returned error contains a Frame set to the caller's location and -// implements Formatter to show this information when printed with details. -func New(text string) error { - return &errorString{text, Caller(1)} -} - -func (e *errorString) Error() string { - return e.s -} - -func (e *errorString) Format(s fmt.State, v rune) { FormatError(e, s, v) } - -func (e *errorString) FormatError(p Printer) (next error) { - p.Print(e.s) - e.frame.Format(p) - return nil -} diff --git a/vendor/golang.org/x/xerrors/fmt.go b/vendor/golang.org/x/xerrors/fmt.go deleted file mode 100644 index 829862d..0000000 --- a/vendor/golang.org/x/xerrors/fmt.go +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2018 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 xerrors - -import ( - "fmt" - "strings" - "unicode" - "unicode/utf8" - - "golang.org/x/xerrors/internal" -) - -const percentBangString = "%!" - -// Errorf formats according to a format specifier and returns the string as a -// value that satisfies error. -// -// The returned error includes the file and line number of the caller when -// formatted with additional detail enabled. If the last argument is an error -// the returned error's Format method will return it if the format string ends -// with ": %s", ": %v", or ": %w". If the last argument is an error and the -// format string ends with ": %w", the returned error implements an Unwrap -// method returning it. -// -// If the format specifier includes a %w verb with an error operand in a -// position other than at the end, the returned error will still implement an -// Unwrap method returning the operand, but the error's Format method will not -// return the wrapped error. -// -// It is invalid to include more than one %w verb or to supply it with an -// operand that does not implement the error interface. The %w verb is otherwise -// a synonym for %v. -func Errorf(format string, a ...interface{}) error { - format = formatPlusW(format) - // Support a ": %[wsv]" suffix, which works well with xerrors.Formatter. - wrap := strings.HasSuffix(format, ": %w") - idx, format2, ok := parsePercentW(format) - percentWElsewhere := !wrap && idx >= 0 - if !percentWElsewhere && (wrap || strings.HasSuffix(format, ": %s") || strings.HasSuffix(format, ": %v")) { - err := errorAt(a, len(a)-1) - if err == nil { - return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)} - } - // TODO: this is not entirely correct. The error value could be - // printed elsewhere in format if it mixes numbered with unnumbered - // substitutions. With relatively small changes to doPrintf we can - // have it optionally ignore extra arguments and pass the argument - // list in its entirety. - msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...) - frame := Frame{} - if internal.EnableTrace { - frame = Caller(1) - } - if wrap { - return &wrapError{msg, err, frame} - } - return &noWrapError{msg, err, frame} - } - // Support %w anywhere. - // TODO: don't repeat the wrapped error's message when %w occurs in the middle. - msg := fmt.Sprintf(format2, a...) - if idx < 0 { - return &noWrapError{msg, nil, Caller(1)} - } - err := errorAt(a, idx) - if !ok || err == nil { - // Too many %ws or argument of %w is not an error. Approximate the Go - // 1.13 fmt.Errorf message. - return &noWrapError{fmt.Sprintf("%sw(%s)", percentBangString, msg), nil, Caller(1)} - } - frame := Frame{} - if internal.EnableTrace { - frame = Caller(1) - } - return &wrapError{msg, err, frame} -} - -func errorAt(args []interface{}, i int) error { - if i < 0 || i >= len(args) { - return nil - } - err, ok := args[i].(error) - if !ok { - return nil - } - return err -} - -// formatPlusW is used to avoid the vet check that will barf at %w. -func formatPlusW(s string) string { - return s -} - -// Return the index of the only %w in format, or -1 if none. -// Also return a rewritten format string with %w replaced by %v, and -// false if there is more than one %w. -// TODO: handle "%[N]w". -func parsePercentW(format string) (idx int, newFormat string, ok bool) { - // Loosely copied from golang.org/x/tools/go/analysis/passes/printf/printf.go. - idx = -1 - ok = true - n := 0 - sz := 0 - var isW bool - for i := 0; i < len(format); i += sz { - if format[i] != '%' { - sz = 1 - continue - } - // "%%" is not a format directive. - if i+1 < len(format) && format[i+1] == '%' { - sz = 2 - continue - } - sz, isW = parsePrintfVerb(format[i:]) - if isW { - if idx >= 0 { - ok = false - } else { - idx = n - } - // "Replace" the last character, the 'w', with a 'v'. - p := i + sz - 1 - format = format[:p] + "v" + format[p+1:] - } - n++ - } - return idx, format, ok -} - -// Parse the printf verb starting with a % at s[0]. -// Return how many bytes it occupies and whether the verb is 'w'. -func parsePrintfVerb(s string) (int, bool) { - // Assume only that the directive is a sequence of non-letters followed by a single letter. - sz := 0 - var r rune - for i := 1; i < len(s); i += sz { - r, sz = utf8.DecodeRuneInString(s[i:]) - if unicode.IsLetter(r) { - return i + sz, r == 'w' - } - } - return len(s), false -} - -type noWrapError struct { - msg string - err error - frame Frame -} - -func (e *noWrapError) Error() string { - return fmt.Sprint(e) -} - -func (e *noWrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) } - -func (e *noWrapError) FormatError(p Printer) (next error) { - p.Print(e.msg) - e.frame.Format(p) - return e.err -} - -type wrapError struct { - msg string - err error - frame Frame -} - -func (e *wrapError) Error() string { - return fmt.Sprint(e) -} - -func (e *wrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) } - -func (e *wrapError) FormatError(p Printer) (next error) { - p.Print(e.msg) - e.frame.Format(p) - return e.err -} - -func (e *wrapError) Unwrap() error { - return e.err -} diff --git a/vendor/golang.org/x/xerrors/format.go b/vendor/golang.org/x/xerrors/format.go deleted file mode 100644 index 1bc9c26..0000000 --- a/vendor/golang.org/x/xerrors/format.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2018 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 xerrors - -// A Formatter formats error messages. -type Formatter interface { - error - - // FormatError prints the receiver's first error and returns the next error in - // the error chain, if any. - FormatError(p Printer) (next error) -} - -// A Printer formats error messages. -// -// The most common implementation of Printer is the one provided by package fmt -// during Printf (as of Go 1.13). Localization packages such as golang.org/x/text/message -// typically provide their own implementations. -type Printer interface { - // Print appends args to the message output. - Print(args ...interface{}) - - // Printf writes a formatted string. - Printf(format string, args ...interface{}) - - // Detail reports whether error detail is requested. - // After the first call to Detail, all text written to the Printer - // is formatted as additional detail, or ignored when - // detail has not been requested. - // If Detail returns false, the caller can avoid printing the detail at all. - Detail() bool -} diff --git a/vendor/golang.org/x/xerrors/frame.go b/vendor/golang.org/x/xerrors/frame.go deleted file mode 100644 index 0de628e..0000000 --- a/vendor/golang.org/x/xerrors/frame.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2018 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 xerrors - -import ( - "runtime" -) - -// A Frame contains part of a call stack. -type Frame struct { - // Make room for three PCs: the one we were asked for, what it called, - // and possibly a PC for skipPleaseUseCallersFrames. See: - // https://go.googlesource.com/go/+/032678e0fb/src/runtime/extern.go#169 - frames [3]uintptr -} - -// Caller returns a Frame that describes a frame on the caller's stack. -// The argument skip is the number of frames to skip over. -// Caller(0) returns the frame for the caller of Caller. -func Caller(skip int) Frame { - var s Frame - runtime.Callers(skip+1, s.frames[:]) - return s -} - -// location reports the file, line, and function of a frame. -// -// The returned function may be "" even if file and line are not. -func (f Frame) location() (function, file string, line int) { - frames := runtime.CallersFrames(f.frames[:]) - if _, ok := frames.Next(); !ok { - return "", "", 0 - } - fr, ok := frames.Next() - if !ok { - return "", "", 0 - } - return fr.Function, fr.File, fr.Line -} - -// Format prints the stack as error detail. -// It should be called from an error's Format implementation -// after printing any other error detail. -func (f Frame) Format(p Printer) { - if p.Detail() { - function, file, line := f.location() - if function != "" { - p.Printf("%s\n ", function) - } - if file != "" { - p.Printf("%s:%d\n", file, line) - } - } -} diff --git a/vendor/golang.org/x/xerrors/go.mod b/vendor/golang.org/x/xerrors/go.mod deleted file mode 100644 index 870d4f6..0000000 --- a/vendor/golang.org/x/xerrors/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module golang.org/x/xerrors - -go 1.11 diff --git a/vendor/golang.org/x/xerrors/internal/internal.go b/vendor/golang.org/x/xerrors/internal/internal.go deleted file mode 100644 index 89f4eca..0000000 --- a/vendor/golang.org/x/xerrors/internal/internal.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2018 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 internal - -// EnableTrace indicates whether stack information should be recorded in errors. -var EnableTrace = true diff --git a/vendor/golang.org/x/xerrors/wrap.go b/vendor/golang.org/x/xerrors/wrap.go deleted file mode 100644 index 9a3b510..0000000 --- a/vendor/golang.org/x/xerrors/wrap.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2018 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 xerrors - -import ( - "reflect" -) - -// A Wrapper provides context around another error. -type Wrapper interface { - // Unwrap returns the next error in the error chain. - // If there is no next error, Unwrap returns nil. - Unwrap() error -} - -// Opaque returns an error with the same error formatting as err -// but that does not match err and cannot be unwrapped. -func Opaque(err error) error { - return noWrapper{err} -} - -type noWrapper struct { - error -} - -func (e noWrapper) FormatError(p Printer) (next error) { - if f, ok := e.error.(Formatter); ok { - return f.FormatError(p) - } - p.Print(e.error) - return nil -} - -// Unwrap returns the result of calling the Unwrap method on err, if err implements -// Unwrap. Otherwise, Unwrap returns nil. -func Unwrap(err error) error { - u, ok := err.(Wrapper) - if !ok { - return nil - } - return u.Unwrap() -} - -// Is reports whether any error in err's chain matches target. -// -// An error is considered to match a target if it is equal to that target or if -// it implements a method Is(error) bool such that Is(target) returns true. -func Is(err, target error) bool { - if target == nil { - return err == target - } - - isComparable := reflect.TypeOf(target).Comparable() - for { - if isComparable && err == target { - return true - } - if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) { - return true - } - // TODO: consider supporing target.Is(err). This would allow - // user-definable predicates, but also may allow for coping with sloppy - // APIs, thereby making it easier to get away with them. - if err = Unwrap(err); err == nil { - return false - } - } -} - -// As finds the first error in err's chain that matches the type to which target -// points, and if so, sets the target to its value and returns true. An error -// matches a type if it is assignable to the target type, or if it has a method -// As(interface{}) bool such that As(target) returns true. As will panic if target -// is not a non-nil pointer to a type which implements error or is of interface type. -// -// The As method should set the target to its value and return true if err -// matches the type to which target points. -func As(err error, target interface{}) bool { - if target == nil { - panic("errors: target cannot be nil") - } - val := reflect.ValueOf(target) - typ := val.Type() - if typ.Kind() != reflect.Ptr || val.IsNil() { - panic("errors: target must be a non-nil pointer") - } - if e := typ.Elem(); e.Kind() != reflect.Interface && !e.Implements(errorType) { - panic("errors: *target must be interface or implement error") - } - targetType := typ.Elem() - for err != nil { - if reflect.TypeOf(err).AssignableTo(targetType) { - val.Elem().Set(reflect.ValueOf(err)) - return true - } - if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) { - return true - } - err = Unwrap(err) - } - return false -} - -var errorType = reflect.TypeOf((*error)(nil)).Elem() diff --git a/vendor/modules.txt b/vendor/modules.txt index be3736d..15cdba3 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -69,28 +69,17 @@ github.com/matttproud/golang_protobuf_extensions/pbutil github.com/modern-go/concurrent # github.com/modern-go/reflect2 v1.0.1 github.com/modern-go/reflect2 -<<<<<<< HEAD # github.com/nxadm/tail v1.4.8 -======= -# github.com/nxadm/tail v1.4.4 ->>>>>>> 33cbc1d (add batchrelease controller) github.com/nxadm/tail github.com/nxadm/tail/ratelimiter github.com/nxadm/tail/util github.com/nxadm/tail/watch github.com/nxadm/tail/winfile -<<<<<<< HEAD # github.com/onsi/ginkgo v1.16.5 ## explicit github.com/onsi/ginkgo github.com/onsi/ginkgo/config github.com/onsi/ginkgo/formatter -======= -# github.com/onsi/ginkgo v1.14.1 -## explicit -github.com/onsi/ginkgo -github.com/onsi/ginkgo/config ->>>>>>> 33cbc1d (add batchrelease controller) github.com/onsi/ginkgo/internal/codelocation github.com/onsi/ginkgo/internal/containernode github.com/onsi/ginkgo/internal/failer @@ -108,22 +97,11 @@ github.com/onsi/ginkgo/reporters/stenographer github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty github.com/onsi/ginkgo/types -<<<<<<< HEAD # github.com/onsi/gomega v1.17.0 ## explicit github.com/onsi/gomega github.com/onsi/gomega/format github.com/onsi/gomega/internal -======= -# github.com/onsi/gomega v1.10.2 -## explicit -github.com/onsi/gomega -github.com/onsi/gomega/format -github.com/onsi/gomega/internal/assertion -github.com/onsi/gomega/internal/asyncassertion -github.com/onsi/gomega/internal/oraclematcher -github.com/onsi/gomega/internal/testingtsupport ->>>>>>> 33cbc1d (add batchrelease controller) github.com/onsi/gomega/matchers github.com/onsi/gomega/matchers/support/goraph/bipartitegraph github.com/onsi/gomega/matchers/support/goraph/edge @@ -188,11 +166,7 @@ golang.org/x/oauth2/jwt golang.org/x/sys/internal/unsafeheader golang.org/x/sys/unix golang.org/x/sys/windows -<<<<<<< HEAD # golang.org/x/text v0.3.6 -======= -# golang.org/x/text v0.3.4 ->>>>>>> 33cbc1d (add batchrelease controller) golang.org/x/text/encoding golang.org/x/text/encoding/charmap golang.org/x/text/encoding/htmlindex @@ -215,9 +189,6 @@ golang.org/x/text/unicode/bidi golang.org/x/text/unicode/norm # golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e golang.org/x/time/rate -# golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 -golang.org/x/xerrors -golang.org/x/xerrors/internal # gomodules.xyz/jsonpatch/v2 v2.1.0 gomodules.xyz/jsonpatch/v2 # google.golang.org/appengine v1.6.6 @@ -266,11 +237,7 @@ google.golang.org/protobuf/types/known/timestamppb gopkg.in/inf.v0 # gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 gopkg.in/tomb.v1 -<<<<<<< HEAD # gopkg.in/yaml.v2 v2.4.0 -======= -# gopkg.in/yaml.v2 v2.3.0 ->>>>>>> 33cbc1d (add batchrelease controller) ## explicit gopkg.in/yaml.v2 # gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 @@ -327,7 +294,6 @@ k8s.io/api/storage/v1beta1 k8s.io/apiextensions-apiserver/pkg/apis/apiextensions k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1 k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1 -<<<<<<< HEAD k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1 @@ -335,8 +301,6 @@ k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextension k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1 k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1 -======= ->>>>>>> 33cbc1d (add batchrelease controller) # k8s.io/apimachinery v0.20.10 ## explicit k8s.io/apimachinery/pkg/api/equality