Upgrade clusterprofile API (#1316)

Signed-off-by: Jian Qiu <jqiu@redhat.com>
This commit is contained in:
Jian Qiu
2026-01-07 16:56:35 +08:00
committed by GitHub
parent 81eb7f54e6
commit 46de05b285
30 changed files with 751 additions and 682 deletions

10
go.mod
View File

@@ -43,7 +43,7 @@ require (
open-cluster-management.io/api v1.1.1-0.20251222023835-510285203ee6
open-cluster-management.io/sdk-go v1.1.1-0.20251218093423-de3e6c682fd0
sigs.k8s.io/about-api v0.0.0-20250131010323-518069c31c03
sigs.k8s.io/cluster-inventory-api v0.0.0-20240730014211-ef0154379848
sigs.k8s.io/cluster-inventory-api v0.0.0-20251124125836-445319b6307a
sigs.k8s.io/controller-runtime v0.22.4
sigs.k8s.io/kube-storage-version-migrator v0.0.6-0.20230721195810-5c8923c5ff96
sigs.k8s.io/yaml v1.6.0
@@ -96,9 +96,9 @@ require (
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.3.0 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-openapi/jsonpointer v0.21.1 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.1 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
@@ -121,7 +121,7 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect

25
go.sum
View File

@@ -95,7 +95,6 @@ github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03V
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE=
github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -153,14 +152,12 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
@@ -257,18 +254,16 @@ github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zt
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/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.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
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/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo=
github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg=
github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE=
@@ -598,8 +593,8 @@ sigs.k8s.io/about-api v0.0.0-20250131010323-518069c31c03 h1:1ShFiMjGQOR/8jTBkmZr
sigs.k8s.io/about-api v0.0.0-20250131010323-518069c31c03/go.mod h1:F1pT4mK53U6F16/zuaPSYpBaR7x5Kjym6aKJJC0/DHU=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
sigs.k8s.io/cluster-inventory-api v0.0.0-20240730014211-ef0154379848 h1:WYPi2PdQyZwZkHG648v2jQl6deyCgyjJ0fkLYgUJ618=
sigs.k8s.io/cluster-inventory-api v0.0.0-20240730014211-ef0154379848/go.mod h1:/aN4e7RWOMHgT4xAjCNkV4YFcpKfpZCeumMIL7S+KNM=
sigs.k8s.io/cluster-inventory-api v0.0.0-20251124125836-445319b6307a h1:EFfnrAOUotV1XAfTavkqdH8jEnMMRFJe7Nt/znItVGA=
sigs.k8s.io/cluster-inventory-api v0.0.0-20251124125836-445319b6307a/go.mod h1:guwenlZ9iIfYlNxn7ExCfugOLTh6wjjRX3adC36YCmQ=
sigs.k8s.io/controller-runtime v0.22.4 h1:GEjV7KV3TY8e+tJ2LCTxUTanW4z/FmNB7l327UfMq9A=
sigs.k8s.io/controller-runtime v0.22.4/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=

View File

@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.14.0
controller-gen.kubebuilder.io/version: v0.17.3
name: clusterprofiles.multicluster.x-k8s.io
spec:
group: multicluster.x-k8s.io
@@ -62,20 +62,98 @@ spec:
status:
description: ClusterProfileStatus defines the observed state of ClusterProfile.
properties:
accessProviders:
description: |-
AccessProviders is a list of cluster access providers that can provide access
information for clusters.
items:
description: |-
AccessProvider defines how to access the cluster.
It contains the name of the provider name and the cluster connection details.
The name is used to identify different access info types, such as "kubeconfig" or "oidc".
The Cluster field contains the actual cluster connection details, such as server address,
certificate authority data, and authentication information.
properties:
cluster:
description: Cluster contains information about how to communicate
with a kubernetes cluster
properties:
certificate-authority:
description: CertificateAuthority is the path to a cert
file for the certificate authority.
type: string
certificate-authority-data:
description: CertificateAuthorityData contains PEM-encoded
certificate authority certificates. Overrides CertificateAuthority
format: byte
type: string
disable-compression:
description: |-
DisableCompression allows client to opt-out of response compression for all requests to the server. This is useful
to speed up requests (specifically lists) when client-server network bandwidth is ample, by saving time on
compression (server-side) and decompression (client-side): https://github.com/kubernetes/kubernetes/issues/112296.
type: boolean
extensions:
description: Extensions holds additional information. This
is useful for extenders so that reads and writes don't
clobber unknown fields
items:
description: NamedExtension relates nicknames to extension
information
properties:
extension:
description: Extension holds the extension information
type: object
x-kubernetes-preserve-unknown-fields: true
name:
description: Name is the nickname for this Extension
type: string
required:
- extension
- name
type: object
type: array
insecure-skip-tls-verify:
description: InsecureSkipTLSVerify skips the validity check
for the server's certificate. This will make your HTTPS
connections insecure.
type: boolean
proxy-url:
description: |-
ProxyURL is the URL to the proxy to be used for all requests made by this
client. URLs with "http", "https", and "socks5" schemes are supported. If
this configuration is not provided or the empty string, the client
attempts to construct a proxy configuration from http_proxy and
https_proxy environment variables. If these environment variables are not
set, the client does not attempt to proxy requests.
socks5 proxying does not currently support spdy streaming endpoints (exec,
attach, port forward).
type: string
server:
description: Server is the address of the kubernetes cluster
(https://hostname:port).
type: string
tls-server-name:
description: TLSServerName is used to check server certificate.
If TLSServerName is empty, the hostname used to contact
the server is used.
type: string
required:
- server
type: object
name:
type: string
required:
- name
type: object
type: array
conditions:
description: Conditions contains the different condition statuses
for this cluster.
items:
description: "Condition contains details for one aspect of the current
state of this API Resource.\n---\nThis struct is intended for
direct use as an array at the field path .status.conditions. For
example,\n\n\n\ttype FooStatus struct{\n\t // Represents the
observations of a foo's current state.\n\t // Known .status.conditions.type
are: \"Available\", \"Progressing\", and \"Degraded\"\n\t //
+patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t
\ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\"
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
\ // other fields\n\t}"
description: Condition contains details for one aspect of the current
state of this API Resource.
properties:
lastTransitionTime:
description: |-
@@ -116,12 +194,7 @@ spec:
- Unknown
type: string
type:
description: |-
type of condition in CamelCase or in foo.example.com/CamelCase.
---
Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
useful (see .node.status.conditions), the ability to deconflict is important.
The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
description: type of condition in CamelCase or in foo.example.com/CamelCase.
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
@@ -133,24 +206,115 @@ spec:
- type
type: object
type: array
properties:
credentialProviders:
description: |-
Properties defines name/value pairs to represent properties of a cluster.
It could be a collection of ClusterProperty (KEP-2149) resources,
but could also be info based on other implementations.
The names of the properties can be predefined names from ClusterProperty resources
and is allowed to be customized by different cluster managers.
CredentialProviders is a list of cluster access providers that can provide access
information for clusters.
Deprecated: Use AccessProviders instead. If both AccessProviders and CredentialProviders are provided, both are used. In case they specify a provider with the same name, the one in AccessProviders is preferred.
items:
description: |-
Property defines a name/value pair to represent a property of a cluster.
It could be a ClusterProperty (KEP-2149) resource,
but could also be info based on other implementations.
The name of the property can be predefined name from a ClusterProperty resource
and is allowed to be customized by different cluster managers.
This property can store various configurable details and metrics of a cluster,
which may include information such as the number of nodes, total and free CPU,
and total and free memory, among other potential attributes.
AccessProvider defines how to access the cluster.
It contains the name of the provider name and the cluster connection details.
The name is used to identify different access info types, such as "kubeconfig" or "oidc".
The Cluster field contains the actual cluster connection details, such as server address,
certificate authority data, and authentication information.
properties:
cluster:
description: Cluster contains information about how to communicate
with a kubernetes cluster
properties:
certificate-authority:
description: CertificateAuthority is the path to a cert
file for the certificate authority.
type: string
certificate-authority-data:
description: CertificateAuthorityData contains PEM-encoded
certificate authority certificates. Overrides CertificateAuthority
format: byte
type: string
disable-compression:
description: |-
DisableCompression allows client to opt-out of response compression for all requests to the server. This is useful
to speed up requests (specifically lists) when client-server network bandwidth is ample, by saving time on
compression (server-side) and decompression (client-side): https://github.com/kubernetes/kubernetes/issues/112296.
type: boolean
extensions:
description: Extensions holds additional information. This
is useful for extenders so that reads and writes don't
clobber unknown fields
items:
description: NamedExtension relates nicknames to extension
information
properties:
extension:
description: Extension holds the extension information
type: object
x-kubernetes-preserve-unknown-fields: true
name:
description: Name is the nickname for this Extension
type: string
required:
- extension
- name
type: object
type: array
insecure-skip-tls-verify:
description: InsecureSkipTLSVerify skips the validity check
for the server's certificate. This will make your HTTPS
connections insecure.
type: boolean
proxy-url:
description: |-
ProxyURL is the URL to the proxy to be used for all requests made by this
client. URLs with "http", "https", and "socks5" schemes are supported. If
this configuration is not provided or the empty string, the client
attempts to construct a proxy configuration from http_proxy and
https_proxy environment variables. If these environment variables are not
set, the client does not attempt to proxy requests.
socks5 proxying does not currently support spdy streaming endpoints (exec,
attach, port forward).
type: string
server:
description: Server is the address of the kubernetes cluster
(https://hostname:port).
type: string
tls-server-name:
description: TLSServerName is used to check server certificate.
If TLSServerName is empty, the hostname used to contact
the server is used.
type: string
required:
- server
type: object
name:
type: string
required:
- name
type: object
type: array
properties:
description: |-
Properties defines cluster characteristics through a list of Property objects.
Each Property can be one of:
1. A ClusterProperty resource (as defined in KEP-2149)
2. Custom information from cluster manager implementations
Property names support both:
- Standard names from ClusterProperty resources
- Custom names defined by cluster managers
items:
description: |-
Property defines the data structure to represent a property of a cluster.
It contains a name/value pair and the last observed time of the property on the cluster.
This property can store various configurable details and metrics of a cluster,
which may include information such as the entry point of the cluster, types of nodes, location, etc. according to KEP 4322.
properties:
lastObservedTime:
description: |-
LastObservedTime is the last time the property was observed on the corresponding cluster.
The value is the timestamp when the property was observed not the time when the property was updated in the cluster-profile.
format: date-time
type: string
name:
description: |-
Name is the name of a property resource on cluster. It's a well-known

View File

@@ -1,12 +1,6 @@
linters-settings:
govet:
check-shadowing: true
golint:
min-confidence: 0
gocyclo:
min-complexity: 45
maligned:
suggest-new: true
dupl:
threshold: 200
goconst:
@@ -16,7 +10,7 @@ linters-settings:
linters:
enable-all: true
disable:
- maligned
- recvcheck
- unparam
- lll
- gochecknoinits
@@ -29,9 +23,6 @@ linters:
- wrapcheck
- testpackage
- nlreturn
- gomnd
- exhaustivestruct
- goerr113
- errorlint
- nestif
- godot
@@ -39,7 +30,6 @@ linters:
- paralleltest
- tparallel
- thelper
- ifshort
- exhaustruct
- varnamelen
- gci
@@ -52,10 +42,15 @@ linters:
- forcetypeassert
- cyclop
# deprecated linters
- deadcode
- interfacer
- scopelint
- varcheck
- structcheck
- golint
- nosnakecase
#- deadcode
#- interfacer
#- scopelint
#- varcheck
#- structcheck
#- golint
#- nosnakecase
#- maligned
#- goerr113
#- ifshort
#- gomnd
#- exhaustivestruct

18
vendor/github.com/go-openapi/jsonpointer/errors.go generated vendored Normal file
View File

@@ -0,0 +1,18 @@
package jsonpointer
type pointerError string
func (e pointerError) Error() string {
return string(e)
}
const (
// ErrPointer is an error raised by the jsonpointer package
ErrPointer pointerError = "JSON pointer error"
// ErrInvalidStart states that a JSON pointer must start with a separator ("/")
ErrInvalidStart pointerError = `JSON pointer must be empty or start with a "` + pointerSeparator
// ErrUnsupportedValueType indicates that a value of the wrong type is being set
ErrUnsupportedValueType pointerError = "only structs, pointers, maps and slices are supported for setting values"
)

View File

@@ -39,9 +39,6 @@ import (
const (
emptyPointer = ``
pointerSeparator = `/`
invalidStart = `JSON pointer must be empty or start with a "` + pointerSeparator
notFound = `Can't find the pointer in the document`
)
var jsonPointableType = reflect.TypeOf(new(JSONPointable)).Elem()
@@ -80,7 +77,7 @@ func (p *Pointer) parse(jsonPointerString string) error {
if jsonPointerString != emptyPointer {
if !strings.HasPrefix(jsonPointerString, pointerSeparator) {
err = errors.New(invalidStart)
err = errors.Join(ErrInvalidStart, ErrPointer)
} else {
referenceTokens := strings.Split(jsonPointerString, pointerSeparator)
p.referenceTokens = append(p.referenceTokens, referenceTokens[1:]...)
@@ -128,7 +125,7 @@ func getSingleImpl(node any, decodedToken string, nameProvider *swag.NameProvide
rValue := reflect.Indirect(reflect.ValueOf(node))
kind := rValue.Kind()
if isNil(node) {
return nil, kind, fmt.Errorf("nil value has not field %q", decodedToken)
return nil, kind, fmt.Errorf("nil value has no field %q: %w", decodedToken, ErrPointer)
}
switch typed := node.(type) {
@@ -146,7 +143,7 @@ func getSingleImpl(node any, decodedToken string, nameProvider *swag.NameProvide
case reflect.Struct:
nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
if !ok {
return nil, kind, fmt.Errorf("object has no field %q", decodedToken)
return nil, kind, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer)
}
fld := rValue.FieldByName(nm)
return fld.Interface(), kind, nil
@@ -158,7 +155,7 @@ func getSingleImpl(node any, decodedToken string, nameProvider *swag.NameProvide
if mv.IsValid() {
return mv.Interface(), kind, nil
}
return nil, kind, fmt.Errorf("object has no key %q", decodedToken)
return nil, kind, fmt.Errorf("object has no key %q: %w", decodedToken, ErrPointer)
case reflect.Slice:
tokenIndex, err := strconv.Atoi(decodedToken)
@@ -167,14 +164,14 @@ func getSingleImpl(node any, decodedToken string, nameProvider *swag.NameProvide
}
sLength := rValue.Len()
if tokenIndex < 0 || tokenIndex >= sLength {
return nil, kind, fmt.Errorf("index out of bounds array[0,%d] index '%d'", sLength-1, tokenIndex)
return nil, kind, fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", sLength-1, tokenIndex, ErrPointer)
}
elem := rValue.Index(tokenIndex)
return elem.Interface(), kind, nil
default:
return nil, kind, fmt.Errorf("invalid token reference %q", decodedToken)
return nil, kind, fmt.Errorf("invalid token reference %q: %w", decodedToken, ErrPointer)
}
}
@@ -194,7 +191,7 @@ func setSingleImpl(node, data any, decodedToken string, nameProvider *swag.NameP
case reflect.Struct:
nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
if !ok {
return fmt.Errorf("object has no field %q", decodedToken)
return fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer)
}
fld := rValue.FieldByName(nm)
if fld.IsValid() {
@@ -214,18 +211,18 @@ func setSingleImpl(node, data any, decodedToken string, nameProvider *swag.NameP
}
sLength := rValue.Len()
if tokenIndex < 0 || tokenIndex >= sLength {
return fmt.Errorf("index out of bounds array[0,%d] index '%d'", sLength, tokenIndex)
return fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", sLength, tokenIndex, ErrPointer)
}
elem := rValue.Index(tokenIndex)
if !elem.CanSet() {
return fmt.Errorf("can't set slice index %s to %v", decodedToken, data)
return fmt.Errorf("can't set slice index %s to %v: %w", decodedToken, data, ErrPointer)
}
elem.Set(reflect.ValueOf(data))
return nil
default:
return fmt.Errorf("invalid token reference %q", decodedToken)
return fmt.Errorf("invalid token reference %q: %w", decodedToken, ErrPointer)
}
}
@@ -244,7 +241,6 @@ func (p *Pointer) get(node any, nameProvider *swag.NameProvider) (any, reflect.K
}
for _, token := range p.referenceTokens {
decodedToken := Unescape(token)
r, knd, err := getSingleImpl(node, decodedToken, nameProvider)
@@ -264,7 +260,10 @@ func (p *Pointer) set(node, data any, nameProvider *swag.NameProvider) error {
knd := reflect.ValueOf(node).Kind()
if knd != reflect.Ptr && knd != reflect.Struct && knd != reflect.Map && knd != reflect.Slice && knd != reflect.Array {
return errors.New("only structs, pointers, maps and slices are supported for setting values")
return errors.Join(
ErrUnsupportedValueType,
ErrPointer,
)
}
if nameProvider == nil {
@@ -307,7 +306,7 @@ func (p *Pointer) set(node, data any, nameProvider *swag.NameProvider) error {
case reflect.Struct:
nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken)
if !ok {
return fmt.Errorf("object has no field %q", decodedToken)
return fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer)
}
fld := rValue.FieldByName(nm)
if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Ptr {
@@ -321,7 +320,7 @@ func (p *Pointer) set(node, data any, nameProvider *swag.NameProvider) error {
mv := rValue.MapIndex(kv)
if !mv.IsValid() {
return fmt.Errorf("object has no key %q", decodedToken)
return fmt.Errorf("object has no key %q: %w", decodedToken, ErrPointer)
}
if mv.CanAddr() && mv.Kind() != reflect.Interface && mv.Kind() != reflect.Map && mv.Kind() != reflect.Slice && mv.Kind() != reflect.Ptr {
node = mv.Addr().Interface()
@@ -336,7 +335,7 @@ func (p *Pointer) set(node, data any, nameProvider *swag.NameProvider) error {
}
sLength := rValue.Len()
if tokenIndex < 0 || tokenIndex >= sLength {
return fmt.Errorf("index out of bounds array[0,%d] index '%d'", sLength, tokenIndex)
return fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", sLength, tokenIndex, ErrPointer)
}
elem := rValue.Index(tokenIndex)
@@ -347,7 +346,7 @@ func (p *Pointer) set(node, data any, nameProvider *swag.NameProvider) error {
node = elem.Interface()
default:
return fmt.Errorf("invalid token reference %q", decodedToken)
return fmt.Errorf("invalid token reference %q: %w", decodedToken, ErrPointer)
}
}
@@ -404,10 +403,10 @@ func (p *Pointer) Offset(document string) (int64, error) {
return 0, err
}
default:
return 0, fmt.Errorf("invalid token %#v", tk)
return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer)
}
default:
return 0, fmt.Errorf("invalid token %#v", tk)
return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer)
}
}
return offset, nil
@@ -437,16 +436,16 @@ func offsetSingleObject(dec *json.Decoder, decodedToken string) (int64, error) {
return offset, nil
}
default:
return 0, fmt.Errorf("invalid token %#v", tk)
return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer)
}
}
return 0, fmt.Errorf("token reference %q not found", decodedToken)
return 0, fmt.Errorf("token reference %q not found: %w", decodedToken, ErrPointer)
}
func offsetSingleArray(dec *json.Decoder, decodedToken string) (int64, error) {
idx, err := strconv.Atoi(decodedToken)
if err != nil {
return 0, fmt.Errorf("token reference %q is not a number: %v", decodedToken, err)
return 0, fmt.Errorf("token reference %q is not a number: %v: %w", decodedToken, err, ErrPointer)
}
var i int
for i = 0; i < idx && dec.More(); i++ {
@@ -470,7 +469,7 @@ func offsetSingleArray(dec *json.Decoder, decodedToken string) (int64, error) {
}
if !dec.More() {
return 0, fmt.Errorf("token reference %q not found", decodedToken)
return 0, fmt.Errorf("token reference %q not found: %w", decodedToken, ErrPointer)
}
return dec.InputOffset(), nil
}

View File

@@ -1,50 +1,61 @@
linters-settings:
govet:
check-shadowing: true
golint:
min-confidence: 0
gocyclo:
min-complexity: 30
min-complexity: 45
maligned:
suggest-new: true
dupl:
threshold: 100
threshold: 200
goconst:
min-len: 2
min-occurrences: 4
paralleltest:
ignore-missing: true
min-occurrences: 3
linters:
enable-all: true
disable:
- maligned
- unparam
- lll
- gochecknoinits
- gochecknoglobals
- funlen
- godox
- gocognit
- whitespace
- wsl
- funlen
- gochecknoglobals
- gochecknoinits
- scopelint
- wrapcheck
- exhaustivestruct
- exhaustive
- nlreturn
- testpackage
- gci
- gofumpt
- goerr113
- nlreturn
- gomnd
- tparallel
- exhaustivestruct
- goerr113
- errorlint
- nestif
- godot
- errorlint
- varcheck
- interfacer
- deadcode
- golint
- gofumpt
- paralleltest
- tparallel
- thelper
- ifshort
- structcheck
- nosnakecase
- varnamelen
- exhaustruct
- varnamelen
- gci
- depguard
- errchkjson
- inamedparam
- nonamedreturns
- musttag
- ireturn
- forcetypeassert
- cyclop
# deprecated linters
- deadcode
- interfacer
- scopelint
- varcheck
- structcheck
- golint
- nosnakecase

View File

@@ -1,15 +1,19 @@
# gojsonreference [![Build Status](https://travis-ci.org/go-openapi/jsonreference.svg?branch=master)](https://travis-ci.org/go-openapi/jsonreference) [![codecov](https://codecov.io/gh/go-openapi/jsonreference/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/jsonreference) [![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
# gojsonreference [![Build Status](https://github.com/go-openapi/jsonreference/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/jsonreference/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/jsonreference/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/jsonreference)
[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io)
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/jsonreference/master/LICENSE)
[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/jsonreference.svg)](https://pkg.go.dev/github.com/go-openapi/jsonreference)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/jsonreference)](https://goreportcard.com/report/github.com/go-openapi/jsonreference)
[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/jsonreference/master/LICENSE) [![GoDoc](https://godoc.org/github.com/go-openapi/jsonreference?status.svg)](http://godoc.org/github.com/go-openapi/jsonreference)
An implementation of JSON Reference - Go language
## Status
Feature complete. Stable API
## Dependencies
https://github.com/go-openapi/jsonpointer
* https://github.com/go-openapi/jsonpointer
## References
http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03
* http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
* http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03

View File

@@ -1,22 +1,17 @@
linters-settings:
govet:
check-shadowing: true
golint:
min-confidence: 0
gocyclo:
min-complexity: 45
maligned:
suggest-new: true
dupl:
threshold: 200
goconst:
min-len: 3
min-len: 2
min-occurrences: 3
linters:
enable-all: true
disable:
- maligned
- recvcheck
- unparam
- lll
- gochecknoinits
- gochecknoglobals
@@ -28,9 +23,6 @@ linters:
- wrapcheck
- testpackage
- nlreturn
- gomnd
- exhaustivestruct
- goerr113
- errorlint
- nestif
- godot
@@ -38,7 +30,6 @@ linters:
- paralleltest
- tparallel
- thelper
- ifshort
- exhaustruct
- varnamelen
- gci
@@ -51,10 +42,15 @@ linters:
- forcetypeassert
- cyclop
# deprecated linters
- deadcode
- interfacer
- scopelint
- varcheck
- structcheck
- golint
- nosnakecase
#- deadcode
#- interfacer
#- scopelint
#- varcheck
#- structcheck
#- golint
#- nosnakecase
#- maligned
#- goerr113
#- ifshort
#- gomnd
#- exhaustivestruct

15
vendor/github.com/go-openapi/swag/errors.go generated vendored Normal file
View File

@@ -0,0 +1,15 @@
package swag
type swagError string
const (
// ErrYAML is an error raised by YAML utilities
ErrYAML swagError = "yaml error"
// ErrLoader is an error raised by the file loader utility
ErrLoader swagError = "loader error"
)
func (e swagError) Error() string {
return string(e)
}

View File

@@ -126,7 +126,8 @@ func ConcatJSON(blobs ...[]byte) []byte {
continue // don't know how to concatenate non container objects
}
if len(b) < 3 { // yep empty but also the last one, so closing this thing
const minLengthIfNotEmpty = 3
if len(b) < minLengthIfNotEmpty { // yep empty but also the last one, so closing this thing
if i == last && a > 0 {
if err := buf.WriteByte(closing); err != nil {
log.Println(err)

View File

@@ -168,7 +168,7 @@ func loadHTTPBytes(timeout time.Duration) func(path string) ([]byte, error) {
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("could not access document at %q [%s] ", path, resp.Status)
return nil, fmt.Errorf("could not access document at %q [%s]: %w", path, resp.Status, ErrLoader)
}
return io.ReadAll(resp.Body)

View File

@@ -16,7 +16,6 @@ package swag
import (
"encoding/json"
"errors"
"fmt"
"path/filepath"
"reflect"
@@ -51,7 +50,7 @@ func BytesToYAMLDoc(data []byte) (interface{}, error) {
return nil, err
}
if document.Kind != yaml.DocumentNode || len(document.Content) != 1 || document.Content[0].Kind != yaml.MappingNode {
return nil, errors.New("only YAML documents that are objects are supported")
return nil, fmt.Errorf("only YAML documents that are objects are supported: %w", ErrYAML)
}
return &document, nil
}
@@ -69,31 +68,32 @@ func yamlNode(root *yaml.Node) (interface{}, error) {
case yaml.AliasNode:
return yamlNode(root.Alias)
default:
return nil, fmt.Errorf("unsupported YAML node type: %v", root.Kind)
return nil, fmt.Errorf("unsupported YAML node type: %v: %w", root.Kind, ErrYAML)
}
}
func yamlDocument(node *yaml.Node) (interface{}, error) {
if len(node.Content) != 1 {
return nil, fmt.Errorf("unexpected YAML Document node content length: %d", len(node.Content))
return nil, fmt.Errorf("unexpected YAML Document node content length: %d: %w", len(node.Content), ErrYAML)
}
return yamlNode(node.Content[0])
}
func yamlMapping(node *yaml.Node) (interface{}, error) {
m := make(JSONMapSlice, len(node.Content)/2)
const sensibleAllocDivider = 2
m := make(JSONMapSlice, len(node.Content)/sensibleAllocDivider)
var j int
for i := 0; i < len(node.Content); i += 2 {
var nmi JSONMapItem
k, err := yamlStringScalarC(node.Content[i])
if err != nil {
return nil, fmt.Errorf("unable to decode YAML map key: %w", err)
return nil, fmt.Errorf("unable to decode YAML map key: %w: %w", err, ErrYAML)
}
nmi.Key = k
v, err := yamlNode(node.Content[i+1])
if err != nil {
return nil, fmt.Errorf("unable to process YAML map value for key %q: %w", k, err)
return nil, fmt.Errorf("unable to process YAML map value for key %q: %w: %w", k, err, ErrYAML)
}
nmi.Value = v
m[j] = nmi
@@ -109,7 +109,7 @@ func yamlSequence(node *yaml.Node) (interface{}, error) {
v, err := yamlNode(node.Content[i])
if err != nil {
return nil, fmt.Errorf("unable to decode YAML sequence value: %w", err)
return nil, fmt.Errorf("unable to decode YAML sequence value: %w: %w", err, ErrYAML)
}
s = append(s, v)
}
@@ -132,19 +132,19 @@ func yamlScalar(node *yaml.Node) (interface{}, error) {
case yamlBoolScalar:
b, err := strconv.ParseBool(node.Value)
if err != nil {
return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting bool content: %w", node.Value, err)
return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting bool content: %w: %w", node.Value, err, ErrYAML)
}
return b, nil
case yamlIntScalar:
i, err := strconv.ParseInt(node.Value, 10, 64)
if err != nil {
return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting integer content: %w", node.Value, err)
return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting integer content: %w: %w", node.Value, err, ErrYAML)
}
return i, nil
case yamlFloatScalar:
f, err := strconv.ParseFloat(node.Value, 64)
if err != nil {
return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting float content: %w", node.Value, err)
return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting float content: %w: %w", node.Value, err, ErrYAML)
}
return f, nil
case yamlTimestamp:
@@ -152,19 +152,19 @@ func yamlScalar(node *yaml.Node) (interface{}, error) {
case yamlNull:
return nil, nil //nolint:nilnil
default:
return nil, fmt.Errorf("YAML tag %q is not supported", node.LongTag())
return nil, fmt.Errorf("YAML tag %q is not supported: %w", node.LongTag(), ErrYAML)
}
}
func yamlStringScalarC(node *yaml.Node) (string, error) {
if node.Kind != yaml.ScalarNode {
return "", fmt.Errorf("expecting a string scalar but got %q", node.Kind)
return "", fmt.Errorf("expecting a string scalar but got %q: %w", node.Kind, ErrYAML)
}
switch node.LongTag() {
case yamlStringScalar, yamlIntScalar, yamlFloatScalar:
return node.Value, nil
default:
return "", fmt.Errorf("YAML tag %q is not supported as map key", node.LongTag())
return "", fmt.Errorf("YAML tag %q is not supported as map key: %w", node.LongTag(), ErrYAML)
}
}
@@ -349,7 +349,7 @@ func json2yaml(item interface{}) (*yaml.Node, error) {
Value: strconv.FormatBool(val),
}, nil
default:
return nil, fmt.Errorf("unhandled type: %T", val)
return nil, fmt.Errorf("unhandled type: %T: %w", val, ErrYAML)
}
}
@@ -416,7 +416,7 @@ func transformData(input interface{}) (out interface{}, err error) {
case int64:
return strconv.FormatInt(k, 10), nil
default:
return "", fmt.Errorf("unexpected map key type, got: %T", k)
return "", fmt.Errorf("unexpected map key type, got: %T: %w", k, ErrYAML)
}
}

View File

@@ -8,7 +8,6 @@
package jlexer
import (
"reflect"
"unsafe"
)
@@ -18,7 +17,5 @@ import (
// chunk may be either blocked from being freed by GC because of a single string or the buffer.Data
// may be garbage-collected even when the string exists.
func bytesToStr(data []byte) string {
h := (*reflect.SliceHeader)(unsafe.Pointer(&data))
shdr := reflect.StringHeader{Data: h.Data, Len: h.Len}
return *(*string)(unsafe.Pointer(&shdr))
return *(*string)(unsafe.Pointer(&data))
}

View File

@@ -19,21 +19,21 @@ import (
"github.com/josharian/intern"
)
// tokenKind determines type of a token.
type tokenKind byte
// TokenKind determines type of a token.
type TokenKind byte
const (
tokenUndef tokenKind = iota // No token.
tokenDelim // Delimiter: one of '{', '}', '[' or ']'.
tokenString // A string literal, e.g. "abc\u1234"
tokenNumber // Number literal, e.g. 1.5e5
tokenBool // Boolean literal: true or false.
tokenNull // null keyword.
TokenUndef TokenKind = iota // No token.
TokenDelim // Delimiter: one of '{', '}', '[' or ']'.
TokenString // A string literal, e.g. "abc\u1234"
TokenNumber // Number literal, e.g. 1.5e5
TokenBool // Boolean literal: true or false.
TokenNull // null keyword.
)
// token describes a single token: type, position in the input and value.
type token struct {
kind tokenKind // Type of a token.
kind TokenKind // Type of a token.
boolValue bool // Value if a boolean literal token.
byteValueCloned bool // true if byteValue was allocated and does not refer to original json body
@@ -47,7 +47,7 @@ type Lexer struct {
start int // Start of the current token.
pos int // Current unscanned position in the input stream.
token token // Last scanned token, if token.kind != tokenUndef.
token token // Last scanned token, if token.kind != TokenUndef.
firstElement bool // Whether current element is the first in array or an object.
wantSep byte // A comma or a colon character, which need to occur before a token.
@@ -59,7 +59,7 @@ type Lexer struct {
// FetchToken scans the input for the next token.
func (r *Lexer) FetchToken() {
r.token.kind = tokenUndef
r.token.kind = TokenUndef
r.start = r.pos
// Check if r.Data has r.pos element
@@ -90,7 +90,7 @@ func (r *Lexer) FetchToken() {
r.errSyntax()
}
r.token.kind = tokenString
r.token.kind = TokenString
r.fetchString()
return
@@ -99,7 +99,7 @@ func (r *Lexer) FetchToken() {
r.errSyntax()
}
r.firstElement = true
r.token.kind = tokenDelim
r.token.kind = TokenDelim
r.token.delimValue = r.Data[r.pos]
r.pos++
return
@@ -109,7 +109,7 @@ func (r *Lexer) FetchToken() {
r.errSyntax()
}
r.wantSep = 0
r.token.kind = tokenDelim
r.token.kind = TokenDelim
r.token.delimValue = r.Data[r.pos]
r.pos++
return
@@ -118,7 +118,7 @@ func (r *Lexer) FetchToken() {
if r.wantSep != 0 {
r.errSyntax()
}
r.token.kind = tokenNumber
r.token.kind = TokenNumber
r.fetchNumber()
return
@@ -127,7 +127,7 @@ func (r *Lexer) FetchToken() {
r.errSyntax()
}
r.token.kind = tokenNull
r.token.kind = TokenNull
r.fetchNull()
return
@@ -136,7 +136,7 @@ func (r *Lexer) FetchToken() {
r.errSyntax()
}
r.token.kind = tokenBool
r.token.kind = TokenBool
r.token.boolValue = true
r.fetchTrue()
return
@@ -146,7 +146,7 @@ func (r *Lexer) FetchToken() {
r.errSyntax()
}
r.token.kind = tokenBool
r.token.kind = TokenBool
r.token.boolValue = false
r.fetchFalse()
return
@@ -391,7 +391,7 @@ func (r *Lexer) fetchString() {
// scanToken scans the next token if no token is currently available in the lexer.
func (r *Lexer) scanToken() {
if r.token.kind != tokenUndef || r.fatalError != nil {
if r.token.kind != TokenUndef || r.fatalError != nil {
return
}
@@ -400,7 +400,7 @@ func (r *Lexer) scanToken() {
// consume resets the current token to allow scanning the next one.
func (r *Lexer) consume() {
r.token.kind = tokenUndef
r.token.kind = TokenUndef
r.token.byteValueCloned = false
r.token.delimValue = 0
}
@@ -443,10 +443,10 @@ func (r *Lexer) errInvalidToken(expected string) {
switch expected {
case "[":
r.token.delimValue = ']'
r.token.kind = tokenDelim
r.token.kind = TokenDelim
case "{":
r.token.delimValue = '}'
r.token.kind = tokenDelim
r.token.kind = TokenDelim
}
r.addNonfatalError(&LexerError{
Reason: fmt.Sprintf("expected %s", expected),
@@ -475,7 +475,7 @@ func (r *Lexer) GetPos() int {
// Delim consumes a token and verifies that it is the given delimiter.
func (r *Lexer) Delim(c byte) {
if r.token.kind == tokenUndef && r.Ok() {
if r.token.kind == TokenUndef && r.Ok() {
r.FetchToken()
}
@@ -489,7 +489,7 @@ func (r *Lexer) Delim(c byte) {
// IsDelim returns true if there was no scanning error and next token is the given delimiter.
func (r *Lexer) IsDelim(c byte) bool {
if r.token.kind == tokenUndef && r.Ok() {
if r.token.kind == TokenUndef && r.Ok() {
r.FetchToken()
}
return !r.Ok() || r.token.delimValue == c
@@ -497,10 +497,10 @@ func (r *Lexer) IsDelim(c byte) bool {
// Null verifies that the next token is null and consumes it.
func (r *Lexer) Null() {
if r.token.kind == tokenUndef && r.Ok() {
if r.token.kind == TokenUndef && r.Ok() {
r.FetchToken()
}
if !r.Ok() || r.token.kind != tokenNull {
if !r.Ok() || r.token.kind != TokenNull {
r.errInvalidToken("null")
}
r.consume()
@@ -508,15 +508,15 @@ func (r *Lexer) Null() {
// IsNull returns true if the next token is a null keyword.
func (r *Lexer) IsNull() bool {
if r.token.kind == tokenUndef && r.Ok() {
if r.token.kind == TokenUndef && r.Ok() {
r.FetchToken()
}
return r.Ok() && r.token.kind == tokenNull
return r.Ok() && r.token.kind == TokenNull
}
// Skip skips a single token.
func (r *Lexer) Skip() {
if r.token.kind == tokenUndef && r.Ok() {
if r.token.kind == TokenUndef && r.Ok() {
r.FetchToken()
}
r.consume()
@@ -621,10 +621,10 @@ func (r *Lexer) Consumed() {
}
func (r *Lexer) unsafeString(skipUnescape bool) (string, []byte) {
if r.token.kind == tokenUndef && r.Ok() {
if r.token.kind == TokenUndef && r.Ok() {
r.FetchToken()
}
if !r.Ok() || r.token.kind != tokenString {
if !r.Ok() || r.token.kind != TokenString {
r.errInvalidToken("string")
return "", nil
}
@@ -664,10 +664,10 @@ func (r *Lexer) UnsafeFieldName(skipUnescape bool) string {
// String reads a string literal.
func (r *Lexer) String() string {
if r.token.kind == tokenUndef && r.Ok() {
if r.token.kind == TokenUndef && r.Ok() {
r.FetchToken()
}
if !r.Ok() || r.token.kind != tokenString {
if !r.Ok() || r.token.kind != TokenString {
r.errInvalidToken("string")
return ""
}
@@ -687,10 +687,10 @@ func (r *Lexer) String() string {
// StringIntern reads a string literal, and performs string interning on it.
func (r *Lexer) StringIntern() string {
if r.token.kind == tokenUndef && r.Ok() {
if r.token.kind == TokenUndef && r.Ok() {
r.FetchToken()
}
if !r.Ok() || r.token.kind != tokenString {
if !r.Ok() || r.token.kind != TokenString {
r.errInvalidToken("string")
return ""
}
@@ -705,10 +705,10 @@ func (r *Lexer) StringIntern() string {
// Bytes reads a string literal and base64 decodes it into a byte slice.
func (r *Lexer) Bytes() []byte {
if r.token.kind == tokenUndef && r.Ok() {
if r.token.kind == TokenUndef && r.Ok() {
r.FetchToken()
}
if !r.Ok() || r.token.kind != tokenString {
if !r.Ok() || r.token.kind != TokenString {
r.errInvalidToken("string")
return nil
}
@@ -731,10 +731,10 @@ func (r *Lexer) Bytes() []byte {
// Bool reads a true or false boolean keyword.
func (r *Lexer) Bool() bool {
if r.token.kind == tokenUndef && r.Ok() {
if r.token.kind == TokenUndef && r.Ok() {
r.FetchToken()
}
if !r.Ok() || r.token.kind != tokenBool {
if !r.Ok() || r.token.kind != TokenBool {
r.errInvalidToken("bool")
return false
}
@@ -744,10 +744,10 @@ func (r *Lexer) Bool() bool {
}
func (r *Lexer) number() string {
if r.token.kind == tokenUndef && r.Ok() {
if r.token.kind == TokenUndef && r.Ok() {
r.FetchToken()
}
if !r.Ok() || r.token.kind != tokenNumber {
if !r.Ok() || r.token.kind != TokenNumber {
r.errInvalidToken("number")
return ""
}
@@ -1151,7 +1151,7 @@ func (r *Lexer) GetNonFatalErrors() []*LexerError {
// JsonNumber fetches and json.Number from 'encoding/json' package.
// Both int, float or string, contains them are valid values
func (r *Lexer) JsonNumber() json.Number {
if r.token.kind == tokenUndef && r.Ok() {
if r.token.kind == TokenUndef && r.Ok() {
r.FetchToken()
}
if !r.Ok() {
@@ -1160,11 +1160,11 @@ func (r *Lexer) JsonNumber() json.Number {
}
switch r.token.kind {
case tokenString:
case TokenString:
return json.Number(r.String())
case tokenNumber:
case TokenNumber:
return json.Number(r.Raw())
case tokenNull:
case TokenNull:
r.Null()
return json.Number("")
default:
@@ -1175,7 +1175,7 @@ func (r *Lexer) JsonNumber() json.Number {
// Interface fetches an interface{} analogous to the 'encoding/json' package.
func (r *Lexer) Interface() interface{} {
if r.token.kind == tokenUndef && r.Ok() {
if r.token.kind == TokenUndef && r.Ok() {
r.FetchToken()
}
@@ -1183,13 +1183,13 @@ func (r *Lexer) Interface() interface{} {
return nil
}
switch r.token.kind {
case tokenString:
case TokenString:
return r.String()
case tokenNumber:
case TokenNumber:
return r.Float64()
case tokenBool:
case TokenBool:
return r.Bool()
case tokenNull:
case TokenNull:
r.Null()
return nil
}
@@ -1242,3 +1242,16 @@ func (r *Lexer) WantColon() {
r.wantSep = ':'
r.firstElement = false
}
// CurrentToken returns current token kind if there were no errors and TokenUndef otherwise
func (r *Lexer) CurrentToken() TokenKind {
if r.token.kind == TokenUndef && r.Ok() {
r.FetchToken()
}
if !r.Ok() {
return TokenUndef
}
return r.token.kind
}

View File

@@ -67,6 +67,18 @@ func (w *Writer) RawString(s string) {
w.Buffer.AppendString(s)
}
// RawBytesString appends string from bytes to the buffer.
func (w *Writer) RawBytesString(data []byte, err error) {
switch {
case w.Error != nil:
return
case err != nil:
w.Error = err
default:
w.String(string(data))
}
}
// Raw appends raw binary data to the buffer or sets the error if it is given. Useful for
// calling with results of MarshalJSON-like functions.
func (w *Writer) Raw(data []byte, err error) {

16
vendor/modules.txt vendored
View File

@@ -278,14 +278,14 @@ github.com/go-logr/stdr
# github.com/go-logr/zapr v1.3.0
## explicit; go 1.18
github.com/go-logr/zapr
# github.com/go-openapi/jsonpointer v0.21.0
# github.com/go-openapi/jsonpointer v0.21.1
## explicit; go 1.20
github.com/go-openapi/jsonpointer
# github.com/go-openapi/jsonreference v0.20.2
## explicit; go 1.13
# github.com/go-openapi/jsonreference v0.21.0
## explicit; go 1.20
github.com/go-openapi/jsonreference
github.com/go-openapi/jsonreference/internal
# github.com/go-openapi/swag v0.23.0
# github.com/go-openapi/swag v0.23.1
## explicit; go 1.20
github.com/go-openapi/swag
# github.com/go-task/slim-sprig/v3 v3.0.0
@@ -435,8 +435,8 @@ github.com/json-iterator/go
# github.com/kylelemons/godebug v1.1.0
## explicit; go 1.11
github.com/kylelemons/godebug/diff
# github.com/mailru/easyjson v0.7.7
## explicit; go 1.12
# github.com/mailru/easyjson v0.9.0
## explicit; go 1.20
github.com/mailru/easyjson/buffer
github.com/mailru/easyjson/jlexer
github.com/mailru/easyjson/jwriter
@@ -2045,8 +2045,8 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client
sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/client/metrics
sigs.k8s.io/apiserver-network-proxy/konnectivity-client/pkg/common/metrics
sigs.k8s.io/apiserver-network-proxy/konnectivity-client/proto/client
# sigs.k8s.io/cluster-inventory-api v0.0.0-20240730014211-ef0154379848
## explicit; go 1.22.0
# sigs.k8s.io/cluster-inventory-api v0.0.0-20251124125836-445319b6307a
## explicit; go 1.24.0
sigs.k8s.io/cluster-inventory-api/apis/v1alpha1
sigs.k8s.io/cluster-inventory-api/client/clientset/versioned
sigs.k8s.io/cluster-inventory-api/client/clientset/versioned/fake

View File

@@ -18,6 +18,7 @@ package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clientcmdv1 "k8s.io/client-go/tools/clientcmd/api/v1"
)
// ClusterProfileSpec defines the desired state of ClusterProfile.
@@ -60,15 +61,41 @@ type ClusterProfileStatus struct {
// +optional
Version ClusterVersion `json:"version,omitempty"`
// Properties defines name/value pairs to represent properties of a cluster.
// It could be a collection of ClusterProperty (KEP-2149) resources,
// but could also be info based on other implementations.
// The names of the properties can be predefined names from ClusterProperty resources
// and is allowed to be customized by different cluster managers.
// Properties defines cluster characteristics through a list of Property objects.
// Each Property can be one of:
// 1. A ClusterProperty resource (as defined in KEP-2149)
// 2. Custom information from cluster manager implementations
// Property names support both:
// - Standard names from ClusterProperty resources
// - Custom names defined by cluster managers
// +optional
Properties []Property `json:"properties,omitempty"`
// CredentialProviders is a list of cluster access providers that can provide access
// information for clusters.
// Deprecated: Use AccessProviders instead. If both AccessProviders and CredentialProviders are provided, both are used. In case they specify a provider with the same name, the one in AccessProviders is preferred.
// +optional
// +deprecated
CredentialProviders []CredentialProvider `json:"credentialProviders,omitempty"`
// AccessProviders is a list of cluster access providers that can provide access
// information for clusters.
// +optional
AccessProviders []AccessProvider `json:"accessProviders,omitempty"`
}
// AccessProvider defines how to access the cluster.
// It contains the name of the provider name and the cluster connection details.
// The name is used to identify different access info types, such as "kubeconfig" or "oidc".
// The Cluster field contains the actual cluster connection details, such as server address,
// certificate authority data, and authentication information.
type AccessProvider struct {
Name string `json:"name"`
Cluster clientcmdv1.Cluster `json:"cluster,omitempty"`
}
type CredentialProvider = AccessProvider
// ClusterVersion represents version information about the cluster.
type ClusterVersion struct {
// Kubernetes is the kubernetes version of the cluster.
@@ -76,14 +103,10 @@ type ClusterVersion struct {
Kubernetes string `json:"kubernetes,omitempty"`
}
// Property defines a name/value pair to represent a property of a cluster.
// It could be a ClusterProperty (KEP-2149) resource,
// but could also be info based on other implementations.
// The name of the property can be predefined name from a ClusterProperty resource
// and is allowed to be customized by different cluster managers.
// Property defines the data structure to represent a property of a cluster.
// It contains a name/value pair and the last observed time of the property on the cluster.
// This property can store various configurable details and metrics of a cluster,
// which may include information such as the number of nodes, total and free CPU,
// and total and free memory, among other potential attributes.
// which may include information such as the entry point of the cluster, types of nodes, location, etc. according to KEP 4322.
type Property struct {
// Name is the name of a property resource on cluster. It's a well-known
// or customized name to identify the property.
@@ -97,6 +120,13 @@ type Property struct {
// +kubebuilder:validation:MinLength=1
// +required
Value string `json:"value"`
// LastObservedTime is the last time the property was observed on the corresponding cluster.
// The value is the timestamp when the property was observed not the time when the property was updated in the cluster-profile.
// +kubebuilder:validation:Type=string
// +kubebuilder:validation:Format=date-time
// +optional
LastObservedTime metav1.Time `json:"lastObservedTime,omitempty"`
}
// Predefined healthy conditions indicate the cluster is in a good state or not.

View File

@@ -26,9 +26,19 @@ import (
"sigs.k8s.io/controller-runtime/pkg/scheme"
)
const (
// Group is the API group.
Group = "multicluster.x-k8s.io"
// Version is the API version.
Version = "v1alpha1"
// Kind is the resource kind.
Kind = "ClusterProfile"
resource = "clusterprofiles"
)
var (
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "multicluster.x-k8s.io", Version: "v1alpha1"}
GroupVersion = schema.GroupVersion{Group: Group, Version: Version}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
@@ -37,6 +47,20 @@ var (
// Deprecated
SchemeGroupVersion = GroupVersion
// SchemeGroupVersionKind is the group, version and kind for the ClusterProfile CR.
SchemeGroupVersionKind = schema.GroupVersionKind{
Group: Group,
Version: Version,
Kind: Kind,
}
// SchemeGroupVersionResource is the group, version and resource for the ClusterProfile CR.
SchemeGroupVersionResource = schema.GroupVersionResource{
Group: Group,
Version: Version,
Resource: resource,
}
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)

View File

@@ -25,6 +25,22 @@ import (
"k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AccessProvider) DeepCopyInto(out *AccessProvider) {
*out = *in
in.Cluster.DeepCopyInto(&out.Cluster)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AccessProvider.
func (in *AccessProvider) DeepCopy() *AccessProvider {
if in == nil {
return nil
}
out := new(AccessProvider)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterManager) DeepCopyInto(out *ClusterManager) {
*out = *in
@@ -129,7 +145,23 @@ func (in *ClusterProfileStatus) DeepCopyInto(out *ClusterProfileStatus) {
if in.Properties != nil {
in, out := &in.Properties, &out.Properties
*out = make([]Property, len(*in))
copy(*out, *in)
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.CredentialProviders != nil {
in, out := &in.CredentialProviders, &out.CredentialProviders
*out = make([]CredentialProvider, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.AccessProviders != nil {
in, out := &in.AccessProviders, &out.AccessProviders
*out = make([]AccessProvider, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
@@ -161,6 +193,7 @@ func (in *ClusterVersion) DeepCopy() *ClusterVersion {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Property) DeepCopyInto(out *Property) {
*out = *in
in.LastObservedTime.DeepCopyInto(&out.LastObservedTime)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Property.

View File

@@ -18,8 +18,8 @@ limitations under the License.
package versioned
import (
"fmt"
"net/http"
fmt "fmt"
http "net/http"
discovery "k8s.io/client-go/discovery"
rest "k8s.io/client-go/rest"

View File

@@ -30,8 +30,12 @@ import (
// NewSimpleClientset returns a clientset that will respond with the provided objects.
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
// without applying any validations and/or defaults. It shouldn't be considered a replacement
// without applying any field management, validations and/or defaults. It shouldn't be considered a replacement
// for a real clientset and is mostly useful in simple unit tests.
//
// DEPRECATED: NewClientset replaces this with support for field management, which significantly improves
// server side apply testing. NewClientset is only available when apply configurations are generated (e.g.
// via --with-applyconfig).
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
for _, obj := range objects {

View File

@@ -18,11 +18,11 @@ limitations under the License.
package v1alpha1
import (
"net/http"
http "net/http"
rest "k8s.io/client-go/rest"
v1alpha1 "sigs.k8s.io/cluster-inventory-api/apis/v1alpha1"
"sigs.k8s.io/cluster-inventory-api/client/clientset/versioned/scheme"
apisv1alpha1 "sigs.k8s.io/cluster-inventory-api/apis/v1alpha1"
scheme "sigs.k8s.io/cluster-inventory-api/client/clientset/versioned/scheme"
)
type ApisV1alpha1Interface interface {
@@ -84,10 +84,10 @@ func New(c rest.Interface) *ApisV1alpha1Client {
}
func setConfigDefaults(config *rest.Config) error {
gv := v1alpha1.SchemeGroupVersion
gv := apisv1alpha1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
config.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(scheme.Scheme, scheme.Codecs).WithoutConversion()
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()

View File

@@ -18,14 +18,13 @@ limitations under the License.
package v1alpha1
import (
"context"
"time"
context "context"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
v1alpha1 "sigs.k8s.io/cluster-inventory-api/apis/v1alpha1"
gentype "k8s.io/client-go/gentype"
apisv1alpha1 "sigs.k8s.io/cluster-inventory-api/apis/v1alpha1"
scheme "sigs.k8s.io/cluster-inventory-api/client/clientset/versioned/scheme"
)
@@ -37,158 +36,34 @@ type ClusterProfilesGetter interface {
// ClusterProfileInterface has methods to work with ClusterProfile resources.
type ClusterProfileInterface interface {
Create(ctx context.Context, clusterProfile *v1alpha1.ClusterProfile, opts v1.CreateOptions) (*v1alpha1.ClusterProfile, error)
Update(ctx context.Context, clusterProfile *v1alpha1.ClusterProfile, opts v1.UpdateOptions) (*v1alpha1.ClusterProfile, error)
UpdateStatus(ctx context.Context, clusterProfile *v1alpha1.ClusterProfile, opts v1.UpdateOptions) (*v1alpha1.ClusterProfile, error)
Create(ctx context.Context, clusterProfile *apisv1alpha1.ClusterProfile, opts v1.CreateOptions) (*apisv1alpha1.ClusterProfile, error)
Update(ctx context.Context, clusterProfile *apisv1alpha1.ClusterProfile, opts v1.UpdateOptions) (*apisv1alpha1.ClusterProfile, error)
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
UpdateStatus(ctx context.Context, clusterProfile *apisv1alpha1.ClusterProfile, opts v1.UpdateOptions) (*apisv1alpha1.ClusterProfile, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ClusterProfile, error)
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ClusterProfileList, error)
Get(ctx context.Context, name string, opts v1.GetOptions) (*apisv1alpha1.ClusterProfile, error)
List(ctx context.Context, opts v1.ListOptions) (*apisv1alpha1.ClusterProfileList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterProfile, err error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *apisv1alpha1.ClusterProfile, err error)
ClusterProfileExpansion
}
// clusterProfiles implements ClusterProfileInterface
type clusterProfiles struct {
client rest.Interface
ns string
*gentype.ClientWithList[*apisv1alpha1.ClusterProfile, *apisv1alpha1.ClusterProfileList]
}
// newClusterProfiles returns a ClusterProfiles
func newClusterProfiles(c *ApisV1alpha1Client, namespace string) *clusterProfiles {
return &clusterProfiles{
client: c.RESTClient(),
ns: namespace,
gentype.NewClientWithList[*apisv1alpha1.ClusterProfile, *apisv1alpha1.ClusterProfileList](
"clusterprofiles",
c.RESTClient(),
scheme.ParameterCodec,
namespace,
func() *apisv1alpha1.ClusterProfile { return &apisv1alpha1.ClusterProfile{} },
func() *apisv1alpha1.ClusterProfileList { return &apisv1alpha1.ClusterProfileList{} },
),
}
}
// Get takes name of the clusterProfile, and returns the corresponding clusterProfile object, and an error if there is any.
func (c *clusterProfiles) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ClusterProfile, err error) {
result = &v1alpha1.ClusterProfile{}
err = c.client.Get().
Namespace(c.ns).
Resource("clusterprofiles").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do(ctx).
Into(result)
return
}
// List takes label and field selectors, and returns the list of ClusterProfiles that match those selectors.
func (c *clusterProfiles) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ClusterProfileList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha1.ClusterProfileList{}
err = c.client.Get().
Namespace(c.ns).
Resource("clusterprofiles").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do(ctx).
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested clusterProfiles.
func (c *clusterProfiles) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("clusterprofiles").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch(ctx)
}
// Create takes the representation of a clusterProfile and creates it. Returns the server's representation of the clusterProfile, and an error, if there is any.
func (c *clusterProfiles) Create(ctx context.Context, clusterProfile *v1alpha1.ClusterProfile, opts v1.CreateOptions) (result *v1alpha1.ClusterProfile, err error) {
result = &v1alpha1.ClusterProfile{}
err = c.client.Post().
Namespace(c.ns).
Resource("clusterprofiles").
VersionedParams(&opts, scheme.ParameterCodec).
Body(clusterProfile).
Do(ctx).
Into(result)
return
}
// Update takes the representation of a clusterProfile and updates it. Returns the server's representation of the clusterProfile, and an error, if there is any.
func (c *clusterProfiles) Update(ctx context.Context, clusterProfile *v1alpha1.ClusterProfile, opts v1.UpdateOptions) (result *v1alpha1.ClusterProfile, err error) {
result = &v1alpha1.ClusterProfile{}
err = c.client.Put().
Namespace(c.ns).
Resource("clusterprofiles").
Name(clusterProfile.Name).
VersionedParams(&opts, scheme.ParameterCodec).
Body(clusterProfile).
Do(ctx).
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *clusterProfiles) UpdateStatus(ctx context.Context, clusterProfile *v1alpha1.ClusterProfile, opts v1.UpdateOptions) (result *v1alpha1.ClusterProfile, err error) {
result = &v1alpha1.ClusterProfile{}
err = c.client.Put().
Namespace(c.ns).
Resource("clusterprofiles").
Name(clusterProfile.Name).
SubResource("status").
VersionedParams(&opts, scheme.ParameterCodec).
Body(clusterProfile).
Do(ctx).
Into(result)
return
}
// Delete takes name of the clusterProfile and deletes it. Returns an error if one occurs.
func (c *clusterProfiles) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("clusterprofiles").
Name(name).
Body(&opts).
Do(ctx).
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *clusterProfiles) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
var timeout time.Duration
if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("clusterprofiles").
VersionedParams(&listOpts, scheme.ParameterCodec).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
// Patch applies the patch and returns the patched clusterProfile.
func (c *clusterProfiles) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterProfile, err error) {
result = &v1alpha1.ClusterProfile{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("clusterprofiles").
Name(name).
SubResource(subresources...).
VersionedParams(&opts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}

View File

@@ -28,7 +28,7 @@ type FakeApisV1alpha1 struct {
}
func (c *FakeApisV1alpha1) ClusterProfiles(namespace string) v1alpha1.ClusterProfileInterface {
return &FakeClusterProfiles{c, namespace}
return newFakeClusterProfiles(c, namespace)
}
// RESTClient returns a RESTClient that is used to communicate

View File

@@ -18,123 +18,34 @@ limitations under the License.
package fake
import (
"context"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
gentype "k8s.io/client-go/gentype"
v1alpha1 "sigs.k8s.io/cluster-inventory-api/apis/v1alpha1"
apisv1alpha1 "sigs.k8s.io/cluster-inventory-api/client/clientset/versioned/typed/apis/v1alpha1"
)
// FakeClusterProfiles implements ClusterProfileInterface
type FakeClusterProfiles struct {
// fakeClusterProfiles implements ClusterProfileInterface
type fakeClusterProfiles struct {
*gentype.FakeClientWithList[*v1alpha1.ClusterProfile, *v1alpha1.ClusterProfileList]
Fake *FakeApisV1alpha1
ns string
}
var clusterprofilesResource = v1alpha1.SchemeGroupVersion.WithResource("clusterprofiles")
var clusterprofilesKind = v1alpha1.SchemeGroupVersion.WithKind("ClusterProfile")
// Get takes name of the clusterProfile, and returns the corresponding clusterProfile object, and an error if there is any.
func (c *FakeClusterProfiles) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ClusterProfile, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(clusterprofilesResource, c.ns, name), &v1alpha1.ClusterProfile{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ClusterProfile), err
}
// List takes label and field selectors, and returns the list of ClusterProfiles that match those selectors.
func (c *FakeClusterProfiles) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ClusterProfileList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(clusterprofilesResource, clusterprofilesKind, c.ns, opts), &v1alpha1.ClusterProfileList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.ClusterProfileList{ListMeta: obj.(*v1alpha1.ClusterProfileList).ListMeta}
for _, item := range obj.(*v1alpha1.ClusterProfileList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
func newFakeClusterProfiles(fake *FakeApisV1alpha1, namespace string) apisv1alpha1.ClusterProfileInterface {
return &fakeClusterProfiles{
gentype.NewFakeClientWithList[*v1alpha1.ClusterProfile, *v1alpha1.ClusterProfileList](
fake.Fake,
namespace,
v1alpha1.SchemeGroupVersion.WithResource("clusterprofiles"),
v1alpha1.SchemeGroupVersion.WithKind("ClusterProfile"),
func() *v1alpha1.ClusterProfile { return &v1alpha1.ClusterProfile{} },
func() *v1alpha1.ClusterProfileList { return &v1alpha1.ClusterProfileList{} },
func(dst, src *v1alpha1.ClusterProfileList) { dst.ListMeta = src.ListMeta },
func(list *v1alpha1.ClusterProfileList) []*v1alpha1.ClusterProfile {
return gentype.ToPointerSlice(list.Items)
},
func(list *v1alpha1.ClusterProfileList, items []*v1alpha1.ClusterProfile) {
list.Items = gentype.FromPointerSlice(items)
},
),
fake,
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested clusterProfiles.
func (c *FakeClusterProfiles) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(clusterprofilesResource, c.ns, opts))
}
// Create takes the representation of a clusterProfile and creates it. Returns the server's representation of the clusterProfile, and an error, if there is any.
func (c *FakeClusterProfiles) Create(ctx context.Context, clusterProfile *v1alpha1.ClusterProfile, opts v1.CreateOptions) (result *v1alpha1.ClusterProfile, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(clusterprofilesResource, c.ns, clusterProfile), &v1alpha1.ClusterProfile{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ClusterProfile), err
}
// Update takes the representation of a clusterProfile and updates it. Returns the server's representation of the clusterProfile, and an error, if there is any.
func (c *FakeClusterProfiles) Update(ctx context.Context, clusterProfile *v1alpha1.ClusterProfile, opts v1.UpdateOptions) (result *v1alpha1.ClusterProfile, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(clusterprofilesResource, c.ns, clusterProfile), &v1alpha1.ClusterProfile{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ClusterProfile), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeClusterProfiles) UpdateStatus(ctx context.Context, clusterProfile *v1alpha1.ClusterProfile, opts v1.UpdateOptions) (*v1alpha1.ClusterProfile, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(clusterprofilesResource, "status", c.ns, clusterProfile), &v1alpha1.ClusterProfile{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ClusterProfile), err
}
// Delete takes name of the clusterProfile and deletes it. Returns an error if one occurs.
func (c *FakeClusterProfiles) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteActionWithOptions(clusterprofilesResource, c.ns, name, opts), &v1alpha1.ClusterProfile{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeClusterProfiles) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(clusterprofilesResource, c.ns, listOpts)
_, err := c.Fake.Invokes(action, &v1alpha1.ClusterProfileList{})
return err
}
// Patch applies the patch and returns the patched clusterProfile.
func (c *FakeClusterProfiles) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterProfile, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(clusterprofilesResource, c.ns, name, pt, data, subresources...), &v1alpha1.ClusterProfile{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha1.ClusterProfile), err
}

View File

@@ -18,24 +18,24 @@ limitations under the License.
package v1alpha1
import (
"context"
context "context"
time "time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
apisv1alpha1 "sigs.k8s.io/cluster-inventory-api/apis/v1alpha1"
clusterinventoryapiapisv1alpha1 "sigs.k8s.io/cluster-inventory-api/apis/v1alpha1"
versioned "sigs.k8s.io/cluster-inventory-api/client/clientset/versioned"
internalinterfaces "sigs.k8s.io/cluster-inventory-api/client/informers/externalversions/internalinterfaces"
v1alpha1 "sigs.k8s.io/cluster-inventory-api/client/listers/apis/v1alpha1"
apisv1alpha1 "sigs.k8s.io/cluster-inventory-api/client/listers/apis/v1alpha1"
)
// ClusterProfileInformer provides access to a shared informer and lister for
// ClusterProfiles.
type ClusterProfileInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha1.ClusterProfileLister
Lister() apisv1alpha1.ClusterProfileLister
}
type clusterProfileInformer struct {
@@ -70,7 +70,7 @@ func NewFilteredClusterProfileInformer(client versioned.Interface, namespace str
return client.ApisV1alpha1().ClusterProfiles(namespace).Watch(context.TODO(), options)
},
},
&apisv1alpha1.ClusterProfile{},
&clusterinventoryapiapisv1alpha1.ClusterProfile{},
resyncPeriod,
indexers,
)
@@ -81,9 +81,9 @@ func (f *clusterProfileInformer) defaultInformer(client versioned.Interface, res
}
func (f *clusterProfileInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&apisv1alpha1.ClusterProfile{}, f.defaultInformer)
return f.factory.InformerFor(&clusterinventoryapiapisv1alpha1.ClusterProfile{}, f.defaultInformer)
}
func (f *clusterProfileInformer) Lister() v1alpha1.ClusterProfileLister {
return v1alpha1.NewClusterProfileLister(f.Informer().GetIndexer())
func (f *clusterProfileInformer) Lister() apisv1alpha1.ClusterProfileLister {
return apisv1alpha1.NewClusterProfileLister(f.Informer().GetIndexer())
}

View File

@@ -227,6 +227,7 @@ type SharedInformerFactory interface {
// Start initializes all requested informers. They are handled in goroutines
// which run until the stop channel gets closed.
// Warning: Start does not block. When run in a go-routine, it will race with a later WaitForCacheSync.
Start(stopCh <-chan struct{})
// Shutdown marks a factory as shutting down. At that point no new

View File

@@ -18,7 +18,7 @@ limitations under the License.
package externalversions
import (
"fmt"
fmt "fmt"
schema "k8s.io/apimachinery/pkg/runtime/schema"
cache "k8s.io/client-go/tools/cache"

View File

@@ -18,10 +18,10 @@ limitations under the License.
package v1alpha1
import (
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
v1alpha1 "sigs.k8s.io/cluster-inventory-api/apis/v1alpha1"
labels "k8s.io/apimachinery/pkg/labels"
listers "k8s.io/client-go/listers"
cache "k8s.io/client-go/tools/cache"
apisv1alpha1 "sigs.k8s.io/cluster-inventory-api/apis/v1alpha1"
)
// ClusterProfileLister helps list ClusterProfiles.
@@ -29,7 +29,7 @@ import (
type ClusterProfileLister interface {
// List lists all ClusterProfiles in the indexer.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v1alpha1.ClusterProfile, err error)
List(selector labels.Selector) (ret []*apisv1alpha1.ClusterProfile, err error)
// ClusterProfiles returns an object that can list and get ClusterProfiles.
ClusterProfiles(namespace string) ClusterProfileNamespaceLister
ClusterProfileListerExpansion
@@ -37,25 +37,17 @@ type ClusterProfileLister interface {
// clusterProfileLister implements the ClusterProfileLister interface.
type clusterProfileLister struct {
indexer cache.Indexer
listers.ResourceIndexer[*apisv1alpha1.ClusterProfile]
}
// NewClusterProfileLister returns a new ClusterProfileLister.
func NewClusterProfileLister(indexer cache.Indexer) ClusterProfileLister {
return &clusterProfileLister{indexer: indexer}
}
// List lists all ClusterProfiles in the indexer.
func (s *clusterProfileLister) List(selector labels.Selector) (ret []*v1alpha1.ClusterProfile, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha1.ClusterProfile))
})
return ret, err
return &clusterProfileLister{listers.New[*apisv1alpha1.ClusterProfile](indexer, apisv1alpha1.Resource("clusterprofile"))}
}
// ClusterProfiles returns an object that can list and get ClusterProfiles.
func (s *clusterProfileLister) ClusterProfiles(namespace string) ClusterProfileNamespaceLister {
return clusterProfileNamespaceLister{indexer: s.indexer, namespace: namespace}
return clusterProfileNamespaceLister{listers.NewNamespaced[*apisv1alpha1.ClusterProfile](s.ResourceIndexer, namespace)}
}
// ClusterProfileNamespaceLister helps list and get ClusterProfiles.
@@ -63,36 +55,15 @@ func (s *clusterProfileLister) ClusterProfiles(namespace string) ClusterProfileN
type ClusterProfileNamespaceLister interface {
// List lists all ClusterProfiles in the indexer for a given namespace.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v1alpha1.ClusterProfile, err error)
List(selector labels.Selector) (ret []*apisv1alpha1.ClusterProfile, err error)
// Get retrieves the ClusterProfile from the indexer for a given namespace and name.
// Objects returned here must be treated as read-only.
Get(name string) (*v1alpha1.ClusterProfile, error)
Get(name string) (*apisv1alpha1.ClusterProfile, error)
ClusterProfileNamespaceListerExpansion
}
// clusterProfileNamespaceLister implements the ClusterProfileNamespaceLister
// interface.
type clusterProfileNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all ClusterProfiles in the indexer for a given namespace.
func (s clusterProfileNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ClusterProfile, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha1.ClusterProfile))
})
return ret, err
}
// Get retrieves the ClusterProfile from the indexer for a given namespace and name.
func (s clusterProfileNamespaceLister) Get(name string) (*v1alpha1.ClusterProfile, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1alpha1.Resource("clusterprofile"), name)
}
return obj.(*v1alpha1.ClusterProfile), nil
listers.ResourceIndexer[*apisv1alpha1.ClusterProfile]
}