simplify the logic of license and remove the ability of scale limit (#3581)

* add launcher in resource moudle
* add license webhook
* complete the scale limit for cluster via license
This commit is contained in:
fckc
2023-07-26 12:05:49 +08:00
committed by GitHub
parent 6e9afb76ae
commit 59e7dd10e0
87 changed files with 2568 additions and 2562 deletions
+2 -2
View File
@@ -86,7 +86,7 @@ jobs:
- { name: db-adminer, path: db/adminer }
- { name: resources, path: resources }
- { name: resources-metering, path: resources/metering }
- { name: cloud, path: cloud }
- { name: licenseissuer, path: licenseissuer }
steps:
- name: Checkout
uses: actions/checkout@v3
@@ -190,7 +190,7 @@ jobs:
- { name: db-adminer, path: db/adminer }
- { name: resources, path: resources }
- { name: resources-metering, path: resources/metering }
- { name: cloud, path: cloud }
- { name: licenseissuer, path: licenseissuer }
steps:
- name: Checkout
uses: actions/checkout@v3
@@ -1,56 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: launchers.cloud.sealos.io
spec:
group: cloud.sealos.io
names:
kind: Launcher
listKind: LauncherList
plural: launchers
singular: launcher
scope: Namespaced
versions:
- name: v1
schema:
openAPIV3Schema:
description: Launcher is the Schema for the launchers API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: LauncherSpec defines the desired state of Launcher
properties:
description:
type: string
name:
type: string
type: object
status:
description: LauncherStatus defines the observed state of Launcher
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
-10
View File
@@ -1,10 +0,0 @@
FROM scratch
USER 65532:65532
COPY registry registry
COPY manifests manifests
ENV canConnectToExternalNetwork="false"
CMD ["kubectl apply -f manifests"]
@@ -1,32 +0,0 @@
apiVersion: v1
data:
config.json: |
{
"CollectorURL": "https://anqp0y.laf.dev/CollectorHandle",
"NotificationURL": "https://anqp0y.laf.dev/NotificationHandle",
"RegisterURL": "https://anqp0y.laf.dev/RegisterHandle",
"CloudSyncURL": "https://anqp0y.laf.dev/CloudSyncHandle",
"LicenseMonitorURL": "https://anqp0y.laf.dev/LicenseMonitor"
}
kind: ConfigMap
metadata:
name: cloud-config
namespace: cloud-system
---
apiVersion: v1
data: null
kind: ConfigMap
metadata:
name: cloud-license-history
namespace: cloud-system
---
apiVersion: v1
kind: Secret
metadata:
name: cloud-secret
namespace: cloud-system
labels:
registered: "false"
data:
"uid": "e30="
"key": "e30="
-76
View File
@@ -1,76 +0,0 @@
module github.com/labring/sealos/controllers/cloud
go 1.19
require (
github.com/go-logr/logr v1.2.3
github.com/labring/sealos/controllers/common v0.0.0-00010101000000-000000000000
github.com/onsi/ginkgo/v2 v2.6.0
github.com/onsi/gomega v1.24.1
k8s.io/api v0.26.3
k8s.io/apimachinery v0.26.3
k8s.io/client-go v0.26.1
sigs.k8s.io/controller-runtime v0.13.0
)
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/zapr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/swag v0.19.14 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/term v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/time v0.3.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.26.1 // indirect
k8s.io/component-base v0.26.1 // indirect
k8s.io/klog/v2 v2.80.1 // indirect
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)
replace (
github.com/labring/sealos => ../../
github.com/labring/sealos/controllers/cloud => ../../controllers/cloud
)
-618
View File
@@ -1,618 +0,0 @@
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=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
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=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE=
github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A=
github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
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=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/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=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
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/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM=
github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc=
github.com/onsi/ginkgo/v2 v2.6.0/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E=
github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
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/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
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/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=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
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/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=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
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=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY=
gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
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=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/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.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
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/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.26.3 h1:emf74GIQMTik01Aum9dPP0gAypL8JTLl/lHa4V9RFSU=
k8s.io/api v0.26.3/go.mod h1:PXsqwPMXBSBcL1lJ9CYDKy7kIReUydukS5JiRlxC3qE=
k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI=
k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM=
k8s.io/apimachinery v0.26.3 h1:dQx6PNETJ7nODU3XPtrwkfuubs6w7sX0M8n61zHIV/k=
k8s.io/apimachinery v0.26.3/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I=
k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU=
k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE=
k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4=
k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU=
k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E=
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y=
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ=
sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI=
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
@@ -1,145 +0,0 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controller
import (
"context"
"errors"
"net/http"
"time"
"github.com/go-logr/logr"
cloudv1 "github.com/labring/sealos/controllers/cloud/api/v1"
"github.com/labring/sealos/controllers/cloud/internal/controller/util"
cloud "github.com/labring/sealos/controllers/cloud/internal/manager"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/predicate"
)
// CloudSyncReconciler reconciles a CloudSync object
type CloudSyncReconciler struct {
client.Client
Scheme *runtime.Scheme
logger logr.Logger
needSync bool
syncCache cloud.SyncResponse
}
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=cloudsyncs,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=cloudsyncs/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=cloudsyncs/finalizers,verbs=update
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
// TODO(user): Modify the Reconcile function to compare the state specified by
// the CloudSync object against the actual cluster state, and then
// perform operations to make the cluster state reflect the state specified by
// the user.
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.4/pkg/reconcile
func (r *CloudSyncReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
r.logger.Info("Enter CloudSyncReconcile", "namespace:", req.Namespace, "name", req.Name)
var err error
var config cloud.Config
var secret corev1.Secret
var sync cloud.SyncRequest
var resp cloud.SyncResponse
var configMap corev1.ConfigMap
r.logger.Info("Start to get resources that need sync...")
err = r.Client.Get(ctx, types.NamespacedName{Namespace: string(cloud.Namespace), Name: string(cloud.SecretName)}, &secret)
if err != nil {
r.logger.Error(err, "failed to get secret...")
return ctrl.Result{}, err
}
err = r.Client.Get(ctx, types.NamespacedName{Namespace: string(cloud.Namespace), Name: string(cloud.ConfigName)}, &configMap)
if err != nil {
r.logger.Error(err, "failed to get configmap...")
return ctrl.Result{}, err
}
config, err = util.ReadConfigFromConfigMap(string(cloud.ConfigName), &configMap)
if err != nil {
r.logger.Error(err, "failed to get config...")
return ctrl.Result{}, err
}
url := config.CloudSyncURL
sync.UID = string(secret.Data["uid"])
if r.needSync {
r.logger.Info("Start to communicate with cloud...")
httpBody, err := cloud.CommunicateWithCloud("POST", url, sync)
if err != nil {
r.logger.Error(err, "failed to communicate with cloud...")
return ctrl.Result{}, err
}
if !cloud.IsSuccessfulStatusCode(httpBody.StatusCode) {
err := errors.New(http.StatusText(httpBody.StatusCode))
r.logger.Error(err, err.Error())
return ctrl.Result{}, err
}
err = cloud.Convert(httpBody.Body, &resp)
if err != nil {
r.logger.Error(err, "failed to convert to cloud.SyncResponse")
return ctrl.Result{}, err
}
r.syncCache = resp
} else {
resp = r.syncCache
}
newConfig := resp.Config
if ok := cloud.IsConfigMapChanged(newConfig, &configMap); ok {
r.logger.Info("Start to sync the resources...")
if err := r.Client.Update(ctx, &configMap); err != nil {
r.needSync = false
return ctrl.Result{}, err
}
}
secret.Data["key"] = []byte(resp.Key)
err = r.Client.Update(ctx, &secret)
if err != nil {
r.needSync = false
return ctrl.Result{}, err
}
r.needSync = true
r.syncCache = cloud.SyncResponse{}
return ctrl.Result{RequeueAfter: time.Second * 3600}, nil
}
// SetupWithManager sets up the controller with the Manager.
func (r *CloudSyncReconciler) SetupWithManager(mgr ctrl.Manager) error {
r.logger = ctrl.Log.WithName("CloudSyncReconcile")
r.needSync = true
Predicate := predicate.NewPredicateFuncs(func(object client.Object) bool {
return object.GetName() == string(cloud.ClientStartName) &&
object.GetNamespace() == string(cloud.Namespace) &&
object.GetLabels() != nil &&
object.GetLabels()[string(cloud.IsRead)] == cloud.FALSE &&
object.GetLabels()[string(cloud.ExternalNetworkAccessLabel)] == string(cloud.Enabled)
})
return ctrl.NewControllerManagedBy(mgr).
For(&cloudv1.Launcher{}, builder.WithPredicates(Predicate)).
Complete(r)
}
@@ -1,122 +0,0 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controller
import (
"context"
"github.com/go-logr/logr"
cloudv1 "github.com/labring/sealos/controllers/cloud/api/v1"
"github.com/labring/sealos/controllers/cloud/internal/controller/util"
cloud "github.com/labring/sealos/controllers/cloud/internal/manager"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/predicate"
)
// LauncherReconciler reconciles a Launcher object
type LauncherReconciler struct {
client.Client
Scheme *runtime.Scheme
Users cloud.UserCategory
logger logr.Logger
Retries int
}
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=launchers,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=launchers/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=launchers/finalizers,verbs=update
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
// TODO(user): Modify the Reconcile function to compare the state specified by
// the Launcher object against the actual cluster state, and then
// perform operations to make the cluster state reflect the state specified by
// the user.
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.4/pkg/reconcile
func (r *LauncherReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctl ctrl.Result, err error) {
r.logger.Info("Enter LauncherReconcile", "namespace:", req.Namespace, "name", req.Name)
if r.Retries > 5 {
return ctrl.Result{}, nil
}
r.Retries++
r.logger.Info("Start the cloud module...")
if err = r.Users.GetNameSpace(ctx, r.Client); err != nil {
r.logger.Error(err, "failed to get users info")
return ctrl.Result{}, err
}
var secret corev1.Secret
var configMap corev1.ConfigMap
r.logger.Info("Try to get the cloud secret&configmap resource...")
err = r.Client.Get(ctx, types.NamespacedName{Namespace: string(cloud.Namespace), Name: string(cloud.SecretName)}, &secret)
if err != nil {
r.logger.Error(err, "failed to get secret...")
return ctrl.Result{}, err
}
err = r.Client.Get(ctx, types.NamespacedName{Namespace: string(cloud.Namespace), Name: string(cloud.ConfigName)}, &configMap)
if err != nil {
r.logger.Error(err, "failed to get configmap...")
return ctrl.Result{}, err
}
config, err := util.ReadConfigFromConfigMap(string(cloud.ConfigName), &configMap)
if err != nil {
r.logger.Error(err, "failed to get config...")
return ctrl.Result{}, err
}
if value, ok := secret.Labels["registered"]; ok && value == cloud.TRUE {
r.logger.Info("Cluster has registered...")
} else {
r.logger.Info("Try to register and start the cloud module...")
}
rasd := util.NewRegisterAndStartData(ctx, r.Client, &secret, r.Users, config, r.logger)
err = util.RegisterAndStart(rasd)
if err != nil {
r.logger.Error(err, "failed to register and start")
return ctrl.Result{}, err
}
r.Retries = 0
return ctrl.Result{}, nil
}
// SetupWithManager sets up the controller with the Manager.
func (r *LauncherReconciler) SetupWithManager(mgr ctrl.Manager) error {
r.Users = cloud.UserCategory{}
r.logger = ctrl.Log.WithName("LauncherReconcile")
r.Retries = 0
nameFilter := cloud.CloudStartName
namespaceFilter := cloud.Namespace
Predicates := predicate.NewPredicateFuncs(func(obj client.Object) bool {
return obj.GetName() == string(nameFilter) &&
obj.GetNamespace() == string(namespaceFilter) &&
obj.GetLabels()[string(cloud.ExternalNetworkAccessLabel)] == string(cloud.Enabled)
})
return ctrl.NewControllerManagedBy(mgr).
For(&cloudv1.Launcher{}, builder.WithPredicates(Predicates)).
Complete(r)
}
@@ -1,255 +0,0 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controller
import (
"context"
"errors"
"os"
"strconv"
"time"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"github.com/go-logr/logr"
accountv1 "github.com/labring/sealos/controllers/account/api/v1"
cloudv1 "github.com/labring/sealos/controllers/cloud/api/v1"
"github.com/labring/sealos/controllers/cloud/internal/controller/util"
cloud "github.com/labring/sealos/controllers/cloud/internal/manager"
"github.com/labring/sealos/controllers/pkg/crypto"
)
// LicenseReconciler reconciles a License object
type LicenseReconciler struct {
client.Client
Scheme *runtime.Scheme
needRecharge bool
logger logr.Logger
Retries int
}
//+kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=account.sealos.io,resources=accounts,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=account.sealos.io,resources=accounts/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=notification.sealos.io,resources=notifications,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=licenses,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=licenses/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=licenses/finalizers,verbs=update
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
// TODO(user): Modify the Reconcile function to compare the state specified by
// the License object against the actual cluster state, and then
// perform operations to make the cluster state reflect the state specified by
// the user.
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.4/pkg/reconcile
func (r *LicenseReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
r.logger.Info("Enter LicenseReconcile", "namespace:", req.Namespace, "name", req.Name)
if r.Retries > 5 {
pack := cloud.NewNotificationPackage(cloud.UnKnownErrorOfLicense, cloud.SEALOS, cloud.UnKnownErrorOfLicenseCotentent)
r.logger.Info("over the max retries")
util.SubmitNotificationWithUser(ctx, r.Client, r.logger, req.Namespace, pack)
return ctrl.Result{}, nil
}
r.Retries++
r.logger.Info("Start to get license-related resource...")
var canConnectToExternalNetwork bool
var license cloudv1.License
var secret corev1.Secret
var config cloud.Config
var configMap corev1.ConfigMap
var payload map[string]interface{}
var ok bool
err := r.Client.Get(ctx, types.NamespacedName{Namespace: req.Namespace, Name: req.Name}, &license)
if err != nil {
r.logger.Error(err, "failed to get license", "namespace:", req.Namespace, "name:", req.Name)
return ctrl.Result{}, err
}
if license.Labels == nil {
license.Labels = make(map[string]string)
}
license.Labels[string(cloud.IsRead)] = cloud.TRUE
if err = r.Client.Update(ctx, &license); err != nil {
r.logger.Error(err, "failed to update the license")
return ctrl.Result{RequeueAfter: time.Second * 5}, nil
}
canConnectToExternalNetwork = os.Getenv(cloud.NetWorkEnv) == cloud.TRUE
if canConnectToExternalNetwork {
r.logger.Info("can connect to ExternalNetwork")
} else {
r.logger.Info("can't connect to ExternalNetwork")
}
err = r.Client.Get(ctx, types.NamespacedName{Namespace: string(cloud.Namespace), Name: string(cloud.SecretName)}, &secret)
if err != nil {
r.logger.Error(err, "failed to get secret")
return ctrl.Result{}, err
}
err = r.Client.Get(ctx, types.NamespacedName{Namespace: string(cloud.Namespace), Name: string(cloud.ConfigName)}, &configMap)
if err != nil {
r.logger.Error(err, "failed to get configMap")
return ctrl.Result{}, err
}
config, err = util.ReadConfigFromConfigMap(string(cloud.ConfigName), &configMap)
if err != nil {
r.logger.Error(err, "failed to read config from configMap")
return ctrl.Result{}, err
}
r.logger.Info("Start to check license...")
if canConnectToExternalNetwork {
license.Spec.Key = string(secret.Data["key"])
}
if canConnectToExternalNetwork {
payload, ok = cloud.LicenseCheckOnExternalNetwork(license, secret, config.LicenseMonitorURL, r.logger)
} else {
payload, ok = cloud.LicenseCheckOnInternalNetwork(license)
}
if !ok {
err = errors.New("error license")
r.logger.Error(err, "license invalid", "namespace:", req.Namespace, "name:", req.Name)
pack := cloud.NewNotificationPackage(cloud.InvalidLicenseTitle, cloud.SEALOS, cloud.InvalidLicenseContent)
util.SubmitNotificationWithUser(ctx, r.Client, r.logger, req.Namespace, pack)
return ctrl.Result{}, nil
}
var licenseHistory corev1.ConfigMap
err = r.Client.Get(ctx, types.NamespacedName{Namespace: string(cloud.Namespace), Name: string(cloud.LicenseHistory)}, &licenseHistory)
if err != nil {
r.logger.Error(err, "failed to get license-history configmap", "namespace:", req.Namespace, "name:", req.Name)
return ctrl.Result{RequeueAfter: time.Second * 5}, nil
}
ok = util.CheckLicenseExists(&licenseHistory, license.Spec.Token)
if ok {
pack := cloud.NewNotificationPackage(cloud.DuplicateLicenseTitle, cloud.SEALOS, cloud.DuplicateLicenseContent)
r.logger.Info("the license has been used")
util.SubmitNotificationWithUser(ctx, r.Client, r.logger, req.Namespace, pack)
return ctrl.Result{}, err
}
if r.needRecharge {
r.logger.Info("Start to recharge...")
amount, err := util.InterfaceToInt64(payload["amt"])
if err != nil {
r.logger.Error(err, "license invalid", "namespace:", req.Namespace, "name:", req.Name)
pack := cloud.NewNotificationPackage(cloud.InvalidLicenseTitle, cloud.SEALOS, cloud.InvalidLicenseContent)
util.SubmitNotificationWithUser(ctx, r.Client, r.logger, req.Namespace, pack)
return ctrl.Result{}, nil
}
t, err := util.InterfaceToInt64(payload["iat"])
if err != nil {
r.logger.Error(err, "license invalid", "namespace:", req.Namespace, "name:", req.Name)
pack := cloud.NewNotificationPackage(cloud.InvalidLicenseTitle, cloud.SEALOS, cloud.InvalidLicenseContent)
util.SubmitNotificationWithUser(ctx, r.Client, r.logger, req.Namespace, pack)
return ctrl.Result{}, nil
}
if t < time.Now().Add(-3*time.Hour).Unix() {
r.logger.Error(err, "license invalid", "namespace:", req.Namespace, "name:", req.Name)
pack := cloud.NewNotificationPackage(cloud.InvalidLicenseTitle, cloud.SEALOS, cloud.LicenseTimeOutContent)
util.SubmitNotificationWithUser(ctx, r.Client, r.logger, req.Namespace, pack)
return ctrl.Result{}, nil
}
var account accountv1.Account
err = r.Client.Get(ctx, types.NamespacedName{Namespace: "sealos-system", Name: license.Spec.UID}, &account)
if err != nil {
r.logger.Error(err, "failed to get account cr", "namespace:", req.Namespace, "name:", req.Name)
return ctrl.Result{RequeueAfter: time.Second * 5}, nil
}
charge := amount * cloud.BaseCount
account.Status.Balance += charge
err = crypto.RechargeBalance(account.Status.EncryptBalance, charge)
if err != nil {
r.logger.Error(err, "Recharge Failed, failed to encrypt the balance", "namespace:", req.Namespace, "name:", req.Name)
pack := cloud.NewNotificationPackage(cloud.RechargeFailedTitle, cloud.SEALOS, cloud.RechargeFailedContent)
util.SubmitNotificationWithUser(ctx, r.Client, r.logger, req.Namespace, pack)
return ctrl.Result{RequeueAfter: time.Second * 5}, nil
}
err = r.Client.Status().Update(ctx, &account)
if err != nil {
r.logger.Error(err, "Recharge Failed, failed to modify the status", "namespace:", req.Namespace, "name:", req.Name)
pack := cloud.NewNotificationPackage(cloud.RechargeFailedTitle, cloud.SEALOS, cloud.RechargeFailedContent)
util.SubmitNotificationWithUser(ctx, r.Client, r.logger, req.Namespace, pack)
return ctrl.Result{RequeueAfter: time.Second * 5}, nil
}
r.logger.Info("Recharge Success...")
}
size := int64(0)
for _, value := range licenseHistory.Data {
size += int64(len(value))
}
maxSizeThreshold := resource.MustParse(cloud.MaxSizeThresholdStr)
if size >= maxSizeThreshold.Value() {
licenseHistory.Data = make(map[string]string)
}
suffix := util.GetNextLicenseKeySuffix(licenseHistory.Data)
newLicenseKeyName := "license-" + strconv.Itoa(suffix)
if licenseHistory.Data == nil {
licenseHistory.Data = make(map[string]string)
}
licenseHistory.Data[newLicenseKeyName] = license.Spec.Token
err = r.Client.Update(ctx, &licenseHistory)
if err != nil {
r.needRecharge = false
r.Retries = 0
r.logger.Error(err, "failed to store license")
return ctrl.Result{RequeueAfter: time.Second * 5}, nil
}
r.needRecharge = true
r.logger.Info("Success!")
pack := cloud.NewNotificationPackage(cloud.ValidLicenseTitle, cloud.SEALOS, cloud.ValidLicenseContent)
util.SubmitNotificationWithUser(ctx, r.Client, r.logger, req.Namespace, pack)
r.Retries = 0
return ctrl.Result{}, nil
}
// SetupWithManager sets up the controller with the Manager.
func (r *LicenseReconciler) SetupWithManager(mgr ctrl.Manager) error {
r.logger = ctrl.Log.WithName("LicenseReconcile")
r.Retries = 0
r.needRecharge = true
Predicate := predicate.Funcs{
CreateFunc: func(e event.CreateEvent) bool {
return e.Object.GetName() == string(cloud.LicenseName) &&
e.Object.GetLabels() != nil && e.Object.GetLabels()[string(cloud.IsRead)] == cloud.FALSE
},
UpdateFunc: func(e event.UpdateEvent) bool {
return e.ObjectNew.GetName() == string(cloud.LicenseName) &&
e.ObjectNew.GetLabels() != nil && e.ObjectNew.GetLabels()[string(cloud.IsRead)] == cloud.FALSE
},
DeleteFunc: func(e event.DeleteEvent) bool {
// Ignore delete events
return false
},
GenericFunc: func(e event.GenericEvent) bool {
return e.Object.GetName() == string(cloud.LicenseName)
},
}
return ctrl.NewControllerManagedBy(mgr).
For(&cloudv1.License{}, builder.WithPredicates(Predicate)).
Complete(r)
}
@@ -1,280 +0,0 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"sync"
"time"
"github.com/go-logr/logr"
cloudv1 "github.com/labring/sealos/controllers/cloud/api/v1"
cloud "github.com/labring/sealos/controllers/cloud/internal/manager"
ntf "github.com/labring/sealos/controllers/common/notification/api/v1"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
cl "sigs.k8s.io/controller-runtime/pkg/client"
)
func ReadConfigFromConfigMap(expectName string, configMap *corev1.ConfigMap) (cloud.Config, error) {
if configMap.Name != expectName {
err := errors.New("not expected configmap")
return cloud.Config{}, err
}
var config cloud.Config
err := json.Unmarshal([]byte(configMap.Data["config.json"]), &config)
if err != nil {
return cloud.Config{}, err
}
return config, nil
}
// ----------------------------------------------------------------------------------------------------------//
type RegisterAndStartData struct {
logger logr.Logger
Users cloud.UserCategory
ctx context.Context
client cl.Client
FreeLicense cloud.License
clusterScret *corev1.Secret
config cloud.Config
}
func NewRegisterAndStartData(ctx context.Context, client cl.Client, clusterScret *corev1.Secret,
users cloud.UserCategory, config cloud.Config, logger logr.Logger) RegisterAndStartData {
return RegisterAndStartData{
ctx: ctx,
client: client,
clusterScret: clusterScret,
config: config,
logger: logger,
Users: users,
}
}
// ----------------------------------------------------------------------------------------------------------//
type RegisterAndStartCallBack func(data RegisterAndStartData) error
func RegisterAndStart(data RegisterAndStartData) error {
value, ok := data.clusterScret.Labels["registered"]
if !ok {
return fmt.Errorf("RegisterAndStart: the Yaml of cloud secret if error, less registered label")
}
if value != cloud.TRUE {
err := data.Register()
if err != nil {
return fmt.Errorf("RegisterAndStart: %w", err)
}
pack := cloud.NewNotificationPackage(cloud.RegistrationSuccessTitle, cloud.SEALOS, cloud.RegistrationSuccessContent)
SubmitNotificationWithUserCategory(data.ctx, data.client, data.logger, data.Users, cloud.AdmPrefix, pack)
}
err := data.StartCloudModule()
if err != nil {
return fmt.Errorf("RegisterAndStart: %w", err)
}
return nil
}
func (rd *RegisterAndStartData) Register() error {
url := rd.config.RegisterURL
// get&store the cluster info
httpbody, err := cloud.CommunicateWithCloud("GET", url, nil)
if err != nil {
return fmt.Errorf("Register: %w", err)
}
if !cloud.IsSuccessfulStatusCode(httpbody.StatusCode) {
return fmt.Errorf("Register: %s", http.StatusText(httpbody.StatusCode))
}
var clusterInfo cloud.ClusterInfo
err = cloud.Convert(httpbody.Body, &clusterInfo)
if err != nil {
return fmt.Errorf("Register: %w", err)
}
if rd.clusterScret.Data == nil {
rd.clusterScret.Data = make(map[string][]byte)
}
rd.clusterScret.Data["key"] = []byte(clusterInfo.Key)
rd.clusterScret.Data["uid"] = []byte(clusterInfo.UID)
rd.clusterScret.Labels["registered"] = cloud.TRUE
// send a notification to cluster adm
err = rd.client.Update(rd.ctx, rd.clusterScret)
if err != nil {
return fmt.Errorf("Register: client.Update: %w", err)
}
return nil
}
func (rd *RegisterAndStartData) StartCloudModule() error {
if err := rd.StartLauncher(); err != nil {
return fmt.Errorf("startLauncher: %w", err)
}
return nil
}
func (rd *RegisterAndStartData) StartLauncher() error {
var startInstance cloudv1.Launcher
startInstance.SetName(string(cloud.ClientStartName))
startInstance.SetNamespace(string(cloud.Namespace))
if err := rd.client.Get(rd.ctx, types.NamespacedName{Namespace: string(cloud.Namespace), Name: string(cloud.ClientStartName)}, &startInstance); err != nil {
if apierrors.IsNotFound(err) {
startInstance.Labels = make(map[string]string)
startInstance.Labels[string(cloud.IsRead)] = cloud.FALSE
startInstance.Labels[string(cloud.ExternalNetworkAccessLabel)] = string(cloud.Enabled)
if err := rd.client.Create(rd.ctx, &startInstance); err != nil {
return fmt.Errorf("startLauncher: client.Create: %w", err)
}
} else {
return fmt.Errorf("startLauncher: client.Get: %w", err)
}
} else {
if startInstance.Labels == nil {
startInstance.Labels = make(map[string]string)
}
startInstance.Labels[string(cloud.IsRead)] = cloud.FALSE
startInstance.Labels[string(cloud.ExternalNetworkAccessLabel)] = string(cloud.Enabled)
if err := rd.client.Update(rd.ctx, &startInstance); err != nil {
return fmt.Errorf("startLauncher: client.Update: %w", err)
}
}
time.Sleep(time.Millisecond * 10000)
if startInstance.Labels == nil {
startInstance.Labels = make(map[string]string)
}
startInstance.Labels[string(cloud.IsRead)] = cloud.TRUE
if err := rd.client.Update(rd.ctx, &startInstance); err != nil {
return fmt.Errorf("startLauncher: client.Update: %w", err)
}
return nil
}
func SubmitNotificationWithUserCategory(ctx context.Context, client cl.Client, logger logr.Logger, users cloud.UserCategory, prefix string, pack cloud.NotificationPackage) {
notification := cloud.NotificationPackageToNotification(pack)
var wg sync.WaitGroup
errchan := make(chan error)
for ns := range users[prefix].Iter() {
wg.Add(1)
notificationTask := cloud.NewNotificationTask(ctx, client, ns, []ntf.Notification{notification})
go cloud.AsyncCloudTask(&wg, errchan, &notificationTask)
}
go func() {
wg.Wait()
close(errchan)
}()
for err := range errchan {
if err != nil {
logger.Error(err, "Failed to deliver registration success.")
}
}
}
func SubmitNotificationWithUser(ctx context.Context, client cl.Client, logger logr.Logger, target string, pack cloud.NotificationPackage) {
notification := cloud.NotificationPackageToNotification(pack)
notificationTask := cloud.NewNotificationTask(ctx, client, target, []ntf.Notification{notification})
var wg sync.WaitGroup
errchan := make(chan error)
wg.Add(1)
go cloud.AsyncCloudTask(&wg, errchan, &notificationTask)
go func() {
wg.Wait()
close(errchan)
}()
for err := range errchan {
if err != nil {
logger.Error(err, "Failed to deliver notification success")
}
}
}
func SubmitLicense(ctx context.Context, client cl.Client, cluster corev1.Secret) error {
var license cloudv1.License
err := client.Get(ctx, types.NamespacedName{Namespace: string(cloud.Namespace), Name: string(cloud.LicenseName)}, &license)
if err != nil {
if apierrors.IsNotFound(err) {
license.SetName(string(cloud.LicenseName))
license.SetNamespace(string(cloud.Namespace))
license.Spec.Token = string(cluster.Data["token"])
license.Spec.Key = string(cluster.Data["key"])
if license.Labels == nil {
license.Labels = make(map[string]string)
}
license.Labels["isRead"] = cloud.FALSE
err := client.Create(ctx, &license)
if err == nil {
return nil
}
}
} else {
license.SetName(string(cloud.LicenseName))
license.SetNamespace(string(cloud.Namespace))
license.Spec.Token = string(cluster.Data["token"])
license.Spec.Key = string(cluster.Data["key"])
if license.Labels == nil {
license.Labels = make(map[string]string)
}
license.Labels["isRead"] = cloud.FALSE
err := client.Update(ctx, &license)
if err == nil {
return nil
}
}
return nil
}
func InterfaceToInt64(value interface{}) (int64, error) {
switch v := value.(type) {
case int64:
return v, nil
case float64:
return int64(v), nil
default:
return 0, errors.New("cannot convert value of type to int64")
}
}
func GetNextLicenseKeySuffix(data map[string]string) int {
maxSuffix := 0
for key := range data {
var currentSuffix int
_, err := fmt.Sscanf(key, "license-%d", &currentSuffix)
if err == nil && currentSuffix > maxSuffix {
maxSuffix = currentSuffix
}
}
return maxSuffix + 1
}
func CheckLicenseExists(configMap *corev1.ConfigMap, license string) bool {
for _, storedLicense := range configMap.Data {
if storedLicense == license {
return true
}
}
return false
}
@@ -1,76 +0,0 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package manager
import (
"net/http"
"github.com/go-logr/logr"
cloudv1 "github.com/labring/sealos/controllers/cloud/api/v1"
"github.com/labring/sealos/controllers/pkg/crypto"
corev1 "k8s.io/api/core/v1"
)
const MaxSizeThresholdStr = "800Ki"
type LicenseMonitorRequest struct {
UID string `json:"uid"`
Token string `json:"token"`
}
type LicenseMonitorResponse struct {
Key string `json:"key"`
}
func NewLicenseMonitorRequest(secret corev1.Secret, license cloudv1.License) LicenseMonitorRequest {
if secret.Name != string(SecretName) || secret.Namespace != string(Namespace) {
return LicenseMonitorRequest{}
}
var lmr LicenseMonitorRequest
lmr.Token = license.Spec.Token
lmr.UID = string(secret.Data["uid"])
return lmr
}
func LicenseCheckOnExternalNetwork(license cloudv1.License, secret corev1.Secret, url string, logger logr.Logger) (map[string]interface{}, bool) {
payload, ok := crypto.IsLicenseValid(license)
mr := NewLicenseMonitorRequest(secret, license)
if !ok {
var resp LicenseMonitorResponse
httpBody, err := CommunicateWithCloud("POST", url, mr)
if err != nil {
logger.Error(err, "failed to communicate with cloud")
return nil, false
}
if !IsSuccessfulStatusCode(httpBody.StatusCode) {
logger.Error(err, http.StatusText(httpBody.StatusCode))
return nil, false
}
err = Convert(httpBody.Body, &resp)
if err != nil {
logger.Error(err, "failed to convert")
return nil, false
}
license.Spec.Key = resp.Key
return crypto.IsLicenseValid(license)
}
return payload, ok
}
func LicenseCheckOnInternalNetwork(license cloudv1.License) (map[string]interface{}, bool) {
return crypto.IsLicenseValid(license)
}
@@ -4,5 +4,5 @@ ARG TARGETARCH
WORKDIR /
USER 65532:65532
COPY bin/controller-cloud-$TARGETARCH /manager
COPY bin/controller-licenseissuer-$TARGETARCH /manager
ENTRYPOINT ["/manager"]
@@ -1,6 +1,6 @@
# Image URL to use all building/pushing image targets
IMG ?= ghcr.io/labring/sealos-cloud-controller:latest
IMG ?= ghcr.io/labring/sealos-licenseissuer-controller:latest
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.26.1
@@ -5,22 +5,22 @@
domain: sealos.io
layout:
- go.kubebuilder.io/v4
projectName: cloud-controller
repo: github.com/labring/sealos/controllers/cloud
projectName: licenseissuer-controller
repo: github.com/labring/sealos/controllers/licenseissuer
resources:
- controller: true
domain: sealos.io
group: cloud
group: infostream
kind: Notification
version: v1
- controller: true
domain: sealos.io
group: cloud
group: infostream
kind: Collector
version: v1
- controller: true
domain: sealos.io
group: cloud
group: infostream
kind: CloudSync
version: v1
- api:
@@ -28,17 +28,26 @@ resources:
namespaced: true
controller: true
domain: sealos.io
group: cloud
group: infostream
kind: License
path: github.com/labring/sealos/controllers/cloud/api/v1
path: github.com/labring/sealos/controllers/licenseissuer/api/v1
version: v1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: sealos.io
group: cloud
group: infostream
kind: Launcher
path: github.com/labring/sealos/controllers/cloud/api/v1
path: github.com/labring/sealos/controllers/licenseissuer/api/v1
version: v1
- controller: true
domain: sealos.io
group: infostream
kind: ScaleMonitor
version: v1
version: "3"
@@ -1,4 +1,4 @@
# cloud-controller
# licenseissuer-controller
// TODO(user): Add simple overview of use/purpose
## Description
@@ -18,13 +18,13 @@ kubectl apply -f config/samples/
2. Build and push your image to the location specified by `IMG`:
```sh
make docker-build docker-push IMG=<some-registry>/cloud-controller:tag
make docker-build docker-push IMG=<some-registry>/licenseissuer-controller:tag
```
3. Deploy the controller to the cluster with the image specified by `IMG`:
```sh
make deploy IMG=<some-registry>/cloud-controller:tag
make deploy IMG=<some-registry>/licenseissuer-controller:tag
```
### Uninstall CRDs
@@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package v1 contains API Schema definitions for the cloud v1 API group
// Package v1 contains API Schema definitions for the infostream v1 API group
// +kubebuilder:object:generate=true
// +groupName=cloud.sealos.io
// +groupName=infostream.sealos.io
package v1
import (
@@ -26,7 +26,7 @@ import (
var (
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "cloud.sealos.io", Version: "v1"}
GroupVersion = schema.GroupVersion{Group: "infostream.sealos.io", Version: "v1"}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
@@ -25,6 +25,7 @@ import (
_ "k8s.io/client-go/plugin/pkg/client/auth"
accountv1 "github.com/labring/sealos/controllers/account/api/v1"
ntf "github.com/labring/sealos/controllers/common/notification/api/v1"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@@ -33,9 +34,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
accountv1 "github.com/labring/sealos/controllers/account/api/v1"
cloudv1 "github.com/labring/sealos/controllers/cloud/api/v1"
"github.com/labring/sealos/controllers/cloud/internal/controller"
issuerv1 "github.com/labring/sealos/controllers/licenseissuer/api/v1"
"github.com/labring/sealos/controllers/licenseissuer/internal/controller"
//+kubebuilder:scaffold:imports
)
@@ -47,7 +47,7 @@ var (
func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
utilruntime.Must(ntf.AddToScheme(scheme))
utilruntime.Must(cloudv1.AddToScheme(scheme))
utilruntime.Must(issuerv1.AddToScheme(scheme))
utilruntime.Must(accountv1.AddToScheme(scheme))
//+kubebuilder:scaffold:scheme
}
@@ -128,6 +128,21 @@ func main() {
setupLog.Error(err, "unable to create controller", "controller", "Launcher")
os.Exit(1)
}
// if err = (&controller.ScaleMonitorReconciler{
// Client: mgr.GetClient(),
// Scheme: mgr.GetScheme(),
// }).SetupWithManager(mgr); err != nil {
// setupLog.Error(err, "unable to create controller", "controller", "ScaleMonitor")
// os.Exit(1)
// }
// if err = mgr.Add(&issuer.ClusterScaleMonitor{Client: mgr.GetClient()}); err != nil {
// setupLog.Error(err, "unable to set up monitor for cluster scale")
// os.Exit(1)
// }
//mgr.GetWebhookServer().Register("/validate-cloud-sealos-io-v1-license", &webhook.Admission{Handler: &controller.ScaleWebhook{Client: mgr.GetClient()}})
//+kubebuilder:scaffold:builder
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
@@ -0,0 +1,39 @@
# The following manifests contain a self-signed issuer CR and a certificate CR.
# More document can be found at https://docs.cert-manager.io
# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes.
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
labels:
app.kubernetes.io/name: certificate
app.kubernetes.io/instance: serving-cert
app.kubernetes.io/component: certificate
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: selfsigned-issuer
namespace: system
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
labels:
app.kubernetes.io/name: certificate
app.kubernetes.io/instance: serving-cert
app.kubernetes.io/component: certificate
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml
namespace: system
spec:
# SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize
dnsNames:
- SERVICE_NAME.SERVICE_NAMESPACE.svc
- SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local
issuerRef:
kind: Issuer
name: selfsigned-issuer
secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize
@@ -0,0 +1,5 @@
resources:
- certificate.yaml
configurations:
- kustomizeconfig.yaml
@@ -0,0 +1,8 @@
# This configuration is for teaching kustomize how to update name ref substitution
nameReference:
- kind: Issuer
group: cert-manager.io
fieldSpecs:
- kind: Certificate
group: cert-manager.io
path: spec/issuerRef/name
@@ -5,9 +5,9 @@ metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: launchers.cloud.sealos.io
name: launchers.infostream.sealos.io
spec:
group: cloud.sealos.io
group: infostream.sealos.io
names:
kind: Launcher
listKind: LauncherList
@@ -5,9 +5,9 @@ metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: licenses.cloud.sealos.io
name: licenses.infostream.sealos.io
spec:
group: cloud.sealos.io
group: infostream.sealos.io
names:
kind: License
listKind: LicenseList
@@ -2,8 +2,8 @@
# since it depends on service name and namespace that are out of this kustomize package.
# It should be run by config/default
resources:
- bases/cloud.sealos.io_licenses.yaml
- bases/cloud.sealos.io_launchers.yaml
- bases/infostream.sealos.io_licenses.yaml
- bases/infostream.sealos.io_launchers.yaml
#+kubebuilder:scaffold:crdkustomizeresource
patchesStrategicMerge:
@@ -1,12 +1,12 @@
# Adds namespace to all resources.
namespace: cloud-system
namespace: sealos-system
# Value of this field is prepended to the
# names of all resources, e.g. a deployment named
# "wordpress" becomes "alices-wordpress".
# Note that it should also match with the prefix (text before '-') of the namespace
# field above.
namePrefix: cloud-
namePrefix: licenseissuer-
# Labels to add to all resources and selectors.
#labels:
@@ -45,7 +45,7 @@ patchesStrategicMerge:
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.
# Uncomment the following replacements to add the cert-manager CA injection annotations
#replacements:
# replacements:
# - source: # Add cert-manager annotation to ValidatingWebhookConfiguration, MutatingWebhookConfiguration and CRDs
# kind: Certificate
# group: cert-manager.io
@@ -0,0 +1,23 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller-manager
namespace: system
spec:
template:
spec:
containers:
- name: manager
ports:
- containerPort: 9443
name: webhook-server
protocol: TCP
volumeMounts:
- mountPath: /tmp/k8s-webhook-server/serving-certs
name: cert
readOnly: true
volumes:
- name: cert
secret:
defaultMode: 420
secretName: webhook-server-cert
@@ -0,0 +1,15 @@
# This patch add annotation to admission webhook config and
# CERTIFICATE_NAMESPACE and CERTIFICATE_NAME will be substituted by kustomize
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
labels:
app.kubernetes.io/name: validatingwebhookconfiguration
app.kubernetes.io/instance: validating-webhook-configuration
app.kubernetes.io/component: webhook
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: validating-webhook-configuration
annotations:
cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
@@ -4,5 +4,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
images:
- name: controller
newName: ghcr.io/labring/sealos-cloud-controller
newName: ghcr.io/labring/sealos-licenseissuer-controller
newTag: latest
@@ -6,8 +6,8 @@ metadata:
app.kubernetes.io/name: namespace
app.kubernetes.io/instance: system
app.kubernetes.io/component: manager
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: system
---
@@ -21,8 +21,8 @@ metadata:
app.kubernetes.io/name: deployment
app.kubernetes.io/instance: controller-manager
app.kubernetes.io/component: manager
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
spec:
selector:
@@ -70,14 +70,19 @@ spec:
- /manager
args:
- --leader-elect
image: ghcr.io/labring/sealos-cloud-controller:latest
image: ghcr.io/labring/sealos-licenseissuer-controller:latest
name: manager
env:
- name: CAN_CONNECT_TO_EXTERNAL_NETWORK
valueFrom:
secretKeyRef:
name: cloud-env
name: licenseissuer-env
key: canConnectToExternalNetwork
- name: MONITOR
valueFrom:
secretKeyRef:
key: isMonitor
name: licenseissuer-env
securityContext:
allowPrivilegeEscalation: false
capabilities:
@@ -100,51 +105,9 @@ spec:
resources:
limits:
cpu: 500m
memory: 128Mi
memory: 1024Mi
requests:
cpu: 10m
memory: 64Mi
memory: 512Mi
serviceAccountName: controller-manager
terminationGracePeriodSeconds: 10
---
apiVersion: v1
kind: ConfigMap
metadata:
name: license-history
namespace: cloud-system
data:
---
apiVersion: v1
kind: ConfigMap
metadata:
name: config
namespace: cloud-system
data:
config.json: |
{
"CollectorURL": "https://anqp0y.laf.dev/CollectorHandle",
"NotificationURL": "https://anqp0y.laf.dev/NotificationHandle",
"RegisterURL": "https://anqp0y.laf.dev/RegisterHandle",
"CloudSyncURL": "https://anqp0y.laf.dev/CloudSyncHandle",
"LicenseMonitorURL": "https://anqp0y.laf.dev/LicenseMonitor"
}
---
apiVersion: cloud.sealos.io/v1
kind: Launcher
metadata:
name: start
namespace: cloud-system
labels:
external-network-access: disabled
spec:
name: Cloud-Launcher
description: This YAML file is responsible for launching the entire cloud module.
---
apiVersion: v1
kind: Secret
metadata:
name: env
namespace: cloud-system
type: Opaque
data:
canConnectToExternalNetwork: RmFsc2U=
@@ -8,8 +8,8 @@ metadata:
app.kubernetes.io/name: servicemonitor
app.kubernetes.io/instance: controller-manager-metrics-monitor
app.kubernetes.io/component: metrics
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: controller-manager-metrics-monitor
namespace: system
@@ -5,8 +5,8 @@ metadata:
app.kubernetes.io/name: clusterrole
app.kubernetes.io/instance: metrics-reader
app.kubernetes.io/component: kube-rbac-proxy
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: metrics-reader
rules:
@@ -5,8 +5,8 @@ metadata:
app.kubernetes.io/name: clusterrole
app.kubernetes.io/instance: proxy-role
app.kubernetes.io/component: kube-rbac-proxy
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: proxy-role
rules:
@@ -5,8 +5,8 @@ metadata:
app.kubernetes.io/name: clusterrolebinding
app.kubernetes.io/instance: proxy-rolebinding
app.kubernetes.io/component: kube-rbac-proxy
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: proxy-rolebinding
roleRef:
@@ -6,8 +6,8 @@ metadata:
app.kubernetes.io/name: service
app.kubernetes.io/instance: controller-manager-metrics-service
app.kubernetes.io/component: kube-rbac-proxy
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: controller-manager-metrics-service
namespace: system
@@ -6,8 +6,8 @@ metadata:
app.kubernetes.io/name: clusterrole
app.kubernetes.io/instance: launcher-editor-role
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: launcher-editor-role
rules:
@@ -6,8 +6,8 @@ metadata:
app.kubernetes.io/name: clusterrole
app.kubernetes.io/instance: launcher-viewer-role
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: launcher-viewer-role
rules:
@@ -6,8 +6,8 @@ metadata:
app.kubernetes.io/name: role
app.kubernetes.io/instance: leader-election-role
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: leader-election-role
rules:
@@ -5,8 +5,8 @@ metadata:
app.kubernetes.io/name: rolebinding
app.kubernetes.io/instance: leader-election-rolebinding
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: leader-election-rolebinding
roleRef:
@@ -6,8 +6,8 @@ metadata:
app.kubernetes.io/name: clusterrole
app.kubernetes.io/instance: license-editor-role
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: license-editor-role
rules:
@@ -6,8 +6,8 @@ metadata:
app.kubernetes.io/name: clusterrole
app.kubernetes.io/instance: license-viewer-role
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: license-viewer-role
rules:
@@ -25,136 +25,6 @@ rules:
- get
- patch
- update
- apiGroups:
- cloud.sealos.io
resources:
- cloudsyncs
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- cloud.sealos.io
resources:
- cloudsyncs/finalizers
verbs:
- update
- apiGroups:
- cloud.sealos.io
resources:
- cloudsyncs/status
verbs:
- get
- patch
- update
- apiGroups:
- cloud.sealos.io
resources:
- collectors
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- cloud.sealos.io
resources:
- collectors/finalizers
verbs:
- update
- apiGroups:
- cloud.sealos.io
resources:
- collectors/status
verbs:
- get
- patch
- update
- apiGroups:
- cloud.sealos.io
resources:
- launchers
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- cloud.sealos.io
resources:
- launchers/finalizers
verbs:
- update
- apiGroups:
- cloud.sealos.io
resources:
- launchers/status
verbs:
- get
- patch
- update
- apiGroups:
- cloud.sealos.io
resources:
- licenses
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- cloud.sealos.io
resources:
- licenses/finalizers
verbs:
- update
- apiGroups:
- cloud.sealos.io
resources:
- licenses/status
verbs:
- get
- patch
- update
- apiGroups:
- cloud.sealos.io
resources:
- notifications
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- cloud.sealos.io
resources:
- notifications/finalizers
verbs:
- update
- apiGroups:
- cloud.sealos.io
resources:
- notifications/status
verbs:
- get
- patch
- update
- apiGroups:
- ""
resources:
@@ -205,6 +75,136 @@ rules:
- patch
- update
- watch
- apiGroups:
- infostream.sealos.io
resources:
- cloudsyncs
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- infostream.sealos.io
resources:
- cloudsyncs/finalizers
verbs:
- update
- apiGroups:
- infostream.sealos.io
resources:
- cloudsyncs/status
verbs:
- get
- patch
- update
- apiGroups:
- infostream.sealos.io
resources:
- collectors
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- infostream.sealos.io
resources:
- collectors/finalizers
verbs:
- update
- apiGroups:
- infostream.sealos.io
resources:
- collectors/status
verbs:
- get
- patch
- update
- apiGroups:
- infostream.sealos.io
resources:
- launchers
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- infostream.sealos.io
resources:
- launchers/finalizers
verbs:
- update
- apiGroups:
- infostream.sealos.io
resources:
- launchers/status
verbs:
- get
- patch
- update
- apiGroups:
- infostream.sealos.io
resources:
- licenses
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- infostream.sealos.io
resources:
- licenses/finalizers
verbs:
- update
- apiGroups:
- infostream.sealos.io
resources:
- licenses/status
verbs:
- get
- patch
- update
- apiGroups:
- infostream.sealos.io
resources:
- notifications
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- infostream.sealos.io
resources:
- notifications/finalizers
verbs:
- update
- apiGroups:
- infostream.sealos.io
resources:
- notifications/status
verbs:
- get
- patch
- update
- apiGroups:
- notification.sealos.io
resources:
@@ -5,8 +5,8 @@ metadata:
app.kubernetes.io/name: clusterrolebinding
app.kubernetes.io/instance: manager-rolebinding
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: manager-rolebinding
roleRef:
@@ -5,8 +5,8 @@ metadata:
app.kubernetes.io/name: serviceaccount
app.kubernetes.io/instance: controller-manager-sa
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: controller-manager
namespace: system
@@ -4,9 +4,9 @@ metadata:
labels:
app.kubernetes.io/name: launcher
app.kubernetes.io/instance: launcher-sample
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
name: launcher-sample
spec:
# TODO(user): Add fields here
@@ -4,9 +4,9 @@ metadata:
labels:
app.kubernetes.io/name: license
app.kubernetes.io/instance: license-sample
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
name: license-sample
spec:
# TODO(user): Add fields here
@@ -0,0 +1,6 @@
# resources:
# - manifests.yaml
# - service.yaml
# configurations:
# - kustomizeconfig.yaml
@@ -0,0 +1,14 @@
# the following config is for teaching kustomize where to look at when substituting nameReference.
# It requires kustomize v2.1.0 or newer to work properly.
# nameReference:
# - kind: Service
# version: v1
# fieldSpecs:
# - kind: ValidatingWebhookConfiguration
# group: admissionregistration.k8s.io
# path: webhooks/clientConfig/service/name
# namespace:
# - kind: ValidatingWebhookConfiguration
# group: admissionregistration.k8s.io
# path: webhooks/clientConfig/service/namespace
# create: true
@@ -0,0 +1,27 @@
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
creationTimestamp: null
name: validating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
service:
name: webhook-service
namespace: system
path: /validate-infostream-sealos-io-v1-license
failurePolicy: Ignore
name: vlicense.kb.io
rules:
- apiGroups:
- '*'
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- pods
sideEffects: None
@@ -0,0 +1,20 @@
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: service
app.kubernetes.io/instance: webhook-service
app.kubernetes.io/component: webhook
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/part-of: licenseissuer-controller
app.kubernetes.io/managed-by: kustomize
name: webhook-service
namespace: system
spec:
ports:
- port: 443
protocol: TCP
targetPort: 9443
selector:
control-plane: controller-manager
+16
View File
@@ -0,0 +1,16 @@
FROM scratch
USER 65532:65532
COPY registry registry
COPY manifests manifests
ENV canConnectToExternalNetwork "true"
ENV enableMonitor "true"
ENV CollectorURL "https://license.sealos.io/CollectorHandle",
ENV NotificationURL "https://license.sealos.io/NotificationHandle",
ENV RegisterURL "https://license.sealos.io/RegisterHandle",
ENV CloudSyncURL "https://license.sealos.io/CloudSyncHandle",
ENV LicenseMonitorURL "https://license.sealos.io/LicenseMonitor"
CMD ["kubectl apply -f manifests"]
@@ -0,0 +1,40 @@
apiVersion: v1
data: null
kind: ConfigMap
metadata:
name: license-history
namespace: sealos-system
---
apiVersion: infostream.sealos.io/v1
kind: Launcher
metadata:
name: launcher
namespace: sealos-system
spec:
description: This YAML file is responsible for launching the entire cloud module.
name: Cloud-Launcher
---
apiVersion: v1
kind: Secret
metadata:
name: licenseissuer-env
namespace: sealos-system
stringData:
canConnectToExternalNetwork: "true"
isMonitor: "true"
---
apiVersion: v1
data:
config.json: |
{
"CollectorURL": "https://license.sealos.io/CollectorHandle",
"NotificationURL": "https://license.sealos.io/NotificationHandle",
"RegisterURL": "https://license.sealos.io/RegisterHandle",
"CloudSyncURL": "https://license.sealos.io/CloudSyncHandle",
"LicenseMonitorURL": "https://license.sealos.io/LicenseMonitor"
}
kind: ConfigMap
metadata:
name: url-config
namespace: sealos-system
@@ -0,0 +1,23 @@
apiVersion: v1
kind: Secret
metadata:
name: licenseissuer-env
namespace: sealos-system
stringData:
canConnectToExternalNetwork: "{{ .canConnectToExternalNetwork }}"
isMonitor: "{{ .enableMonitor }}"
---
apiVersion: v1
data:
config.json: |
{
"CollectorURL": {{ .CollectorURL }},
"NotificationURL": {{ .NotificationURL }},
"RegisterURL": {{ .RegisterURL }},
"CloudSyncURL": {{ .CloudSyncURL }},
"LicenseMonitorURL": {{ .LicenseMonitorURL }}
}
kind: ConfigMap
metadata:
name: url-config
namespace: sealos-system
@@ -3,13 +3,13 @@ kind: Namespace
metadata:
labels:
app.kubernetes.io/component: manager
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/instance: system
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: namespace
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/part-of: licenseissuer-controller
control-plane: controller-manager
name: cloud-system
name: sealos-system
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
@@ -17,9 +17,9 @@ metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: launchers.cloud.sealos.io
name: launchers.infostream.sealos.io
spec:
group: cloud.sealos.io
group: infostream.sealos.io
names:
kind: Launcher
listKind: LauncherList
@@ -73,9 +73,9 @@ metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: licenses.cloud.sealos.io
name: licenses.infostream.sealos.io
spec:
group: cloud.sealos.io
group: infostream.sealos.io
names:
kind: License
listKind: LicenseList
@@ -130,26 +130,26 @@ kind: ServiceAccount
metadata:
labels:
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/instance: controller-manager-sa
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: serviceaccount
app.kubernetes.io/part-of: cloud-controller
name: cloud-controller-manager
namespace: cloud-system
app.kubernetes.io/part-of: licenseissuer-controller
name: licenseissuer-controller-manager
namespace: sealos-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/instance: leader-election-role
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: role
app.kubernetes.io/part-of: cloud-controller
name: cloud-leader-election-role
namespace: cloud-system
app.kubernetes.io/part-of: licenseissuer-controller
name: licenseissuer-leader-election-role
namespace: sealos-system
rules:
- apiGroups:
- ""
@@ -187,7 +187,7 @@ apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
name: cloud-manager-role
name: licenseissuer-manager-role
rules:
- apiGroups:
- account.sealos.io
@@ -209,136 +209,6 @@ rules:
- get
- patch
- update
- apiGroups:
- cloud.sealos.io
resources:
- cloudsyncs
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- cloud.sealos.io
resources:
- cloudsyncs/finalizers
verbs:
- update
- apiGroups:
- cloud.sealos.io
resources:
- cloudsyncs/status
verbs:
- get
- patch
- update
- apiGroups:
- cloud.sealos.io
resources:
- collectors
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- cloud.sealos.io
resources:
- collectors/finalizers
verbs:
- update
- apiGroups:
- cloud.sealos.io
resources:
- collectors/status
verbs:
- get
- patch
- update
- apiGroups:
- cloud.sealos.io
resources:
- launchers
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- cloud.sealos.io
resources:
- launchers/finalizers
verbs:
- update
- apiGroups:
- cloud.sealos.io
resources:
- launchers/status
verbs:
- get
- patch
- update
- apiGroups:
- cloud.sealos.io
resources:
- licenses
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- cloud.sealos.io
resources:
- licenses/finalizers
verbs:
- update
- apiGroups:
- cloud.sealos.io
resources:
- licenses/status
verbs:
- get
- patch
- update
- apiGroups:
- cloud.sealos.io
resources:
- notifications
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- cloud.sealos.io
resources:
- notifications/finalizers
verbs:
- update
- apiGroups:
- cloud.sealos.io
resources:
- notifications/status
verbs:
- get
- patch
- update
- apiGroups:
- ""
resources:
@@ -389,6 +259,136 @@ rules:
- patch
- update
- watch
- apiGroups:
- infostream.sealos.io
resources:
- cloudsyncs
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- infostream.sealos.io
resources:
- cloudsyncs/finalizers
verbs:
- update
- apiGroups:
- infostream.sealos.io
resources:
- cloudsyncs/status
verbs:
- get
- patch
- update
- apiGroups:
- infostream.sealos.io
resources:
- collectors
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- infostream.sealos.io
resources:
- collectors/finalizers
verbs:
- update
- apiGroups:
- infostream.sealos.io
resources:
- collectors/status
verbs:
- get
- patch
- update
- apiGroups:
- infostream.sealos.io
resources:
- launchers
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- infostream.sealos.io
resources:
- launchers/finalizers
verbs:
- update
- apiGroups:
- infostream.sealos.io
resources:
- launchers/status
verbs:
- get
- patch
- update
- apiGroups:
- infostream.sealos.io
resources:
- licenses
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- infostream.sealos.io
resources:
- licenses/finalizers
verbs:
- update
- apiGroups:
- infostream.sealos.io
resources:
- licenses/status
verbs:
- get
- patch
- update
- apiGroups:
- infostream.sealos.io
resources:
- notifications
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- infostream.sealos.io
resources:
- notifications/finalizers
verbs:
- update
- apiGroups:
- infostream.sealos.io
resources:
- notifications/status
verbs:
- get
- patch
- update
- apiGroups:
- notification.sealos.io
resources:
@@ -407,12 +407,12 @@ kind: ClusterRole
metadata:
labels:
app.kubernetes.io/component: kube-rbac-proxy
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/instance: metrics-reader
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: clusterrole
app.kubernetes.io/part-of: cloud-controller
name: cloud-metrics-reader
app.kubernetes.io/part-of: licenseissuer-controller
name: licenseissuer-metrics-reader
rules:
- nonResourceURLs:
- /metrics
@@ -424,12 +424,12 @@ kind: ClusterRole
metadata:
labels:
app.kubernetes.io/component: kube-rbac-proxy
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/instance: proxy-role
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: clusterrole
app.kubernetes.io/part-of: cloud-controller
name: cloud-proxy-role
app.kubernetes.io/part-of: licenseissuer-controller
name: licenseissuer-proxy-role
rules:
- apiGroups:
- authentication.k8s.io
@@ -449,75 +449,75 @@ kind: RoleBinding
metadata:
labels:
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/instance: leader-election-rolebinding
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: rolebinding
app.kubernetes.io/part-of: cloud-controller
name: cloud-leader-election-rolebinding
namespace: cloud-system
app.kubernetes.io/part-of: licenseissuer-controller
name: licenseissuer-leader-election-rolebinding
namespace: sealos-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: cloud-leader-election-role
name: licenseissuer-leader-election-role
subjects:
- kind: ServiceAccount
name: cloud-controller-manager
namespace: cloud-system
name: licenseissuer-controller-manager
namespace: sealos-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/instance: manager-rolebinding
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: clusterrolebinding
app.kubernetes.io/part-of: cloud-controller
name: cloud-manager-rolebinding
app.kubernetes.io/part-of: licenseissuer-controller
name: licenseissuer-manager-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cloud-manager-role
name: licenseissuer-manager-role
subjects:
- kind: ServiceAccount
name: cloud-controller-manager
namespace: cloud-system
name: licenseissuer-controller-manager
namespace: sealos-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/component: kube-rbac-proxy
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/instance: proxy-rolebinding
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: clusterrolebinding
app.kubernetes.io/part-of: cloud-controller
name: cloud-proxy-rolebinding
app.kubernetes.io/part-of: licenseissuer-controller
name: licenseissuer-proxy-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cloud-proxy-role
name: licenseissuer-proxy-role
subjects:
- kind: ServiceAccount
name: cloud-controller-manager
namespace: cloud-system
name: licenseissuer-controller-manager
namespace: sealos-system
---
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/component: kube-rbac-proxy
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/instance: controller-manager-metrics-service
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: service
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/part-of: licenseissuer-controller
control-plane: controller-manager
name: cloud-controller-manager-metrics-service
namespace: cloud-system
name: licenseissuer-controller-manager-metrics-service
namespace: sealos-system
spec:
ports:
- name: https
@@ -532,14 +532,14 @@ kind: Deployment
metadata:
labels:
app.kubernetes.io/component: manager
app.kubernetes.io/created-by: cloud-controller
app.kubernetes.io/created-by: licenseissuer-controller
app.kubernetes.io/instance: controller-manager
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: deployment
app.kubernetes.io/part-of: cloud-controller
app.kubernetes.io/part-of: licenseissuer-controller
control-plane: controller-manager
name: cloud-controller-manager
namespace: cloud-system
name: licenseissuer-controller-manager
namespace: sealos-system
spec:
replicas: 1
selector:
@@ -600,8 +600,16 @@ spec:
- /manager
env:
- name: CAN_CONNECT_TO_EXTERNAL_NETWORK
value: '{{ .canConnectToExternalNetwork }}'
image: ghcr.io/labring/sealos-cloud-controller:latest
valueFrom:
secretKeyRef:
key: canConnectToExternalNetwork
name: licenseissuer-env
- name: MONITOR
valueFrom:
secretKeyRef:
key: isMonitor
name: licenseissuer-env
image: ghcr.io/labring/sealos-licenseissuer-controller:latest
livenessProbe:
httpGet:
path: /healthz
@@ -618,10 +626,10 @@ spec:
resources:
limits:
cpu: 500m
memory: 128Mi
memory: 1024Mi
requests:
cpu: 10m
memory: 64Mi
memory: 512Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
@@ -629,16 +637,5 @@ spec:
- ALL
securityContext:
runAsNonRoot: true
serviceAccountName: cloud-controller-manager
serviceAccountName: licenseissuer-controller-manager
terminationGracePeriodSeconds: 10
---
apiVersion: cloud.sealos.io/v1
kind: Launcher
metadata:
labels:
external-network-access: disabled
name: cloud-start
namespace: cloud-system
spec:
description: This YAML file is responsible for launching the entire cloud module.
name: Cloud-Launcher
+87
View File
@@ -0,0 +1,87 @@
module github.com/labring/sealos/controllers/licenseissuer
go 1.19
require (
github.com/go-logr/logr v1.2.4
github.com/labring/sealos v0.0.0
github.com/labring/sealos/controllers/account v0.0.0
github.com/labring/sealos/controllers/common v0.0.0
github.com/onsi/ginkgo/v2 v2.9.7
github.com/onsi/gomega v1.27.8
k8s.io/api v0.26.3
k8s.io/apimachinery v0.26.3
k8s.io/client-go v0.26.2
sigs.k8s.io/controller-runtime v0.13.0
)
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.10.1 // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/zapr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic v0.6.9 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/labring/sealos/controllers/user v0.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.15.1 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/term v0.9.0 // indirect
golang.org/x/text v0.10.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.9.3 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.26.1 // indirect
k8s.io/component-base v0.26.2 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)
replace (
github.com/labring/sealos => ../../
github.com/labring/sealos/controllers/account => ../../controllers/account
github.com/labring/sealos/controllers/common => ../../controllers/common
github.com/labring/sealos/controllers/licenseissuer => ../../controllers/licenseissuer
github.com/labring/sealos/controllers/pkg => ../../controllers/pkg
github.com/labring/sealos/controllers/user => ../../controllers/user
)
+330
View File
@@ -0,0 +1,330 @@
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=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
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=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ=
github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A=
github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
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=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0=
github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0=
github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ=
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/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI=
github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
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/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
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=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
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=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY=
gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
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=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/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.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.26.3 h1:emf74GIQMTik01Aum9dPP0gAypL8JTLl/lHa4V9RFSU=
k8s.io/api v0.26.3/go.mod h1:PXsqwPMXBSBcL1lJ9CYDKy7kIReUydukS5JiRlxC3qE=
k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI=
k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM=
k8s.io/apimachinery v0.26.3 h1:dQx6PNETJ7nODU3XPtrwkfuubs6w7sX0M8n61zHIV/k=
k8s.io/apimachinery v0.26.3/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I=
k8s.io/client-go v0.26.2 h1:s1WkVujHX3kTp4Zn4yGNFK+dlDXy1bAAkIl+cFAiuYI=
k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU=
k8s.io/component-base v0.26.2 h1:IfWgCGUDzrD6wLLgXEstJKYZKAFS2kO+rBRi0p3LqcI=
k8s.io/component-base v0.26.2/go.mod h1:DxbuIe9M3IZPRxPIzhch2m1eT7uFrSBJUBuVCQEBivs=
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E=
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk=
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ=
sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
@@ -25,9 +25,9 @@ import (
"time"
"github.com/go-logr/logr"
cloudv1 "github.com/labring/sealos/controllers/cloud/api/v1"
"github.com/labring/sealos/controllers/cloud/internal/controller/util"
cloud "github.com/labring/sealos/controllers/cloud/internal/manager"
cloudv1 "github.com/labring/sealos/controllers/licenseissuer/api/v1"
"github.com/labring/sealos/controllers/licenseissuer/internal/controller/util"
issuer "github.com/labring/sealos/controllers/licenseissuer/internal/manager"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
@@ -40,13 +40,14 @@ import (
// CollectorReconciler reconciles a Collector object
type CollectorReconciler struct {
client.Client
Scheme *runtime.Scheme
logger logr.Logger
Scheme *runtime.Scheme
logger logr.Logger
lastCollectedTime int64
}
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=collectors,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=collectors/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=collectors/finalizers,verbs=update
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=collectors,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=collectors/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=collectors/finalizers,verbs=update
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
@@ -60,29 +61,55 @@ type CollectorReconciler struct {
func (r *CollectorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
r.logger.Info("Enter CollectorReconcile", "namespace:", req.Namespace, "name", req.Name)
var secret corev1.Secret
var configMap corev1.ConfigMap
var (
info corev1.Secret
configMap corev1.ConfigMap
launcher cloudv1.Launcher
)
err := r.Client.Get(ctx, types.NamespacedName{Namespace: string(cloud.Namespace), Name: string(cloud.SecretName)}, &secret)
if err != nil {
r.logger.Error(err, "failed to get secret...")
var (
readOperations issuer.ReadOperationList
writeOperations issuer.WriteOperationList
)
// read and write operations
(&issuer.ReadEventBuilder{}).WithContext(ctx).WithClient(r.Client).WithObject(&launcher).
WithTag(types.NamespacedName{Namespace: string(issuer.Namespace), Name: string(issuer.ClientStartName)}).
AddToList(&readOperations)
(&issuer.WriteEventBuilder{}).WithCallback(func() error {
if launcher.Labels[string(issuer.CollectorLable)] == issuer.TRUE {
return nil
}
launcher.Labels[string(issuer.CollectorLable)] = issuer.TRUE
return r.Client.Update(ctx, &launcher)
}).AddToList(&writeOperations)
(&issuer.ReadEventBuilder{}).WithContext(ctx).WithClient(r.Client).WithObject(&info).
WithTag(types.NamespacedName{Namespace: string(issuer.Namespace), Name: string(issuer.ClusterInfoSecretName)}).
AddToList(&readOperations)
(&issuer.ReadEventBuilder{}).WithContext(ctx).WithClient(r.Client).WithObject(&configMap).
WithTag(types.NamespacedName{Namespace: string(issuer.Namespace), Name: string(issuer.URLConfigName)}).
AddToList(&readOperations)
if err := readOperations.Execute(); err != nil {
r.logger.Error(err, "failed to read resources...")
return ctrl.Result{}, err
}
err = r.Client.Get(ctx, types.NamespacedName{Namespace: string(cloud.Namespace), Name: string(cloud.ConfigName)}, &configMap)
if err != nil {
r.logger.Error(err, "failed to get configmap...")
if err := writeOperations.Execute(); err != nil {
r.logger.Error(err, "failed to write resources...")
return ctrl.Result{}, err
}
config, err := util.ReadConfigFromConfigMap(string(cloud.ConfigName), &configMap)
// collect the resource info of the cluster
config, err := util.ReadConfigFromConfigMap(string(issuer.URLConfigName), &configMap)
if err != nil {
r.logger.Error(err, "failed to read config")
return ctrl.Result{}, err
}
r.logger.Info("Start to get the node info of the cluster")
clusterResource := cloud.NewClusterResource()
totalNodesResource := cloud.NewTotalNodesResource(`\w+\.com/gpu`)
clusterResource := issuer.NewClusterResource()
totalNodesResource := issuer.NewTotalNodesResource(`\w+\.com/gpu`)
nodeList := &corev1.NodeList{}
err = r.Client.List(ctx, nodeList)
@@ -114,18 +141,18 @@ func (r *CollectorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
clusterResource.Memory = totalNodesResource.TotalMemory.String()
clusterResource.Disk = totalNodesResource.TotalPVCapacity.String()
collector := cloud.CollectorInfo{
UID: string(secret.Data["uid"]),
InfoType: cloud.ResourceOnCluster,
collector := issuer.CollectorInfo{
UID: string(info.Data["uid"]),
InfoType: issuer.ResourceOnCluster,
ClusterResource: clusterResource,
}
r.logger.Info("Start to collector the node info of the cluster")
httpBody, err := cloud.CommunicateWithCloud("POST", config.CollectorURL, collector)
httpBody, err := issuer.CommunicateWithCloud("POST", config.CollectorURL, collector)
if err != nil {
r.logger.Error(err, "failed to communicate with cloud")
return ctrl.Result{}, err
}
if !cloud.IsSuccessfulStatusCode(httpBody.StatusCode) {
if !issuer.IsSuccessfulStatusCode(httpBody.StatusCode) {
err := errors.New(http.StatusText(httpBody.StatusCode))
r.logger.Error(err, err.Error())
return ctrl.Result{}, err
@@ -137,12 +164,12 @@ func (r *CollectorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
// SetupWithManager sets up the controller with the Manager.
func (r *CollectorReconciler) SetupWithManager(mgr ctrl.Manager) error {
r.logger = ctrl.Log.WithName("CollectorReconcile")
r.lastCollectedTime = time.Now().Add(time.Hour * 100).Unix()
Predicate := predicate.NewPredicateFuncs(func(object client.Object) bool {
return object.GetName() == string(cloud.ClientStartName) &&
object.GetNamespace() == string(cloud.Namespace) &&
return object.GetName() == string(issuer.ClientStartName) &&
object.GetNamespace() == string(issuer.Namespace) &&
object.GetLabels() != nil &&
object.GetLabels()[string(cloud.IsRead)] == string(cloud.FALSE)
object.GetLabels()[string(issuer.CollectorLable)] == string(issuer.FALSE)
})
return ctrl.NewControllerManagedBy(mgr).
For(&cloudv1.Launcher{}, builder.WithPredicates(Predicate)).
@@ -0,0 +1,182 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controller
import (
"context"
"errors"
"net/http"
"time"
"github.com/go-logr/logr"
issuerv1 "github.com/labring/sealos/controllers/licenseissuer/api/v1"
"github.com/labring/sealos/controllers/licenseissuer/internal/controller/util"
issuer "github.com/labring/sealos/controllers/licenseissuer/internal/manager"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/predicate"
)
// CloudSyncReconciler reconciles a CloudSync object
type CloudSyncReconciler struct {
client.Client
Scheme *runtime.Scheme
logger logr.Logger
needSync bool
syncCache issuer.SyncResponse
}
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=cloudsyncs,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=cloudsyncs/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=cloudsyncs/finalizers,verbs=update
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
// TODO(user): Modify the Reconcile function to compare the state specified by
// the CloudSync object against the actual cluster state, and then
// perform operations to make the cluster state reflect the state specified by
// the user.
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.4/pkg/reconcile
func (r *CloudSyncReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// Logging the start of the sync operation
r.logger.Info("Enter CloudSyncReconcile", "namespace:", req.Namespace, "name", req.Name)
// Defining error and operation lists
var err error
var (
readOperations issuer.ReadOperationList
writeOperations issuer.WriteOperationList
)
// Defining the necessary variables
var (
config issuer.Config
secret corev1.Secret
sync issuer.SyncRequest
resp issuer.SyncResponse
configMap corev1.ConfigMap
launcher issuerv1.Launcher
)
r.logger.Info("Start to get the resource for data sync...")
// Building read operations to fetch necessary resources
// Here, we fetch the Launcher, Secret and ConfigMap
// The fetched objects are added to readOperations list
(&issuer.ReadEventBuilder{}).WithContext(ctx).WithClient(r.Client).WithObject(&launcher).
WithTag(types.NamespacedName{Namespace: req.Namespace, Name: string(issuer.ClientStartName)}).
AddToList(&readOperations)
(&issuer.ReadEventBuilder{}).WithContext(ctx).WithClient(r.Client).WithObject(&secret).
WithTag(types.NamespacedName{Namespace: string(issuer.Namespace), Name: string(issuer.ClusterInfoSecretName)}).
AddToList(&readOperations)
(&issuer.ReadEventBuilder{}).WithContext(ctx).WithClient(r.Client).WithObject(&configMap).
WithTag(types.NamespacedName{Namespace: string(issuer.Namespace), Name: string(issuer.URLConfigName)}).
AddToList(&readOperations)
// Executing the read operations. If there is an error, it's logged and returned
if err := readOperations.Execute(); err != nil {
r.logger.Error(err, "failed to read resources...")
return ctrl.Result{}, err
}
// register a callback function to update the launcher
(&issuer.WriteEventBuilder{}).WithCallback(func() error {
if launcher.Labels[string(issuer.SyncLable)] == issuer.TRUE {
return nil
}
launcher.Labels[string(issuer.SyncLable)] = issuer.TRUE
return r.Client.Update(ctx, &launcher)
}).AddToList(&writeOperations)
// Extracting the config from the ConfigMap
config, err = util.ReadConfigFromConfigMap(string(issuer.URLConfigName), &configMap)
if err != nil {
r.logger.Error(err, "failed to get config...")
return ctrl.Result{}, err
}
url := config.CloudSyncURL
sync.UID = string(secret.Data["uid"])
// Checking if we need to sync. If true, we communicate with the cloud and get the response
if r.needSync {
r.logger.Info("Start to communicate with cloud...")
httpBody, err := issuer.CommunicateWithCloud("POST", url, sync)
if err != nil {
r.logger.Error(err, "failed to communicate with cloud...")
return ctrl.Result{}, err
}
if !issuer.IsSuccessfulStatusCode(httpBody.StatusCode) {
err := errors.New(http.StatusText(httpBody.StatusCode))
r.logger.Error(err, err.Error())
return ctrl.Result{}, err
}
err = issuer.Convert(httpBody.Body, &resp)
if err != nil {
r.logger.Error(err, "failed to convert to cloud.SyncResponse")
return ctrl.Result{}, err
}
r.syncCache = resp
} else {
resp = r.syncCache
}
// Building write operations to update the configmap and secret
(&issuer.WriteEventBuilder{}).WithCallback(func() error {
// Checking if the new config is different from the old one.
// If true, we sync the resources
// If false, we do nothing
if ok := issuer.IsConfigMapChanged(resp.Config, &configMap); ok {
r.logger.Info("Update the configmap...")
err := r.Client.Update(ctx, &configMap)
if err != nil {
r.logger.Error(err, "failed to update configmap...")
}
return err
}
return nil
}).AddToList(&writeOperations)
// Executing the write operations.
// If there is an error, it's logged and returned
if err := writeOperations.Execute(); err != nil {
r.logger.Error(err, "failed to write resources...")
r.needSync = false
return ctrl.Result{}, err
}
r.needSync = true
r.syncCache = issuer.SyncResponse{}
r.logger.Info("Finish to sync the resources...")
return ctrl.Result{RequeueAfter: time.Second * 3600}, nil
}
// SetupWithManager sets up the controller with the Manager.
func (r *CloudSyncReconciler) SetupWithManager(mgr ctrl.Manager) error {
r.logger = ctrl.Log.WithName("DataSyncReconcile")
r.needSync = true
Predicate := predicate.NewPredicateFuncs(func(object client.Object) bool {
return object.GetName() == string(issuer.ClientStartName) &&
object.GetNamespace() == string(issuer.Namespace) &&
object.GetLabels() != nil &&
object.GetLabels()[string(issuer.SyncLable)] == issuer.FALSE
})
return ctrl.NewControllerManagedBy(mgr).
For(&issuerv1.Launcher{}, builder.WithPredicates(Predicate)).
Complete(r)
}
@@ -0,0 +1,164 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controller
import (
"context"
"os"
"github.com/go-logr/logr"
issurev1 "github.com/labring/sealos/controllers/licenseissuer/api/v1"
"github.com/labring/sealos/controllers/licenseissuer/internal/controller/util"
issuer "github.com/labring/sealos/controllers/licenseissuer/internal/manager"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/predicate"
)
// LauncherReconciler reconciles a Launcher object
type LauncherReconciler struct {
client.Client
Scheme *runtime.Scheme
logger logr.Logger
justSync bool
//justRestart bool
}
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=launchers,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=launchers/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=launchers/finalizers,verbs=update
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
// TODO(user): Modify the Reconcile function to compare the state specified by
// the Launcher object against the actual cluster state, and then
// perform operations to make the cluster state reflect the state specified by
// the user.
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.4/pkg/reconcile
func (r *LauncherReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctl ctrl.Result, err error) {
r.logger.Info("Enter LauncherReconcile", "namespace:", req.Namespace, "name", req.Name)
r.logger.Info("Start the infostream module...")
// read operations for the env and configmap and secret
canConnectToExternalNetwork := os.Getenv(string(issuer.NetWorkEnv)) == issuer.TRUE
var (
secret corev1.Secret
configMap corev1.ConfigMap
)
r.logger.Info("Try to get the cloud secret&configmap resource...")
err = r.Client.Get(ctx, types.NamespacedName{Namespace: string(issuer.Namespace), Name: string(issuer.URLConfigName)}, &configMap)
if err != nil {
r.logger.Error(err, "failed to get configmap...")
return ctrl.Result{}, err
}
config, err := util.ReadConfigFromConfigMap(string(issuer.URLConfigName), &configMap)
if err != nil {
r.logger.Error(err, "failed to get config...")
return ctrl.Result{}, err
}
// Checking if we need to sync.
// If true, we communicate with the cloud and get the response
if r.justSync && canConnectToExternalNetwork {
_, err := issuer.SyncWithCloud("POST", config.RegisterURL, issuer.RegisterRequest{UID: string(secret.Data["uid"])})
if err != nil {
r.justSync = true
r.logger.Error(err, "failed sync register info to cloud")
return ctrl.Result{}, err
}
r.justSync = false
err = util.StartCloudModule(ctx, r.Client)
if err != nil {
r.logger.Error(err, "failed to start cloud moudle")
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
}
// Checking if we need to restart the cloud module.
// If registered, we start the cloud module
err = r.Client.Get(ctx, types.NamespacedName{Namespace: string(issuer.Namespace), Name: string(issuer.ClusterInfoSecretName)}, &secret)
if err == nil {
r.logger.Info("start to launch cloud moudle")
err := util.StartCloudModule(ctx, r.Client)
if err != nil {
r.logger.Error(err, "failed to start cloud moudle")
return ctrl.Result{}, err
}
r.logger.Info("success to launch monitor")
return ctrl.Result{}, nil
}
// generate the uuid and register to the cloud
secret.Data = make(map[string][]byte)
uuid, err := util.Register()
if err != nil {
r.logger.Error(err, "failed to get register...")
return ctrl.Result{}, err
}
rr := issuer.RegisterRequest{
UID: uuid,
}
secret.Data["uid"] = []byte(uuid)
secret.SetName(string(issuer.ClusterInfoSecretName))
secret.SetNamespace(string(issuer.Namespace))
if err := r.Client.Create(ctx, &secret); err != nil {
r.logger.Error(err, "failed to create the register info to the cluster")
return ctrl.Result{}, err
}
if canConnectToExternalNetwork {
_, err = issuer.SyncWithCloud("POST", config.RegisterURL, rr)
if err != nil {
r.justSync = true
r.logger.Error(err, "failed sync register info to cloud")
return ctrl.Result{}, err
}
}
r.justSync = false
// start the cloud module
if err := util.StartCloudModule(ctx, r.Client); err != nil {
r.logger.Error(err, "failed to start cloud module")
return ctrl.Result{}, err
}
r.logger.Info("success to launch monitor")
return ctrl.Result{}, nil
}
// SetupWithManager sets up the controller with the Manager.
func (r *LauncherReconciler) SetupWithManager(mgr ctrl.Manager) error {
r.logger = ctrl.Log.WithName("LauncherReconcile")
nameFilter := issuer.InfostreamLaunchName
namespaceFilter := issuer.Namespace
Predicates := predicate.NewPredicateFuncs(func(obj client.Object) bool {
return obj.GetName() == string(nameFilter) &&
obj.GetNamespace() == string(namespaceFilter)
})
return ctrl.NewControllerManagedBy(mgr).
For(&issurev1.Launcher{}, builder.WithPredicates(Predicates)).
Complete(r)
}
@@ -0,0 +1,214 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package controller
import (
"context"
"os"
"time"
"github.com/go-logr/logr"
accountv1 "github.com/labring/sealos/controllers/account/api/v1"
issuerv1 "github.com/labring/sealos/controllers/licenseissuer/api/v1"
"github.com/labring/sealos/controllers/licenseissuer/internal/controller/util"
issuer "github.com/labring/sealos/controllers/licenseissuer/internal/manager"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/predicate"
)
// LicenseReconciler reconciles a License object
type LicenseReconciler struct {
client.Client
Scheme *runtime.Scheme
needRecharge bool
logger logr.Logger
Retries int
}
//+kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=account.sealos.io,resources=accounts,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=account.sealos.io,resources=accounts/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=notification.sealos.io,resources=notifications,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=licenses,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=licenses/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=licenses/finalizers,verbs=update
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
// TODO(user): Modify the Reconcile function to compare the state specified by
// the License object against the actual cluster state, and then
// perform operations to make the cluster state reflect the state specified by
// the user.
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.4/pkg/reconcile
func (r *LicenseReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
r.logger.Info("Enter LicenseReconcile", "namespace:", req.Namespace, "name", req.Name)
r.logger.Info("Start to get license-related resource...")
var canConnectToExternalNetwork bool
var (
readOperations issuer.ReadOperationList
writeOperations issuer.WriteOperationList
)
var (
license issuerv1.License
clusterLimit corev1.Secret
uidSecret corev1.Secret
urlConfig corev1.ConfigMap
licenseHistory corev1.ConfigMap
account accountv1.Account
)
var (
ok bool
payload map[string]interface{}
)
canConnectToExternalNetwork = os.Getenv(string(issuer.NetWorkEnv)) == issuer.TRUE
// execute read event
(&issuer.ReadEventBuilder{}).WithContext(ctx).WithClient(r.Client).
WithTag(types.NamespacedName{Namespace: req.Namespace, Name: string(issuer.LicenseName)}).
WithObject(&license).AddToList(&readOperations)
(&issuer.ReadEventBuilder{}).WithContext(ctx).WithClient(r.Client).
WithTag(types.NamespacedName{Namespace: string(issuer.Namespace), Name: string(issuer.ClusterInfoSecretName)}).
WithObject(&uidSecret).AddToList(&readOperations)
(&issuer.ReadEventBuilder{}).WithContext(ctx).WithClient(r.Client).
WithTag(types.NamespacedName{Namespace: string(issuer.Namespace), Name: string(issuer.URLConfigName)}).
WithObject(&urlConfig).AddToList(&readOperations)
(&issuer.ReadEventBuilder{}).WithContext(ctx).WithClient(r.Client).
WithTag(types.NamespacedName{Namespace: string(issuer.Namespace), Name: string(issuer.LicenseHistory)}).
WithObject(&licenseHistory).AddToList(&readOperations)
(&issuer.ReadEventBuilder{}).WithContext(ctx).WithClient(r.Client).
WithTag(types.NamespacedName{Namespace: string(issuer.Namespace), Name: string(issuer.AvailableScaleSecretName)}).
WithObject(&clusterLimit).WithCallback(func() error {
clusterLimit.SetName(string(issuer.AvailableScaleSecretName))
clusterLimit.SetNamespace(string(issuer.Namespace))
clusterLimit.SetLabels(map[string]string{})
return r.Client.Create(ctx, &clusterLimit)
}).AddToList(&readOperations)
// execute read event
if err := readOperations.Execute(); err != nil {
r.logger.Error(err, "failed to read resources...")
return ctrl.Result{}, err
}
// get account
err := r.Client.Get(ctx, types.NamespacedName{Namespace: "sealos-system", Name: license.Spec.UID}, &account)
if err != nil {
r.logger.Error(err, "failed to get account")
return ctrl.Result{}, err
}
// security judgement before write
config, err := util.ReadConfigFromConfigMap(string(issuer.URLConfigName), &urlConfig)
if err != nil {
r.logger.Error(err, "failed to read url config")
return ctrl.Result{}, err
}
if issuer.CheckLicenseExists(&licenseHistory, license.Spec.Token) {
pack := issuer.NewNotificationPackage(issuer.LicenseNoticeTitle, issuer.SEALOS, issuer.DuplicateLicenseMessage)
issuer.SubmitNotificationWithUser(ctx, r.Client, req.Namespace, pack)
return ctrl.Result{}, r.Client.Delete(ctx, &license)
}
if canConnectToExternalNetwork {
payload, ok = issuer.LicenseCheckOnExternalNetwork(license, uidSecret, config.LicenseMonitorURL, r.logger)
} else {
payload, ok = issuer.LicenseCheckOnInternalNetwork(license)
}
// pre-check for license
if !ok {
pack := issuer.NewNotificationPackage(issuer.LicenseNoticeTitle, issuer.SEALOS, issuer.InvalidLicenseMessage)
issuer.SubmitNotificationWithUser(ctx, r.Client, req.Namespace, pack)
r.logger.Info("invalid license")
return ctrl.Result{}, r.Client.Delete(ctx, &license)
}
// check license creat time
creatTime, err := issuer.InterfaceToInt64(payload[issuer.CreatTimeField])
if err != nil {
r.logger.Error(err, "failed to convert license creat time")
pack := issuer.NewNotificationPackage(issuer.LicenseNoticeTitle, issuer.SEALOS, issuer.InvalidLicenseMessage)
issuer.SubmitNotificationWithUser(ctx, r.Client, req.Namespace, pack)
return ctrl.Result{}, r.Client.Delete(ctx, &license)
}
if time.Unix(creatTime, 0).Add(issuer.LicenseLifetime).Before(time.Now()) {
pack := issuer.NewNotificationPackage(issuer.LicenseNoticeTitle, issuer.SEALOS, issuer.ExpiredLicenseMessage)
issuer.SubmitNotificationWithUser(ctx, r.Client, req.Namespace, pack)
r.logger.Info("expired license")
return ctrl.Result{}, r.Client.Delete(ctx, &license)
}
// recharge
(&issuer.WriteEventBuilder{}).WithCallback(func() error {
if !issuer.ContainsFields(payload, issuer.AmountField) {
return nil
}
err := issuer.RechargeByLicense(ctx, r.Client, r.logger, account, payload)
if err != nil {
pack := issuer.NewNotificationPackage(issuer.LicenseNoticeTitle, issuer.SEALOS, issuer.RechargeFailedMessage)
issuer.SubmitNotificationWithUser(ctx, r.Client, req.Namespace, pack)
return err
}
pack := issuer.NewNotificationPackage(issuer.LicenseNoticeTitle, issuer.SEALOS, issuer.ValidLicenseMessage)
issuer.SubmitNotificationWithUser(ctx, r.Client, req.Namespace, pack)
return nil
}).AddToList(&writeOperations)
// record the license
(&issuer.WriteEventBuilder{}).WithCallback(func() error {
return issuer.RecordLicense(ctx, r.Client, r.logger, license, licenseHistory)
}).AddToList(&writeOperations)
(&issuer.WriteEventBuilder{}).WithCallback(func() error {
return r.Client.Delete(ctx, &license)
}).AddToList(&writeOperations)
_ = writeOperations.Execute()
r.logger.Info("license has been activated")
return ctrl.Result{}, nil
}
// SetupWithManager sets up the controller with the Manager.
func (r *LicenseReconciler) SetupWithManager(mgr ctrl.Manager) error {
r.logger = ctrl.Log.WithName("LicenseReconcile")
r.Retries = 0
r.needRecharge = true
Predicate := predicate.Funcs{
CreateFunc: func(e event.CreateEvent) bool {
return e.Object.GetName() == string(issuer.LicenseName)
},
UpdateFunc: func(e event.UpdateEvent) bool {
return e.ObjectNew.GetName() == string(issuer.LicenseName)
},
DeleteFunc: func(e event.DeleteEvent) bool {
// Ignore delete events
return false
},
GenericFunc: func(e event.GenericEvent) bool {
return e.Object.GetName() == string(issuer.LicenseName)
},
}
return ctrl.NewControllerManagedBy(mgr).
For(&issuerv1.License{}, builder.WithPredicates(Predicate)).
Complete(r)
}
@@ -24,10 +24,10 @@ import (
"time"
"github.com/go-logr/logr"
cloudv1 "github.com/labring/sealos/controllers/cloud/api/v1"
"github.com/labring/sealos/controllers/cloud/internal/controller/util"
cloud "github.com/labring/sealos/controllers/cloud/internal/manager"
ntf "github.com/labring/sealos/controllers/common/notification/api/v1"
issuerv1 "github.com/labring/sealos/controllers/licenseissuer/api/v1"
"github.com/labring/sealos/controllers/licenseissuer/internal/controller/util"
issuer "github.com/labring/sealos/controllers/licenseissuer/internal/manager"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
@@ -41,17 +41,17 @@ import (
type NotificationReconciler struct {
client.Client
Scheme *runtime.Scheme
NotificationMgr *cloud.NotificationManager
Users cloud.UserCategory
NotificationMgr *issuer.NotificationManager
Users issuer.UserCategory
logger logr.Logger
}
//+kubebuilder:rbac:groups=core,resources=nodes,verbs=get;list;watch
//+kubebuilder:rbac:groups=core,resources=persistentvolumes,verbs=get;list;watch
//+kubebuilder:rbac:groups=core,resources=namespaces,verbs=get;list;watch;create;update
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=notifications,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=notifications/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=cloud.sealos.io,resources=notifications/finalizers,verbs=update
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=notifications,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=notifications/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=infostream.sealos.io,resources=notifications/finalizers,verbs=update
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
@@ -62,6 +62,7 @@ type NotificationReconciler struct {
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.4/pkg/reconcile
func (r *NotificationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
r.logger.Info("Enter NotificationReconcile", "namespace:", req.Namespace, "name", req.Name)
if err := r.Users.GetNameSpace(ctx, r.Client); err != nil {
@@ -69,49 +70,73 @@ func (r *NotificationReconciler) Reconcile(ctx context.Context, req ctrl.Request
return ctrl.Result{}, err
}
r.logger.Info("Start to get the resource for pull notification...")
var err error
var configMap corev1.ConfigMap
var url string
var clusterScret corev1.Secret
var (
err error
configMap corev1.ConfigMap
url string
clusterScret corev1.Secret
launcher issuerv1.Launcher
)
var (
readOperations issuer.ReadOperationList
writeOperations issuer.WriteOperationList
)
err = r.Client.Get(ctx, types.NamespacedName{Namespace: string(cloud.Namespace), Name: string(cloud.SecretName)}, &clusterScret)
if err != nil {
r.logger.Error(err, "failed to get secret...")
// read the resource for pull notification
(&issuer.ReadEventBuilder{}).WithContext(ctx).WithClient(r.Client).WithObject(&launcher).
WithTag(req.NamespacedName).AddToList(&readOperations)
(&issuer.WriteEventBuilder{}).WithCallback(func() error {
if launcher.Labels[string(issuer.NotificationLable)] == string(issuer.TRUE) {
return nil
}
launcher.Labels[string(issuer.NotificationLable)] = issuer.TRUE
return r.Client.Update(ctx, &launcher)
}).AddToList(&writeOperations)
(&issuer.ReadEventBuilder{}).WithContext(ctx).WithClient(r.Client).WithObject(&clusterScret).
WithTag(types.NamespacedName{Namespace: string(issuer.Namespace), Name: string(issuer.ClusterInfoSecretName)}).
AddToList(&readOperations)
(&issuer.ReadEventBuilder{}).WithContext(ctx).WithClient(r.Client).WithObject(&configMap).
WithTag(types.NamespacedName{Namespace: string(issuer.Namespace), Name: string(issuer.URLConfigName)}).
AddToList(&readOperations)
if err := readOperations.Execute(); err != nil {
r.logger.Error(err, "failed to get the resource for pull notification")
return ctrl.Result{}, err
}
if err := writeOperations.Execute(); err != nil {
r.logger.Error(err, "failed to update the launcher")
return ctrl.Result{}, err
}
err = r.Client.Get(ctx, types.NamespacedName{Namespace: string(cloud.Namespace), Name: string(cloud.ConfigName)}, &configMap)
if err != nil {
r.logger.Error(err, "failed to get configmap...")
return ctrl.Result{}, err
}
config, err := util.ReadConfigFromConfigMap(string(cloud.ConfigName), &configMap)
config, err := util.ReadConfigFromConfigMap(string(issuer.URLConfigName), &configMap)
if err != nil {
r.logger.Error(err, "failed to read config")
return ctrl.Result{}, err
}
r.logger.Info("Start to pull notification from cloud...")
url = config.NotificationURL
var requestBody = cloud.NotificationRequest{
var requestBody = issuer.NotificationRequest{
UID: string(clusterScret.Data["uid"]),
Timestamp: r.NotificationMgr.TimeLastPull,
}
// communicate with cloud
r.logger.Info("Starting to communicate with cloud")
httpResp, err := cloud.CommunicateWithCloud("POST", url, requestBody)
httpResp, err := issuer.CommunicateWithCloud("POST", url, requestBody)
if err != nil {
r.logger.Error(err, "failed to communicate with cloud")
return ctrl.Result{}, err
}
if !cloud.IsSuccessfulStatusCode(httpResp.StatusCode) {
if !issuer.IsSuccessfulStatusCode(httpResp.StatusCode) {
r.logger.Error(errors.New(http.StatusText(httpResp.StatusCode)), string(httpResp.Body))
return ctrl.Result{}, errors.New(http.StatusText(httpResp.StatusCode))
}
var notificationResp []cloud.NotificationResponse
// submit the notification to the cluster
var notificationResp []issuer.NotificationResponse
var notificationCache []ntf.Notification
err = cloud.Convert(httpResp.Body, &notificationResp)
err = issuer.Convert(httpResp.Body, &notificationResp)
if err != nil {
r.logger.Error(err, "failed to convert notifications")
return ctrl.Result{}, err
@@ -119,15 +144,15 @@ func (r *NotificationReconciler) Reconcile(ctx context.Context, req ctrl.Request
r.logger.Info("Starting to delivery notifications")
for _, body := range notificationResp {
notificationCache = append(notificationCache, cloud.NotificationResponseToNotification(body))
notificationCache = append(notificationCache, issuer.NotificationResponseToNotification(body))
}
var wg sync.WaitGroup
errchan := make(chan error)
for _, targetMap := range r.Users {
for ns := range targetMap.Iter() {
wg.Add(1)
notificationTask := cloud.NewNotificationTask(ctx, r.Client, ns, notificationCache)
go cloud.AsyncCloudTask(&wg, errchan, &notificationTask)
notificationTask := issuer.NewNotificationTask(ctx, r.Client, ns, notificationCache)
go issuer.AsyncCloudTask(&wg, errchan, &notificationTask)
}
}
go func() {
@@ -146,16 +171,16 @@ func (r *NotificationReconciler) Reconcile(ctx context.Context, req ctrl.Request
// SetupWithManager sets up the controller with the Manager.
func (r *NotificationReconciler) SetupWithManager(mgr ctrl.Manager) error {
r.logger = ctrl.Log.WithName("NotificationReconcile")
r.NotificationMgr = cloud.NewNotificationManager()
r.Users = cloud.UserCategory{}
r.NotificationMgr = issuer.NewNotificationManager()
r.Users = issuer.UserCategory{}
Predicate := predicate.NewPredicateFuncs(func(object client.Object) bool {
return object.GetName() == string(cloud.ClientStartName) &&
object.GetNamespace() == string(cloud.Namespace) &&
return object.GetName() == string(issuer.ClientStartName) &&
object.GetNamespace() == string(issuer.Namespace) &&
object.GetLabels() != nil &&
object.GetLabels()[string(cloud.IsRead)] == cloud.FALSE &&
object.GetLabels()[string(cloud.ExternalNetworkAccessLabel)] == string(cloud.Enabled)
object.GetLabels()[string(issuer.NotificationLable)] == string(issuer.FALSE)
})
return ctrl.NewControllerManagedBy(mgr).
For(&cloudv1.Launcher{}, builder.WithPredicates(Predicate)).
For(&issuerv1.Launcher{}, builder.WithPredicates(Predicate)).
Complete(r)
}
@@ -30,7 +30,7 @@ import (
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
cloudv1 "github.com/labring/sealos/controllers/cloud/api/v1"
licenseissuerv1 "github.com/labring/sealos/controllers/licenseissuer/api/v1"
//+kubebuilder:scaffold:imports
)
@@ -62,7 +62,7 @@ var _ = BeforeSuite(func() {
Expect(err).NotTo(HaveOccurred())
Expect(cfg).NotTo(BeNil())
err = cloudv1.AddToScheme(scheme.Scheme)
err = licenseissuerv1.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())
//+kubebuilder:scaffold:scheme
@@ -0,0 +1,118 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"context"
"crypto/rand"
"encoding/json"
"errors"
"fmt"
"os"
issuerv1 "github.com/labring/sealos/controllers/licenseissuer/api/v1"
issuer "github.com/labring/sealos/controllers/licenseissuer/internal/manager"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
cl "sigs.k8s.io/controller-runtime/pkg/client"
)
func ReadConfigFromConfigMap(expectName string, configMap *corev1.ConfigMap) (issuer.Config, error) {
if configMap.Name != expectName {
err := errors.New("not expected configmap")
return issuer.Config{}, err
}
var config issuer.Config
err := json.Unmarshal([]byte(configMap.Data["config.json"]), &config)
if err != nil {
return issuer.Config{}, err
}
return config, nil
}
func Register() (string, error) {
return newUUID()
}
func newUUID() (string, error) {
uuid := make([]byte, 16)
n, err := rand.Read(uuid)
if n != len(uuid) || err != nil {
return "", err
}
uuid[6] = (uuid[6] & 0x0f) | 0x40
uuid[8] = (uuid[8] & 0x3f) | 0x80
return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:]), nil
}
// StartCloudModule is a function that initializes a cloud module in a cloud-native environment.
// The function checks if the current environment is set as a monitor. If it is, the function
// locates a launcher by its namespaced name. If the launcher does not exist, the function creates
// a new launcher with the necessary labels and attempts to create it in the client's context.
// If the launcher already exists, the function updates the launcher's labels and attempts to
// update it in the client's context. If there are any errors during these operations, the function
// wraps them with a contextual message and returns them. If the environment is not set as a monitor,
// or if the operations are successful, the function returns nil.
func StartCloudModule(ctx context.Context, client cl.Client) error {
isMonitor := os.Getenv(string(issuer.IsMonitor))
if isMonitor == issuer.TRUE {
nn := types.NamespacedName{
Namespace: string(issuer.Namespace),
Name: string(issuer.ClientStartName),
}
var launcher issuerv1.Launcher
err := client.Get(ctx, nn, &launcher)
if err != nil && apierrors.IsNotFound(err) {
return createLauncher(ctx, client, nn, &launcher)
}
if err != nil {
return fmt.Errorf("StartCloudModule: %w", err)
}
return updateLauncher(ctx, client, &launcher)
}
return nil
}
var launchData = map[string]string{
string(issuer.CollectorLable): issuer.FALSE,
string(issuer.SyncLable): issuer.FALSE,
string(issuer.NotificationLable): issuer.FALSE,
}
func createLauncher(ctx context.Context, client cl.Client, nn types.NamespacedName, launcher *issuerv1.Launcher) error {
launcher.SetName(nn.Name)
launcher.SetNamespace(nn.Namespace)
launcher.Labels = launchData
if err := client.Create(ctx, launcher); err != nil {
return fmt.Errorf("StartCloudModule: %w", err)
}
return nil
}
func updateLauncher(ctx context.Context, client cl.Client, launcher *issuerv1.Launcher) error {
launcher.Labels = launchData
if err := client.Update(ctx, launcher); err != nil {
return fmt.Errorf("StartCloudModule: %w", err)
}
return nil
}
@@ -33,17 +33,21 @@ type Title string
type Source string
type TypeInfo string
type Resource string
type ENV string
const BaseCount = 1000000
const Key = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFvbFBTSzB0UjFKeDZtb25lL2ppeApSWGN6UGlxcU5SSXRmdW1mdWNyNGMxc2dqdlJha0NwcWtDU21lMTR1akJkU0x6QlZzRjkvUWl0UnFNb2NvaEN1CkJ6R25EQ29hWnZXbWVHeE96NEZSejVTeUg1QTlDa3dnbUEzYnFnMWxKSEZTMlZyVjVHVFhFWnphZTZtRmhHOVcKenJMTnpZMlptYTMzOVE1WTNJSDZ6RXIrcTRQbTZDOXBHVGpsSnVodlRvb0dSY2w0bmpZRXc2eHB6ZHZrdi9uSApmZmxsWGZVNDNyRGdQaGkwZDRjWnNuTUJlazUxQkNiRFRuSHlNVFdGT1RoTjc1VVM0bzJxRm9JSEhsM0N0RzE4ClZIZEdRSE1IR0dYcGN3bVhhck1EQndwVWFOSk9kMkhjTTB5dlZEY2xDZzRITkIwVUFWeFNweFlRV3BwNWJzN2gKbHdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg=="
const (
Namespace Resource = "cloud-system"
LicenseHistory Resource = "cloud-license-history"
LicenseName Resource = "license"
SecretName Resource = "cloud-secret"
ConfigName Resource = "cloud-config"
CloudStartName Resource = "cloud-start"
ClientStartName Resource = "client-start"
Namespace Resource = "sealos-system"
AvailableScaleSecretName Resource = "cluster-scale"
LicenseHistory Resource = "license-history"
LicenseName Resource = "license"
ClusterInfoSecretName Resource = "cluster-info"
URLConfigName Resource = "url-config"
InfostreamLaunchName Resource = "launcher"
ClientStartName Resource = "client-start"
)
const (
@@ -54,34 +58,25 @@ const (
)
const (
SEALOS Source = "Sealos Cloud"
ErrorLicenseTitle Title = "License Activation Failed"
InvalidLicenseTitle Title = "Invalid License"
UnKnownErrorOfLicense Title = "UnKnown error about license"
ValidLicenseTitle Title = "License Activated"
RechargeFailedTitle Title = "Recharge failed"
DuplicateLicenseTitle Title = "Duplicate License"
RegistrationSuccessTitle Title = "Registration Success"
InvalidLicenseContent Message = "The provided license is invalid. Please check and try."
ErrorLicenseTitleContent Message = "License delivery encountered an unexpected error. Please ensure your cluster is operating normally..."
UnKnownErrorOfLicenseCotentent Message = "During the license activation process, a location issue occurred, possibly due to network problems. If it affects your usage, please contact us."
LicenseTimeOutContent Message = "The provided license has expired. Please check and try."
ValidLicenseContent Message = "Your license has been successfully activated and is ready to use. Enjoy your experience!"
DuplicateLicenseContent Message = "The provided license has already been used. Please use a different license."
RegistrationSuccessContent Message = "Congratulations! You have successfully registered. Welcome aboard!"
RechargeFailedContent Message = "Your license failed to recharge."
SEALOS Source = "Sealos Cloud"
ClusterCapacityNoticeTitle Title = "Notice: Cluster Capacity"
LicenseNoticeTitle Title = "Notice: License"
InvalidLicenseMessage Message = "The provided license is invalid. Please check and try."
ExpiredLicenseMessage Message = "The provided license has expired. Please check and try."
ValidLicenseMessage Message = "Your license has been successfully activated and is ready to use. Enjoy your experience!"
DuplicateLicenseMessage Message = "The provided license has already been used. Please use a different license."
RechargeFailedMessage Message = "License recharge failed."
)
const (
ExternalNetworkAccessLabel Label = "external-network-access"
IsDisabled Label = "isDisabled"
IsRead Label = "isRead"
Enabled Label = "enabled"
Disabled Label = "disabled"
CollectorLable Label = "enableCollect"
NotificationLable Label = "enableNotify"
SyncLable Label = "enableSync"
)
const (
NetWorkEnv string = "CAN_CONNECT_TO_EXTERNAL_NETWORK"
IsMonitor ENV = "MONITOR"
NetWorkEnv ENV = "CAN_CONNECT_TO_EXTERNAL_NETWORK"
)
const (
@@ -89,13 +84,15 @@ const (
FALSE = "false"
)
type PolicyAction string
type NotificationRequest struct {
UID string `json:"uid"`
Timestamp int64 `json:"timestamp"`
}
type RegisterRequest struct {
UID string `json:"uid"`
}
type NotificationResponse struct {
ID string `json:"_id"`
Type string `json:"msgType"`
@@ -130,6 +127,18 @@ type ConvertOptions interface {
callbackConvert(data interface{}) error
}
func SyncWithCloud(method string, url string, content interface{}) (HTTPResponse, error) {
httpBody, err := CommunicateWithCloud(method, url, content)
if err != nil {
return HTTPResponse{}, fmt.Errorf(err.Error(), "failed to communicate with cloud")
}
if !IsSuccessfulStatusCode(httpBody.StatusCode) {
text := http.StatusText(httpBody.StatusCode)
return HTTPResponse{}, fmt.Errorf(text, "failed to communicate with cloud")
}
return httpBody, nil
}
func CommunicateWithCloud(method string, url string, content interface{}) (HTTPResponse, error) {
var req *http.Request
var resp *http.Response
@@ -0,0 +1,359 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package manager
import (
"context"
"errors"
"fmt"
"net/http"
"strconv"
"time"
"github.com/go-logr/logr"
accountv1 "github.com/labring/sealos/controllers/account/api/v1"
issuerv1 "github.com/labring/sealos/controllers/licenseissuer/api/v1"
"github.com/labring/sealos/controllers/pkg/crypto"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
)
const MaxSizeThresholdStr = "800Ki"
const LicenseLifetime = time.Hour * 24 // 24 hours
const (
CreatTimeField = "iat"
AmountField = "amt"
NodeField = "nod"
CPUField = "cpu"
DurationField = "tte"
AddNodeField = "and"
AddCPUField = "adc"
)
const retryInterval = time.Second * 5 // Retry every 5 seconds
const timeout = time.Minute * 3 // Stop retrying after 3 minutes
type Operation interface {
Execute() error
}
type ReadOperationList struct {
readOperations []Operation
}
type WriteOperationList struct {
writeOperations []Operation
}
type ReWriteOperationList struct {
reWriteOperations []Operation
}
func (list *ReadOperationList) Execute() error {
for _, op := range list.readOperations {
err := op.Execute()
if err != nil {
return err
}
}
return nil
}
func (list *WriteOperationList) Execute() error {
reWriteList := &ReWriteOperationList{}
for _, op := range list.writeOperations {
err := op.Execute()
if err != nil {
reWriteList.AddToList(op)
}
}
if len(reWriteList.reWriteOperations) > 0 {
err := reWriteList.Execute()
if err != nil {
return fmt.Errorf("an error occurred, some operations still failed after retries: %v", err)
}
}
return nil
}
func (list *ReWriteOperationList) AddToList(op Operation) {
list.reWriteOperations = append(list.reWriteOperations, op)
}
func (list *ReWriteOperationList) Execute() error {
startTime := time.Now()
for {
remainingOps := []Operation{}
for _, op := range list.reWriteOperations {
err := op.Execute()
if err != nil {
remainingOps = append(remainingOps, op)
}
}
if len(remainingOps) == 0 {
break
}
// Update the list of reWriteOperations with the remaining operations
list.reWriteOperations = remainingOps
// Check if the timeout has been reached
if time.Since(startTime) >= timeout {
return fmt.Errorf("timeout reached, some operations still failed")
}
// Wait for the retry interval before trying again
time.Sleep(retryInterval)
}
return nil
}
type ReadEventBuilder struct {
obj client.Object
ctx context.Context
client client.Client
tag types.NamespacedName
callback WriteFunc
}
type WriteEventBuilder struct {
callback WriteFunc
}
type WriteFunc func() error
func (reb *ReadEventBuilder) WithClient(client client.Client) *ReadEventBuilder {
reb.client = client
return reb
}
func (reb *ReadEventBuilder) WithContext(ctx context.Context) *ReadEventBuilder {
reb.ctx = ctx
return reb
}
func (reb *ReadEventBuilder) WithObject(obj client.Object) *ReadEventBuilder {
reb.obj = obj
return reb
}
func (reb *ReadEventBuilder) WithCallback(callback WriteFunc) *ReadEventBuilder {
reb.callback = callback
return reb
}
func (reb *ReadEventBuilder) WithTag(tag types.NamespacedName) *ReadEventBuilder {
reb.tag = tag
return reb
}
func (reb *ReadEventBuilder) Read() error {
err := reb.client.Get(reb.ctx, reb.tag, reb.obj)
if err != nil && reb.callback != nil {
return reb.callback()
}
return err
}
func (reb *ReadEventBuilder) AddToList(list *ReadOperationList) *ReadOperationList {
list.readOperations = append(list.readOperations, reb)
return list
}
func (reb *ReadEventBuilder) Execute() error {
if reb != nil {
return reb.Read()
}
return fmt.Errorf("ReadEventBuilder excute error: %s", "value can't be nil")
}
func (web *WriteEventBuilder) WithCallback(callback WriteFunc) *WriteEventBuilder {
web.callback = callback
return web
}
func (web *WriteEventBuilder) Write() error {
if web.callback == nil {
return nil
}
return web.callback()
}
func (web *WriteEventBuilder) Execute() error {
if web != nil {
return web.Write()
}
return fmt.Errorf("WriteEventBuilder excute error: %s", "value can't be nil")
}
func (web *WriteEventBuilder) AddToList(list *WriteOperationList) *WriteOperationList {
list.writeOperations = append(list.writeOperations, web)
return list
}
type LicenseMonitorRequest struct {
UID string `json:"uid"`
Token string `json:"token"`
}
type LicenseMonitorResponse struct {
Key string `json:"key"`
}
func NewLicenseMonitorRequest(secret corev1.Secret, license issuerv1.License) LicenseMonitorRequest {
if secret.Name != string(ClusterInfoSecretName) || secret.Namespace != string(Namespace) {
return LicenseMonitorRequest{}
}
var lmr LicenseMonitorRequest
lmr.Token = license.Spec.Token
lmr.UID = string(secret.Data["uid"])
return lmr
}
func LicenseCheckOnExternalNetwork(license issuerv1.License, secret corev1.Secret, url string, logger logr.Logger) (map[string]interface{}, bool) {
license.Spec.Key = Key
payload, ok := crypto.IsLicenseValid(license)
mr := NewLicenseMonitorRequest(secret, license)
if !ok {
var resp LicenseMonitorResponse
httpBody, err := CommunicateWithCloud("POST", url, mr)
if err != nil {
logger.Error(err, "failed to communicate with cloud")
return nil, false
}
if !IsSuccessfulStatusCode(httpBody.StatusCode) {
logger.Error(err, http.StatusText(httpBody.StatusCode))
return nil, false
}
err = Convert(httpBody.Body, &resp)
if err != nil {
logger.Error(err, "failed to convert")
return nil, false
}
license.Spec.Key = resp.Key
return crypto.IsLicenseValid(license)
}
return payload, ok
}
func LicenseCheckOnInternalNetwork(license issuerv1.License) (map[string]interface{}, bool) {
license.Spec.Key = Key
return crypto.IsLicenseValid(license)
}
func RechargeByLicense(ctx context.Context, client client.Client, logger logr.Logger, account accountv1.Account, payload map[string]interface{}) error {
if !ContainsFields(payload, "amt") {
return nil
}
amount, err := InterfaceToInt64(payload["amt"])
if err != nil {
return errors.New("amount error type")
}
charge := amount * BaseCount
account.Status.Balance += charge
err = crypto.RechargeBalance(account.Status.EncryptBalance, charge)
if err != nil {
logger.Error(err, "Failed to crypto the account balance")
return err
}
err = client.Status().Update(ctx, &account)
if err != nil {
logger.Error(err, "Recharge Failed, failed to modify the status")
return err
}
return nil
}
func RecordLicense(ctx context.Context, client client.Client, logger logr.Logger, ls issuerv1.License, lsh corev1.ConfigMap) error {
size := int64(0)
for _, value := range lsh.Data {
size += int64(len(value))
}
maxSizeThreshold := resource.MustParse(MaxSizeThresholdStr)
if size >= maxSizeThreshold.Value() {
lsh.Data = make(map[string]string)
}
tmpValue := make(map[string]interface{})
for k, v := range lsh.Data {
tmpValue[k] = v
}
suffix := GetNextMapKeySuffix(tmpValue, "license")
newLicenseKeyName := "license-" + strconv.Itoa(suffix)
if lsh.Data == nil {
lsh.Data = make(map[string]string)
}
lsh.Data[newLicenseKeyName] = ls.Spec.Token
err := client.Update(ctx, &lsh)
if err != nil {
logger.Error(err, "failed to store license")
return err
}
return nil
}
func CheckLicenseExists(configMap *corev1.ConfigMap, license string) bool {
for _, storedLicense := range configMap.Data {
if storedLicense == license {
return true
}
}
return false
}
func GetNextMapKeySuffix(data map[string]interface{}, prefix string) int {
maxSuffix := 0
for key := range data {
var currentSuffix int
_, err := fmt.Sscanf(key, prefix+"-%d", &currentSuffix)
if err == nil && currentSuffix > maxSuffix {
maxSuffix = currentSuffix
}
}
return maxSuffix + 1
}
func ContainsFields(data map[string]interface{}, fields ...string) bool {
for _, field := range fields {
_, ok := data[field]
if !ok {
return false
}
}
return true
}
func InterfaceToInt64(value interface{}) (int64, error) {
switch v := value.(type) {
case int64:
return v, nil
case float64:
return int64(v), nil
default:
return 0, errors.New("cannot convert value of type to int64")
}
}
@@ -22,13 +22,16 @@ import (
"io"
"strconv"
"strings"
"sync"
"time"
"github.com/go-logr/logr"
ntf "github.com/labring/sealos/controllers/common/notification/api/v1"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
cl "sigs.k8s.io/controller-runtime/pkg/client"
)
@@ -39,11 +42,6 @@ const (
AdmPrefix string = "adm-"
)
const (
ToUser Target = "user"
ToAdm Target = "adm"
)
type NotificationManager struct {
TimeLastPull int64
}
@@ -59,6 +57,7 @@ type NotificationPackage struct {
Title Title
From Source
Message Message
Level ntf.Type
}
const (
@@ -90,6 +89,20 @@ func NewNotificationPackage(title Title, from Source, message Message) Notificat
}
}
func NewNotificationPackageWithLevel(title Title, from Source, message Message, level ntf.Type) NotificationPackage {
id, err := randStringBytes(idLength)
if err != nil || id == "" {
id = strings.ToLower(strconv.Itoa(int(time.Now().Unix())))
}
return NotificationPackage{
Name: id,
Title: title,
From: from,
Message: message,
Level: level,
}
}
type NotificationTask struct {
ctx context.Context
client cl.Client
@@ -113,6 +126,7 @@ func NotificationPackageToNotification(pack NotificationPackage) ntf.Notificatio
notification.Spec.From = string(pack.From)
notification.Spec.Message = string(pack.Message)
notification.Spec.Title = string(pack.Title)
notification.Spec.Importance = pack.Level
return notification
}
@@ -121,15 +135,13 @@ func (nt *NotificationTask) Run() error {
data.Namespace = nt.Target
var tmp ntf.Notification
err := nt.client.Get(nt.ctx, types.NamespacedName{Namespace: data.Namespace, Name: data.Name}, &tmp)
if err == nil {
continue
} else if apierrors.IsNotFound(err) {
err := nt.client.Create(nt.ctx, &data)
if err == nil {
continue
if err != nil && apierrors.IsNotFound(err) {
if err = nt.client.Create(nt.ctx, &data); err != nil {
return err
}
return err
} else {
continue
}
if err != nil {
return err
}
}
@@ -218,3 +230,52 @@ func (uc *UserCategory) GetNameSpace(ctx context.Context, client cl.Client) erro
}
return nil
}
var noticeLogger logr.Logger
func init() {
noticeLogger = ctrl.Log.WithName("SubNotification")
}
// SubmitNotificationWithUserCategory is a function that submits a notification to a group of users specified by a category.
// It creates a new goroutine for each user in the category to concurrently send notifications.
// It will log any errors occurred during the process.
func SubmitNotificationWithUserCategory(ctx context.Context, client cl.Client, users UserCategory, prefix string, pack NotificationPackage) {
notification := NotificationPackageToNotification(pack)
var wg sync.WaitGroup
errchan := make(chan error)
for ns := range users[prefix].Iter() {
wg.Add(1)
notificationTask := NewNotificationTask(ctx, client, ns, []ntf.Notification{notification})
go AsyncCloudTask(&wg, errchan, &notificationTask)
}
go func() {
wg.Wait()
close(errchan)
}()
for err := range errchan {
if err != nil {
noticeLogger.Error(err, "Failed to deliver notification success.")
}
}
}
// SubmitNotificationWithUser is a function that submits a notification to a single user.
// It creates a new goroutine to send the notification and logs any errors occurred during the process.
func SubmitNotificationWithUser(ctx context.Context, client cl.Client, target string, pack NotificationPackage) {
notification := NotificationPackageToNotification(pack)
notificationTask := NewNotificationTask(ctx, client, target, []ntf.Notification{notification})
var wg sync.WaitGroup
errchan := make(chan error)
wg.Add(1)
go AsyncCloudTask(&wg, errchan, &notificationTask)
go func() {
wg.Wait()
close(errchan)
}()
for err := range errchan {
if err != nil {
noticeLogger.Error(err, "Failed to deliver notification success")
}
}
}
+2 -1
View File
@@ -30,7 +30,7 @@ import (
"strconv"
jwt "github.com/golang-jwt/jwt/v4"
v1 "github.com/labring/sealos/controllers/cloud/api/v1"
v1 "github.com/labring/sealos/controllers/licenseissuer/api/v1"
)
var encryptionKey = []byte("0123456789ABCDEF0123456789ABCDEF")
@@ -159,6 +159,7 @@ func IsLicenseValid(license v1.License) (map[string]interface{}, bool) {
return nil, false
}
publicKey, err := parseRSAPublicKeyFromPEM(string(decodeKey))
//fmt.Println(string(decodeKey))
if err != nil {
return nil, false
}
+19 -50
View File
@@ -1,61 +1,30 @@
package crypto
import (
"fmt"
"testing"
"time"
v1 "github.com/labring/sealos/controllers/licenseissuer/api/v1"
)
func TestRechargeBalance(t *testing.T) {
rawInt := int64(100_000_000)
addInt := int64(200_000_000)
expectedInt := int64(300_000_000)
const Token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJTZWFsb3MiLCJpYXQiOjE2ODkxNDYyOTAsImFtdCI6NTAwMCwibm9kIjoxLCJ0dGUiOjMwfQ.lj1IYb_6vvWfYiLhm3DRpjAu4E3SsjWR9TA09ynB09HXx5Qa3FNXSE-kmpccjhn-lZd0miDwAEVxLDLNhFCGnrqMsSCAlwIK_ymoCSlNFntYAIMRU-uF6eu6JMc44Ol6eR2MlOdklYsfj0lxEwEG55uTIZGfMcHjJapGr4J0ONsloMYGn-eqEjLv3gXzNc5IsNWkRzDyLnK1IbuQo7pXo3yGcR7TQZn5cvOm03xU-jvCaYrl-MDhTbRnJ2XPTqgrtQxgspjApk6gvWKIfZTLY78e4QHFMiv36cdHXLvvvXO5eC8ImVenrjbNeHofP9_OsqbrVaiydc9aj3tHWbqYSQ"
const Key = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFvbFBTSzB0UjFKeDZtb25lL2ppeApSWGN6UGlxcU5SSXRmdW1mdWNyNGMxc2dqdlJha0NwcWtDU21lMTR1akJkU0x6QlZzRjkvUWl0UnFNb2NvaEN1CkJ6R25EQ29hWnZXbWVHeE96NEZSejVTeUg1QTlDa3dnbUEzYnFnMWxKSEZTMlZyVjVHVFhFWnphZTZtRmhHOVcKenJMTnpZMlptYTMzOVE1WTNJSDZ6RXIrcTRQbTZDOXBHVGpsSnVodlRvb0dSY2w0bmpZRXc2eHB6ZHZrdi9uSApmZmxsWGZVNDNyRGdQaGkwZDRjWnNuTUJlazUxQkNiRFRuSHlNVFdGT1RoTjc1VVM0bzJxRm9JSEhsM0N0RzE4ClZIZEdRSE1IR0dYcGN3bVhhck1EQndwVWFOSk9kMkhjTTB5dlZEY2xDZzRITkIwVUFWeFNweFlRV3BwNWJzN2gKbHdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg=="
account := createEncryptedAccount(t, rawInt)
rechargeAccount(t, account, addInt)
validateAccount(t, account, expectedInt, "recharge balance failed")
}
func TestDeductBalance(t *testing.T) {
rawInt := int64(300_000_000)
deductInt := int64(200_000_000)
expectedInt := int64(100_000_000)
account := createEncryptedAccount(t, rawInt)
deductAccount(t, account, deductInt)
validateAccount(t, account, expectedInt, "deduct balance failed")
}
func createEncryptedAccount(t *testing.T, rawInt int64) *string {
account, err := EncryptInt64(rawInt)
if err != nil {
t.Fatal(err)
func TestIsLicenseValid(t *testing.T) {
fakePublicKey := Key
fakeLicense := v1.License{
Spec: v1.LicenseSpec{
Key: fakePublicKey,
Token: Token,
},
}
return account
}
fmt.Println(time.Now().Unix())
claims, valid := IsLicenseValid(fakeLicense)
func rechargeAccount(t *testing.T, account *string, amount int64) {
err := RechargeBalance(account, amount)
if err != nil {
t.Fatal(err)
}
}
func deductAccount(t *testing.T, account *string, amount int64) {
err := DeductBalance(account, amount)
if err != nil {
t.Fatal(err)
}
}
func validateAccount(t *testing.T, account *string, expectedInt int64, errMsg string) {
decryptedInt, err := DecryptInt64(*account)
if err != nil {
t.Fatal(err)
}
if decryptedInt != expectedInt {
t.Fatalf("%s: expected %d, got %d", errMsg, expectedInt, decryptedInt)
if valid {
t.Logf("content after decoding: %v\n", claims)
} else {
t.Error("decoded error")
}
}
+2 -2
View File
@@ -27,8 +27,8 @@ require (
github.com/labring/image-cri-shim v0.0.0
github.com/labring/lvscare v0.0.0
github.com/labring/sealos/controllers/account v0.0.0
github.com/labring/sealos/controllers/cloud v0.0.0-00010101000000-000000000000
github.com/labring/sealos/controllers/imagehub v0.0.0
github.com/labring/sealos/controllers/licenseissuer v0.0.0
github.com/manifoldco/promptui v0.9.0
github.com/modood/table v0.0.0-20220527013332-8d47e76dad33
github.com/onsi/ginkgo v1.16.5
@@ -302,7 +302,7 @@ replace (
github.com/labring/lvscare => ./staging/src/github.com/labring/lvscare
github.com/labring/sealos => ./
github.com/labring/sealos/controllers/account => ./controllers/account
github.com/labring/sealos/controllers/cloud => ./controllers/cloud
github.com/labring/sealos/controllers/imagehub => ./controllers/imagehub
github.com/labring/sealos/controllers/licenseissuer => ./controllers/licenseissuer
github.com/labring/sealos/controllers/user => ./controllers/user
)
+1 -2
View File
@@ -11,7 +11,6 @@ use (
./controllers/infra
./controllers/metering
./controllers/terminal
./controllers/cloud
./controllers/user
./controllers/resources
./service/auth
@@ -22,5 +21,5 @@ use (
./webhooks/whitelist
./controllers/common
./test/e2e
./controllers/licenseissuer
)
+199 -288
View File
File diff suppressed because it is too large Load Diff