mirror of
https://github.com/prometheus-operator/prometheus-operator.git
synced 2025-04-15 16:56:24 +00:00
prometheus: Introduce RuleFile Custom Resource Definition
This patch introduces a new Custom Resource Definition to the Prometheus Operator - the Rule CRD. It addresses two main needs: 1. Prometheus (alerting and recording) Rule validation during creation time via Kubernetes Custom Resource Definition validation. 2. Life-cycle management of Prometheus application Rules alongside the application itself, inside the applications Kubernetes namespace, not necessarily the namespace of the scraping Prometheus instance. A user defines Prometheus alerting and recording Rules via a Kubernetes Custom Resource Definition. These Custom Resource Definitions can be fully validated by the Kubernetes API server during creation time via automatically generated OpenAPI specifications. Instead of the restriction of a Prometheus instance to only select Rule definitions inside its own namespace, the Prometheus specification is extended to also specify namespaces to look for Rule Custom Resource Definitions outside its own namespace. --- Dependent technical changes: - prometheus: Use github.com/jimmidyson/configmap-reload to reload rules - prometheus: Remove Prometheus Statefulset deletion function. Starting with K8s >=1.8 this is handled via OwnerReferences. - prometheus: Do not add rule files checksum to Prometheus configuration secret - prometheus: Update StatefulSet only on relevant changes. Instead of updating the Prometheus StatefulSet on every `sync()` run, only update it if the input parameters to `makeStatefulSet` change. Enforce this via a checksum of the parameters which is saved inside the annotations of the statefulset. - e2e/prometheus: Check how often resources (Secret, ConfigMap, Prometheus CRD, Service) are updated to enforce that Prometheus Operator only updated created resources if necessary. - contrib/prometheus-config-reloader: Remove logic to retriev K8s ConfigMaps. These are mounted into the pod right away now.
This commit is contained in:
parent
894695f48f
commit
89fc4e3069
789 changed files with 4235 additions and 321888 deletions
|
@ -26,6 +26,11 @@ This Document documents the types introduced by the Prometheus Operator to be co
|
|||
* [RelabelConfig](#relabelconfig)
|
||||
* [RemoteReadSpec](#remotereadspec)
|
||||
* [RemoteWriteSpec](#remotewritespec)
|
||||
* [Rule](#rule)
|
||||
* [RuleFile](#rulefile)
|
||||
* [RuleFileList](#rulefilelist)
|
||||
* [RuleFileSpec](#rulefilespec)
|
||||
* [RuleGroup](#rulegroup)
|
||||
* [ServiceMonitor](#servicemonitor)
|
||||
* [ServiceMonitorList](#servicemonitorlist)
|
||||
* [ServiceMonitorSpec](#servicemonitorspec)
|
||||
|
@ -211,7 +216,9 @@ Specification of the desired behavior of the Prometheus cluster. More info: http
|
|||
| externalUrl | The external URL the Prometheus instances will be available under. This is necessary to generate correct URLs. This is necessary if Prometheus is not served from root of a DNS name. | string | false |
|
||||
| routePrefix | The route prefix Prometheus registers HTTP handlers for. This is useful, if using ExternalURL and a proxy is rewriting HTTP routes of a request, and the actual ExternalURL is still true, but the server serves requests under a different route prefix. For example for use with `kubectl proxy`. | string | false |
|
||||
| storage | Storage spec to specify how storage shall be used. | *[StorageSpec](#storagespec) | false |
|
||||
| ruleSelector | A selector to select which ConfigMaps to mount for loading rule files from. | *[metav1.LabelSelector](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#labelselector-v1-meta) | false |
|
||||
| ruleFileSelector | A selector to select which RuleFiles to mount for loading alerting rules from. | *[metav1.LabelSelector](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#labelselector-v1-meta) | false |
|
||||
| ruleSelector | DEPRECATED with Prometheus Operator 'v0.20.0'. Any value in this field will just be copied to 'RuleFileSelector' field | *[metav1.LabelSelector](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#labelselector-v1-meta) | false |
|
||||
| ruleFileNamespaceSelector | Namespaces to be selected for RuleFiles discovery. If empty, only check own namespace. | *[metav1.LabelSelector](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#labelselector-v1-meta) | false |
|
||||
| alerting | Define details regarding alerting. | *[AlertingSpec](#alertingspec) | false |
|
||||
| resources | Define resources requests and limits for single Pods. | [v1.ResourceRequirements](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#resourcerequirements-v1-core) | false |
|
||||
| nodeSelector | Define which Nodes the Pods are scheduled on. | map[string]string | false |
|
||||
|
@ -294,6 +301,65 @@ RemoteWriteSpec defines the remote_write configuration for prometheus.
|
|||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
## Rule
|
||||
|
||||
Rule describes an alerting or recording rule.
|
||||
|
||||
| Field | Description | Scheme | Required |
|
||||
| ----- | ----------- | ------ | -------- |
|
||||
| record | | string | false |
|
||||
| alert | | string | false |
|
||||
| expr | | string | true |
|
||||
| for | | time.Duration | false |
|
||||
| labels | | map[string]string | false |
|
||||
| annotations | | map[string]string | false |
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
## RuleFile
|
||||
|
||||
RuleFile defines alerting rules for a Prometheus instance
|
||||
|
||||
| Field | Description | Scheme | Required |
|
||||
| ----- | ----------- | ------ | -------- |
|
||||
| metadata | Standard object’s metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata | [metav1.ObjectMeta](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#objectmeta-v1-meta) | false |
|
||||
| spec | Specification of desired alerting rule definitions for Prometheus. | [RuleFileSpec](#rulefilespec) | true |
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
## RuleFileList
|
||||
|
||||
A list of RuleFiles.
|
||||
|
||||
| Field | Description | Scheme | Required |
|
||||
| ----- | ----------- | ------ | -------- |
|
||||
| metadata | Standard list metadata More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata | [metav1.ListMeta](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#listmeta-v1-meta) | false |
|
||||
| items | List of Rules | []*[RuleFile](#rulefile) | true |
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
## RuleFileSpec
|
||||
|
||||
RuleFileSpec contains specification parameters for a Rule.
|
||||
|
||||
| Field | Description | Scheme | Required |
|
||||
| ----- | ----------- | ------ | -------- |
|
||||
| groups | Content of Prometheus rule file | [][RuleGroup](#rulegroup) | false |
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
## RuleGroup
|
||||
|
||||
RuleGroup is a list of sequentially evaluated recording and alerting rules.
|
||||
|
||||
| Field | Description | Scheme | Required |
|
||||
| ----- | ----------- | ------ | -------- |
|
||||
| name | | string | true |
|
||||
| interval | | time.Duration | false |
|
||||
| rules | | [][Rule](#rule) | true |
|
||||
|
||||
[Back to TOC](#table-of-contents)
|
||||
|
||||
## ServiceMonitor
|
||||
|
||||
ServiceMonitor defines monitoring for a set of services.
|
||||
|
|
|
@ -40,6 +40,7 @@ rules:
|
|||
- prometheuses/finalizers
|
||||
- alertmanagers/finalizers
|
||||
- servicemonitors
|
||||
- rulefiles
|
||||
verbs:
|
||||
- "*"
|
||||
- apiGroups:
|
||||
|
|
|
@ -54,6 +54,7 @@ rules:
|
|||
- prometheuses/finalizers
|
||||
- alertmanagers/finalizers
|
||||
- servicemonitors
|
||||
- rulefiles
|
||||
verbs:
|
||||
- "*"
|
||||
- apiGroups:
|
||||
|
|
58
Gopkg.lock
generated
58
Gopkg.lock
generated
|
@ -61,43 +61,6 @@
|
|||
revision = "26b41036311f2da8242db402557a0dbd09dc83da"
|
||||
version = "v2.6.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/ericchiang/k8s"
|
||||
packages = [
|
||||
".",
|
||||
"api/resource",
|
||||
"api/unversioned",
|
||||
"api/v1",
|
||||
"apis/apps/v1alpha1",
|
||||
"apis/apps/v1beta1",
|
||||
"apis/authentication/v1",
|
||||
"apis/authentication/v1beta1",
|
||||
"apis/authorization/v1",
|
||||
"apis/authorization/v1beta1",
|
||||
"apis/autoscaling/v1",
|
||||
"apis/autoscaling/v2alpha1",
|
||||
"apis/batch/v1",
|
||||
"apis/batch/v2alpha1",
|
||||
"apis/certificates/v1alpha1",
|
||||
"apis/certificates/v1beta1",
|
||||
"apis/extensions/v1beta1",
|
||||
"apis/imagepolicy/v1alpha1",
|
||||
"apis/meta/v1",
|
||||
"apis/policy/v1alpha1",
|
||||
"apis/policy/v1beta1",
|
||||
"apis/rbac/v1alpha1",
|
||||
"apis/rbac/v1beta1",
|
||||
"apis/settings/v1alpha1",
|
||||
"apis/storage/v1",
|
||||
"apis/storage/v1beta1",
|
||||
"runtime",
|
||||
"runtime/schema",
|
||||
"util/intstr",
|
||||
"watch/versioned"
|
||||
]
|
||||
revision = "68b0248f880c5967d1ba7166486cb216af849b15"
|
||||
version = "v0.4.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/fsnotify/fsnotify"
|
||||
packages = ["."]
|
||||
|
@ -246,6 +209,15 @@
|
|||
packages = ["."]
|
||||
revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/kylelemons/godebug"
|
||||
packages = [
|
||||
"diff",
|
||||
"pretty"
|
||||
]
|
||||
revision = "d65d576e9348f5982d7f6d83682b694e731a45c6"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mailru/easyjson"
|
||||
|
@ -404,16 +376,6 @@
|
|||
packages = ["rate"]
|
||||
revision = "fbb02b2291d28baffd63558aa44b4b56f178d650"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/tools"
|
||||
packages = [
|
||||
"go/ast/astutil",
|
||||
"go/buildutil",
|
||||
"go/loader"
|
||||
]
|
||||
revision = "2226533658007779ffd629b495a088530c84dc50"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/alecthomas/kingpin.v2"
|
||||
packages = ["."]
|
||||
|
@ -595,6 +557,6 @@
|
|||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "46a17224425510beb17903cabf6407f31d7c7b24fd75037df3a5cfd0c7436f28"
|
||||
inputs-digest = "f195376f6f2edf7355611d989c4b2e1370722a23205711e61e97aa903ebf4e5a"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
|
@ -59,3 +59,7 @@
|
|||
[[override]]
|
||||
name = "github.com/ericchiang/k8s"
|
||||
version = "v0.4.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/kylelemons/godebug"
|
||||
|
|
7
Makefile
7
Makefile
|
@ -23,9 +23,10 @@ po-crdgen:
|
|||
|
||||
crossbuild: promu
|
||||
@$(PROMU) crossbuild
|
||||
cd contrib/prometheus-config-reloader && make build
|
||||
|
||||
test:
|
||||
@go test -short $(pkgs)
|
||||
@go test $(TEST_RUN_ARGS) -short $(pkgs)
|
||||
|
||||
format:
|
||||
go fmt $(pkgs)
|
||||
|
@ -35,6 +36,7 @@ check-license:
|
|||
|
||||
container:
|
||||
docker build -t $(REPO):$(TAG) .
|
||||
cd contrib/prometheus-config-reloader && docker build -t quay.io/coreos/prometheus-config-reloader:$(TAG) .
|
||||
|
||||
e2e-test:
|
||||
go test -timeout 55m -v ./test/e2e/ $(TEST_RUN_ARGS) --kubeconfig=$(KUBECONFIG) --operator-image=$(REPO):$(TAG) --namespace=$(NAMESPACE)
|
||||
|
@ -48,7 +50,7 @@ e2e:
|
|||
|
||||
e2e-helm:
|
||||
./helm/hack/e2e-test.sh
|
||||
# package the chart and verify if they have the version bumped
|
||||
# package the chart and verify if they have the version bumped
|
||||
helm/hack/helm-package.sh "alertmanager grafana prometheus prometheus-operator exporter-kube-dns exporter-kube-scheduler exporter-kubelets exporter-node exporter-kube-controller-manager exporter-kube-etcd exporter-kube-state exporter-kubernetes exporter-coredns"
|
||||
helm/hack/sync-repo.sh false
|
||||
|
||||
|
@ -126,5 +128,6 @@ generate-crd: generate-openapi po-crdgen
|
|||
po-crdgen prometheus > example/prometheus-operator-crd/prometheus.crd.yaml
|
||||
po-crdgen alertmanager > example/prometheus-operator-crd/alertmanager.crd.yaml
|
||||
po-crdgen servicemonitor > example/prometheus-operator-crd/servicemonitor.crd.yaml
|
||||
po-crdgen rulefile > example/prometheus-operator-crd/rulefile.crd.yaml
|
||||
|
||||
.PHONY: all build crossbuild test format check-license container e2e-test e2e-status e2e clean-e2e embedmd apidocgen docs generate-crd jb
|
||||
|
|
|
@ -36,6 +36,7 @@ rules:
|
|||
- prometheuses/finalizers
|
||||
- alertmanagers/finalizers
|
||||
- servicemonitors
|
||||
- rulefiles
|
||||
verbs:
|
||||
- "*"
|
||||
- apiGroups:
|
||||
|
|
|
@ -45,7 +45,7 @@ func initFlags(crdkind monitoringv1.CrdKind, flagset *flag.FlagSet) *flag.FlagSe
|
|||
func init() {
|
||||
var command *flag.FlagSet
|
||||
if len(os.Args) == 1 {
|
||||
fmt.Println("usage: po-crdgen [prometheus | alertmanager | servicemonitor] [<options>]")
|
||||
fmt.Println("usage: po-crdgen [prometheus | alertmanager | servicemonitor | rulefile] [<options>]")
|
||||
os.Exit(1)
|
||||
}
|
||||
switch os.Args[1] {
|
||||
|
@ -55,8 +55,10 @@ func init() {
|
|||
command = initFlags(monitoringv1.DefaultCrdKinds.ServiceMonitor, flag.NewFlagSet("servicemonitor", flag.ExitOnError))
|
||||
case "alertmanager":
|
||||
command = initFlags(monitoringv1.DefaultCrdKinds.Alertmanager, flag.NewFlagSet("alertmanager", flag.ExitOnError))
|
||||
case "rulefile":
|
||||
command = initFlags(monitoringv1.DefaultCrdKinds.RuleFile, flag.NewFlagSet("rulefile", flag.ExitOnError))
|
||||
default:
|
||||
fmt.Printf("%q is not valid command.\n choices: [prometheus, alertmanager, servicemonitor]", os.Args[1])
|
||||
fmt.Printf("%q is not valid command.\n choices: [prometheus, alertmanager, servicemonitor, rulefile]", os.Args[1])
|
||||
os.Exit(2)
|
||||
}
|
||||
command.Parse(os.Args[2:])
|
||||
|
|
|
@ -3,14 +3,15 @@ image:
|
|||
|
||||
generate: image
|
||||
@echo ">> Compiling assets and generating Kubernetes manifests"
|
||||
docker run --rm -u=$(shell id -u $(USER)):$(shell id -g $(USER)) -v $(shell dirname $(dir $(abspath $(dir $$PWD)))):/go/src/github.com/coreos/prometheus-operator/ --workdir /go/src/github.com/coreos/prometheus-operator/contrib/kube-prometheus po-jsonnet make crdtojsonnet generate-raw
|
||||
docker run --rm -u=$(shell id -u $(USER)):$(shell id -g $(USER)) -v $(shell dirname $(dir $(abspath $(dir $$PWD)))):/go/src/github.com/coreos/prometheus-operator/ --workdir /go/src/github.com/coreos/prometheus-operator/contrib/kube-prometheus po-jsonnet make generate-raw
|
||||
|
||||
crdtojsonnet:
|
||||
cat ../../example/prometheus-operator-crd/alertmanager.crd.yaml | gojsontoyaml -yamltojson > jsonnet/kube-prometheus/prometheus-operator/alertmanager-crd.libsonnet
|
||||
cat ../../example/prometheus-operator-crd/prometheus.crd.yaml | gojsontoyaml -yamltojson > jsonnet/kube-prometheus/prometheus-operator/prometheus-crd.libsonnet
|
||||
cat ../../example/prometheus-operator-crd/servicemonitor.crd.yaml | gojsontoyaml -yamltojson > jsonnet/kube-prometheus/prometheus-operator/servicemonitor-crd.libsonnet
|
||||
cat ../../example/prometheus-operator-crd/rulefile.crd.yaml | gojsontoyaml -yamltojson > jsonnet/kube-prometheus/prometheus-operator/rulefile-crd.libsonnet
|
||||
|
||||
generate-raw:
|
||||
generate-raw: crdtojsonnet
|
||||
jb install
|
||||
./build.sh
|
||||
|
||||
|
|
|
@ -86,6 +86,10 @@ set -x
|
|||
# only exit with zero if all commands of the pipeline exit successfully
|
||||
set -o pipefail
|
||||
|
||||
# Make sure to start with a clean 'manifests' dir
|
||||
rm -rf manifests
|
||||
mkdir manifests
|
||||
|
||||
# optional, but we would like to generate yaml, not json
|
||||
jsonnet -J vendor -m manifests example.jsonnet | xargs -I{} sh -c 'cat $1 | gojsontoyaml > $1.yaml; rm -f $1' -- {}
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@ set -x
|
|||
# only exit with zero if all commands of the pipeline exit successfully
|
||||
set -o pipefail
|
||||
|
||||
# Make sure to start with a clean 'manifests' dir
|
||||
rm -rf manifests
|
||||
mkdir manifests
|
||||
|
||||
# optional, but we would like to generate yaml, not json
|
||||
jsonnet -J vendor -m manifests example.jsonnet | xargs -I{} sh -c 'cat $1 | gojsontoyaml > $1.yaml; rm -f $1' -- {}
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -666,7 +666,7 @@ spec:
|
|||
description: Specify whether the ConfigMap must be defined
|
||||
type: boolean
|
||||
prefix:
|
||||
description: An optional identifer to prepend to each key
|
||||
description: An optional identifier to prepend to each key
|
||||
in the ConfigMap. Must be a C_IDENTIFIER.
|
||||
type: string
|
||||
secretRef:
|
||||
|
@ -1120,6 +1120,14 @@ spec:
|
|||
description: Whether this container has a read-only root filesystem.
|
||||
Default is false.
|
||||
type: boolean
|
||||
runAsGroup:
|
||||
description: The GID to run the entrypoint of the container
|
||||
process. Uses runtime default if unset. May also be set
|
||||
in PodSecurityContext. If set in both SecurityContext and
|
||||
PodSecurityContext, the value specified in SecurityContext
|
||||
takes precedence.
|
||||
format: int64
|
||||
type: integer
|
||||
runAsNonRoot:
|
||||
description: Indicates that the container must run as a non-root
|
||||
user. If true, the Kubelet will validate the image at runtime
|
||||
|
@ -1231,8 +1239,7 @@ spec:
|
|||
description: mountPropagation determines how mounts are
|
||||
propagated from the host to container and the other way
|
||||
around. When not set, MountPropagationHostToContainer
|
||||
is used. This field is alpha in 1.8 and can be reworked
|
||||
or removed in a future release.
|
||||
is used. This field is beta in 1.10.
|
||||
type: string
|
||||
name:
|
||||
description: This must match the Name of a Volume.
|
||||
|
@ -1614,6 +1621,13 @@ spec:
|
|||
If unset, the Kubelet will not modify the ownership and permissions of any volume.
|
||||
format: int64
|
||||
type: integer
|
||||
runAsGroup:
|
||||
description: The GID to run the entrypoint of the container process.
|
||||
Uses runtime default if unset. May also be set in SecurityContext. If
|
||||
set in both SecurityContext and PodSecurityContext, the value
|
||||
specified in SecurityContext takes precedence for that container.
|
||||
format: int64
|
||||
type: integer
|
||||
runAsNonRoot:
|
||||
description: Indicates that the container must run as a non-root
|
||||
user. If true, the Kubelet will validate the image at runtime
|
||||
|
|
|
@ -27,6 +27,21 @@ spec:
|
|||
description: 'Specification of the desired behavior of the Prometheus cluster.
|
||||
More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status'
|
||||
properties:
|
||||
additionalAlertManagerConfigs:
|
||||
description: SecretKeySelector selects a key of a Secret.
|
||||
properties:
|
||||
key:
|
||||
description: The key of the secret to select from. Must be a valid
|
||||
secret key.
|
||||
type: string
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
|
||||
type: string
|
||||
optional:
|
||||
description: Specify whether the Secret or it's key must be defined
|
||||
type: boolean
|
||||
required:
|
||||
- key
|
||||
additionalScrapeConfigs:
|
||||
description: SecretKeySelector selects a key of a Secret.
|
||||
properties:
|
||||
|
@ -734,7 +749,7 @@ spec:
|
|||
description: Specify whether the ConfigMap must be defined
|
||||
type: boolean
|
||||
prefix:
|
||||
description: An optional identifer to prepend to each key
|
||||
description: An optional identifier to prepend to each key
|
||||
in the ConfigMap. Must be a C_IDENTIFIER.
|
||||
type: string
|
||||
secretRef:
|
||||
|
@ -1188,6 +1203,14 @@ spec:
|
|||
description: Whether this container has a read-only root filesystem.
|
||||
Default is false.
|
||||
type: boolean
|
||||
runAsGroup:
|
||||
description: The GID to run the entrypoint of the container
|
||||
process. Uses runtime default if unset. May also be set
|
||||
in PodSecurityContext. If set in both SecurityContext and
|
||||
PodSecurityContext, the value specified in SecurityContext
|
||||
takes precedence.
|
||||
format: int64
|
||||
type: integer
|
||||
runAsNonRoot:
|
||||
description: Indicates that the container must run as a non-root
|
||||
user. If true, the Kubelet will validate the image at runtime
|
||||
|
@ -1299,8 +1322,7 @@ spec:
|
|||
description: mountPropagation determines how mounts are
|
||||
propagated from the host to container and the other way
|
||||
around. When not set, MountPropagationHostToContainer
|
||||
is used. This field is alpha in 1.8 and can be reworked
|
||||
or removed in a future release.
|
||||
is used. This field is beta in 1.10.
|
||||
type: string
|
||||
name:
|
||||
description: This must match the Name of a Volume.
|
||||
|
@ -1877,6 +1899,90 @@ spec:
|
|||
the server serves requests under a different route prefix. For example
|
||||
for use with `kubectl proxy`.
|
||||
type: string
|
||||
ruleFileNamespaceSelector:
|
||||
description: A label selector is a label query over a set of resources.
|
||||
The result of matchLabels and matchExpressions are ANDed. An empty
|
||||
label selector matches all objects. A null label selector matches
|
||||
no objects.
|
||||
properties:
|
||||
matchExpressions:
|
||||
description: matchExpressions is a list of label selector requirements.
|
||||
The requirements are ANDed.
|
||||
items:
|
||||
description: A label selector requirement is a selector that contains
|
||||
values, a key, and an operator that relates the key and values.
|
||||
properties:
|
||||
key:
|
||||
description: key is the label key that the selector applies
|
||||
to.
|
||||
type: string
|
||||
operator:
|
||||
description: operator represents a key's relationship to a
|
||||
set of values. Valid operators are In, NotIn, Exists and
|
||||
DoesNotExist.
|
||||
type: string
|
||||
values:
|
||||
description: values is an array of string values. If the operator
|
||||
is In or NotIn, the values array must be non-empty. If the
|
||||
operator is Exists or DoesNotExist, the values array must
|
||||
be empty. This array is replaced during a strategic merge
|
||||
patch.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- key
|
||||
- operator
|
||||
type: array
|
||||
matchLabels:
|
||||
description: matchLabels is a map of {key,value} pairs. A single
|
||||
{key,value} in the matchLabels map is equivalent to an element
|
||||
of matchExpressions, whose key field is "key", the operator is
|
||||
"In", and the values array contains only "value". The requirements
|
||||
are ANDed.
|
||||
type: object
|
||||
ruleFileSelector:
|
||||
description: A label selector is a label query over a set of resources.
|
||||
The result of matchLabels and matchExpressions are ANDed. An empty
|
||||
label selector matches all objects. A null label selector matches
|
||||
no objects.
|
||||
properties:
|
||||
matchExpressions:
|
||||
description: matchExpressions is a list of label selector requirements.
|
||||
The requirements are ANDed.
|
||||
items:
|
||||
description: A label selector requirement is a selector that contains
|
||||
values, a key, and an operator that relates the key and values.
|
||||
properties:
|
||||
key:
|
||||
description: key is the label key that the selector applies
|
||||
to.
|
||||
type: string
|
||||
operator:
|
||||
description: operator represents a key's relationship to a
|
||||
set of values. Valid operators are In, NotIn, Exists and
|
||||
DoesNotExist.
|
||||
type: string
|
||||
values:
|
||||
description: values is an array of string values. If the operator
|
||||
is In or NotIn, the values array must be non-empty. If the
|
||||
operator is Exists or DoesNotExist, the values array must
|
||||
be empty. This array is replaced during a strategic merge
|
||||
patch.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- key
|
||||
- operator
|
||||
type: array
|
||||
matchLabels:
|
||||
description: matchLabels is a map of {key,value} pairs. A single
|
||||
{key,value} in the matchLabels map is equivalent to an element
|
||||
of matchExpressions, whose key field is "key", the operator is
|
||||
"In", and the values array contains only "value". The requirements
|
||||
are ANDed.
|
||||
type: object
|
||||
ruleSelector:
|
||||
description: A label selector is a label query over a set of resources.
|
||||
The result of matchLabels and matchExpressions are ANDed. An empty
|
||||
|
@ -1948,6 +2054,13 @@ spec:
|
|||
If unset, the Kubelet will not modify the ownership and permissions of any volume.
|
||||
format: int64
|
||||
type: integer
|
||||
runAsGroup:
|
||||
description: The GID to run the entrypoint of the container process.
|
||||
Uses runtime default if unset. May also be set in SecurityContext. If
|
||||
set in both SecurityContext and PodSecurityContext, the value
|
||||
specified in SecurityContext takes precedence for that container.
|
||||
format: int64
|
||||
type: integer
|
||||
runAsNonRoot:
|
||||
description: Indicates that the container must run as a non-root
|
||||
user. If true, the Kubelet will validate the image at runtime
|
||||
|
|
|
@ -16,8 +16,9 @@ data:
|
|||
\ - \"expr\": |\n sum by (namespace, label_name) (\n sum(kube_pod_container_resource_requests_memory_bytes{job=\"kube-state-metrics\"})
|
||||
by (namespace, pod)\n * on (namespace, pod) group_left(label_name)\n label_replace(kube_pod_labels{job=\"kube-state-metrics\"},
|
||||
\"pod_name\", \"$1\", \"pod\", \"(.*)\")\n )\n \"record\": \"namespace_name:kube_pod_container_resource_requests_memory_bytes:sum\"\n
|
||||
\ - \"expr\": |\n sum by (namespace, label_name) (\n sum(kube_pod_container_resource_requests_cpu_cores{job=\"kube-state-metrics\"})
|
||||
by (namespace, pod)\n * on (namespace, pod) group_left(label_name)\n label_replace(kube_pod_labels{job=\"kube-state-metrics\"},
|
||||
\ - \"expr\": |\n sum by (namespace, label_name) (\n sum(kube_pod_container_resource_requests_cpu_cores{job=\"kube-state-metrics\"}
|
||||
and on(pod) kube_pod_status_scheduled{condition=\"true\"}) by (namespace, pod)\n
|
||||
\ * on (namespace, pod) group_left(label_name)\n label_replace(kube_pod_labels{job=\"kube-state-metrics\"},
|
||||
\"pod_name\", \"$1\", \"pod\", \"(.*)\")\n )\n \"record\": \"namespace_name:kube_pod_container_resource_requests_cpu_cores:sum\"\n-
|
||||
\"name\": \"node.rules\"\n \"rules\": \n - \"expr\": \"sum(min(kube_pod_info)
|
||||
by (node))\"\n \"record\": \":kube_pod_info_node_count:\"\n - \"expr\": |\n
|
||||
|
|
|
@ -16,18 +16,10 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ericchiang/k8s"
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/log/level"
|
||||
"github.com/improbable-eng/thanos/pkg/reloader"
|
||||
"github.com/oklog/run"
|
||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||
|
@ -43,9 +35,6 @@ func main() {
|
|||
cfgFile := app.Flag("config-file", "config file watched by the reloader").
|
||||
String()
|
||||
|
||||
ruleListFile := app.Flag("rule-list-file", "file listing configmaps of rules to load dynamically").
|
||||
String()
|
||||
|
||||
cfgSubstFile := app.Flag("config-envsubst-file", "output file for environment variable substituted config file").
|
||||
String()
|
||||
|
||||
|
@ -59,15 +48,11 @@ func main() {
|
|||
os.Exit(2)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(*ruleDir, 0777); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
client, err := k8s.NewInClusterClient()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
if *ruleDir != "" {
|
||||
if err := os.MkdirAll(*ruleDir, 0777); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
var g run.Group
|
||||
|
@ -81,115 +66,9 @@ func main() {
|
|||
cancel()
|
||||
})
|
||||
}
|
||||
{
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
tick := time.NewTicker(1 * time.Minute)
|
||||
|
||||
rfet := newRuleFetcher(client, *ruleListFile, *ruleDir)
|
||||
|
||||
g.Add(func() error {
|
||||
defer tick.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-tick.C:
|
||||
if err := rfet.Refresh(ctx); err != nil {
|
||||
level.Error(logger).Log("msg", "updating rules failed", "err", err)
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}, func(error) {
|
||||
cancel()
|
||||
})
|
||||
}
|
||||
|
||||
if err := g.Run(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
type configMapRef struct {
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
type ruleFetcher struct {
|
||||
client *k8s.Client
|
||||
listFile string
|
||||
outDir string
|
||||
|
||||
lastHash [sha256.Size]byte
|
||||
}
|
||||
|
||||
func newRuleFetcher(client *k8s.Client, listFile, outDir string) *ruleFetcher {
|
||||
return &ruleFetcher{
|
||||
client: client,
|
||||
listFile: listFile,
|
||||
outDir: outDir,
|
||||
}
|
||||
}
|
||||
|
||||
func (rf *ruleFetcher) Refresh(ctx context.Context) error {
|
||||
b, err := ioutil.ReadFile(rf.listFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h := sha256.Sum256(b)
|
||||
if rf.lastHash == h {
|
||||
return nil
|
||||
}
|
||||
|
||||
var cms struct {
|
||||
Items []*configMapRef `json:"items"`
|
||||
}
|
||||
err = json.Unmarshal(b, &cms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := rf.refresh(ctx, cms.Items); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rf.lastHash = h
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rf *ruleFetcher) refresh(ctx context.Context, cms []*configMapRef) error {
|
||||
tmpdir := rf.outDir + ".tmp"
|
||||
|
||||
if err := os.MkdirAll(tmpdir, 0777); err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
for i, cm := range cms {
|
||||
parts := strings.Split(cm.Key, "/")
|
||||
if len(parts) != 2 {
|
||||
return fmt.Errorf("malformatted configmap key: %s, must be namespace/name", cm.Key)
|
||||
}
|
||||
namespace, name := parts[0], parts[1]
|
||||
|
||||
cm, err := rf.client.CoreV1().GetConfigMap(ctx, name, namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dir := filepath.Join(tmpdir, fmt.Sprintf("rules-%d", i))
|
||||
|
||||
if err = os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
for fn, content := range cm.Data {
|
||||
if err := ioutil.WriteFile(filepath.Join(dir, fn), []byte(content), 0666); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(rf.outDir); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tmpdir, rf.outDir)
|
||||
}
|
||||
|
|
|
@ -1900,6 +1900,90 @@ spec:
|
|||
the server serves requests under a different route prefix. For example
|
||||
for use with `kubectl proxy`.
|
||||
type: string
|
||||
ruleFileNamespaceSelector:
|
||||
description: A label selector is a label query over a set of resources.
|
||||
The result of matchLabels and matchExpressions are ANDed. An empty
|
||||
label selector matches all objects. A null label selector matches
|
||||
no objects.
|
||||
properties:
|
||||
matchExpressions:
|
||||
description: matchExpressions is a list of label selector requirements.
|
||||
The requirements are ANDed.
|
||||
items:
|
||||
description: A label selector requirement is a selector that contains
|
||||
values, a key, and an operator that relates the key and values.
|
||||
properties:
|
||||
key:
|
||||
description: key is the label key that the selector applies
|
||||
to.
|
||||
type: string
|
||||
operator:
|
||||
description: operator represents a key's relationship to a
|
||||
set of values. Valid operators are In, NotIn, Exists and
|
||||
DoesNotExist.
|
||||
type: string
|
||||
values:
|
||||
description: values is an array of string values. If the operator
|
||||
is In or NotIn, the values array must be non-empty. If the
|
||||
operator is Exists or DoesNotExist, the values array must
|
||||
be empty. This array is replaced during a strategic merge
|
||||
patch.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- key
|
||||
- operator
|
||||
type: array
|
||||
matchLabels:
|
||||
description: matchLabels is a map of {key,value} pairs. A single
|
||||
{key,value} in the matchLabels map is equivalent to an element
|
||||
of matchExpressions, whose key field is "key", the operator is
|
||||
"In", and the values array contains only "value". The requirements
|
||||
are ANDed.
|
||||
type: object
|
||||
ruleFileSelector:
|
||||
description: A label selector is a label query over a set of resources.
|
||||
The result of matchLabels and matchExpressions are ANDed. An empty
|
||||
label selector matches all objects. A null label selector matches
|
||||
no objects.
|
||||
properties:
|
||||
matchExpressions:
|
||||
description: matchExpressions is a list of label selector requirements.
|
||||
The requirements are ANDed.
|
||||
items:
|
||||
description: A label selector requirement is a selector that contains
|
||||
values, a key, and an operator that relates the key and values.
|
||||
properties:
|
||||
key:
|
||||
description: key is the label key that the selector applies
|
||||
to.
|
||||
type: string
|
||||
operator:
|
||||
description: operator represents a key's relationship to a
|
||||
set of values. Valid operators are In, NotIn, Exists and
|
||||
DoesNotExist.
|
||||
type: string
|
||||
values:
|
||||
description: values is an array of string values. If the operator
|
||||
is In or NotIn, the values array must be non-empty. If the
|
||||
operator is Exists or DoesNotExist, the values array must
|
||||
be empty. This array is replaced during a strategic merge
|
||||
patch.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- key
|
||||
- operator
|
||||
type: array
|
||||
matchLabels:
|
||||
description: matchLabels is a map of {key,value} pairs. A single
|
||||
{key,value} in the matchLabels map is equivalent to an element
|
||||
of matchExpressions, whose key field is "key", the operator is
|
||||
"In", and the values array contains only "value". The requirements
|
||||
are ANDed.
|
||||
type: object
|
||||
ruleSelector:
|
||||
description: A label selector is a label query over a set of resources.
|
||||
The result of matchLabels and matchExpressions are ANDed. An empty
|
||||
|
|
343
example/prometheus-operator-crd/rulefile.crd.yaml
Normal file
343
example/prometheus-operator-crd/rulefile.crd.yaml
Normal file
|
@ -0,0 +1,343 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: rulefiles.monitoring.coreos.com
|
||||
spec:
|
||||
group: monitoring.coreos.com
|
||||
names:
|
||||
kind: RuleFile
|
||||
plural: rulefiles
|
||||
scope: Namespaced
|
||||
validation:
|
||||
openAPIV3Schema:
|
||||
description: RuleFile defines alerting rules for a Prometheus instance
|
||||
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/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/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
description: ObjectMeta is metadata that all persisted resources must have,
|
||||
which includes all objects users must create.
|
||||
properties:
|
||||
annotations:
|
||||
description: 'Annotations is an unstructured key value map stored with
|
||||
a resource that may be set by external tools to store and retrieve
|
||||
arbitrary metadata. They are not queryable and should be preserved
|
||||
when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations'
|
||||
type: object
|
||||
clusterName:
|
||||
description: The name of the cluster which the object belongs to. This
|
||||
is used to distinguish resources with same name and namespace in different
|
||||
clusters. This field is not set anywhere right now and apiserver is
|
||||
going to ignore it if set in create or update request.
|
||||
type: string
|
||||
creationTimestamp:
|
||||
format: date-time
|
||||
type: string
|
||||
deletionGracePeriodSeconds:
|
||||
description: Number of seconds allowed for this object to gracefully
|
||||
terminate before it will be removed from the system. Only set when
|
||||
deletionTimestamp is also set. May only be shortened. Read-only.
|
||||
format: int64
|
||||
type: integer
|
||||
deletionTimestamp:
|
||||
format: date-time
|
||||
type: string
|
||||
finalizers:
|
||||
description: Must be empty before the object is deleted from the registry.
|
||||
Each entry is an identifier for the responsible component that will
|
||||
remove the entry from the list. If the deletionTimestamp of the object
|
||||
is non-nil, entries in this list can only be removed.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
generateName:
|
||||
description: |-
|
||||
GenerateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.
|
||||
|
||||
If this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header).
|
||||
|
||||
Applied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency
|
||||
type: string
|
||||
generation:
|
||||
description: A sequence number representing a specific generation of
|
||||
the desired state. Populated by the system. Read-only.
|
||||
format: int64
|
||||
type: integer
|
||||
initializers:
|
||||
description: Initializers tracks the progress of initialization.
|
||||
properties:
|
||||
pending:
|
||||
description: Pending is a list of initializers that must execute
|
||||
in order before this object is visible. When the last pending
|
||||
initializer is removed, and no failing result is set, the initializers
|
||||
struct will be set to nil and the object is considered as initialized
|
||||
and visible to all clients.
|
||||
items:
|
||||
description: Initializer is information about an initializer that
|
||||
has not yet completed.
|
||||
properties:
|
||||
name:
|
||||
description: name of the process that is responsible for initializing
|
||||
this object.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: array
|
||||
result:
|
||||
description: Status is a return value for calls that don't return
|
||||
other objects.
|
||||
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/api-conventions.md#resources'
|
||||
type: string
|
||||
code:
|
||||
description: Suggested HTTP return code for this status, 0 if
|
||||
not set.
|
||||
format: int32
|
||||
type: integer
|
||||
details:
|
||||
description: StatusDetails is a set of additional properties
|
||||
that MAY be set by the server to provide additional information
|
||||
about a response. The Reason field of a Status object defines
|
||||
what attributes will be set. Clients must ignore fields that
|
||||
do not match the defined type of each attribute, and should
|
||||
assume that any attribute may be empty, invalid, or under
|
||||
defined.
|
||||
properties:
|
||||
causes:
|
||||
description: The Causes array includes more details associated
|
||||
with the StatusReason failure. Not all StatusReasons may
|
||||
provide detailed causes.
|
||||
items:
|
||||
description: StatusCause provides more information about
|
||||
an api.Status failure, including cases when multiple
|
||||
errors are encountered.
|
||||
properties:
|
||||
field:
|
||||
description: |-
|
||||
The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional.
|
||||
|
||||
Examples:
|
||||
"name" - the field "name" on the current resource
|
||||
"items[0].name" - the field "name" on the first array entry in "items"
|
||||
type: string
|
||||
message:
|
||||
description: A human-readable description of the cause
|
||||
of the error. This field may be presented as-is
|
||||
to a reader.
|
||||
type: string
|
||||
reason:
|
||||
description: A machine-readable description of the
|
||||
cause of the error. If this value is empty there
|
||||
is no information available.
|
||||
type: string
|
||||
type: array
|
||||
group:
|
||||
description: The group attribute of the resource associated
|
||||
with the status StatusReason.
|
||||
type: string
|
||||
kind:
|
||||
description: 'The kind attribute of the resource associated
|
||||
with the status StatusReason. On some operations may differ
|
||||
from the requested resource Kind. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
name:
|
||||
description: The name attribute of the resource associated
|
||||
with the status StatusReason (when there is a single name
|
||||
which can be described).
|
||||
type: string
|
||||
retryAfterSeconds:
|
||||
description: If specified, the time in seconds before the
|
||||
operation should be retried. Some errors may indicate
|
||||
the client must take an alternate action - for those errors
|
||||
this field may indicate how long to wait before taking
|
||||
the alternate action.
|
||||
format: int32
|
||||
type: integer
|
||||
uid:
|
||||
description: 'UID of the resource. (when there is a single
|
||||
resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
|
||||
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/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
message:
|
||||
description: A human-readable description of the status of this
|
||||
operation.
|
||||
type: string
|
||||
metadata:
|
||||
description: ListMeta describes metadata that synthetic resources
|
||||
must have, including lists and various status objects. A resource
|
||||
may have only one of {ObjectMeta, ListMeta}.
|
||||
properties:
|
||||
continue:
|
||||
description: continue may be set if the user set a limit
|
||||
on the number of items returned, and indicates that the
|
||||
server has more data available. The value is opaque and
|
||||
may be used to issue another request to the endpoint that
|
||||
served this list to retrieve the next set of available
|
||||
objects. Continuing a list may not be possible if the
|
||||
server configuration has changed or more than a few minutes
|
||||
have passed. The resourceVersion field returned when using
|
||||
this continue value will be identical to the value in
|
||||
the first response.
|
||||
type: string
|
||||
resourceVersion:
|
||||
description: 'String that identifies the server''s internal
|
||||
version of this object that can be used by clients to
|
||||
determine when objects have changed. Value must be treated
|
||||
as opaque by clients and passed unmodified back to the
|
||||
server. Populated by the system. Read-only. More info:
|
||||
https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency'
|
||||
type: string
|
||||
selfLink:
|
||||
description: selfLink is a URL representing this object.
|
||||
Populated by the system. Read-only.
|
||||
type: string
|
||||
reason:
|
||||
description: A machine-readable description of why this operation
|
||||
is in the "Failure" status. If this value is empty there is
|
||||
no information available. A Reason clarifies an HTTP status
|
||||
code but does not override it.
|
||||
type: string
|
||||
status:
|
||||
description: 'Status of the operation. One of: "Success" or
|
||||
"Failure". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status'
|
||||
type: string
|
||||
required:
|
||||
- pending
|
||||
labels:
|
||||
description: 'Map of string keys and values that can be used to organize
|
||||
and categorize (scope and select) objects. May match selectors of
|
||||
replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels'
|
||||
type: object
|
||||
name:
|
||||
description: 'Name must be unique within a namespace. Is required when
|
||||
creating resources, although some resources may allow a client to
|
||||
request the generation of an appropriate name automatically. Name
|
||||
is primarily intended for creation idempotence and configuration definition.
|
||||
Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
|
||||
type: string
|
||||
namespace:
|
||||
description: |-
|
||||
Namespace defines the space within each name must be unique. An empty namespace is equivalent to the "default" namespace, but "default" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.
|
||||
|
||||
Must be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces
|
||||
type: string
|
||||
ownerReferences:
|
||||
description: List of objects depended by this object. If ALL objects
|
||||
in the list have been deleted, this object will be garbage collected.
|
||||
If this object is managed by a controller, then an entry in this list
|
||||
will point to this controller, with the controller field set to true.
|
||||
There cannot be more than one managing controller.
|
||||
items:
|
||||
description: OwnerReference contains enough information to let you
|
||||
identify an owning object. Currently, an owning object must be in
|
||||
the same namespace, so there is no namespace field.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: API version of the referent.
|
||||
type: string
|
||||
blockOwnerDeletion:
|
||||
description: If true, AND if the owner has the "foregroundDeletion"
|
||||
finalizer, then the owner cannot be deleted from the key-value
|
||||
store until this reference is removed. Defaults to false. To
|
||||
set this field, a user needs "delete" permission of the owner,
|
||||
otherwise 422 (Unprocessable Entity) will be returned.
|
||||
type: boolean
|
||||
controller:
|
||||
description: If true, this reference points to the managing controller.
|
||||
type: boolean
|
||||
kind:
|
||||
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
name:
|
||||
description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
|
||||
type: string
|
||||
uid:
|
||||
description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
|
||||
type: string
|
||||
required:
|
||||
- apiVersion
|
||||
- kind
|
||||
- name
|
||||
- uid
|
||||
type: array
|
||||
resourceVersion:
|
||||
description: |-
|
||||
An opaque value that represents the internal version of this object that can be used by clients to determine when objects have changed. May be used for optimistic concurrency, change detection, and the watch operation on a resource or set of resources. Clients must treat these values as opaque and passed unmodified back to the server. They may only be valid for a particular resource or set of resources.
|
||||
|
||||
Populated by the system. Read-only. Value must be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency
|
||||
type: string
|
||||
selfLink:
|
||||
description: SelfLink is a URL representing this object. Populated by
|
||||
the system. Read-only.
|
||||
type: string
|
||||
uid:
|
||||
description: |-
|
||||
UID is the unique in time and space value for this object. It is typically generated by the server on successful creation of a resource and is not allowed to change on PUT operations.
|
||||
|
||||
Populated by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids
|
||||
type: string
|
||||
spec:
|
||||
description: RuleFileSpec contains specification parameters for a Rule.
|
||||
properties:
|
||||
groups:
|
||||
description: Content of Prometheus rule file
|
||||
items:
|
||||
description: RuleGroup is a list of sequentially evaluated recording
|
||||
and alerting rules.
|
||||
properties:
|
||||
interval:
|
||||
format: int64
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
rules:
|
||||
items:
|
||||
description: Rule describes an alerting or recording rule.
|
||||
properties:
|
||||
alert:
|
||||
type: string
|
||||
annotations:
|
||||
type: object
|
||||
expr:
|
||||
type: string
|
||||
for:
|
||||
format: int64
|
||||
type: integer
|
||||
labels:
|
||||
type: object
|
||||
record:
|
||||
type: string
|
||||
required:
|
||||
- expr
|
||||
type: array
|
||||
required:
|
||||
- name
|
||||
- rules
|
||||
type: array
|
||||
required:
|
||||
- spec
|
||||
version: v1
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: null
|
|
@ -23,6 +23,7 @@ rules:
|
|||
- prometheuses/finalizers
|
||||
- alertmanagers/finalizers
|
||||
- servicemonitors
|
||||
- rulefiles
|
||||
verbs:
|
||||
- "*"
|
||||
- apiGroups:
|
||||
|
|
|
@ -29,6 +29,7 @@ const (
|
|||
PrometheusKindKey = "prometheus"
|
||||
AlertManagerKindKey = "alertmanager"
|
||||
ServiceMonitorKindKey = "servicemonitor"
|
||||
RuleFileKindKey = "rulefile"
|
||||
)
|
||||
|
||||
type CrdKind struct {
|
||||
|
@ -42,6 +43,7 @@ type CrdKinds struct {
|
|||
Prometheus CrdKind
|
||||
Alertmanager CrdKind
|
||||
ServiceMonitor CrdKind
|
||||
RuleFile CrdKind
|
||||
}
|
||||
|
||||
var DefaultCrdKinds CrdKinds = CrdKinds{
|
||||
|
@ -49,6 +51,7 @@ var DefaultCrdKinds CrdKinds = CrdKinds{
|
|||
Prometheus: CrdKind{Plural: PrometheusName, Kind: PrometheusesKind, SpecName: "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.Prometheus"},
|
||||
ServiceMonitor: CrdKind{Plural: ServiceMonitorName, Kind: ServiceMonitorsKind, SpecName: "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.ServiceMonitor"},
|
||||
Alertmanager: CrdKind{Plural: AlertmanagerName, Kind: AlertmanagersKind, SpecName: "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.Alertmanager"},
|
||||
RuleFile: CrdKind{Plural: RuleFileName, Kind: RuleFilesKind, SpecName: "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.RuleFile"},
|
||||
}
|
||||
|
||||
// Implement the flag.Value interface
|
||||
|
@ -60,10 +63,12 @@ func (crdkinds *CrdKinds) String() string {
|
|||
func (crdkinds *CrdKinds) Set(value string) error {
|
||||
*crdkinds = DefaultCrdKinds
|
||||
if value == "" {
|
||||
value = fmt.Sprintf("%s=%s:%s,%s=%s:%s,%s=%s:%s",
|
||||
value = fmt.Sprintf("%s=%s:%s,%s=%s:%s,%s=%s:%s,%s=%s:%s",
|
||||
PrometheusKindKey, PrometheusesKind, PrometheusName,
|
||||
AlertManagerKindKey, AlertmanagersKind, AlertmanagerName,
|
||||
ServiceMonitorKindKey, ServiceMonitorsKind, ServiceMonitorName)
|
||||
ServiceMonitorKindKey, ServiceMonitorsKind, ServiceMonitorName,
|
||||
RuleFileKindKey, RuleFilesKind, RuleFileName,
|
||||
)
|
||||
}
|
||||
splited := strings.Split(value, ",")
|
||||
for _, pair := range splited {
|
||||
|
@ -77,6 +82,8 @@ func (crdkinds *CrdKinds) Set(value string) error {
|
|||
(*crdkinds).ServiceMonitor = crdKind
|
||||
case AlertManagerKindKey:
|
||||
(*crdkinds).Alertmanager = crdKind
|
||||
case RuleFileKindKey:
|
||||
(*crdkinds).RuleFile = crdKind
|
||||
default:
|
||||
fmt.Printf("Warning: unknown kind: %s... ignoring", kindKey)
|
||||
}
|
||||
|
@ -93,6 +100,7 @@ type MonitoringV1Interface interface {
|
|||
PrometheusesGetter
|
||||
AlertmanagersGetter
|
||||
ServiceMonitorsGetter
|
||||
RuleFilesGetter
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=false
|
||||
|
@ -114,6 +122,10 @@ func (c *MonitoringV1Client) ServiceMonitors(namespace string) ServiceMonitorInt
|
|||
return newServiceMonitors(c.restClient, c.dynamicClient, c.crdKinds.ServiceMonitor, namespace)
|
||||
}
|
||||
|
||||
func (c *MonitoringV1Client) RuleFiles(namespace string) RuleFileInterface {
|
||||
return newRuleFiles(c.restClient, c.dynamicClient, c.crdKinds.RuleFile, namespace)
|
||||
}
|
||||
|
||||
func (c *MonitoringV1Client) RESTClient() rest.Interface {
|
||||
return c.restClient
|
||||
}
|
||||
|
|
|
@ -787,9 +787,21 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
|||
Ref: ref("github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.StorageSpec"),
|
||||
},
|
||||
},
|
||||
"ruleFileSelector": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A selector to select which RuleFiles to mount for loading alerting rules from.",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"),
|
||||
},
|
||||
},
|
||||
"ruleSelector": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A selector to select which ConfigMaps to mount for loading rule files from.",
|
||||
Description: "DEPRECATED with Prometheus Operator 'v0.20.0'. Any value in this field will just be copied to 'RuleFileSelector' field",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"),
|
||||
},
|
||||
},
|
||||
"ruleFileNamespaceSelector": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Namespaces to be selected for RuleFiles discovery. If empty, only check own namespace.",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"),
|
||||
},
|
||||
},
|
||||
|
@ -1193,6 +1205,210 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
|||
Dependencies: []string{
|
||||
"github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.BasicAuth", "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.RelabelConfig", "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.TLSConfig"},
|
||||
},
|
||||
"github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.Rule": {
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Rule describes an alerting or recording rule.",
|
||||
Properties: map[string]spec.Schema{
|
||||
"record": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"alert": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"expr": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"for": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"integer"},
|
||||
Format: "int64",
|
||||
},
|
||||
},
|
||||
"labels": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"object"},
|
||||
AdditionalProperties: &spec.SchemaOrBool{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"annotations": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"object"},
|
||||
AdditionalProperties: &spec.SchemaOrBool{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"expr"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{},
|
||||
},
|
||||
"github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.RuleFile": {
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "RuleFile defines alerting rules for a Prometheus instance",
|
||||
Properties: map[string]spec.Schema{
|
||||
"kind": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
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/api-conventions.md#types-kinds",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"apiVersion": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
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/api-conventions.md#resources",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"metadata": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Standard object’s metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
|
||||
},
|
||||
},
|
||||
"spec": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Specification of desired alerting rule definitions for Prometheus.",
|
||||
Ref: ref("github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.RuleFileSpec"),
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"spec"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.RuleFileSpec", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
|
||||
},
|
||||
"github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.RuleFileList": {
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A list of RuleFiles.",
|
||||
Properties: map[string]spec.Schema{
|
||||
"kind": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
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/api-conventions.md#types-kinds",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"apiVersion": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
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/api-conventions.md#resources",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"metadata": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Standard list metadata More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
|
||||
},
|
||||
},
|
||||
"items": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "List of Rules",
|
||||
Type: []string{"array"},
|
||||
Items: &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Ref: ref("github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.RuleFile"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"items"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.RuleFile", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
|
||||
},
|
||||
"github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.RuleFileSpec": {
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "RuleFileSpec contains specification parameters for a Rule.",
|
||||
Properties: map[string]spec.Schema{
|
||||
"groups": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Content of Prometheus rule file",
|
||||
Type: []string{"array"},
|
||||
Items: &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Ref: ref("github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.RuleGroup"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.RuleGroup"},
|
||||
},
|
||||
"github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.RuleGroup": {
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "RuleGroup is a list of sequentially evaluated recording and alerting rules.",
|
||||
Properties: map[string]spec.Schema{
|
||||
"name": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"interval": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"integer"},
|
||||
Format: "int64",
|
||||
},
|
||||
},
|
||||
"rules": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"array"},
|
||||
Items: &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Ref: ref("github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.Rule"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"name", "rules"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.Rule"},
|
||||
},
|
||||
"github.com/coreos/prometheus-operator/pkg/client/monitoring/v1.ServiceMonitor": {
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
|
|
200
pkg/client/monitoring/v1/rulefile.go
Normal file
200
pkg/client/monitoring/v1/rulefile.go
Normal file
|
@ -0,0 +1,200 @@
|
|||
// Copyright 2016 The prometheus-operator Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
const (
|
||||
RuleFilesKind = "RuleFile"
|
||||
RuleFileName = "rulefiles"
|
||||
)
|
||||
|
||||
type RuleFilesGetter interface {
|
||||
RuleFiles(namespace string) RuleFileInterface
|
||||
}
|
||||
|
||||
var _ RuleFileInterface = &rulefiles{}
|
||||
|
||||
type RuleFileInterface interface {
|
||||
Create(*RuleFile) (*RuleFile, error)
|
||||
Get(name string, opts metav1.GetOptions) (*RuleFile, error)
|
||||
Update(*RuleFile) (*RuleFile, error)
|
||||
Delete(name string, options *metav1.DeleteOptions) error
|
||||
List(opts metav1.ListOptions) (runtime.Object, error)
|
||||
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||
DeleteCollection(dopts *metav1.DeleteOptions, lopts metav1.ListOptions) error
|
||||
}
|
||||
|
||||
type rulefiles struct {
|
||||
restClient rest.Interface
|
||||
client dynamic.ResourceInterface
|
||||
crdKind CrdKind
|
||||
ns string
|
||||
}
|
||||
|
||||
func newRuleFiles(r rest.Interface, c *dynamic.Client, crdKind CrdKind, namespace string) *rulefiles {
|
||||
return &rulefiles{
|
||||
restClient: r,
|
||||
client: c.Resource(
|
||||
&metav1.APIResource{
|
||||
Kind: crdKind.Kind,
|
||||
Name: crdKind.Plural,
|
||||
Namespaced: true,
|
||||
},
|
||||
namespace,
|
||||
),
|
||||
crdKind: crdKind,
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *rulefiles) Create(o *RuleFile) (*RuleFile, error) {
|
||||
us, err := UnstructuredFromRuleFile(o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
us, err = s.client.Create(us)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return RuleFileFromUnstructured(us)
|
||||
}
|
||||
|
||||
func (s *rulefiles) Get(name string, opts metav1.GetOptions) (*RuleFile, error) {
|
||||
obj, err := s.client.Get(name, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return RuleFileFromUnstructured(obj)
|
||||
}
|
||||
|
||||
func (s *rulefiles) Update(o *RuleFile) (*RuleFile, error) {
|
||||
us, err := UnstructuredFromRuleFile(o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
curs, err := s.Get(o.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to get current version for update")
|
||||
}
|
||||
us.SetResourceVersion(curs.ObjectMeta.ResourceVersion)
|
||||
|
||||
us, err = s.client.Update(us)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return RuleFileFromUnstructured(us)
|
||||
}
|
||||
|
||||
func (s *rulefiles) Delete(name string, options *metav1.DeleteOptions) error {
|
||||
return s.client.Delete(name, options)
|
||||
}
|
||||
|
||||
func (s *rulefiles) List(opts metav1.ListOptions) (runtime.Object, error) {
|
||||
req := s.restClient.Get().
|
||||
Namespace(s.ns).
|
||||
Resource(s.crdKind.Plural)
|
||||
|
||||
b, err := req.DoRaw()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var sm RuleFileList
|
||||
return &sm, json.Unmarshal(b, &sm)
|
||||
}
|
||||
|
||||
func (s *rulefiles) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||
r, err := s.restClient.Get().
|
||||
Prefix("watch").
|
||||
Namespace(s.ns).
|
||||
Resource(s.crdKind.Plural).
|
||||
Stream()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return watch.NewStreamWatcher(&ruleFileDecoder{
|
||||
dec: json.NewDecoder(r),
|
||||
close: r.Close,
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (s *rulefiles) DeleteCollection(dopts *metav1.DeleteOptions, lopts metav1.ListOptions) error {
|
||||
return s.client.DeleteCollection(dopts, lopts)
|
||||
}
|
||||
|
||||
// RuleFileFromUnstructured unmarshals a RuleFile object from dynamic client's unstructured
|
||||
func RuleFileFromUnstructured(r *unstructured.Unstructured) (*RuleFile, error) {
|
||||
b, err := json.Marshal(r.Object)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var s RuleFile
|
||||
if err := json.Unmarshal(b, &s); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.TypeMeta.Kind = RuleFilesKind
|
||||
s.TypeMeta.APIVersion = Group + "/" + Version
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
// UnstructuredFromRuleFile marshals a RuleFile object into dynamic client's unstructured
|
||||
func UnstructuredFromRuleFile(s *RuleFile) (*unstructured.Unstructured, error) {
|
||||
s.TypeMeta.Kind = RuleFilesKind
|
||||
s.TypeMeta.APIVersion = Group + "/" + Version
|
||||
b, err := json.Marshal(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var r unstructured.Unstructured
|
||||
if err := json.Unmarshal(b, &r.Object); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
type ruleFileDecoder struct {
|
||||
dec *json.Decoder
|
||||
close func() error
|
||||
}
|
||||
|
||||
func (d *ruleFileDecoder) Close() {
|
||||
d.close()
|
||||
}
|
||||
|
||||
func (d *ruleFileDecoder) Decode() (action watch.EventType, object runtime.Object, err error) {
|
||||
var e struct {
|
||||
Type watch.EventType
|
||||
Object RuleFile
|
||||
}
|
||||
if err := d.dec.Decode(&e); err != nil {
|
||||
return watch.Error, nil, err
|
||||
}
|
||||
return e.Type, &e.Object, nil
|
||||
}
|
|
@ -15,6 +15,8 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
@ -98,8 +100,14 @@ type PrometheusSpec struct {
|
|||
RoutePrefix string `json:"routePrefix,omitempty"`
|
||||
// Storage spec to specify how storage shall be used.
|
||||
Storage *StorageSpec `json:"storage,omitempty"`
|
||||
// A selector to select which ConfigMaps to mount for loading rule files from.
|
||||
// A selector to select which RuleFiles to mount for loading alerting rules from.
|
||||
RuleFileSelector *metav1.LabelSelector `json:"ruleFileSelector,omitempty"`
|
||||
// DEPRECATED with Prometheus Operator 'v0.20.0'. Any value in this field
|
||||
// will just be copied to 'RuleFileSelector' field
|
||||
RuleSelector *metav1.LabelSelector `json:"ruleSelector,omitempty"`
|
||||
// Namespaces to be selected for RuleFiles discovery. If empty, only
|
||||
// check own namespace.
|
||||
RuleFileNamespaceSelector *metav1.LabelSelector `json:"ruleFileNamespaceSelector,omitempty"`
|
||||
// Define details regarding alerting.
|
||||
Alerting *AlertingSpec `json:"alerting,omitempty"`
|
||||
// Define resources requests and limits for single Pods.
|
||||
|
@ -397,6 +405,57 @@ type ServiceMonitorList struct {
|
|||
Items []*ServiceMonitor `json:"items"`
|
||||
}
|
||||
|
||||
// A list of RuleFiles.
|
||||
// +k8s:openapi-gen=true
|
||||
type RuleFileList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard list metadata
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
// List of Rules
|
||||
Items []*RuleFile `json:"items"`
|
||||
}
|
||||
|
||||
// RuleFile defines alerting rules for a Prometheus instance
|
||||
// +k8s:openapi-gen=true
|
||||
type RuleFile struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object’s metadata. More info:
|
||||
// http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
// Specification of desired alerting rule definitions for Prometheus.
|
||||
Spec RuleFileSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// RuleFileSpec contains specification parameters for a Rule.
|
||||
// +k8s:openapi-gen=true
|
||||
type RuleFileSpec struct {
|
||||
// Content of Prometheus rule file
|
||||
Groups []RuleGroup `json:"groups,omitempty"`
|
||||
}
|
||||
|
||||
// RuleGroup and Rule are copied instead of vendored because the
|
||||
// upstream Prometheus struct definitions don't have json struct tags.
|
||||
|
||||
// RuleGroup is a list of sequentially evaluated recording and alerting rules.
|
||||
// +k8s:openapi-gen=true
|
||||
type RuleGroup struct {
|
||||
Name string `json:"name"`
|
||||
Interval time.Duration `json:"interval,omitempty"`
|
||||
Rules []Rule `json:"rules"`
|
||||
}
|
||||
|
||||
// Rule describes an alerting or recording rule.
|
||||
// +k8s:openapi-gen=true
|
||||
type Rule struct {
|
||||
Record string `json:"record,omitempty"`
|
||||
Alert string `json:"alert,omitempty"`
|
||||
Expr string `json:"expr"`
|
||||
For time.Duration `json:"for,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
}
|
||||
|
||||
// Describes an Alertmanager cluster.
|
||||
// +k8s:openapi-gen=true
|
||||
type Alertmanager struct {
|
||||
|
@ -550,3 +609,11 @@ func (l *ServiceMonitor) DeepCopyObject() runtime.Object {
|
|||
func (l *ServiceMonitorList) DeepCopyObject() runtime.Object {
|
||||
return l.DeepCopy()
|
||||
}
|
||||
|
||||
func (f *RuleFile) DeepCopyObject() runtime.Object {
|
||||
return f.DeepCopy()
|
||||
}
|
||||
|
||||
func (l *RuleFileList) DeepCopyObject() runtime.Object {
|
||||
return l.DeepCopy()
|
||||
}
|
||||
|
|
|
@ -274,6 +274,7 @@ func (in *CrdKinds) DeepCopyInto(out *CrdKinds) {
|
|||
out.Prometheus = in.Prometheus
|
||||
out.Alertmanager = in.Alertmanager
|
||||
out.ServiceMonitor = in.ServiceMonitor
|
||||
out.RuleFile = in.RuleFile
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -485,6 +486,15 @@ func (in *PrometheusSpec) DeepCopyInto(out *PrometheusSpec) {
|
|||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
if in.RuleFileSelector != nil {
|
||||
in, out := &in.RuleFileSelector, &out.RuleFileSelector
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(meta_v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
if in.RuleSelector != nil {
|
||||
in, out := &in.RuleSelector, &out.RuleSelector
|
||||
if *in == nil {
|
||||
|
@ -494,6 +504,15 @@ func (in *PrometheusSpec) DeepCopyInto(out *PrometheusSpec) {
|
|||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
if in.RuleFileNamespaceSelector != nil {
|
||||
in, out := &in.RuleFileNamespaceSelector, &out.RuleFileNamespaceSelector
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(meta_v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
if in.Alerting != nil {
|
||||
in, out := &in.Alerting, &out.Alerting
|
||||
if *in == nil {
|
||||
|
@ -712,6 +731,131 @@ func (in *RemoteWriteSpec) DeepCopy() *RemoteWriteSpec {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Rule) DeepCopyInto(out *Rule) {
|
||||
*out = *in
|
||||
if in.Labels != nil {
|
||||
in, out := &in.Labels, &out.Labels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.Annotations != nil {
|
||||
in, out := &in.Annotations, &out.Annotations
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Rule.
|
||||
func (in *Rule) DeepCopy() *Rule {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Rule)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RuleFile) DeepCopyInto(out *RuleFile) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuleFile.
|
||||
func (in *RuleFile) DeepCopy() *RuleFile {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RuleFile)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RuleFileList) DeepCopyInto(out *RuleFileList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]*RuleFile, len(*in))
|
||||
for i := range *in {
|
||||
if (*in)[i] == nil {
|
||||
(*out)[i] = nil
|
||||
} else {
|
||||
(*out)[i] = new(RuleFile)
|
||||
(*in)[i].DeepCopyInto((*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuleFileList.
|
||||
func (in *RuleFileList) DeepCopy() *RuleFileList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RuleFileList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RuleFileSpec) DeepCopyInto(out *RuleFileSpec) {
|
||||
*out = *in
|
||||
if in.Groups != nil {
|
||||
in, out := &in.Groups, &out.Groups
|
||||
*out = make([]RuleGroup, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuleFileSpec.
|
||||
func (in *RuleFileSpec) DeepCopy() *RuleFileSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RuleFileSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RuleGroup) DeepCopyInto(out *RuleGroup) {
|
||||
*out = *in
|
||||
if in.Rules != nil {
|
||||
in, out := &in.Rules, &out.Rules
|
||||
*out = make([]Rule, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuleGroup.
|
||||
func (in *RuleGroup) DeepCopy() *RuleGroup {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RuleGroup)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServiceMonitor) DeepCopyInto(out *ServiceMonitor) {
|
||||
*out = *in
|
||||
|
|
|
@ -16,6 +16,8 @@ package prometheus
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
@ -58,12 +60,13 @@ type Operator struct {
|
|||
crdclient apiextensionsclient.Interface
|
||||
logger log.Logger
|
||||
|
||||
promInf cache.SharedIndexInformer
|
||||
smonInf cache.SharedIndexInformer
|
||||
cmapInf cache.SharedIndexInformer
|
||||
secrInf cache.SharedIndexInformer
|
||||
ssetInf cache.SharedIndexInformer
|
||||
nsInf cache.SharedIndexInformer
|
||||
promInf cache.SharedIndexInformer
|
||||
smonInf cache.SharedIndexInformer
|
||||
ruleFileInf cache.SharedIndexInformer
|
||||
cmapInf cache.SharedIndexInformer
|
||||
secrInf cache.SharedIndexInformer
|
||||
ssetInf cache.SharedIndexInformer
|
||||
nsInf cache.SharedIndexInformer
|
||||
|
||||
queue workqueue.RateLimitingInterface
|
||||
|
||||
|
@ -213,6 +216,19 @@ func New(conf Config, logger log.Logger) (*Operator, error) {
|
|||
UpdateFunc: c.handleSmonUpdate,
|
||||
})
|
||||
|
||||
c.ruleFileInf = cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: mclient.MonitoringV1().RuleFiles(c.config.Namespace).List,
|
||||
WatchFunc: mclient.MonitoringV1().RuleFiles(c.config.Namespace).Watch,
|
||||
},
|
||||
&monitoringv1.RuleFile{}, resyncPeriod, cache.Indexers{},
|
||||
)
|
||||
c.ruleFileInf.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.handleRuleAdd,
|
||||
DeleteFunc: c.handleRuleDelete,
|
||||
UpdateFunc: c.handleRuleUpdate,
|
||||
})
|
||||
|
||||
c.cmapInf = cache.NewSharedIndexInformer(
|
||||
cache.NewListWatchFromClient(c.kclient.Core().RESTClient(), "configmaps", c.config.Namespace, fields.Everything()),
|
||||
&v1.ConfigMap{}, resyncPeriod, cache.Indexers{},
|
||||
|
@ -296,6 +312,7 @@ func (c *Operator) Run(stopc <-chan struct{}) error {
|
|||
|
||||
go c.promInf.Run(stopc)
|
||||
go c.smonInf.Run(stopc)
|
||||
go c.ruleFileInf.Run(stopc)
|
||||
go c.cmapInf.Run(stopc)
|
||||
go c.secrInf.Run(stopc)
|
||||
go c.ssetInf.Run(stopc)
|
||||
|
@ -470,6 +487,7 @@ func (c *Operator) syncNodeEndpoints() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// TODO: Don't enque just for the namespace
|
||||
func (c *Operator) handleSmonAdd(obj interface{}) {
|
||||
o, ok := c.getObject(obj)
|
||||
if ok {
|
||||
|
@ -477,6 +495,7 @@ func (c *Operator) handleSmonAdd(obj interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Don't enque just for the namespace
|
||||
func (c *Operator) handleSmonUpdate(old, cur interface{}) {
|
||||
o, ok := c.getObject(cur)
|
||||
if ok {
|
||||
|
@ -484,6 +503,7 @@ func (c *Operator) handleSmonUpdate(old, cur interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Don't enque just for the namespace
|
||||
func (c *Operator) handleSmonDelete(obj interface{}) {
|
||||
o, ok := c.getObject(obj)
|
||||
if ok {
|
||||
|
@ -491,6 +511,31 @@ func (c *Operator) handleSmonDelete(obj interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Don't enque just for the namespace
|
||||
func (c *Operator) handleRuleAdd(obj interface{}) {
|
||||
o, ok := c.getObject(obj)
|
||||
if ok {
|
||||
c.enqueueForNamespace(o.GetNamespace())
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Don't enque just for the namespace
|
||||
func (c *Operator) handleRuleUpdate(old, cur interface{}) {
|
||||
o, ok := c.getObject(cur)
|
||||
if ok {
|
||||
c.enqueueForNamespace(o.GetNamespace())
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Don't enque just for the namespace
|
||||
func (c *Operator) handleRuleDelete(obj interface{}) {
|
||||
o, ok := c.getObject(obj)
|
||||
if ok {
|
||||
c.enqueueForNamespace(o.GetNamespace())
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Do we need to enque secrets just for the namespace or in general?
|
||||
func (c *Operator) handleSecretDelete(obj interface{}) {
|
||||
o, ok := c.getObject(obj)
|
||||
if ok {
|
||||
|
@ -512,6 +557,7 @@ func (c *Operator) handleSecretAdd(obj interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Do we need to enque configmaps just for the namespace or in general?
|
||||
func (c *Operator) handleConfigMapAdd(obj interface{}) {
|
||||
o, ok := c.getObject(obj)
|
||||
if ok {
|
||||
|
@ -673,15 +719,8 @@ func (c *Operator) sync(key string) error {
|
|||
return err
|
||||
}
|
||||
if !exists {
|
||||
// TODO(fabxc): we want to do server side deletion due to the variety of
|
||||
// resources we create.
|
||||
// Doing so just based on the deletion event is not reliable, so
|
||||
// we have to garbage collect the controller-created resources in some other way.
|
||||
//
|
||||
// Let's rely on the index key matching that of the created configmap and StatefulSet for now.
|
||||
// This does not work if we delete Prometheus resources as the
|
||||
// controller is not running – that could be solved via garbage collection later.
|
||||
return c.destroyPrometheus(key)
|
||||
// Dependent resources are cleaned up by K8s via OwnerReferences
|
||||
return nil
|
||||
}
|
||||
|
||||
p := obj.(*monitoringv1.Prometheus)
|
||||
|
@ -691,22 +730,22 @@ func (c *Operator) sync(key string) error {
|
|||
|
||||
level.Info(c.logger).Log("msg", "sync prometheus", "key", key)
|
||||
|
||||
ruleFileConfigMaps, err := c.ruleFileConfigMaps(p)
|
||||
err = c.createOrUpdateRuleFileConfigMap(p)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "retrieving rule file configmaps failed")
|
||||
return err
|
||||
}
|
||||
|
||||
// If no service monitor selectors are configured, the user wants to manage
|
||||
// configuration himself.
|
||||
// configuration themselves.
|
||||
if p.Spec.ServiceMonitorSelector != nil {
|
||||
// We just always regenerate the configuration to be safe.
|
||||
if err := c.createConfig(p, ruleFileConfigMaps); err != nil {
|
||||
if err := c.createOrUpdateConfigurationSecret(p); err != nil {
|
||||
return errors.Wrap(err, "creating config failed")
|
||||
}
|
||||
}
|
||||
|
||||
// Create Secret if it doesn't exist.
|
||||
s, err := makeEmptyConfig(p, ruleFileConfigMaps, c.config)
|
||||
s, err := makeEmptyConfigurationSecret(p, c.config)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "generating empty config secret failed")
|
||||
}
|
||||
|
@ -732,20 +771,37 @@ func (c *Operator) sync(key string) error {
|
|||
return errors.Wrap(err, "retrieving statefulset failed")
|
||||
}
|
||||
|
||||
newSSetInputChecksum, err := createSSetInputChecksum(*p, c.config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
sset, err := makeStatefulSet(*p, nil, &c.config, ruleFileConfigMaps)
|
||||
level.Debug(c.logger).Log("msg", "no current Prometheus statefulset found")
|
||||
sset, err := makeStatefulSet(*p, "", &c.config, newSSetInputChecksum)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "creating statefulset failed")
|
||||
return errors.Wrap(err, "making statefulset failed")
|
||||
}
|
||||
|
||||
level.Debug(c.logger).Log("msg", "creating Prometheus statefulset")
|
||||
if _, err := ssetClient.Create(sset); err != nil {
|
||||
return errors.Wrap(err, "creating statefulset failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
sset, err := makeStatefulSet(*p, obj.(*appsv1.StatefulSet), &c.config, ruleFileConfigMaps)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "updating statefulset failed")
|
||||
|
||||
oldSSetInputChecksum := obj.(*appsv1.StatefulSet).ObjectMeta.Annotations[sSetInputChecksumName]
|
||||
if newSSetInputChecksum == oldSSetInputChecksum {
|
||||
level.Debug(c.logger).Log("msg", "new statefulset generation inputs match current, skipping any actions")
|
||||
return nil
|
||||
}
|
||||
|
||||
sset, err := makeStatefulSet(*p, obj.(*appsv1.StatefulSet).Spec.PodManagementPolicy, &c.config, newSSetInputChecksum)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "making statefulset failed")
|
||||
}
|
||||
|
||||
level.Debug(c.logger).Log("msg", "updating current Prometheus statefulset")
|
||||
if _, err := ssetClient.Update(sset); err != nil {
|
||||
return errors.Wrap(err, "updating statefulset failed")
|
||||
}
|
||||
|
@ -753,22 +809,19 @@ func (c *Operator) sync(key string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Operator) ruleFileConfigMaps(p *monitoringv1.Prometheus) ([]*v1.ConfigMap, error) {
|
||||
res := []*v1.ConfigMap{}
|
||||
|
||||
ruleSelector, err := metav1.LabelSelectorAsSelector(p.Spec.RuleSelector)
|
||||
// TODO: rename sSetInputChecksum
|
||||
func createSSetInputChecksum(p monitoringv1.Prometheus, c Config) (string, error) {
|
||||
json, err := json.Marshal(
|
||||
struct {
|
||||
P monitoringv1.Prometheus
|
||||
C Config
|
||||
}{p, c},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return "", errors.Wrap(err, "failed to marshal Prometheus CRD and config to json")
|
||||
}
|
||||
|
||||
cache.ListAllByNamespace(c.cmapInf.GetIndexer(), p.Namespace, ruleSelector, func(obj interface{}) {
|
||||
_, ok := c.keyFunc(obj)
|
||||
if ok {
|
||||
res = append(res, obj.(*v1.ConfigMap))
|
||||
}
|
||||
})
|
||||
|
||||
return res, nil
|
||||
return fmt.Sprintf("%x", md5.Sum(json)), nil
|
||||
}
|
||||
|
||||
func ListOptions(name string) metav1.ListOptions {
|
||||
|
@ -835,82 +888,18 @@ func needsUpdate(pod *v1.Pod, tmpl v1.PodTemplateSpec) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// TODO(brancz): Remove this function once Kubernetes 1.7 compatibility is dropped.
|
||||
// Starting with Kubernetes 1.8 OwnerReferences are properly handled for CRDs.
|
||||
func (c *Operator) destroyPrometheus(key string) error {
|
||||
ssetKey := prometheusKeyToStatefulSetKey(key)
|
||||
obj, exists, err := c.ssetInf.GetStore().GetByKey(ssetKey)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "retrieving statefulset from cache failed")
|
||||
}
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
sset := obj.(*appsv1.StatefulSet)
|
||||
*sset.Spec.Replicas = 0
|
||||
|
||||
// Update the replica count to 0 and wait for all pods to be deleted.
|
||||
ssetClient := c.kclient.AppsV1beta2().StatefulSets(sset.Namespace)
|
||||
|
||||
if _, err := ssetClient.Update(sset); err != nil {
|
||||
return errors.Wrap(err, "updating statefulset for scale-down failed")
|
||||
}
|
||||
|
||||
podClient := c.kclient.Core().Pods(sset.Namespace)
|
||||
|
||||
// TODO(fabxc): temprorary solution until StatefulSet status provides necessary info to know
|
||||
// whether scale-down completed.
|
||||
for {
|
||||
pods, err := podClient.List(ListOptions(prometheusNameFromStatefulSetName(sset.Name)))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "retrieving pods of statefulset failed")
|
||||
}
|
||||
if len(pods.Items) == 0 {
|
||||
break
|
||||
}
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
|
||||
// StatefulSet scaled down, we can delete it.
|
||||
if err := ssetClient.Delete(sset.Name, nil); err != nil {
|
||||
return errors.Wrap(err, "deleting statefulset failed")
|
||||
}
|
||||
|
||||
// Delete the auto-generate configuration.
|
||||
// TODO(fabxc): add an ownerRef at creation so we don't delete Secrets
|
||||
// manually created for Prometheus servers with no ServiceMonitor selectors.
|
||||
s := c.kclient.Core().Secrets(sset.Namespace)
|
||||
secret, err := s.Get(sset.Name, metav1.GetOptions{})
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
return errors.Wrap(err, "retrieving config Secret failed")
|
||||
}
|
||||
if apierrors.IsNotFound(err) {
|
||||
// Secret does not exist so nothing to clean up
|
||||
return nil
|
||||
}
|
||||
|
||||
value, found := secret.Labels[managedByOperatorLabel]
|
||||
if found && value == managedByOperatorLabelValue {
|
||||
if err := s.Delete(sset.Name, nil); err != nil {
|
||||
return errors.Wrap(err, "deleting config Secret failed")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadAdditionalConfigsSecret(additionalConfigs *v1.SecretKeySelector, s *v1.SecretList) ([]byte, error) {
|
||||
if additionalConfigs != nil {
|
||||
func loadAdditionalScrapeConfigsSecret(additionalScrapeConfigs *v1.SecretKeySelector, s *v1.SecretList) ([]byte, error) {
|
||||
if additionalScrapeConfigs != nil {
|
||||
for _, secret := range s.Items {
|
||||
if secret.Name == additionalConfigs.Name {
|
||||
if c, ok := secret.Data[additionalConfigs.Key]; ok {
|
||||
if secret.Name == additionalScrapeConfigs.Name {
|
||||
if c, ok := secret.Data[additionalScrapeConfigs.Key]; ok {
|
||||
return c, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("key %v could not be found in Secret %v.", additionalConfigs.Key, additionalConfigs.Name)
|
||||
return nil, fmt.Errorf("key %v could not be found in Secret %v.", additionalScrapeConfigs.Key, additionalScrapeConfigs.Name)
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("secret %v could not be found.", additionalConfigs.Name)
|
||||
return nil, fmt.Errorf("secret %v could not be found.", additionalScrapeConfigs.Name)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -997,7 +986,7 @@ func (c *Operator) loadBasicAuthSecrets(mons map[string]*monitoringv1.ServiceMon
|
|||
|
||||
}
|
||||
|
||||
func (c *Operator) createConfig(p *monitoringv1.Prometheus, ruleFileConfigMaps []*v1.ConfigMap) error {
|
||||
func (c *Operator) createOrUpdateConfigurationSecret(p *monitoringv1.Prometheus) error {
|
||||
smons, err := c.selectServiceMonitors(p)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "selecting ServiceMonitors failed")
|
||||
|
@ -1017,25 +1006,22 @@ func (c *Operator) createConfig(p *monitoringv1.Prometheus, ruleFileConfigMaps [
|
|||
return err
|
||||
}
|
||||
|
||||
additionalScrapeConfigs, err := loadAdditionalConfigsSecret(p.Spec.AdditionalScrapeConfigs, listSecrets)
|
||||
additionalScrapeConfigs, err := loadAdditionalScrapeConfigsSecret(p.Spec.AdditionalScrapeConfigs, listSecrets)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "loading additional scrape configs from Secret failed")
|
||||
}
|
||||
additionalAlertManagerConfigs, err := loadAdditionalConfigsSecret(p.Spec.AdditionalAlertManagerConfigs, listSecrets)
|
||||
additionalAlertManagerConfigs, err := loadAdditionalScrapeConfigsSecret(p.Spec.AdditionalAlertManagerConfigs, listSecrets)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "loading additional alert manager configs from Secret failed")
|
||||
}
|
||||
|
||||
// Update secret based on the most recent configuration.
|
||||
conf, err := generateConfig(p, smons, len(ruleFileConfigMaps), basicAuthSecrets, additionalScrapeConfigs, additionalAlertManagerConfigs)
|
||||
conf, err := generateConfig(p, smons, basicAuthSecrets, additionalScrapeConfigs, additionalAlertManagerConfigs)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "generating config failed")
|
||||
}
|
||||
|
||||
s, err := makeConfigSecret(p, ruleFileConfigMaps, c.config)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "generating base secret failed")
|
||||
}
|
||||
s := makeConfigSecret(p, c.config)
|
||||
s.ObjectMeta.Annotations = map[string]string{
|
||||
"generated": "true",
|
||||
}
|
||||
|
@ -1049,23 +1035,21 @@ func (c *Operator) createConfig(p *monitoringv1.Prometheus, ruleFileConfigMaps [
|
|||
}
|
||||
|
||||
var (
|
||||
generatedConf = s.Data[configFilename]
|
||||
generatedConfigMaps = s.Data[ruleConfigmapsFilename]
|
||||
curConfig, curConfigFound = curSecret.Data[configFilename]
|
||||
curConfigMaps, curConfigMapsFound = curSecret.Data[ruleConfigmapsFilename]
|
||||
generatedConf = s.Data[configFilename]
|
||||
curConfig, curConfigFound = curSecret.Data[configFilename]
|
||||
)
|
||||
if curConfigFound && curConfigMapsFound {
|
||||
if bytes.Equal(curConfig, generatedConf) && bytes.Equal(curConfigMaps, generatedConfigMaps) {
|
||||
level.Debug(c.logger).Log("msg", "updating config skipped, no configuration change")
|
||||
if curConfigFound {
|
||||
if bytes.Equal(curConfig, generatedConf) {
|
||||
level.Debug(c.logger).Log("msg", "updating Prometheus configuration secret skipped, no configuration change")
|
||||
return nil
|
||||
} else {
|
||||
level.Debug(c.logger).Log("msg", "current config or current configmaps has changed")
|
||||
level.Debug(c.logger).Log("msg", "current Prometheus configuration has changed")
|
||||
}
|
||||
} else {
|
||||
level.Debug(c.logger).Log("msg", "no current config or current configmaps found", "currentConfigFound", curConfigFound, "currentConfigMapsFound", curConfigMapsFound)
|
||||
level.Debug(c.logger).Log("msg", "no current Prometheus configuration secret found", "currentConfigFound", curConfigFound)
|
||||
}
|
||||
|
||||
level.Debug(c.logger).Log("msg", "updating configuration")
|
||||
level.Debug(c.logger).Log("msg", "updating Prometheus configuration secret")
|
||||
_, err = sClient.Update(s)
|
||||
return err
|
||||
}
|
||||
|
@ -1117,8 +1101,9 @@ func (c *Operator) selectServiceMonitors(p *monitoringv1.Prometheus) (map[string
|
|||
func (c *Operator) createCRDs() error {
|
||||
_, pErr := c.mclient.MonitoringV1().Prometheuses(c.config.Namespace).List(metav1.ListOptions{})
|
||||
_, sErr := c.mclient.MonitoringV1().ServiceMonitors(c.config.Namespace).List(metav1.ListOptions{})
|
||||
if pErr == nil && sErr == nil {
|
||||
// If Prometheus and ServiceMonitor objects are already registered, we
|
||||
_, rErr := c.mclient.MonitoringV1().RuleFiles(c.config.Namespace).List(metav1.ListOptions{})
|
||||
if pErr == nil && sErr == nil && rErr == nil {
|
||||
// If Prometheus, RuleFile and ServiceMonitor objects are already registered, we
|
||||
// won't attempt to do so again.
|
||||
return nil
|
||||
}
|
||||
|
@ -1126,6 +1111,7 @@ func (c *Operator) createCRDs() error {
|
|||
crds := []*extensionsobj.CustomResourceDefinition{
|
||||
k8sutil.NewCustomResourceDefinition(c.config.CrdKinds.Prometheus, c.config.CrdGroup, c.config.Labels.LabelsMap, c.config.EnableValidation),
|
||||
k8sutil.NewCustomResourceDefinition(c.config.CrdKinds.ServiceMonitor, c.config.CrdGroup, c.config.Labels.LabelsMap, c.config.EnableValidation),
|
||||
k8sutil.NewCustomResourceDefinition(c.config.CrdKinds.RuleFile, c.config.CrdGroup, c.config.Labels.LabelsMap, c.config.EnableValidation),
|
||||
}
|
||||
|
||||
crdClient := c.crdclient.ApiextensionsV1beta1().CustomResourceDefinitions()
|
||||
|
@ -1143,6 +1129,7 @@ func (c *Operator) createCRDs() error {
|
|||
}{
|
||||
{"Prometheus", c.mclient.MonitoringV1().Prometheuses(c.config.Namespace).List},
|
||||
{"ServiceMonitor", c.mclient.MonitoringV1().ServiceMonitors(c.config.Namespace).List},
|
||||
{"RuleFile", c.mclient.MonitoringV1().RuleFiles(c.config.Namespace).List},
|
||||
}
|
||||
|
||||
for _, crdListFunc := range crdListFuncs {
|
||||
|
|
|
@ -16,6 +16,8 @@ package prometheus
|
|||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
monitoringv1 "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1"
|
||||
)
|
||||
|
||||
func TestListOptions(t *testing.T) {
|
||||
|
@ -26,3 +28,24 @@ func TestListOptions(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateStatefulSetChecksum(t *testing.T) {
|
||||
p1 := monitoringv1.Prometheus{}
|
||||
p1.Spec.Version = "v1.7.0"
|
||||
p2 := monitoringv1.Prometheus{}
|
||||
p2.Spec.Version = "v1.7.2"
|
||||
c := Config{}
|
||||
|
||||
p1Checksum, err := createSSetInputChecksum(p1, c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
p2Checksum, err := createSSetInputChecksum(p2, c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if p1Checksum == p2Checksum {
|
||||
t.Fatal("expected two different Prometheus CRDs to result in two different checksums but got equal checksums")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,10 +36,6 @@ func sanitizeLabelName(name string) string {
|
|||
return invalidLabelCharRE.ReplaceAllString(name, "_")
|
||||
}
|
||||
|
||||
func configMapRuleFileFolder(configMapNumber int) string {
|
||||
return fmt.Sprintf("/etc/prometheus/config_out/rules/rules-%d/", configMapNumber)
|
||||
}
|
||||
|
||||
func stringMapToMapSlice(m map[string]string) yaml.MapSlice {
|
||||
res := yaml.MapSlice{}
|
||||
ks := make([]string, 0)
|
||||
|
@ -90,7 +86,7 @@ func buildExternalLabels(p *v1.Prometheus) yaml.MapSlice {
|
|||
return stringMapToMapSlice(m)
|
||||
}
|
||||
|
||||
func generateConfig(p *v1.Prometheus, mons map[string]*v1.ServiceMonitor, ruleConfigMaps int, basicAuthSecrets map[string]BasicAuthCredentials, additionalScrapeConfigs []byte, additionalAlertManagerConfigs []byte) ([]byte, error) {
|
||||
func generateConfig(p *v1.Prometheus, mons map[string]*v1.ServiceMonitor, basicAuthSecrets map[string]BasicAuthCredentials, additionalScrapeConfigs []byte, additionalAlertManagerConfigs []byte) ([]byte, error) {
|
||||
versionStr := p.Spec.Version
|
||||
if versionStr == "" {
|
||||
versionStr = DefaultVersion
|
||||
|
@ -122,16 +118,10 @@ func generateConfig(p *v1.Prometheus, mons map[string]*v1.ServiceMonitor, ruleCo
|
|||
},
|
||||
})
|
||||
|
||||
if ruleConfigMaps > 0 {
|
||||
configMaps := make([]string, ruleConfigMaps)
|
||||
for i := 0; i < ruleConfigMaps; i++ {
|
||||
configMaps[i] = configMapRuleFileFolder(i) + "*"
|
||||
}
|
||||
cfg = append(cfg, yaml.MapItem{
|
||||
Key: "rule_files",
|
||||
Value: configMaps,
|
||||
})
|
||||
}
|
||||
cfg = append(cfg, yaml.MapItem{
|
||||
Key: "rule_files",
|
||||
Value: []string{"/etc/prometheus/rules/*.yaml"},
|
||||
})
|
||||
|
||||
identifiers := make([]string, len(mons))
|
||||
i := 0
|
||||
|
|
|
@ -25,6 +25,8 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
||||
monitoringv1 "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1"
|
||||
|
||||
"github.com/kylelemons/godebug/pretty"
|
||||
)
|
||||
|
||||
func TestConfigGeneration(t *testing.T) {
|
||||
|
@ -104,7 +106,6 @@ func TestAlertmanagerBearerToken(t *testing.T) {
|
|||
},
|
||||
},
|
||||
nil,
|
||||
0,
|
||||
map[string]BasicAuthCredentials{},
|
||||
nil,
|
||||
nil,
|
||||
|
@ -122,6 +123,8 @@ func TestAlertmanagerBearerToken(t *testing.T) {
|
|||
external_labels:
|
||||
prometheus: default/test
|
||||
prometheus_replica: $(POD_NAME)
|
||||
rule_files:
|
||||
- /etc/prometheus/rules/*.yaml
|
||||
scrape_configs: []
|
||||
alerting:
|
||||
alert_relabel_configs:
|
||||
|
@ -150,7 +153,8 @@ alerting:
|
|||
result := string(cfg)
|
||||
|
||||
if expected != result {
|
||||
t.Fatalf("Unexpected result.\n\nGot:\n\n%s\n\nExpected:\n\n%s\n\n", result, expected)
|
||||
pretty.Compare(expected, result)
|
||||
t.Fatal("expected Prometheus configuration and actual configuration do not match")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,7 +187,7 @@ func generateTestConfig(version string) ([]byte, error) {
|
|||
"group": "group1",
|
||||
},
|
||||
},
|
||||
RuleSelector: &metav1.LabelSelector{
|
||||
RuleFileSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"role": "rulefile",
|
||||
},
|
||||
|
@ -202,7 +206,6 @@ func generateTestConfig(version string) ([]byte, error) {
|
|||
},
|
||||
},
|
||||
makeServiceMonitors(),
|
||||
1,
|
||||
map[string]BasicAuthCredentials{},
|
||||
nil,
|
||||
nil,
|
||||
|
|
212
pkg/prometheus/rulefile.go
Normal file
212
pkg/prometheus/rulefile.go
Normal file
|
@ -0,0 +1,212 @@
|
|||
// Copyright 2016 The prometheus-operator Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
monitoringv1 "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
"github.com/go-kit/kit/log/level"
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func (c *Operator) createOrUpdateRuleFileConfigMap(p *monitoringv1.Prometheus) error {
|
||||
cClient := c.kclient.CoreV1().ConfigMaps(p.Namespace)
|
||||
|
||||
namespaces, err := c.selectRuleFileNamespaces(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ruleFiles, err := c.selectRuleFiles(p, namespaces)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newConfigMap := c.makeRulesConfigMap(p, ruleFiles)
|
||||
|
||||
currentConfigMap, err := cClient.Get(prometheusRuleFilesConfigMapName(p.Name), metav1.GetOptions{})
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
isNotFound := false
|
||||
if apierrors.IsNotFound(err) {
|
||||
level.Debug(c.logger).Log(
|
||||
"msg", "no RuleFiles configmap created yet",
|
||||
"namespace", p.Namespace,
|
||||
"prometheus", p.Name,
|
||||
)
|
||||
isNotFound = true
|
||||
}
|
||||
|
||||
newChecksum := checksumRuleFiles(ruleFiles)
|
||||
currentChecksum := checksumRuleFiles(currentConfigMap.Data)
|
||||
|
||||
if newChecksum == currentChecksum && !isNotFound {
|
||||
level.Debug(c.logger).Log(
|
||||
"msg", "no RuleFile changes",
|
||||
"namespace", p.Namespace,
|
||||
"prometheus", p.Name,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
if isNotFound {
|
||||
level.Debug(c.logger).Log(
|
||||
"msg", "no RuleFile found, creating new one",
|
||||
"namespace", p.Namespace,
|
||||
"prometheus", p.Name,
|
||||
)
|
||||
_, err = cClient.Create(newConfigMap)
|
||||
} else {
|
||||
level.Debug(c.logger).Log(
|
||||
"msg", "updating RuleFile",
|
||||
"namespace", p.Namespace,
|
||||
"prometheus", p.Name,
|
||||
)
|
||||
_, err = cClient.Update(newConfigMap)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Operator) selectRuleFileNamespaces(p *monitoringv1.Prometheus) ([]string, error) {
|
||||
namespaces := []string{}
|
||||
|
||||
// If 'RuleFilesNamespaceSelector' is nil, only check own namespace.
|
||||
if p.Spec.RuleFileNamespaceSelector == nil {
|
||||
namespaces = append(namespaces, p.Namespace)
|
||||
} else {
|
||||
ruleFileNamespaceSelector, err := metav1.LabelSelectorAsSelector(p.Spec.RuleFileNamespaceSelector)
|
||||
if err != nil {
|
||||
return namespaces, errors.Wrap(err, "convert rule file namespace label selector to selector")
|
||||
}
|
||||
|
||||
cache.ListAll(c.nsInf.GetStore(), ruleFileNamespaceSelector, func(obj interface{}) {
|
||||
namespaces = append(namespaces, obj.(*v1.Namespace).Name)
|
||||
})
|
||||
}
|
||||
|
||||
level.Debug(c.logger).Log(
|
||||
"msg", "selected RuleFileNamespaces",
|
||||
"namespaces", strings.Join(namespaces, ","),
|
||||
"namespace", p.Namespace,
|
||||
"prometheus", p.Name,
|
||||
)
|
||||
|
||||
return namespaces, nil
|
||||
}
|
||||
|
||||
func (c *Operator) selectRuleFiles(p *monitoringv1.Prometheus, namespaces []string) (map[string]string, error) {
|
||||
ruleFiles := map[string]string{}
|
||||
|
||||
// With Prometheus Operator v0.20.0 the 'RuleSelector' field in the Prometheus
|
||||
// CRD Spec is deprecated. Any value in 'RuleSelector' is just copied to the new
|
||||
// field 'RuleFileSelector'.
|
||||
if p.Spec.RuleFileSelector == nil && p.Spec.RuleSelector != nil {
|
||||
p.Spec.RuleFileSelector = p.Spec.RuleSelector
|
||||
}
|
||||
|
||||
fileSelector, err := metav1.LabelSelectorAsSelector(p.Spec.RuleFileSelector)
|
||||
if err != nil {
|
||||
return ruleFiles, errors.Wrap(err, "convert rule file label selector to selector")
|
||||
}
|
||||
|
||||
for _, ns := range namespaces {
|
||||
var marshalErr error
|
||||
err := cache.ListAllByNamespace(c.ruleFileInf.GetIndexer(), ns, fileSelector, func(obj interface{}) {
|
||||
file := obj.(*monitoringv1.RuleFile)
|
||||
content, err := yaml.Marshal(file.Spec)
|
||||
if err != nil {
|
||||
marshalErr = err
|
||||
return
|
||||
}
|
||||
ruleFiles[fmt.Sprintf("%v-%v.yaml", file.Namespace, file.Name)] = string(content)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if marshalErr != nil {
|
||||
return nil, marshalErr
|
||||
}
|
||||
}
|
||||
|
||||
// sort ruleFiles map
|
||||
filenames := []string{}
|
||||
for k, _ := range ruleFiles {
|
||||
filenames = append(filenames, k)
|
||||
}
|
||||
sort.Strings(filenames)
|
||||
sortedRuleFiles := map[string]string{}
|
||||
for _, name := range filenames {
|
||||
sortedRuleFiles[name] = ruleFiles[name]
|
||||
}
|
||||
|
||||
level.Debug(c.logger).Log(
|
||||
"msg", "selected RuleFiles",
|
||||
"rulefiles", strings.Join(filenames, ","),
|
||||
"namespace", p.Namespace,
|
||||
"prometheus", p.Name,
|
||||
)
|
||||
|
||||
return sortedRuleFiles, nil
|
||||
}
|
||||
|
||||
func (c *Operator) makeRulesConfigMap(p *monitoringv1.Prometheus, ruleFiles map[string]string) *v1.ConfigMap {
|
||||
boolTrue := true
|
||||
return &v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: prometheusRuleFilesConfigMapName(p.Name),
|
||||
Labels: managedByOperatorLabels,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: p.APIVersion,
|
||||
BlockOwnerDeletion: &boolTrue,
|
||||
Controller: &boolTrue,
|
||||
Kind: p.Kind,
|
||||
Name: p.Name,
|
||||
UID: p.UID,
|
||||
},
|
||||
},
|
||||
},
|
||||
Data: ruleFiles,
|
||||
}
|
||||
}
|
||||
|
||||
func checksumRuleFiles(files map[string]string) string {
|
||||
var sum string
|
||||
for name, value := range files {
|
||||
sum = sum + name + value
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%x", sha256.Sum256([]byte(sum)))
|
||||
}
|
||||
|
||||
func prometheusRuleFilesConfigMapName(prometheusName string) string {
|
||||
return "prometheus-" + prometheusName + "-rules"
|
||||
}
|
|
@ -15,12 +15,9 @@
|
|||
package prometheus
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1beta2"
|
||||
|
@ -32,7 +29,6 @@ import (
|
|||
"github.com/blang/semver"
|
||||
monitoringv1 "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1"
|
||||
"github.com/pkg/errors"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -42,11 +38,11 @@ const (
|
|||
storageDir = "/prometheus"
|
||||
confDir = "/etc/prometheus/config"
|
||||
confOutDir = "/etc/prometheus/config_out"
|
||||
rulesDir = "/etc/prometheus/config_out/rules"
|
||||
rulesDir = "/etc/prometheus/rules"
|
||||
secretsDir = "/etc/prometheus/secrets/"
|
||||
configFilename = "prometheus.yaml"
|
||||
configEnvsubstFilename = "prometheus.env.yaml"
|
||||
ruleConfigmapsFilename = "configmaps.json"
|
||||
sSetInputChecksumName = "prometheus-operator-input-checksum"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -78,7 +74,12 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
func makeStatefulSet(p monitoringv1.Prometheus, old *appsv1.StatefulSet, config *Config, ruleConfigMaps []*v1.ConfigMap) (*appsv1.StatefulSet, error) {
|
||||
func makeStatefulSet(
|
||||
p monitoringv1.Prometheus,
|
||||
previousPodManagementPolicy appsv1.PodManagementPolicyType,
|
||||
config *Config,
|
||||
inputChecksum string,
|
||||
) (*appsv1.StatefulSet, error) {
|
||||
// TODO(fabxc): is this the right point to inject defaults?
|
||||
// Ideally we would do it before storing but that's currently not possible.
|
||||
// Potentially an update handler on first insertion.
|
||||
|
@ -126,7 +127,7 @@ func makeStatefulSet(p monitoringv1.Prometheus, old *appsv1.StatefulSet, config
|
|||
}
|
||||
}
|
||||
|
||||
spec, err := makeStatefulSetSpec(p, config, ruleConfigMaps)
|
||||
spec, err := makeStatefulSetSpec(p, config)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "make StatefulSet spec")
|
||||
}
|
||||
|
@ -151,6 +152,14 @@ func makeStatefulSet(p monitoringv1.Prometheus, old *appsv1.StatefulSet, config
|
|||
Spec: *spec,
|
||||
}
|
||||
|
||||
if statefulset.ObjectMeta.Annotations == nil {
|
||||
statefulset.ObjectMeta.Annotations = map[string]string{
|
||||
sSetInputChecksumName: inputChecksum,
|
||||
}
|
||||
} else {
|
||||
statefulset.ObjectMeta.Annotations[sSetInputChecksumName] = inputChecksum
|
||||
}
|
||||
|
||||
if p.Spec.ImagePullSecrets != nil && len(p.Spec.ImagePullSecrets) > 0 {
|
||||
statefulset.Spec.Template.Spec.ImagePullSecrets = p.Spec.ImagePullSecrets
|
||||
}
|
||||
|
@ -179,21 +188,15 @@ func makeStatefulSet(p monitoringv1.Prometheus, old *appsv1.StatefulSet, config
|
|||
statefulset.Spec.VolumeClaimTemplates = append(statefulset.Spec.VolumeClaimTemplates, pvcTemplate)
|
||||
}
|
||||
|
||||
if old != nil {
|
||||
statefulset.Annotations = old.Annotations
|
||||
|
||||
// Updates to statefulset spec for fields other than 'replicas', 'template', and 'updateStrategy' are forbidden.
|
||||
statefulset.Spec.PodManagementPolicy = old.Spec.PodManagementPolicy
|
||||
}
|
||||
// Updates to statefulset spec for fields other than 'replicas',
|
||||
// 'template', and 'updateStrategy' are forbidden.
|
||||
statefulset.Spec.PodManagementPolicy = previousPodManagementPolicy
|
||||
|
||||
return statefulset, nil
|
||||
}
|
||||
|
||||
func makeEmptyConfig(p *monitoringv1.Prometheus, configMaps []*v1.ConfigMap, config Config) (*v1.Secret, error) {
|
||||
s, err := makeConfigSecret(p, configMaps, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func makeEmptyConfigurationSecret(p *monitoringv1.Prometheus, config Config) (*v1.Secret, error) {
|
||||
s := makeConfigSecret(p, config)
|
||||
|
||||
s.ObjectMeta.Annotations = map[string]string{
|
||||
"empty": "true",
|
||||
|
@ -223,50 +226,7 @@ func (l *ConfigMapReferenceList) Swap(i, j int) {
|
|||
l.Items[i], l.Items[j] = l.Items[j], l.Items[i]
|
||||
}
|
||||
|
||||
func makeRuleConfigMap(cm *v1.ConfigMap) (*ConfigMapReference, error) {
|
||||
keys := []string{}
|
||||
for k, _ := range cm.Data {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
m := yaml.MapSlice{}
|
||||
for _, k := range keys {
|
||||
m = append(m, yaml.MapItem{Key: k, Value: cm.Data[k]})
|
||||
}
|
||||
|
||||
b, err := yaml.Marshal(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ConfigMapReference{
|
||||
Key: cm.Namespace + "/" + cm.Name,
|
||||
Checksum: fmt.Sprintf("%x", sha256.Sum256(b)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func makeRuleConfigMapListFile(configMaps []*v1.ConfigMap) ([]byte, error) {
|
||||
cml := &ConfigMapReferenceList{}
|
||||
|
||||
for _, cm := range configMaps {
|
||||
configmap, err := makeRuleConfigMap(cm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cml.Items = append(cml.Items, configmap)
|
||||
}
|
||||
|
||||
sort.Sort(cml)
|
||||
return json.Marshal(cml)
|
||||
}
|
||||
|
||||
func makeConfigSecret(p *monitoringv1.Prometheus, configMaps []*v1.ConfigMap, config Config) (*v1.Secret, error) {
|
||||
b, err := makeRuleConfigMapListFile(configMaps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func makeConfigSecret(p *monitoringv1.Prometheus, config Config) *v1.Secret {
|
||||
boolTrue := true
|
||||
return &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
|
@ -284,10 +244,9 @@ func makeConfigSecret(p *monitoringv1.Prometheus, configMaps []*v1.ConfigMap, co
|
|||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
configFilename: []byte{},
|
||||
ruleConfigmapsFilename: b,
|
||||
configFilename: []byte{},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func makeStatefulSetService(p *monitoringv1.Prometheus, config Config) *v1.Service {
|
||||
|
@ -315,7 +274,7 @@ func makeStatefulSetService(p *monitoringv1.Prometheus, config Config) *v1.Servi
|
|||
return svc
|
||||
}
|
||||
|
||||
func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []*v1.ConfigMap) (*appsv1.StatefulSetSpec, error) {
|
||||
func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config) (*appsv1.StatefulSetSpec, error) {
|
||||
// Prometheus may take quite long to shut down to checkpoint existing data.
|
||||
// Allow up to 10 minutes for clean termination.
|
||||
terminationGracePeriod := int64(600)
|
||||
|
@ -446,6 +405,16 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
|
|||
EmptyDir: &v1.EmptyDirVolumeSource{},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "rules",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
ConfigMap: &v1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: v1.LocalObjectReference{
|
||||
Name: prometheusRuleFilesConfigMapName(p.Name),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
promVolumeMounts := []v1.VolumeMount{
|
||||
|
@ -454,6 +423,10 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
|
|||
ReadOnly: true,
|
||||
MountPath: confOutDir,
|
||||
},
|
||||
{
|
||||
Name: "rules",
|
||||
MountPath: "/etc/prometheus/rules",
|
||||
},
|
||||
{
|
||||
Name: volumeName(p.Name),
|
||||
MountPath: storageDir,
|
||||
|
@ -482,6 +455,10 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
|
|||
Name: "config",
|
||||
MountPath: confDir,
|
||||
},
|
||||
{
|
||||
Name: "rules",
|
||||
MountPath: "/etc/prometheus/rules",
|
||||
},
|
||||
{
|
||||
Name: "config-out",
|
||||
MountPath: confOutDir,
|
||||
|
@ -491,9 +468,7 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
|
|||
configReloadArgs := []string{
|
||||
fmt.Sprintf("--reload-url=%s", localReloadURL),
|
||||
fmt.Sprintf("--config-file=%s", path.Join(confDir, configFilename)),
|
||||
fmt.Sprintf("--rule-list-file=%s", path.Join(confDir, ruleConfigmapsFilename)),
|
||||
fmt.Sprintf("--config-envsubst-file=%s", path.Join(confOutDir, configEnvsubstFilename)),
|
||||
fmt.Sprintf("--rule-dir=%s", rulesDir),
|
||||
}
|
||||
|
||||
var livenessProbeHandler v1.Handler
|
||||
|
@ -600,6 +575,7 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
|
|||
},
|
||||
},
|
||||
},
|
||||
Command: []string{"/bin/prometheus-config-reloader"},
|
||||
Args: configReloadArgs,
|
||||
VolumeMounts: configReloadVolumeMounts,
|
||||
Resources: v1.ResourceRequirements{
|
||||
|
@ -609,6 +585,27 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *Config, ruleConfigMaps []
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "alerting-rule-files-configmap-reloader",
|
||||
Image: c.ConfigReloaderImage,
|
||||
Args: []string{
|
||||
fmt.Sprintf("--webhook-url=%s", localReloadURL),
|
||||
fmt.Sprintf("--volume-dir=%s", "/etc/prometheus/rules"),
|
||||
},
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: "rules",
|
||||
ReadOnly: true,
|
||||
MountPath: "/etc/prometheus/rules",
|
||||
},
|
||||
},
|
||||
Resources: v1.ResourceRequirements{
|
||||
Limits: v1.ResourceList{
|
||||
v1.ResourceCPU: resource.MustParse("5m"),
|
||||
v1.ResourceMemory: resource.MustParse("10Mi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, p.Spec.Containers...),
|
||||
SecurityContext: securityContext,
|
||||
ServiceAccountName: p.Spec.ServiceAccountName,
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
package prometheus
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
|
@ -24,6 +25,8 @@ import (
|
|||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/kylelemons/godebug/pretty"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -45,7 +48,7 @@ func TestStatefulSetLabelingAndAnnotations(t *testing.T) {
|
|||
Labels: labels,
|
||||
Annotations: annotations,
|
||||
},
|
||||
}, nil, defaultTestConfig, []*v1.ConfigMap{})
|
||||
}, "", defaultTestConfig, "")
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -69,7 +72,7 @@ func TestPodLabelsAnnotations(t *testing.T) {
|
|||
Labels: labels,
|
||||
},
|
||||
},
|
||||
}, nil, defaultTestConfig, []*v1.ConfigMap{})
|
||||
}, "", defaultTestConfig, "")
|
||||
require.NoError(t, err)
|
||||
if _, ok := sset.Spec.Template.ObjectMeta.Labels["testlabel"]; !ok {
|
||||
t.Fatal("Pod labes are not properly propagated")
|
||||
|
@ -109,7 +112,7 @@ func TestStatefulSetPVC(t *testing.T) {
|
|||
VolumeClaimTemplate: pvc,
|
||||
},
|
||||
},
|
||||
}, nil, defaultTestConfig, []*v1.ConfigMap{})
|
||||
}, "", defaultTestConfig, "")
|
||||
|
||||
require.NoError(t, err)
|
||||
ssetPvc := sset.Spec.VolumeClaimTemplates[0]
|
||||
|
@ -141,7 +144,7 @@ func TestStatefulSetEmptyDir(t *testing.T) {
|
|||
EmptyDir: &emptyDir,
|
||||
},
|
||||
},
|
||||
}, nil, defaultTestConfig, []*v1.ConfigMap{})
|
||||
}, "", defaultTestConfig, "")
|
||||
|
||||
require.NoError(t, err)
|
||||
ssetVolumes := sset.Spec.Template.Spec.Volumes
|
||||
|
@ -164,7 +167,12 @@ func TestStatefulSetVolumeInitial(t *testing.T) {
|
|||
MountPath: "/etc/prometheus/config_out",
|
||||
SubPath: "",
|
||||
}, {
|
||||
Name: "prometheus--db",
|
||||
Name: "rules",
|
||||
ReadOnly: false,
|
||||
MountPath: "/etc/prometheus/rules",
|
||||
SubPath: "",
|
||||
}, {
|
||||
Name: "prometheus-volume-init-test-db",
|
||||
ReadOnly: false,
|
||||
MountPath: "/prometheus",
|
||||
SubPath: "",
|
||||
|
@ -182,7 +190,7 @@ func TestStatefulSetVolumeInitial(t *testing.T) {
|
|||
Name: "config",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
Secret: &v1.SecretVolumeSource{
|
||||
SecretName: configSecretName(""),
|
||||
SecretName: configSecretName("volume-init-test"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -192,6 +200,16 @@ func TestStatefulSetVolumeInitial(t *testing.T) {
|
|||
EmptyDir: &v1.EmptyDirVolumeSource{},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "rules",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
ConfigMap: &v1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: v1.LocalObjectReference{
|
||||
Name: "prometheus-volume-init-test-rules",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "secret-test-secret1",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
|
@ -201,7 +219,7 @@ func TestStatefulSetVolumeInitial(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
Name: "prometheus--db",
|
||||
Name: "prometheus-volume-init-test-db",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
EmptyDir: &v1.EmptyDirVolumeSource{},
|
||||
},
|
||||
|
@ -213,43 +231,28 @@ func TestStatefulSetVolumeInitial(t *testing.T) {
|
|||
}
|
||||
|
||||
sset, err := makeStatefulSet(monitoringv1.Prometheus{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "volume-init-test",
|
||||
},
|
||||
Spec: monitoringv1.PrometheusSpec{
|
||||
Secrets: []string{
|
||||
"test-secret1",
|
||||
},
|
||||
},
|
||||
}, nil, defaultTestConfig, []*v1.ConfigMap{})
|
||||
}, "", defaultTestConfig, "")
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
if !reflect.DeepEqual(expected.Spec.Template.Spec.Volumes, sset.Spec.Template.Spec.Volumes) {
|
||||
t.Fatalf("Unexpected volumes: want %v, got %v",
|
||||
expected.Spec.Template.Spec.Volumes,
|
||||
sset.Spec.Template.Spec.Volumes)
|
||||
fmt.Println(pretty.Compare(expected.Spec.Template.Spec.Volumes, sset.Spec.Template.Spec.Volumes))
|
||||
t.Fatal("expected volumes to match")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expected.Spec.Template.Spec.Containers[0].VolumeMounts, sset.Spec.Template.Spec.Containers[0].VolumeMounts) {
|
||||
t.Fatalf("Unexpected volume mounts: want %v, got %v",
|
||||
expected.Spec.Template.Spec.Containers[0].VolumeMounts,
|
||||
sset.Spec.Template.Spec.Containers[0].VolumeMounts)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeterministicRuleFileHashing(t *testing.T) {
|
||||
cmr, err := makeRuleConfigMap(makeConfigMap())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
fmt.Println(pretty.Compare(expected.Spec.Template.Spec.Containers[0].VolumeMounts, sset.Spec.Template.Spec.Containers[0].VolumeMounts))
|
||||
t.Fatal("expected volume mounts to match")
|
||||
}
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
testcmr, err := makeRuleConfigMap(makeConfigMap())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if cmr.Checksum != testcmr.Checksum {
|
||||
t.Fatalf("Non-deterministic rule file hash generation")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMemoryRequestNotAdjustedWhenLimitLarger2Gi(t *testing.T) {
|
||||
|
@ -262,7 +265,7 @@ func TestMemoryRequestNotAdjustedWhenLimitLarger2Gi(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
}, nil, defaultTestConfig, []*v1.ConfigMap{})
|
||||
}, "", defaultTestConfig, "")
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error while making StatefulSet: %v", err)
|
||||
}
|
||||
|
@ -289,7 +292,7 @@ func TestMemoryRequestAdjustedWhenOnlyLimitGiven(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
}, nil, defaultTestConfig, []*v1.ConfigMap{})
|
||||
}, "", defaultTestConfig, "")
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error while making StatefulSet: %v", err)
|
||||
}
|
||||
|
@ -311,7 +314,7 @@ func TestListenLocal(t *testing.T) {
|
|||
Spec: monitoringv1.PrometheusSpec{
|
||||
ListenLocal: true,
|
||||
},
|
||||
}, nil, defaultTestConfig, []*v1.ConfigMap{})
|
||||
}, "", defaultTestConfig, "")
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error while making StatefulSet: %v", err)
|
||||
}
|
||||
|
@ -339,19 +342,3 @@ func TestListenLocal(t *testing.T) {
|
|||
t.Fatal("Prometheus container should have 0 ports defined")
|
||||
}
|
||||
}
|
||||
|
||||
func makeConfigMap() *v1.ConfigMap {
|
||||
res := &v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "testcm",
|
||||
Namespace: "default",
|
||||
},
|
||||
Data: map[string]string{},
|
||||
}
|
||||
|
||||
res.Data["test1"] = "value 1"
|
||||
res.Data["test2"] = "value 2"
|
||||
res.Data["test3"] = "value 3"
|
||||
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -306,6 +306,8 @@ func TestAlertmanagerZeroDowntimeRollingDeployment(t *testing.T) {
|
|||
ns := ctx.CreateNamespace(t, framework.KubeClient)
|
||||
ctx.SetupPrometheusRBAC(t, ns, framework.KubeClient)
|
||||
|
||||
alertName := "ExampleAlert"
|
||||
|
||||
whReplicas := int32(1)
|
||||
whdpl := &appsv1.Deployment{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
|
@ -411,7 +413,7 @@ inhibit_rules:
|
|||
if _, err := framework.KubeClient.CoreV1().Secrets(ns).Create(amcfg); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := framework.MonClient.Alertmanagers(ns).Create(alertmanager); err != nil {
|
||||
if _, err := framework.MonClientV1.Alertmanagers(ns).Create(alertmanager); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := testFramework.CreateServiceAndWaitUntilReady(framework.KubeClient, ns, amsvc); err != nil {
|
||||
|
@ -421,27 +423,12 @@ inhibit_rules:
|
|||
p := framework.MakeBasicPrometheus(ns, "test", "test", 3)
|
||||
p.Spec.EvaluationInterval = "100ms"
|
||||
framework.AddAlertingToPrometheus(p, ns, alertmanager.Name)
|
||||
alertRule := &v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: fmt.Sprintf("prometheus-%s-rules", p.Name),
|
||||
Labels: map[string]string{
|
||||
"role": "rulefile",
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"alerting.rules": `
|
||||
groups:
|
||||
- name: ./alerting.rules
|
||||
rules:
|
||||
- alert: ExampleAlert
|
||||
expr: vector(1)
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
if _, err := framework.KubeClient.CoreV1().ConfigMaps(ns).Create(alertRule); err != nil {
|
||||
_, err = framework.MakeAndCreateFiringRuleFile(ns, p.Name, alertName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := framework.CreatePrometheusAndWaitUntilReady(ns, p); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -456,7 +443,7 @@ groups:
|
|||
// The Prometheus config reloader reloads Prometheus periodically, not on
|
||||
// alert rule change. Thereby one has to wait for Prometheus actually firing
|
||||
// the alert.
|
||||
err = framework.WaitForPrometheusFiringAlert(p.Namespace, pSVC.Name, "ExampleAlert")
|
||||
err = framework.WaitForPrometheusFiringAlert(p.Namespace, pSVC.Name, alertName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -490,7 +477,7 @@ groups:
|
|||
}
|
||||
|
||||
alertmanager.Spec.Version = "v0.14.0"
|
||||
if _, err := framework.MonClient.Alertmanagers(ns).Update(alertmanager); err != nil {
|
||||
if _, err := framework.MonClientV1.Alertmanagers(ns).Update(alertmanager); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
|
@ -47,19 +47,19 @@ func TestMain(m *testing.M) {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = k8sutil.WaitForCRDReady(framework.MonClient.Prometheuses(v1.NamespaceAll).List)
|
||||
err = k8sutil.WaitForCRDReady(framework.MonClientV1.Prometheuses(v1.NamespaceAll).List)
|
||||
if err != nil {
|
||||
log.Printf("Prometheus CRD not ready: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = k8sutil.WaitForCRDReady(framework.MonClient.ServiceMonitors(v1.NamespaceAll).List)
|
||||
err = k8sutil.WaitForCRDReady(framework.MonClientV1.ServiceMonitors(v1.NamespaceAll).List)
|
||||
if err != nil {
|
||||
log.Printf("ServiceMonitor CRD not ready: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = k8sutil.WaitForCRDReady(framework.MonClient.Alertmanagers(v1.NamespaceAll).List)
|
||||
err = k8sutil.WaitForCRDReady(framework.MonClientV1.Alertmanagers(v1.NamespaceAll).List)
|
||||
if err != nil {
|
||||
log.Printf("Alertmanagers CRD not ready: %v\n", err)
|
||||
os.Exit(1)
|
||||
|
|
|
@ -16,6 +16,7 @@ package e2e
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
|
@ -26,6 +27,7 @@ import (
|
|||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
@ -35,6 +37,8 @@ import (
|
|||
monitoringv1 "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1"
|
||||
"github.com/coreos/prometheus-operator/pkg/prometheus"
|
||||
testFramework "github.com/coreos/prometheus-operator/test/framework"
|
||||
|
||||
"github.com/kylelemons/godebug/pretty"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -48,10 +52,10 @@ func TestPrometheusCreateDeleteCluster(t *testing.T) {
|
|||
|
||||
name := "test"
|
||||
|
||||
prometheusTPR := framework.MakeBasicPrometheus(ns, name, name, 1)
|
||||
prometheusTPR.Namespace = ns
|
||||
prometheusCRD := framework.MakeBasicPrometheus(ns, name, name, 1)
|
||||
prometheusCRD.Namespace = ns
|
||||
|
||||
if err := framework.CreatePrometheusAndWaitUntilReady(ns, prometheusTPR); err != nil {
|
||||
if err := framework.CreatePrometheusAndWaitUntilReady(ns, prometheusCRD); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -148,7 +152,7 @@ func TestPrometheusResourceUpdate(t *testing.T) {
|
|||
v1.ResourceMemory: resource.MustParse("200Mi"),
|
||||
},
|
||||
}
|
||||
_, err = framework.MonClient.Prometheuses(ns).Update(p)
|
||||
_, err = framework.MonClientV1.Prometheuses(ns).Update(p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -177,6 +181,8 @@ func TestPrometheusResourceUpdate(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPrometheusReloadConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := framework.NewTestCtx(t)
|
||||
defer ctx.Cleanup(t)
|
||||
ns := ctx.CreateNamespace(t, framework.KubeClient)
|
||||
|
@ -269,6 +275,8 @@ scrape_configs:
|
|||
}
|
||||
|
||||
func TestPrometheusAdditionalScrapeConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := framework.NewTestCtx(t)
|
||||
defer ctx.Cleanup(t)
|
||||
ns := ctx.CreateNamespace(t, framework.KubeClient)
|
||||
|
@ -279,7 +287,7 @@ func TestPrometheusAdditionalScrapeConfig(t *testing.T) {
|
|||
svc := framework.MakePrometheusService(prometheusName, group, v1.ServiceTypeClusterIP)
|
||||
|
||||
s := framework.MakeBasicServiceMonitor(group)
|
||||
if _, err := framework.MonClient.ServiceMonitors(ns).Create(s); err != nil {
|
||||
if _, err := framework.MonClientV1.ServiceMonitors(ns).Create(s); err != nil {
|
||||
t.Fatal("Creating ServiceMonitor failed: ", err)
|
||||
}
|
||||
|
||||
|
@ -335,7 +343,7 @@ func TestPrometheusAdditionalAlertManagerConfig(t *testing.T) {
|
|||
svc := framework.MakePrometheusService(prometheusName, group, v1.ServiceTypeClusterIP)
|
||||
|
||||
s := framework.MakeBasicServiceMonitor(group)
|
||||
if _, err := framework.MonClient.ServiceMonitors(ns).Create(s); err != nil {
|
||||
if _, err := framework.MonClientV1.ServiceMonitors(ns).Create(s); err != nil {
|
||||
t.Fatal("Creating ServiceMonitor failed: ", err)
|
||||
}
|
||||
|
||||
|
@ -412,25 +420,16 @@ func TestPrometheusReloadRules(t *testing.T) {
|
|||
ctx.SetupPrometheusRBAC(t, ns, framework.KubeClient)
|
||||
|
||||
name := "test"
|
||||
firtAlertName := "firstAlert"
|
||||
secondAlertName := "secondAlert"
|
||||
|
||||
ruleFileConfigMap := &v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: fmt.Sprintf("prometheus-%s-rules", name),
|
||||
Labels: map[string]string{
|
||||
"role": "rulefile",
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"alerting.rules": "",
|
||||
},
|
||||
}
|
||||
|
||||
_, err := framework.KubeClient.CoreV1().ConfigMaps(ns).Create(ruleFileConfigMap)
|
||||
ruleFile, err := framework.MakeAndCreateFiringRuleFile(ns, name, firtAlertName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
p := framework.MakeBasicPrometheus(ns, name, name, 1)
|
||||
p.Spec.EvaluationInterval = "1s"
|
||||
if err := framework.CreatePrometheusAndWaitUntilReady(ns, p); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -442,25 +441,354 @@ func TestPrometheusReloadRules(t *testing.T) {
|
|||
ctx.AddFinalizerFn(finalizerFn)
|
||||
}
|
||||
|
||||
ruleFileConfigMap.Data["alerting.rules"] = `
|
||||
groups:
|
||||
- name: ./alerting.rules
|
||||
rules:
|
||||
- alert: ExampleAlert
|
||||
expr: vector(1)
|
||||
`
|
||||
_, err = framework.KubeClient.CoreV1().ConfigMaps(ns).Update(ruleFileConfigMap)
|
||||
err = framework.WaitForPrometheusFiringAlert(p.Namespace, pSVC.Name, firtAlertName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = framework.WaitForPrometheusFiringAlert(p.Namespace, pSVC.Name, "ExampleAlert")
|
||||
ruleFile.Spec.Groups = []monitoringv1.RuleGroup{
|
||||
monitoringv1.RuleGroup{
|
||||
Name: "my-alerting-group",
|
||||
Rules: []monitoringv1.Rule{
|
||||
monitoringv1.Rule{
|
||||
Alert: secondAlertName,
|
||||
Expr: "vector(1)",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
err = framework.UpdateRuleFile(ns, ruleFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = framework.WaitForPrometheusFiringAlert(p.Namespace, pSVC.Name, secondAlertName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// With Prometheus Operator v0.20.0 the 'RuleSelector' field in the Prometheus
|
||||
// CRD Spec is deprecated. We need to ensure to still support it until the field
|
||||
// is removed. Any value in 'RuleSelector' should just be copied to the new
|
||||
// field 'RuleFileSelector'.
|
||||
func TestPrometheusDeprecatedRuleSelectorField(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := framework.NewTestCtx(t)
|
||||
defer ctx.Cleanup(t)
|
||||
ns := ctx.CreateNamespace(t, framework.KubeClient)
|
||||
ctx.SetupPrometheusRBAC(t, ns, framework.KubeClient)
|
||||
|
||||
name := "test"
|
||||
firtAlertName := "firstAlert"
|
||||
|
||||
_, err := framework.MakeAndCreateFiringRuleFile(ns, name, firtAlertName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
p := framework.MakeBasicPrometheus(ns, name, name, 1)
|
||||
p.Spec.EvaluationInterval = "1s"
|
||||
// Reset new 'RuleFileSelector' field
|
||||
p.Spec.RuleFileSelector = nil
|
||||
// Specify old 'RuleFile' field
|
||||
p.Spec.RuleSelector = &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"role": "rulefile",
|
||||
},
|
||||
}
|
||||
if err := framework.CreatePrometheusAndWaitUntilReady(ns, p); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pSVC := framework.MakePrometheusService(p.Name, "not-relevant", v1.ServiceTypeClusterIP)
|
||||
if finalizerFn, err := testFramework.CreateServiceAndWaitUntilReady(framework.KubeClient, ns, pSVC); err != nil {
|
||||
t.Fatal(errors.Wrap(err, "creating Prometheus service failed"))
|
||||
} else {
|
||||
ctx.AddFinalizerFn(finalizerFn)
|
||||
}
|
||||
|
||||
err = framework.WaitForPrometheusFiringAlert(p.Namespace, pSVC.Name, firtAlertName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrometheusMultipleRuleFilesSameNS(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := framework.NewTestCtx(t)
|
||||
defer ctx.Cleanup(t)
|
||||
ns := ctx.CreateNamespace(t, framework.KubeClient)
|
||||
ctx.SetupPrometheusRBAC(t, ns, framework.KubeClient)
|
||||
|
||||
name := "test"
|
||||
alertNames := []string{"first-alert", "second-alert"}
|
||||
|
||||
for _, alertName := range alertNames {
|
||||
_, err := framework.MakeAndCreateFiringRuleFile(ns, alertName, alertName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
p := framework.MakeBasicPrometheus(ns, name, name, 1)
|
||||
p.Spec.EvaluationInterval = "1s"
|
||||
if err := framework.CreatePrometheusAndWaitUntilReady(ns, p); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pSVC := framework.MakePrometheusService(p.Name, "not-relevant", v1.ServiceTypeClusterIP)
|
||||
if finalizerFn, err := testFramework.CreateServiceAndWaitUntilReady(framework.KubeClient, ns, pSVC); err != nil {
|
||||
t.Fatal(errors.Wrap(err, "creating Prometheus service failed"))
|
||||
} else {
|
||||
ctx.AddFinalizerFn(finalizerFn)
|
||||
}
|
||||
|
||||
for _, alertName := range alertNames {
|
||||
err := framework.WaitForPrometheusFiringAlert(p.Namespace, pSVC.Name, alertName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrometheusMultipleRuleFilesDifferentNS(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := framework.NewTestCtx(t)
|
||||
defer ctx.Cleanup(t)
|
||||
rootNS := ctx.CreateNamespace(t, framework.KubeClient)
|
||||
alertNSOne := ctx.CreateNamespace(t, framework.KubeClient)
|
||||
alertNSTwo := ctx.CreateNamespace(t, framework.KubeClient)
|
||||
ctx.SetupPrometheusRBAC(t, rootNS, framework.KubeClient)
|
||||
|
||||
name := "test"
|
||||
ruleFiles := []struct {
|
||||
alertName string
|
||||
ns string
|
||||
}{{"first-alert", alertNSOne}, {"second-alert", alertNSTwo}}
|
||||
|
||||
ruleFilesNamespaceSelector := map[string]string{"prometheus": rootNS}
|
||||
|
||||
for _, file := range ruleFiles {
|
||||
testFramework.AddLabelsToNamespace(framework.KubeClient, file.ns, ruleFilesNamespaceSelector)
|
||||
}
|
||||
|
||||
for _, file := range ruleFiles {
|
||||
_, err := framework.MakeAndCreateFiringRuleFile(file.ns, file.alertName, file.alertName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
p := framework.MakeBasicPrometheus(rootNS, name, name, 1)
|
||||
p.Spec.EvaluationInterval = "1s"
|
||||
p.Spec.RuleFileNamespaceSelector = &metav1.LabelSelector{
|
||||
MatchLabels: ruleFilesNamespaceSelector,
|
||||
}
|
||||
if err := framework.CreatePrometheusAndWaitUntilReady(rootNS, p); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pSVC := framework.MakePrometheusService(p.Name, "not-relevant", v1.ServiceTypeClusterIP)
|
||||
if finalizerFn, err := testFramework.CreateServiceAndWaitUntilReady(framework.KubeClient, rootNS, pSVC); err != nil {
|
||||
t.Fatal(errors.Wrap(err, "creating Prometheus service failed"))
|
||||
} else {
|
||||
ctx.AddFinalizerFn(finalizerFn)
|
||||
}
|
||||
|
||||
for _, file := range ruleFiles {
|
||||
err := framework.WaitForPrometheusFiringAlert(p.Namespace, pSVC.Name, file.alertName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the Prometheus operator only updates the Prometheus config secret
|
||||
// and the Prometheus rules configmap on relevant changes
|
||||
func TestPrometheusOnlyUpdatedOnRelevantChanges(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCTX := framework.NewTestCtx(t)
|
||||
defer testCTX.Cleanup(t)
|
||||
ns := testCTX.CreateNamespace(t, framework.KubeClient)
|
||||
testCTX.SetupPrometheusRBAC(t, ns, framework.KubeClient)
|
||||
|
||||
name := "test"
|
||||
prometheus := framework.MakeBasicPrometheus(ns, name, name, 1)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
type versionedResource interface {
|
||||
GetResourceVersion() string
|
||||
}
|
||||
|
||||
// TODO: rename resouceDefinitions
|
||||
resourceDefinitions := []struct {
|
||||
Name string
|
||||
Getter func(prometheusName string) (versionedResource, error)
|
||||
Versions map[string]interface{}
|
||||
ExpectedChanges int
|
||||
}{
|
||||
{
|
||||
Name: "crd",
|
||||
Getter: func(prometheusName string) (versionedResource, error) {
|
||||
return framework.
|
||||
MonClientV1.
|
||||
Prometheuses(ns).
|
||||
Get(prometheusName, metav1.GetOptions{})
|
||||
},
|
||||
ExpectedChanges: 1,
|
||||
},
|
||||
{
|
||||
Name: "rulesConfigMap",
|
||||
Getter: func(prometheusName string) (versionedResource, error) {
|
||||
return framework.
|
||||
KubeClient.
|
||||
CoreV1().
|
||||
ConfigMaps(ns).
|
||||
Get("prometheus-"+prometheusName+"-rules", metav1.GetOptions{})
|
||||
},
|
||||
ExpectedChanges: 1,
|
||||
},
|
||||
{
|
||||
Name: "configurationSecret",
|
||||
Getter: func(prometheusName string) (versionedResource, error) {
|
||||
return framework.
|
||||
KubeClient.
|
||||
CoreV1().
|
||||
Secrets(ns).
|
||||
Get("prometheus-"+prometheusName, metav1.GetOptions{})
|
||||
},
|
||||
ExpectedChanges: 1,
|
||||
},
|
||||
{
|
||||
Name: "statefulset",
|
||||
Getter: func(prometheusName string) (versionedResource, error) {
|
||||
return framework.
|
||||
KubeClient.
|
||||
AppsV1().
|
||||
StatefulSets(ns).
|
||||
Get("prometheus-"+prometheusName, metav1.GetOptions{})
|
||||
},
|
||||
// First is the creation of the StatefulSet itself, second is the
|
||||
// update of the ReadyReplicas status field
|
||||
ExpectedChanges: 2,
|
||||
},
|
||||
{
|
||||
Name: "service",
|
||||
Getter: func(prometheusName string) (versionedResource, error) {
|
||||
return framework.
|
||||
KubeClient.
|
||||
CoreV1().
|
||||
Services(ns).
|
||||
Get("prometheus-operated", metav1.GetOptions{})
|
||||
},
|
||||
ExpectedChanges: 1,
|
||||
},
|
||||
}
|
||||
|
||||
// Init Versions maps
|
||||
for i, _ := range resourceDefinitions {
|
||||
resourceDefinitions[i].Versions = map[string]interface{}{}
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
for i, resourceDef := range resourceDefinitions {
|
||||
resource, err := resourceDef.Getter(prometheus.Name)
|
||||
if apierrors.IsNotFound(err) {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
cancel()
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
resourceDefinitions[i].Versions[resource.GetResourceVersion()] = resource
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if err := framework.CreatePrometheusAndWaitUntilReady(ns, prometheus); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := framework.DeletePrometheusAndWaitUntilGone(ns, name); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cancel()
|
||||
|
||||
for _, resource := range resourceDefinitions {
|
||||
if len(resource.Versions) != resource.ExpectedChanges {
|
||||
var previous interface{}
|
||||
for _, version := range resource.Versions {
|
||||
if previous == nil {
|
||||
previous = version
|
||||
continue
|
||||
}
|
||||
fmt.Println(pretty.Compare(previous, version))
|
||||
previous = version
|
||||
}
|
||||
|
||||
t.Fatalf(
|
||||
"expected resource %v to be created/updated %v times, but saw %v instead",
|
||||
resource.Name,
|
||||
resource.ExpectedChanges,
|
||||
len(resource.Versions),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrometheusWhenDeleteCRDCleanUpViaOwnerReference(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := framework.NewTestCtx(t)
|
||||
defer ctx.Cleanup(t)
|
||||
ns := ctx.CreateNamespace(t, framework.KubeClient)
|
||||
ctx.SetupPrometheusRBAC(t, ns, framework.KubeClient)
|
||||
|
||||
name := "test"
|
||||
|
||||
p := framework.MakeBasicPrometheus(ns, name, name, 1)
|
||||
if err := framework.CreatePrometheusAndWaitUntilReady(ns, p); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
configMapName := fmt.Sprintf("prometheus-%v-rules", p.Name)
|
||||
|
||||
_, err := framework.WaitForConfigMapExist(ns, configMapName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Waits for Prometheus pods to vanish
|
||||
err = framework.DeletePrometheusAndWaitUntilGone(ns, p.Name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = framework.WaitForConfigMapNotExist(ns, configMapName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrometheusDiscovery(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := framework.NewTestCtx(t)
|
||||
defer ctx.Cleanup(t)
|
||||
ns := ctx.CreateNamespace(t, framework.KubeClient)
|
||||
|
@ -471,7 +799,7 @@ func TestPrometheusDiscovery(t *testing.T) {
|
|||
svc := framework.MakePrometheusService(prometheusName, group, v1.ServiceTypeClusterIP)
|
||||
|
||||
s := framework.MakeBasicServiceMonitor(group)
|
||||
if _, err := framework.MonClient.ServiceMonitors(ns).Create(s); err != nil {
|
||||
if _, err := framework.MonClientV1.ServiceMonitors(ns).Create(s); err != nil {
|
||||
t.Fatal("Creating ServiceMonitor failed: ", err)
|
||||
}
|
||||
|
||||
|
@ -499,6 +827,8 @@ func TestPrometheusDiscovery(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPrometheusAlertmanagerDiscovery(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := framework.NewTestCtx(t)
|
||||
defer ctx.Cleanup(t)
|
||||
ns := ctx.CreateNamespace(t, framework.KubeClient)
|
||||
|
@ -524,7 +854,7 @@ func TestPrometheusAlertmanagerDiscovery(t *testing.T) {
|
|||
}
|
||||
|
||||
s := framework.MakeBasicServiceMonitor(group)
|
||||
if _, err := framework.MonClient.ServiceMonitors(ns).Create(s); err != nil {
|
||||
if _, err := framework.MonClientV1.ServiceMonitors(ns).Create(s); err != nil {
|
||||
t.Fatalf("Creating ServiceMonitor failed: %v", err)
|
||||
}
|
||||
|
||||
|
@ -586,7 +916,7 @@ func TestPrometheusDiscoverTargetPort(t *testing.T) {
|
|||
group := "servicediscovery-test"
|
||||
svc := framework.MakePrometheusService(prometheusName, group, v1.ServiceTypeClusterIP)
|
||||
|
||||
if _, err := framework.MonClient.ServiceMonitors(ns).Create(&monitoringv1.ServiceMonitor{
|
||||
if _, err := framework.MonClientV1.ServiceMonitors(ns).Create(&monitoringv1.ServiceMonitor{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: prometheusName,
|
||||
Labels: map[string]string{
|
||||
|
@ -633,6 +963,8 @@ func TestPrometheusDiscoverTargetPort(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPromOpMatchPromAndServMonInDiffNSs(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := framework.NewTestCtx(t)
|
||||
defer ctx.Cleanup(t)
|
||||
prometheusNSName := ctx.CreateNamespace(t, framework.KubeClient)
|
||||
|
@ -656,7 +988,7 @@ func TestPromOpMatchPromAndServMonInDiffNSs(t *testing.T) {
|
|||
|
||||
s := framework.MakeBasicServiceMonitor(group)
|
||||
|
||||
if _, err := framework.MonClient.ServiceMonitors(serviceMonitorNSName).Create(s); err != nil {
|
||||
if _, err := framework.MonClientV1.ServiceMonitors(serviceMonitorNSName).Create(s); err != nil {
|
||||
t.Fatal("Creating ServiceMonitor failed: ", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ func (f *Framework) CreateAlertmanagerAndWaitUntilReady(ns string, a *monitoring
|
|||
return errors.Wrap(err, fmt.Sprintf("creating alertmanager config secret %v failed", s.Name))
|
||||
}
|
||||
|
||||
_, err = f.MonClient.Alertmanagers(ns).Create(a)
|
||||
_, err = f.MonClientV1.Alertmanagers(ns).Create(a)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("creating alertmanager %v failed", a.Name))
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ func (f *Framework) WaitForAlertmanagerReady(ns, name string, replicas int) erro
|
|||
}
|
||||
|
||||
func (f *Framework) UpdateAlertmanagerAndWaitUntilReady(ns string, a *monitoringv1.Alertmanager) error {
|
||||
_, err := f.MonClient.Alertmanagers(ns).Update(a)
|
||||
_, err := f.MonClientV1.Alertmanagers(ns).Update(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -174,12 +174,12 @@ func (f *Framework) UpdateAlertmanagerAndWaitUntilReady(ns string, a *monitoring
|
|||
}
|
||||
|
||||
func (f *Framework) DeleteAlertmanagerAndWaitUntilGone(ns, name string) error {
|
||||
_, err := f.MonClient.Alertmanagers(ns).Get(name, metav1.GetOptions{})
|
||||
_, err := f.MonClientV1.Alertmanagers(ns).Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("requesting Alertmanager tpr %v failed", name))
|
||||
}
|
||||
|
||||
if err := f.MonClient.Alertmanagers(ns).Delete(name, nil); err != nil {
|
||||
if err := f.MonClientV1.Alertmanagers(ns).Delete(name, nil); err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("deleting Alertmanager tpr %v failed", name))
|
||||
}
|
||||
|
||||
|
|
67
test/framework/config_map.go
Normal file
67
test/framework/config_map.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
// Copyright 2016 The prometheus-operator Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package framework
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
)
|
||||
|
||||
func (f *Framework) WaitForConfigMapExist(ns, name string) (*v1.ConfigMap, error) {
|
||||
var configMap *v1.ConfigMap
|
||||
err := wait.Poll(2*time.Second, f.DefaultTimeout, func() (bool, error) {
|
||||
var err error
|
||||
configMap, err = f.
|
||||
KubeClient.
|
||||
CoreV1().
|
||||
ConfigMaps(ns).
|
||||
Get(name, metav1.GetOptions{})
|
||||
|
||||
if apierrors.IsNotFound(err) {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
return configMap, err
|
||||
}
|
||||
|
||||
func (f *Framework) WaitForConfigMapNotExist(ns, name string) error {
|
||||
err := wait.Poll(2*time.Second, f.DefaultTimeout, func() (bool, error) {
|
||||
var err error
|
||||
_, err = f.
|
||||
KubeClient.
|
||||
CoreV1().
|
||||
ConfigMaps(ns).
|
||||
Get(name, metav1.GetOptions{})
|
||||
|
||||
if apierrors.IsNotFound(err) {
|
||||
return true, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
|
@ -16,6 +16,7 @@ package framework
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -28,18 +29,20 @@ import (
|
|||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
||||
monitoringv1 "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1"
|
||||
monitoringv1alpha1 "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1alpha1"
|
||||
"github.com/coreos/prometheus-operator/pkg/k8sutil"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Framework struct {
|
||||
KubeClient kubernetes.Interface
|
||||
MonClient monitoringv1.MonitoringV1Interface
|
||||
HTTPClient *http.Client
|
||||
MasterHost string
|
||||
Namespace *v1.Namespace
|
||||
OperatorPod *v1.Pod
|
||||
DefaultTimeout time.Duration
|
||||
KubeClient kubernetes.Interface
|
||||
MonClientV1 monitoringv1.MonitoringV1Interface
|
||||
MonClientV1alpha1 monitoringv1alpha1.MonitoringV1alpha1Interface
|
||||
HTTPClient *http.Client
|
||||
MasterHost string
|
||||
Namespace *v1.Namespace
|
||||
OperatorPod *v1.Pod
|
||||
DefaultTimeout time.Duration
|
||||
}
|
||||
|
||||
// Setup setups a test framework and returns it.
|
||||
|
@ -59,9 +62,14 @@ func New(ns, kubeconfig, opImage string) (*Framework, error) {
|
|||
return nil, errors.Wrap(err, "creating http-client failed")
|
||||
}
|
||||
|
||||
mclient, err := monitoringv1.NewForConfig(&monitoringv1.DefaultCrdKinds, monitoringv1.Group, config)
|
||||
mClientV1, err := monitoringv1.NewForConfig(&monitoringv1.DefaultCrdKinds, monitoringv1.Group, config)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "creating monitoring client failed")
|
||||
return nil, errors.Wrap(err, "creating v1 monitoring client failed")
|
||||
}
|
||||
|
||||
mClientV1alpha1, err := monitoringv1alpha1.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "creating v1alpha1 monitoring client failed")
|
||||
}
|
||||
|
||||
namespace, err := CreateNamespace(cli, ns)
|
||||
|
@ -70,12 +78,13 @@ func New(ns, kubeconfig, opImage string) (*Framework, error) {
|
|||
}
|
||||
|
||||
f := &Framework{
|
||||
MasterHost: config.Host,
|
||||
KubeClient: cli,
|
||||
MonClient: mclient,
|
||||
HTTPClient: httpc,
|
||||
Namespace: namespace,
|
||||
DefaultTimeout: time.Minute,
|
||||
MasterHost: config.Host,
|
||||
KubeClient: cli,
|
||||
MonClientV1: mClientV1,
|
||||
MonClientV1alpha1: mClientV1alpha1,
|
||||
HTTPClient: httpc,
|
||||
Namespace: namespace,
|
||||
DefaultTimeout: time.Minute,
|
||||
}
|
||||
|
||||
err = f.Setup(opImage)
|
||||
|
@ -119,8 +128,21 @@ func (f *Framework) setupPrometheusOperator(opImage string) error {
|
|||
if opImage != "" {
|
||||
// Override operator image used, if specified when running tests.
|
||||
deploy.Spec.Template.Spec.Containers[0].Image = opImage
|
||||
repoAndTag := strings.Split(opImage, ":")
|
||||
if len(repoAndTag) != 2 {
|
||||
return errors.Errorf(
|
||||
"expected operator image '%v' split by colon to result in two substrings but got '%v'",
|
||||
opImage,
|
||||
repoAndTag,
|
||||
)
|
||||
}
|
||||
deploy.Spec.Template.Spec.Containers[0].Args[1] = "--prometheus-config-reloader=" +
|
||||
"quay.io/coreos/prometheus-config-reloader:" +
|
||||
repoAndTag[1]
|
||||
}
|
||||
|
||||
deploy.Spec.Template.Spec.Containers[0].Args = append(deploy.Spec.Template.Spec.Containers[0].Args, "--log-level=all")
|
||||
|
||||
err = CreateDeployment(f.KubeClient, f.Namespace.Name, deploy)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -48,36 +48,7 @@ func (f *Framework) MakeBasicPrometheus(ns, name, group string, replicas int32)
|
|||
},
|
||||
},
|
||||
ServiceAccountName: "prometheus",
|
||||
RuleSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"role": "rulefile",
|
||||
},
|
||||
},
|
||||
Resources: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceMemory: resource.MustParse("400Mi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Framework) MakeBasicPrometheusV1alpha1(ns, name, group string, replicas int32) *v1alpha1.Prometheus {
|
||||
return &v1alpha1.Prometheus{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: ns,
|
||||
},
|
||||
Spec: v1alpha1.PrometheusSpec{
|
||||
Replicas: &replicas,
|
||||
Version: prometheus.DefaultVersion,
|
||||
ServiceMonitorSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"group": group,
|
||||
},
|
||||
},
|
||||
ServiceAccountName: "prometheus",
|
||||
RuleSelector: &metav1.LabelSelector{
|
||||
RuleFileSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"role": "rulefile",
|
||||
},
|
||||
|
@ -177,20 +148,20 @@ func (f *Framework) MakePrometheusService(name, group string, serviceType v1.Ser
|
|||
}
|
||||
|
||||
func (f *Framework) CreatePrometheusAndWaitUntilReady(ns string, p *monitoringv1.Prometheus) error {
|
||||
_, err := f.MonClient.Prometheuses(ns).Create(p)
|
||||
_, err := f.MonClientV1.Prometheuses(ns).Create(p)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating %d Prometheus instances failed (%v): %v", p.Spec.Replicas, p.Name, err)
|
||||
return fmt.Errorf("creating %v Prometheus instances failed (%v): %v", p.Spec.Replicas, p.Name, err)
|
||||
}
|
||||
|
||||
if err := f.WaitForPrometheusReady(p, 5*time.Minute); err != nil {
|
||||
return fmt.Errorf("waiting for %d Prometheus instances timed out (%v): %v", p.Spec.Replicas, p.Name, err)
|
||||
return fmt.Errorf("waiting for %v Prometheus instances timed out (%v): %v", p.Spec.Replicas, p.Name, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Framework) UpdatePrometheusAndWaitUntilReady(ns string, p *monitoringv1.Prometheus) error {
|
||||
_, err := f.MonClient.Prometheuses(ns).Update(p)
|
||||
_, err := f.MonClientV1.Prometheuses(ns).Update(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -202,7 +173,7 @@ func (f *Framework) UpdatePrometheusAndWaitUntilReady(ns string, p *monitoringv1
|
|||
}
|
||||
|
||||
func (f *Framework) WaitForPrometheusReady(p *monitoringv1.Prometheus, timeout time.Duration) error {
|
||||
return wait.Poll(2*time.Second, timeout, func() (bool, error) {
|
||||
err := wait.Poll(2*time.Second, timeout, func() (bool, error) {
|
||||
st, _, err := prometheus.PrometheusStatus(f.KubeClient, p)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
|
@ -211,19 +182,19 @@ func (f *Framework) WaitForPrometheusReady(p *monitoringv1.Prometheus, timeout t
|
|||
if st.UpdatedReplicas == *p.Spec.Replicas {
|
||||
return true, nil
|
||||
} else {
|
||||
log.Printf("expected %v Prometheus instances, got %v", *p.Spec.Replicas, st.UpdatedReplicas)
|
||||
return false, nil
|
||||
}
|
||||
})
|
||||
return errors.Wrapf(err, "waiting for Prometheus %v/%v", p.Namespace, p.Name)
|
||||
}
|
||||
|
||||
func (f *Framework) DeletePrometheusAndWaitUntilGone(ns, name string) error {
|
||||
_, err := f.MonClient.Prometheuses(ns).Get(name, metav1.GetOptions{})
|
||||
_, err := f.MonClientV1.Prometheuses(ns).Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("requesting Prometheus tpr %v failed", name))
|
||||
}
|
||||
|
||||
if err := f.MonClient.Prometheuses(ns).Delete(name, nil); err != nil {
|
||||
if err := f.MonClientV1.Prometheuses(ns).Delete(name, nil); err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("deleting Prometheus tpr %v failed", name))
|
||||
}
|
||||
|
||||
|
@ -337,7 +308,12 @@ func (f *Framework) WaitForPrometheusFiringAlert(ns, svcName, alertName string)
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(loopError, err.Error())
|
||||
return errors.Errorf(
|
||||
"waiting for alert '%v' to fire: %v: %v",
|
||||
alertName,
|
||||
err.Error(),
|
||||
loopError.Error(),
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
77
test/framework/rulefile.go
Normal file
77
test/framework/rulefile.go
Normal file
|
@ -0,0 +1,77 @@
|
|||
// Copyright 2016 The prometheus-operator Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package framework
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
monitoringv1 "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func (f *Framework) MakeBasicRuleFile(ns, name string, groups []monitoringv1.RuleGroup) monitoringv1.RuleFile {
|
||||
return monitoringv1.RuleFile{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: ns,
|
||||
Labels: map[string]string{
|
||||
"role": "rulefile",
|
||||
},
|
||||
},
|
||||
Spec: monitoringv1.RuleFileSpec{
|
||||
Groups: groups,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Framework) CreateRuleFile(ns string, ar monitoringv1.RuleFile) error {
|
||||
_, err := f.MonClientV1.RuleFiles(ns).Create(&ar)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating %v RuleFile failed: %v", ar.Name, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Framework) MakeAndCreateFiringRuleFile(ns, name, alertName string) (monitoringv1.RuleFile, error) {
|
||||
groups := []monitoringv1.RuleGroup{
|
||||
monitoringv1.RuleGroup{
|
||||
Name: alertName,
|
||||
Rules: []monitoringv1.Rule{
|
||||
monitoringv1.Rule{
|
||||
Alert: alertName,
|
||||
Expr: "vector(1)",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
file := f.MakeBasicRuleFile(ns, name, groups)
|
||||
|
||||
err := f.CreateRuleFile(ns, file)
|
||||
if err != nil {
|
||||
return file, err
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func (f *Framework) UpdateRuleFile(ns string, ar monitoringv1.RuleFile) error {
|
||||
_, err := f.MonClientV1.RuleFiles(ns).Update(&ar)
|
||||
if err != nil {
|
||||
return fmt.Errorf("updating %v RuleFile failed: %v", ar.Name, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
1
vendor/github.com/ericchiang/k8s/.gitignore
generated
vendored
1
vendor/github.com/ericchiang/k8s/.gitignore
generated
vendored
|
@ -1 +0,0 @@
|
|||
assets
|
21
vendor/github.com/ericchiang/k8s/.travis.yml
generated
vendored
21
vendor/github.com/ericchiang/k8s/.travis.yml
generated
vendored
|
@ -1,21 +0,0 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.7.5
|
||||
- 1.8
|
||||
|
||||
env:
|
||||
# Maybe run minikube later?
|
||||
- K8S_CLIENT_TEST=0
|
||||
|
||||
install:
|
||||
- go get -v ./...
|
||||
- go get -v github.com/ghodss/yaml # Required for examples.
|
||||
|
||||
script:
|
||||
- make test
|
||||
- make test-examples
|
||||
|
||||
|
||||
notifications:
|
||||
email: false
|
7
vendor/github.com/ericchiang/k8s/Makefile
generated
vendored
7
vendor/github.com/ericchiang/k8s/Makefile
generated
vendored
|
@ -1,7 +0,0 @@
|
|||
test:
|
||||
go test -v ./...
|
||||
|
||||
test-examples:
|
||||
@for example in $(shell find examples/ -name '*.go'); do \
|
||||
go build -v $$example || exit 1; \
|
||||
done
|
182
vendor/github.com/ericchiang/k8s/README.md
generated
vendored
182
vendor/github.com/ericchiang/k8s/README.md
generated
vendored
|
@ -1,182 +0,0 @@
|
|||
# A simple Go client for Kubernetes
|
||||
|
||||
[](https://godoc.org/github.com/ericchiang/k8s)
|
||||
|
||||
A slimmed down Go client generated using Kubernetes' new [protocol buffer][protobuf] support. This package behaves similarly to [official Kubernetes' Go client][client-go], but only imports two external dependencies.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/ericchiang/k8s"
|
||||
)
|
||||
|
||||
func main() {
|
||||
client, err := k8s.NewInClusterClient()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
nodes, err := client.CoreV1().ListNodes(context.Background())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
for _, node := range nodes.Items {
|
||||
fmt.Printf("name=%q schedulable=%t\n", *node.Metadata.Name, !*node.Spec.Unschedulable)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
* Go 1.7+ (this package uses "context" features added in 1.7)
|
||||
* Kubernetes 1.3+ (protobuf support was added in 1.3)
|
||||
* [github.com/golang/protobuf/proto][go-proto] (protobuf serialization)
|
||||
* [golang.org/x/net/http2][go-http2] (HTTP/2 support)
|
||||
|
||||
## Versioned supported
|
||||
|
||||
This client supports every API group version present since 1.3.
|
||||
|
||||
## Usage
|
||||
|
||||
### Namespace
|
||||
|
||||
When performing a list or watch operation, the namespace to list or watch in is provided as an argument.
|
||||
|
||||
```go
|
||||
pods, err := core.ListPods(ctx, "custom-namespace") // Pods from the "custom-namespace"
|
||||
```
|
||||
|
||||
A special value `AllNamespaces` indicates that the list or watch should be performed on all cluster resources.
|
||||
|
||||
```go
|
||||
pods, err := core.ListPods(ctx, k8s.AllNamespaces) // Pods in all namespaces.
|
||||
```
|
||||
|
||||
Both in-cluster and out-of-cluster clients are initialized with a primary namespace. This is the recommended value to use when listing or watching.
|
||||
|
||||
```go
|
||||
client, err := k8s.NewInClusterClient()
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
|
||||
// List pods in the namespace the client is running in.
|
||||
pods, err := client.CoreV1().ListPods(ctx, client.Namespace)
|
||||
```
|
||||
|
||||
### Label selectors
|
||||
|
||||
Label selectors can be provided to any list operation.
|
||||
|
||||
```go
|
||||
l := new(k8s.LabelSelector)
|
||||
l.Eq("tier", "production")
|
||||
l.In("app", "database", "frontend")
|
||||
|
||||
pods, err := client.CoreV1().ListPods(ctx, client.Namespace, l.Selector())
|
||||
```
|
||||
|
||||
### Working with resources
|
||||
|
||||
Use the generated API types directly to create and modify resources.
|
||||
|
||||
```go
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ericchiang/k8s"
|
||||
"github.com/ericchiang/k8s/api/v1"
|
||||
metav1 "github.com/ericchiang/k8s/apis/meta/v1"
|
||||
)
|
||||
|
||||
func createConfigMap(client *k8s.Client, name string, values map[string]string) error {
|
||||
cm := &v1.ConfigMap{
|
||||
Metadata: &metav1.ObjectMeta{
|
||||
Name: &name,
|
||||
Namespace: &client.Namespace,
|
||||
},
|
||||
Data: values,
|
||||
}
|
||||
// Will return the created configmap as well.
|
||||
_, err := client.CoreV1().CreateConfigMap(context.TODO(), cm)
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
API structs use pointers to `int`, `bool`, and `string` types to differentiate between the zero value and an unsupplied one. This package provides [convenience methods][string] for creating pointers to literals of basic types.
|
||||
|
||||
### Creating out-of-cluster clients
|
||||
|
||||
Out-of-cluster clients can be constructed by either creating an `http.Client` manually or parsing a [`Config`][config] object. The following is an example of creating a client from a kubeconfig:
|
||||
|
||||
```go
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/ericchiang/k8s"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
)
|
||||
|
||||
// loadClient parses a kubeconfig from a file and returns a Kubernetes
|
||||
// client. It does not support extensions or client auth providers.
|
||||
func loadClient(kubeconfigPath string) (*k8s.Client, error) {
|
||||
data, err := ioutil.ReadFile(kubeconfigPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read kubeconfig: %v", err)
|
||||
}
|
||||
|
||||
// Unmarshal YAML into a Kubernetes config object.
|
||||
var config k8s.Config
|
||||
if err := yaml.Unmarshal(data, &config); err != nil {
|
||||
return nil, fmt.Errorf("unmarshal kubeconfig: %v", err)
|
||||
}
|
||||
return k8s.NewClient(&config)
|
||||
}
|
||||
```
|
||||
|
||||
### Errors
|
||||
|
||||
Errors returned by the Kubernetes API are formatted as [`unversioned.Status`][unversioned-status] objects and surfaced by clients as [`*k8s.APIError`][k8s-error]s. Programs that need to inspect error codes or failure details can use a type cast to access this information.
|
||||
|
||||
```go
|
||||
// createConfigMap creates a configmap in the client's default namespace
|
||||
// but does not return an error if a configmap of the same name already
|
||||
// exists.
|
||||
func createConfigMap(client *k8s.Client, name string, values map[string]string) error {
|
||||
cm := &v1.ConfigMap{
|
||||
Metadata: &metav1.ObjectMeta{
|
||||
Name: &name,
|
||||
Namespace: &client.Namespace,
|
||||
},
|
||||
Data: values,
|
||||
}
|
||||
|
||||
_, err := client.CoreV1().CreateConfigMap(context.TODO(), cm)
|
||||
|
||||
// If an HTTP error was returned by the API server, it will be of type
|
||||
// *k8s.APIError. This can be used to inspect the status code.
|
||||
if apiErr, ok := err.(*k8s.APIError); ok {
|
||||
// Resource already exists. Carry on.
|
||||
if apiErr.Code == http.StatusConflict {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("create configmap: %v", err)
|
||||
}
|
||||
```
|
||||
|
||||
[client-go]: https://github.com/kubernetes/client-go
|
||||
[go-proto]: https://godoc.org/github.com/golang/protobuf/proto
|
||||
[go-http2]: https://godoc.org/golang.org/x/net/http2
|
||||
[protobuf]: https://developers.google.com/protocol-buffers/
|
||||
[unversioned-status]: https://godoc.org/github.com/ericchiang/k8s/api/unversioned#Status
|
||||
[k8s-error]: https://godoc.org/github.com/ericchiang/k8s#APIError
|
||||
[config]: https://godoc.org/github.com/ericchiang/k8s#Config
|
||||
[string]: https://godoc.org/github.com/ericchiang/k8s#String
|
399
vendor/github.com/ericchiang/k8s/api/resource/generated.pb.go
generated
vendored
399
vendor/github.com/ericchiang/k8s/api/resource/generated.pb.go
generated
vendored
|
@ -1,399 +0,0 @@
|
|||
// Code generated by protoc-gen-gogo.
|
||||
// source: k8s.io/kubernetes/pkg/api/resource/generated.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package resource is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
k8s.io/kubernetes/pkg/api/resource/generated.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Quantity
|
||||
*/
|
||||
package resource
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import _ "github.com/ericchiang/k8s/util/intstr"
|
||||
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Quantity is a fixed-point representation of a number.
|
||||
// It provides convenient marshaling/unmarshaling in JSON and YAML,
|
||||
// in addition to String() and Int64() accessors.
|
||||
//
|
||||
// The serialization format is:
|
||||
//
|
||||
// <quantity> ::= <signedNumber><suffix>
|
||||
// (Note that <suffix> may be empty, from the "" case in <decimalSI>.)
|
||||
// <digit> ::= 0 | 1 | ... | 9
|
||||
// <digits> ::= <digit> | <digit><digits>
|
||||
// <number> ::= <digits> | <digits>.<digits> | <digits>. | .<digits>
|
||||
// <sign> ::= "+" | "-"
|
||||
// <signedNumber> ::= <number> | <sign><number>
|
||||
// <suffix> ::= <binarySI> | <decimalExponent> | <decimalSI>
|
||||
// <binarySI> ::= Ki | Mi | Gi | Ti | Pi | Ei
|
||||
// (International System of units; See: http://physics.nist.gov/cuu/Units/binary.html)
|
||||
// <decimalSI> ::= m | "" | k | M | G | T | P | E
|
||||
// (Note that 1024 = 1Ki but 1000 = 1k; I didn't choose the capitalization.)
|
||||
// <decimalExponent> ::= "e" <signedNumber> | "E" <signedNumber>
|
||||
//
|
||||
// No matter which of the three exponent forms is used, no quantity may represent
|
||||
// a number greater than 2^63-1 in magnitude, nor may it have more than 3 decimal
|
||||
// places. Numbers larger or more precise will be capped or rounded up.
|
||||
// (E.g.: 0.1m will rounded up to 1m.)
|
||||
// This may be extended in the future if we require larger or smaller quantities.
|
||||
//
|
||||
// When a Quantity is parsed from a string, it will remember the type of suffix
|
||||
// it had, and will use the same type again when it is serialized.
|
||||
//
|
||||
// Before serializing, Quantity will be put in "canonical form".
|
||||
// This means that Exponent/suffix will be adjusted up or down (with a
|
||||
// corresponding increase or decrease in Mantissa) such that:
|
||||
// a. No precision is lost
|
||||
// b. No fractional digits will be emitted
|
||||
// c. The exponent (or suffix) is as large as possible.
|
||||
// The sign will be omitted unless the number is negative.
|
||||
//
|
||||
// Examples:
|
||||
// 1.5 will be serialized as "1500m"
|
||||
// 1.5Gi will be serialized as "1536Mi"
|
||||
//
|
||||
// NOTE: We reserve the right to amend this canonical format, perhaps to
|
||||
// allow 1.5 to be canonical.
|
||||
// TODO: Remove above disclaimer after all bikeshedding about format is over,
|
||||
// or after March 2015.
|
||||
//
|
||||
// Note that the quantity will NEVER be internally represented by a
|
||||
// floating point number. That is the whole point of this exercise.
|
||||
//
|
||||
// Non-canonical values will still parse as long as they are well formed,
|
||||
// but will be re-emitted in their canonical form. (So always use canonical
|
||||
// form, or don't diff.)
|
||||
//
|
||||
// This format is intended to make it difficult to use these numbers without
|
||||
// writing some sort of special handling code in the hopes that that will
|
||||
// cause implementors to also use a fixed point implementation.
|
||||
//
|
||||
// +protobuf=true
|
||||
// +protobuf.embed=string
|
||||
// +protobuf.options.marshal=false
|
||||
// +protobuf.options.(gogoproto.goproto_stringer)=false
|
||||
// +k8s:openapi-gen=true
|
||||
type Quantity struct {
|
||||
String_ *string `protobuf:"bytes,1,opt,name=string" json:"string,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Quantity) Reset() { *m = Quantity{} }
|
||||
func (m *Quantity) String() string { return proto.CompactTextString(m) }
|
||||
func (*Quantity) ProtoMessage() {}
|
||||
func (*Quantity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} }
|
||||
|
||||
func (m *Quantity) GetString_() string {
|
||||
if m != nil && m.String_ != nil {
|
||||
return *m.String_
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Quantity)(nil), "github.com/ericchiang.k8s.api.resource.Quantity")
|
||||
}
|
||||
func (m *Quantity) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Quantity) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.String_ != nil {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(*m.String_)))
|
||||
i += copy(dAtA[i:], *m.String_)
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
dAtA[offset+2] = uint8(v >> 16)
|
||||
dAtA[offset+3] = uint8(v >> 24)
|
||||
dAtA[offset+4] = uint8(v >> 32)
|
||||
dAtA[offset+5] = uint8(v >> 40)
|
||||
dAtA[offset+6] = uint8(v >> 48)
|
||||
dAtA[offset+7] = uint8(v >> 56)
|
||||
return offset + 8
|
||||
}
|
||||
func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
dAtA[offset+2] = uint8(v >> 16)
|
||||
dAtA[offset+3] = uint8(v >> 24)
|
||||
return offset + 4
|
||||
}
|
||||
func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *Quantity) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.String_ != nil {
|
||||
l = len(*m.String_)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovGenerated(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozGenerated(x uint64) (n int) {
|
||||
return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *Quantity) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Quantity: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Quantity: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field String_", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.String_ = &s
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipGenerated(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthGenerated
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipGenerated(dAtA[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/ericchiang/k8s/api/resource/generated.proto", fileDescriptorGenerated)
|
||||
}
|
||||
|
||||
var fileDescriptorGenerated = []byte{
|
||||
// 166 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x32, 0xca, 0xb6, 0x28, 0xd6,
|
||||
0xcb, 0xcc, 0xd7, 0xcf, 0x2e, 0x4d, 0x4a, 0x2d, 0xca, 0x4b, 0x2d, 0x49, 0x2d, 0xd6, 0x2f, 0xc8,
|
||||
0x4e, 0xd7, 0x4f, 0x2c, 0xc8, 0xd4, 0x2f, 0x4a, 0x2d, 0xce, 0x2f, 0x2d, 0x4a, 0x4e, 0xd5, 0x4f,
|
||||
0x4f, 0xcd, 0x4b, 0x2d, 0x4a, 0x2c, 0x49, 0x4d, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52,
|
||||
0x82, 0xe8, 0xd1, 0x43, 0xe8, 0xd1, 0x2b, 0xc8, 0x4e, 0xd7, 0x4b, 0x2c, 0xc8, 0xd4, 0x83, 0xe9,
|
||||
0x91, 0x32, 0xc4, 0x6e, 0x6e, 0x69, 0x49, 0x66, 0x8e, 0x7e, 0x66, 0x5e, 0x49, 0x71, 0x49, 0x11,
|
||||
0xba, 0xb1, 0x4a, 0x4a, 0x5c, 0x1c, 0x81, 0xa5, 0x89, 0x79, 0x25, 0x99, 0x25, 0x95, 0x42, 0x62,
|
||||
0x5c, 0x6c, 0xc5, 0x25, 0x45, 0x99, 0x79, 0xe9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x50,
|
||||
0x9e, 0x93, 0xd4, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38,
|
||||
0xe3, 0xb1, 0x1c, 0x43, 0x14, 0x07, 0xcc, 0x4a, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x81, 0x00,
|
||||
0xf7, 0xdc, 0xcb, 0x00, 0x00, 0x00,
|
||||
}
|
5614
vendor/github.com/ericchiang/k8s/api/unversioned/generated.pb.go
generated
vendored
5614
vendor/github.com/ericchiang/k8s/api/unversioned/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
32
vendor/github.com/ericchiang/k8s/api/unversioned/time.go
generated
vendored
32
vendor/github.com/ericchiang/k8s/api/unversioned/time.go
generated
vendored
|
@ -1,32 +0,0 @@
|
|||
package unversioned
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
// JSON marshaling logic for the Time type. Need to make
|
||||
// third party resources JSON work.
|
||||
|
||||
func (t Time) MarshalJSON() ([]byte, error) {
|
||||
var seconds, nanos int64
|
||||
if t.Seconds != nil {
|
||||
seconds = *t.Seconds
|
||||
}
|
||||
if t.Nanos != nil {
|
||||
nanos = int64(*t.Nanos)
|
||||
}
|
||||
return json.Marshal(time.Unix(seconds, nanos))
|
||||
}
|
||||
|
||||
func (t *Time) UnmarshalJSON(p []byte) error {
|
||||
var t1 time.Time
|
||||
if err := json.Unmarshal(p, &t1); err != nil {
|
||||
return err
|
||||
}
|
||||
seconds := t1.Unix()
|
||||
nanos := int32(t1.UnixNano())
|
||||
t.Seconds = &seconds
|
||||
t.Nanos = &nanos
|
||||
return nil
|
||||
}
|
52331
vendor/github.com/ericchiang/k8s/api/v1/generated.pb.go
generated
vendored
52331
vendor/github.com/ericchiang/k8s/api/v1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
1227
vendor/github.com/ericchiang/k8s/apis/apps/v1alpha1/generated.pb.go
generated
vendored
1227
vendor/github.com/ericchiang/k8s/apis/apps/v1alpha1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
4697
vendor/github.com/ericchiang/k8s/apis/apps/v1beta1/generated.pb.go
generated
vendored
4697
vendor/github.com/ericchiang/k8s/apis/apps/v1beta1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
1452
vendor/github.com/ericchiang/k8s/apis/authentication/v1/generated.pb.go
generated
vendored
1452
vendor/github.com/ericchiang/k8s/apis/authentication/v1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
1454
vendor/github.com/ericchiang/k8s/apis/authentication/v1beta1/generated.pb.go
generated
vendored
1454
vendor/github.com/ericchiang/k8s/apis/authentication/v1beta1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
2759
vendor/github.com/ericchiang/k8s/apis/authorization/v1/generated.pb.go
generated
vendored
2759
vendor/github.com/ericchiang/k8s/apis/authorization/v1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
2759
vendor/github.com/ericchiang/k8s/apis/authorization/v1beta1/generated.pb.go
generated
vendored
2759
vendor/github.com/ericchiang/k8s/apis/authorization/v1beta1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
4162
vendor/github.com/ericchiang/k8s/apis/autoscaling/v1/generated.pb.go
generated
vendored
4162
vendor/github.com/ericchiang/k8s/apis/autoscaling/v1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
3635
vendor/github.com/ericchiang/k8s/apis/autoscaling/v2alpha1/generated.pb.go
generated
vendored
3635
vendor/github.com/ericchiang/k8s/apis/autoscaling/v2alpha1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
1883
vendor/github.com/ericchiang/k8s/apis/batch/v1/generated.pb.go
generated
vendored
1883
vendor/github.com/ericchiang/k8s/apis/batch/v1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
1743
vendor/github.com/ericchiang/k8s/apis/batch/v2alpha1/generated.pb.go
generated
vendored
1743
vendor/github.com/ericchiang/k8s/apis/batch/v2alpha1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
1505
vendor/github.com/ericchiang/k8s/apis/certificates/v1alpha1/generated.pb.go
generated
vendored
1505
vendor/github.com/ericchiang/k8s/apis/certificates/v1alpha1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
1902
vendor/github.com/ericchiang/k8s/apis/certificates/v1beta1/generated.pb.go
generated
vendored
1902
vendor/github.com/ericchiang/k8s/apis/certificates/v1beta1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
14382
vendor/github.com/ericchiang/k8s/apis/extensions/v1beta1/generated.pb.go
generated
vendored
14382
vendor/github.com/ericchiang/k8s/apis/extensions/v1beta1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
1169
vendor/github.com/ericchiang/k8s/apis/imagepolicy/v1alpha1/generated.pb.go
generated
vendored
1169
vendor/github.com/ericchiang/k8s/apis/imagepolicy/v1alpha1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
8562
vendor/github.com/ericchiang/k8s/apis/meta/v1/generated.pb.go
generated
vendored
8562
vendor/github.com/ericchiang/k8s/apis/meta/v1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
32
vendor/github.com/ericchiang/k8s/apis/meta/v1/time.go
generated
vendored
32
vendor/github.com/ericchiang/k8s/apis/meta/v1/time.go
generated
vendored
|
@ -1,32 +0,0 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
// JSON marshaling logic for the Time type. Need to make
|
||||
// third party resources JSON work.
|
||||
|
||||
func (t Time) MarshalJSON() ([]byte, error) {
|
||||
var seconds, nanos int64
|
||||
if t.Seconds != nil {
|
||||
seconds = *t.Seconds
|
||||
}
|
||||
if t.Nanos != nil {
|
||||
nanos = int64(*t.Nanos)
|
||||
}
|
||||
return json.Marshal(time.Unix(seconds, nanos))
|
||||
}
|
||||
|
||||
func (t *Time) UnmarshalJSON(p []byte) error {
|
||||
var t1 time.Time
|
||||
if err := json.Unmarshal(p, &t1); err != nil {
|
||||
return err
|
||||
}
|
||||
seconds := t1.Unix()
|
||||
nanos := int32(t1.UnixNano())
|
||||
t.Seconds = &seconds
|
||||
t.Nanos = &nanos
|
||||
return nil
|
||||
}
|
1352
vendor/github.com/ericchiang/k8s/apis/policy/v1alpha1/generated.pb.go
generated
vendored
1352
vendor/github.com/ericchiang/k8s/apis/policy/v1alpha1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
1573
vendor/github.com/ericchiang/k8s/apis/policy/v1beta1/generated.pb.go
generated
vendored
1573
vendor/github.com/ericchiang/k8s/apis/policy/v1beta1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
3249
vendor/github.com/ericchiang/k8s/apis/rbac/v1alpha1/generated.pb.go
generated
vendored
3249
vendor/github.com/ericchiang/k8s/apis/rbac/v1alpha1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
3247
vendor/github.com/ericchiang/k8s/apis/rbac/v1beta1/generated.pb.go
generated
vendored
3247
vendor/github.com/ericchiang/k8s/apis/rbac/v1beta1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
1016
vendor/github.com/ericchiang/k8s/apis/settings/v1alpha1/generated.pb.go
generated
vendored
1016
vendor/github.com/ericchiang/k8s/apis/settings/v1alpha1/generated.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
777
vendor/github.com/ericchiang/k8s/apis/storage/v1/generated.pb.go
generated
vendored
777
vendor/github.com/ericchiang/k8s/apis/storage/v1/generated.pb.go
generated
vendored
|
@ -1,777 +0,0 @@
|
|||
// Code generated by protoc-gen-gogo.
|
||||
// source: k8s.io/kubernetes/pkg/apis/storage/v1/generated.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package v1 is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
k8s.io/kubernetes/pkg/apis/storage/v1/generated.proto
|
||||
|
||||
It has these top-level messages:
|
||||
StorageClass
|
||||
StorageClassList
|
||||
*/
|
||||
package v1
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import k8s_io_kubernetes_pkg_apis_meta_v1 "github.com/ericchiang/k8s/apis/meta/v1"
|
||||
import _ "github.com/ericchiang/k8s/runtime"
|
||||
import _ "github.com/ericchiang/k8s/runtime/schema"
|
||||
import _ "github.com/ericchiang/k8s/util/intstr"
|
||||
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// StorageClass describes the parameters for a class of storage for
|
||||
// which PersistentVolumes can be dynamically provisioned.
|
||||
//
|
||||
// StorageClasses are non-namespaced; the name of the storage class
|
||||
// according to etcd is in ObjectMeta.Name.
|
||||
type StorageClass struct {
|
||||
// Standard object's metadata.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
// +optional
|
||||
Metadata *k8s_io_kubernetes_pkg_apis_meta_v1.ObjectMeta `protobuf:"bytes,1,opt,name=metadata" json:"metadata,omitempty"`
|
||||
// Provisioner indicates the type of the provisioner.
|
||||
Provisioner *string `protobuf:"bytes,2,opt,name=provisioner" json:"provisioner,omitempty"`
|
||||
// Parameters holds the parameters for the provisioner that should
|
||||
// create volumes of this storage class.
|
||||
// +optional
|
||||
Parameters map[string]string `protobuf:"bytes,3,rep,name=parameters" json:"parameters,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *StorageClass) Reset() { *m = StorageClass{} }
|
||||
func (m *StorageClass) String() string { return proto.CompactTextString(m) }
|
||||
func (*StorageClass) ProtoMessage() {}
|
||||
func (*StorageClass) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} }
|
||||
|
||||
func (m *StorageClass) GetMetadata() *k8s_io_kubernetes_pkg_apis_meta_v1.ObjectMeta {
|
||||
if m != nil {
|
||||
return m.Metadata
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *StorageClass) GetProvisioner() string {
|
||||
if m != nil && m.Provisioner != nil {
|
||||
return *m.Provisioner
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *StorageClass) GetParameters() map[string]string {
|
||||
if m != nil {
|
||||
return m.Parameters
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StorageClassList is a collection of storage classes.
|
||||
type StorageClassList struct {
|
||||
// Standard list metadata
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
// +optional
|
||||
Metadata *k8s_io_kubernetes_pkg_apis_meta_v1.ListMeta `protobuf:"bytes,1,opt,name=metadata" json:"metadata,omitempty"`
|
||||
// Items is the list of StorageClasses
|
||||
Items []*StorageClass `protobuf:"bytes,2,rep,name=items" json:"items,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *StorageClassList) Reset() { *m = StorageClassList{} }
|
||||
func (m *StorageClassList) String() string { return proto.CompactTextString(m) }
|
||||
func (*StorageClassList) ProtoMessage() {}
|
||||
func (*StorageClassList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{1} }
|
||||
|
||||
func (m *StorageClassList) GetMetadata() *k8s_io_kubernetes_pkg_apis_meta_v1.ListMeta {
|
||||
if m != nil {
|
||||
return m.Metadata
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *StorageClassList) GetItems() []*StorageClass {
|
||||
if m != nil {
|
||||
return m.Items
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*StorageClass)(nil), "github.com/ericchiang.k8s.apis.storage.v1.StorageClass")
|
||||
proto.RegisterType((*StorageClassList)(nil), "github.com/ericchiang.k8s.apis.storage.v1.StorageClassList")
|
||||
}
|
||||
func (m *StorageClass) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *StorageClass) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Metadata != nil {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(m.Metadata.Size()))
|
||||
n1, err := m.Metadata.MarshalTo(dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n1
|
||||
}
|
||||
if m.Provisioner != nil {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(*m.Provisioner)))
|
||||
i += copy(dAtA[i:], *m.Provisioner)
|
||||
}
|
||||
if len(m.Parameters) > 0 {
|
||||
for k, _ := range m.Parameters {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
v := m.Parameters[k]
|
||||
mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v)))
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(mapSize))
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(k)))
|
||||
i += copy(dAtA[i:], k)
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(v)))
|
||||
i += copy(dAtA[i:], v)
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *StorageClassList) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *StorageClassList) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Metadata != nil {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(m.Metadata.Size()))
|
||||
n2, err := m.Metadata.MarshalTo(dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n2
|
||||
}
|
||||
if len(m.Items) > 0 {
|
||||
for _, msg := range m.Items {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(msg.Size()))
|
||||
n, err := msg.MarshalTo(dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
dAtA[offset+2] = uint8(v >> 16)
|
||||
dAtA[offset+3] = uint8(v >> 24)
|
||||
dAtA[offset+4] = uint8(v >> 32)
|
||||
dAtA[offset+5] = uint8(v >> 40)
|
||||
dAtA[offset+6] = uint8(v >> 48)
|
||||
dAtA[offset+7] = uint8(v >> 56)
|
||||
return offset + 8
|
||||
}
|
||||
func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
dAtA[offset+2] = uint8(v >> 16)
|
||||
dAtA[offset+3] = uint8(v >> 24)
|
||||
return offset + 4
|
||||
}
|
||||
func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *StorageClass) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.Metadata != nil {
|
||||
l = m.Metadata.Size()
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if m.Provisioner != nil {
|
||||
l = len(*m.Provisioner)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if len(m.Parameters) > 0 {
|
||||
for k, v := range m.Parameters {
|
||||
_ = k
|
||||
_ = v
|
||||
mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v)))
|
||||
n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize))
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *StorageClassList) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.Metadata != nil {
|
||||
l = m.Metadata.Size()
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if len(m.Items) > 0 {
|
||||
for _, e := range m.Items {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovGenerated(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozGenerated(x uint64) (n int) {
|
||||
return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *StorageClass) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: StorageClass: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: StorageClass: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Metadata == nil {
|
||||
m.Metadata = &k8s_io_kubernetes_pkg_apis_meta_v1.ObjectMeta{}
|
||||
}
|
||||
if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Provisioner", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Provisioner = &s
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Parameters", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
var keykey uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
keykey |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
var stringLenmapkey uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLenmapkey |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLenmapkey := int(stringLenmapkey)
|
||||
if intStringLenmapkey < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postStringIndexmapkey := iNdEx + intStringLenmapkey
|
||||
if postStringIndexmapkey > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
mapkey := string(dAtA[iNdEx:postStringIndexmapkey])
|
||||
iNdEx = postStringIndexmapkey
|
||||
if m.Parameters == nil {
|
||||
m.Parameters = make(map[string]string)
|
||||
}
|
||||
if iNdEx < postIndex {
|
||||
var valuekey uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
valuekey |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
var stringLenmapvalue uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLenmapvalue |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLenmapvalue := int(stringLenmapvalue)
|
||||
if intStringLenmapvalue < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postStringIndexmapvalue := iNdEx + intStringLenmapvalue
|
||||
if postStringIndexmapvalue > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue])
|
||||
iNdEx = postStringIndexmapvalue
|
||||
m.Parameters[mapkey] = mapvalue
|
||||
} else {
|
||||
var mapvalue string
|
||||
m.Parameters[mapkey] = mapvalue
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *StorageClassList) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: StorageClassList: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: StorageClassList: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Metadata == nil {
|
||||
m.Metadata = &k8s_io_kubernetes_pkg_apis_meta_v1.ListMeta{}
|
||||
}
|
||||
if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Items = append(m.Items, &StorageClass{})
|
||||
if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipGenerated(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthGenerated
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipGenerated(dAtA[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/ericchiang/k8s/apis/storage/v1/generated.proto", fileDescriptorGenerated)
|
||||
}
|
||||
|
||||
var fileDescriptorGenerated = []byte{
|
||||
// 361 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x91, 0xcf, 0x4a, 0xeb, 0x40,
|
||||
0x14, 0xc6, 0xef, 0xa4, 0x14, 0x6e, 0xa7, 0x17, 0x6e, 0x09, 0x5d, 0x84, 0x2e, 0x42, 0x28, 0x5c,
|
||||
0xe8, 0xe2, 0x7a, 0x42, 0xaa, 0x42, 0x11, 0xdc, 0x58, 0x04, 0x15, 0x45, 0x89, 0x3b, 0x77, 0xd3,
|
||||
0xf6, 0x10, 0xc7, 0x34, 0x7f, 0x98, 0x39, 0x09, 0xf4, 0x4d, 0x5c, 0xba, 0xf3, 0x55, 0x5c, 0xfa,
|
||||
0x08, 0x52, 0x5f, 0x44, 0xd2, 0x94, 0x1a, 0xda, 0x52, 0x8a, 0xbb, 0xf9, 0xf3, 0xfd, 0xbe, 0x39,
|
||||
0xdf, 0x37, 0xfc, 0x38, 0x1c, 0x68, 0x90, 0x89, 0x1b, 0x66, 0x23, 0x54, 0x31, 0x12, 0x6a, 0x37,
|
||||
0x0d, 0x03, 0x57, 0xa4, 0x52, 0xbb, 0x9a, 0x12, 0x25, 0x02, 0x74, 0x73, 0xcf, 0x0d, 0x30, 0x46,
|
||||
0x25, 0x08, 0x27, 0x90, 0xaa, 0x84, 0x12, 0xf3, 0x5f, 0x89, 0xc1, 0x37, 0x06, 0x69, 0x18, 0x40,
|
||||
0x81, 0xc1, 0x12, 0x83, 0xdc, 0xeb, 0xf4, 0x77, 0xb8, 0x47, 0x48, 0x62, 0x8b, 0x75, 0xe7, 0x60,
|
||||
0x3b, 0xa3, 0xb2, 0x98, 0x64, 0x84, 0x1b, 0xf2, 0xa3, 0xdd, 0x72, 0x3d, 0x7e, 0xc4, 0x48, 0x6c,
|
||||
0x50, 0xde, 0x76, 0x2a, 0x23, 0x39, 0x75, 0x65, 0x4c, 0x9a, 0xd4, 0x3a, 0xd2, 0x7d, 0x31, 0xf8,
|
||||
0x9f, 0xfb, 0x32, 0xda, 0x70, 0x2a, 0xb4, 0x36, 0xaf, 0xf8, 0xef, 0x22, 0xc3, 0x44, 0x90, 0xb0,
|
||||
0x98, 0xc3, 0x7a, 0xcd, 0x3e, 0xc0, 0x8e, 0x5a, 0x0a, 0x2d, 0xe4, 0x1e, 0xdc, 0x8e, 0x9e, 0x70,
|
||||
0x4c, 0x37, 0x48, 0xc2, 0x5f, 0xf1, 0xa6, 0xc3, 0x9b, 0xa9, 0x4a, 0x72, 0xa9, 0x65, 0x12, 0xa3,
|
||||
0xb2, 0x0c, 0x87, 0xf5, 0x1a, 0x7e, 0xf5, 0xc8, 0x1c, 0x73, 0x9e, 0x0a, 0x25, 0x22, 0x24, 0x54,
|
||||
0xda, 0xaa, 0x39, 0xb5, 0x5e, 0xb3, 0x3f, 0x84, 0xbd, 0xbe, 0x01, 0xaa, 0x63, 0xc3, 0xdd, 0xca,
|
||||
0xe5, 0x3c, 0x26, 0x35, 0xf3, 0x2b, 0xb6, 0x9d, 0x53, 0xfe, 0x77, 0xed, 0xda, 0x6c, 0xf1, 0x5a,
|
||||
0x88, 0xb3, 0x45, 0xc0, 0x86, 0x5f, 0x2c, 0xcd, 0x36, 0xaf, 0xe7, 0x62, 0x9a, 0xe1, 0x72, 0xca,
|
||||
0x72, 0x73, 0x62, 0x0c, 0x58, 0xf7, 0x95, 0xf1, 0x56, 0xf5, 0xad, 0x6b, 0xa9, 0xc9, 0xbc, 0xd8,
|
||||
0xa8, 0xe9, 0xff, 0x3e, 0x35, 0x15, 0xec, 0x5a, 0x49, 0x97, 0xbc, 0x2e, 0x09, 0x23, 0x6d, 0x19,
|
||||
0x8b, 0xf4, 0x87, 0x3f, 0x48, 0xef, 0x97, 0x0e, 0x67, 0xed, 0xb7, 0xb9, 0xcd, 0xde, 0xe7, 0x36,
|
||||
0xfb, 0x98, 0xdb, 0xec, 0xf9, 0xd3, 0xfe, 0xf5, 0x60, 0xe4, 0xde, 0x57, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xc7, 0xf1, 0x3e, 0x97, 0x0d, 0x03, 0x00, 0x00,
|
||||
}
|
779
vendor/github.com/ericchiang/k8s/apis/storage/v1beta1/generated.pb.go
generated
vendored
779
vendor/github.com/ericchiang/k8s/apis/storage/v1beta1/generated.pb.go
generated
vendored
|
@ -1,779 +0,0 @@
|
|||
// Code generated by protoc-gen-gogo.
|
||||
// source: k8s.io/kubernetes/pkg/apis/storage/v1beta1/generated.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package v1beta1 is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
k8s.io/kubernetes/pkg/apis/storage/v1beta1/generated.proto
|
||||
|
||||
It has these top-level messages:
|
||||
StorageClass
|
||||
StorageClassList
|
||||
*/
|
||||
package v1beta1
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import k8s_io_kubernetes_pkg_apis_meta_v1 "github.com/ericchiang/k8s/apis/meta/v1"
|
||||
import _ "github.com/ericchiang/k8s/runtime"
|
||||
import _ "github.com/ericchiang/k8s/runtime/schema"
|
||||
import _ "github.com/ericchiang/k8s/util/intstr"
|
||||
import _ "github.com/ericchiang/k8s/api/v1"
|
||||
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// StorageClass describes the parameters for a class of storage for
|
||||
// which PersistentVolumes can be dynamically provisioned.
|
||||
//
|
||||
// StorageClasses are non-namespaced; the name of the storage class
|
||||
// according to etcd is in ObjectMeta.Name.
|
||||
type StorageClass struct {
|
||||
// Standard object's metadata.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
// +optional
|
||||
Metadata *k8s_io_kubernetes_pkg_apis_meta_v1.ObjectMeta `protobuf:"bytes,1,opt,name=metadata" json:"metadata,omitempty"`
|
||||
// Provisioner indicates the type of the provisioner.
|
||||
Provisioner *string `protobuf:"bytes,2,opt,name=provisioner" json:"provisioner,omitempty"`
|
||||
// Parameters holds the parameters for the provisioner that should
|
||||
// create volumes of this storage class.
|
||||
// +optional
|
||||
Parameters map[string]string `protobuf:"bytes,3,rep,name=parameters" json:"parameters,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *StorageClass) Reset() { *m = StorageClass{} }
|
||||
func (m *StorageClass) String() string { return proto.CompactTextString(m) }
|
||||
func (*StorageClass) ProtoMessage() {}
|
||||
func (*StorageClass) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} }
|
||||
|
||||
func (m *StorageClass) GetMetadata() *k8s_io_kubernetes_pkg_apis_meta_v1.ObjectMeta {
|
||||
if m != nil {
|
||||
return m.Metadata
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *StorageClass) GetProvisioner() string {
|
||||
if m != nil && m.Provisioner != nil {
|
||||
return *m.Provisioner
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *StorageClass) GetParameters() map[string]string {
|
||||
if m != nil {
|
||||
return m.Parameters
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StorageClassList is a collection of storage classes.
|
||||
type StorageClassList struct {
|
||||
// Standard list metadata
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
// +optional
|
||||
Metadata *k8s_io_kubernetes_pkg_apis_meta_v1.ListMeta `protobuf:"bytes,1,opt,name=metadata" json:"metadata,omitempty"`
|
||||
// Items is the list of StorageClasses
|
||||
Items []*StorageClass `protobuf:"bytes,2,rep,name=items" json:"items,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *StorageClassList) Reset() { *m = StorageClassList{} }
|
||||
func (m *StorageClassList) String() string { return proto.CompactTextString(m) }
|
||||
func (*StorageClassList) ProtoMessage() {}
|
||||
func (*StorageClassList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{1} }
|
||||
|
||||
func (m *StorageClassList) GetMetadata() *k8s_io_kubernetes_pkg_apis_meta_v1.ListMeta {
|
||||
if m != nil {
|
||||
return m.Metadata
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *StorageClassList) GetItems() []*StorageClass {
|
||||
if m != nil {
|
||||
return m.Items
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*StorageClass)(nil), "github.com/ericchiang.k8s.apis.storage.v1beta1.StorageClass")
|
||||
proto.RegisterType((*StorageClassList)(nil), "github.com/ericchiang.k8s.apis.storage.v1beta1.StorageClassList")
|
||||
}
|
||||
func (m *StorageClass) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *StorageClass) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Metadata != nil {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(m.Metadata.Size()))
|
||||
n1, err := m.Metadata.MarshalTo(dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n1
|
||||
}
|
||||
if m.Provisioner != nil {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(*m.Provisioner)))
|
||||
i += copy(dAtA[i:], *m.Provisioner)
|
||||
}
|
||||
if len(m.Parameters) > 0 {
|
||||
for k, _ := range m.Parameters {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
v := m.Parameters[k]
|
||||
mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v)))
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(mapSize))
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(k)))
|
||||
i += copy(dAtA[i:], k)
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(v)))
|
||||
i += copy(dAtA[i:], v)
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *StorageClassList) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *StorageClassList) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Metadata != nil {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(m.Metadata.Size()))
|
||||
n2, err := m.Metadata.MarshalTo(dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n2
|
||||
}
|
||||
if len(m.Items) > 0 {
|
||||
for _, msg := range m.Items {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(msg.Size()))
|
||||
n, err := msg.MarshalTo(dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
dAtA[offset+2] = uint8(v >> 16)
|
||||
dAtA[offset+3] = uint8(v >> 24)
|
||||
dAtA[offset+4] = uint8(v >> 32)
|
||||
dAtA[offset+5] = uint8(v >> 40)
|
||||
dAtA[offset+6] = uint8(v >> 48)
|
||||
dAtA[offset+7] = uint8(v >> 56)
|
||||
return offset + 8
|
||||
}
|
||||
func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
dAtA[offset+2] = uint8(v >> 16)
|
||||
dAtA[offset+3] = uint8(v >> 24)
|
||||
return offset + 4
|
||||
}
|
||||
func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *StorageClass) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.Metadata != nil {
|
||||
l = m.Metadata.Size()
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if m.Provisioner != nil {
|
||||
l = len(*m.Provisioner)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if len(m.Parameters) > 0 {
|
||||
for k, v := range m.Parameters {
|
||||
_ = k
|
||||
_ = v
|
||||
mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + len(v) + sovGenerated(uint64(len(v)))
|
||||
n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize))
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *StorageClassList) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.Metadata != nil {
|
||||
l = m.Metadata.Size()
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if len(m.Items) > 0 {
|
||||
for _, e := range m.Items {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovGenerated(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozGenerated(x uint64) (n int) {
|
||||
return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *StorageClass) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: StorageClass: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: StorageClass: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Metadata == nil {
|
||||
m.Metadata = &k8s_io_kubernetes_pkg_apis_meta_v1.ObjectMeta{}
|
||||
}
|
||||
if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Provisioner", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Provisioner = &s
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Parameters", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
var keykey uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
keykey |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
var stringLenmapkey uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLenmapkey |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLenmapkey := int(stringLenmapkey)
|
||||
if intStringLenmapkey < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postStringIndexmapkey := iNdEx + intStringLenmapkey
|
||||
if postStringIndexmapkey > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
mapkey := string(dAtA[iNdEx:postStringIndexmapkey])
|
||||
iNdEx = postStringIndexmapkey
|
||||
if m.Parameters == nil {
|
||||
m.Parameters = make(map[string]string)
|
||||
}
|
||||
if iNdEx < postIndex {
|
||||
var valuekey uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
valuekey |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
var stringLenmapvalue uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLenmapvalue |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLenmapvalue := int(stringLenmapvalue)
|
||||
if intStringLenmapvalue < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postStringIndexmapvalue := iNdEx + intStringLenmapvalue
|
||||
if postStringIndexmapvalue > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue])
|
||||
iNdEx = postStringIndexmapvalue
|
||||
m.Parameters[mapkey] = mapvalue
|
||||
} else {
|
||||
var mapvalue string
|
||||
m.Parameters[mapkey] = mapvalue
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *StorageClassList) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: StorageClassList: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: StorageClassList: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Metadata == nil {
|
||||
m.Metadata = &k8s_io_kubernetes_pkg_apis_meta_v1.ListMeta{}
|
||||
}
|
||||
if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Items = append(m.Items, &StorageClass{})
|
||||
if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipGenerated(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthGenerated
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipGenerated(dAtA[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/ericchiang/k8s/apis/storage/v1beta1/generated.proto", fileDescriptorGenerated)
|
||||
}
|
||||
|
||||
var fileDescriptorGenerated = []byte{
|
||||
// 373 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x91, 0xcd, 0x6a, 0xdb, 0x40,
|
||||
0x14, 0x85, 0x3b, 0x32, 0xa6, 0xf5, 0xb8, 0x50, 0x23, 0xba, 0x50, 0xbd, 0x10, 0xc2, 0x2b, 0x53,
|
||||
0xdc, 0x19, 0x64, 0xba, 0x30, 0x86, 0x6e, 0x1a, 0x02, 0x26, 0xe4, 0x0f, 0x65, 0x97, 0xdd, 0xd8,
|
||||
0xbe, 0xc8, 0x13, 0x59, 0x3f, 0xcc, 0x5c, 0x09, 0xfc, 0x26, 0x79, 0x81, 0xec, 0xf2, 0x20, 0x59,
|
||||
0xe6, 0x11, 0x82, 0xf3, 0x22, 0x41, 0x96, 0x70, 0x84, 0xe5, 0x18, 0x93, 0x9d, 0x34, 0x73, 0xbe,
|
||||
0x73, 0xef, 0x39, 0x43, 0xc7, 0xc1, 0x48, 0x33, 0x19, 0xf3, 0x20, 0x9d, 0x82, 0x8a, 0x00, 0x41,
|
||||
0xf3, 0x24, 0xf0, 0xb9, 0x48, 0xa4, 0xe6, 0x1a, 0x63, 0x25, 0x7c, 0xe0, 0x99, 0x3b, 0x05, 0x14,
|
||||
0x2e, 0xf7, 0x21, 0x02, 0x25, 0x10, 0xe6, 0x2c, 0x51, 0x31, 0xc6, 0xe6, 0xef, 0x82, 0x65, 0xef,
|
||||
0x2c, 0x4b, 0x02, 0x9f, 0xe5, 0x2c, 0x2b, 0x59, 0x56, 0xb2, 0xdd, 0xe1, 0x81, 0x39, 0x21, 0xa0,
|
||||
0xe0, 0x59, 0xcd, 0xbf, 0xfb, 0x67, 0x3f, 0xa3, 0xd2, 0x08, 0x65, 0x08, 0x35, 0xf9, 0xdf, 0xc3,
|
||||
0x72, 0x3d, 0x5b, 0x40, 0x28, 0x6a, 0x94, 0xbb, 0x9f, 0x4a, 0x51, 0x2e, 0xb9, 0x8c, 0x50, 0xa3,
|
||||
0xaa, 0x21, 0x83, 0x0f, 0xb3, 0xec, 0x49, 0xd1, 0x7b, 0x30, 0xe8, 0xf7, 0x9b, 0xa2, 0x8d, 0x93,
|
||||
0xa5, 0xd0, 0xda, 0x3c, 0xa3, 0xdf, 0xf2, 0xc4, 0x73, 0x81, 0xc2, 0x22, 0x0e, 0xe9, 0xb7, 0x87,
|
||||
0x8c, 0x1d, 0x68, 0x32, 0xd7, 0xb2, 0xcc, 0x65, 0x57, 0xd3, 0x3b, 0x98, 0xe1, 0x05, 0xa0, 0xf0,
|
||||
0xb6, 0xbc, 0xe9, 0xd0, 0x76, 0xa2, 0xe2, 0x4c, 0x6a, 0x19, 0x47, 0xa0, 0x2c, 0xc3, 0x21, 0xfd,
|
||||
0x96, 0x57, 0x3d, 0x32, 0x17, 0x94, 0x26, 0x42, 0x89, 0x10, 0x10, 0x94, 0xb6, 0x1a, 0x4e, 0xa3,
|
||||
0xdf, 0x1e, 0x4e, 0xd8, 0xf1, 0x2f, 0xc7, 0xaa, 0xbb, 0xb3, 0xeb, 0xad, 0xd5, 0x69, 0x84, 0x6a,
|
||||
0xe5, 0x55, 0xbc, 0xbb, 0xff, 0xe8, 0x8f, 0x9d, 0x6b, 0xb3, 0x43, 0x1b, 0x01, 0xac, 0x36, 0x29,
|
||||
0x5b, 0x5e, 0xfe, 0x69, 0xfe, 0xa4, 0xcd, 0x4c, 0x2c, 0x53, 0x28, 0x57, 0x2d, 0x7e, 0xc6, 0xc6,
|
||||
0x88, 0xf4, 0x1e, 0x09, 0xed, 0x54, 0x67, 0x9d, 0x4b, 0x8d, 0xe6, 0xa4, 0xd6, 0xd5, 0xe0, 0x98,
|
||||
0xae, 0x72, 0x76, 0xa7, 0xa9, 0x4b, 0xda, 0x94, 0x08, 0xa1, 0xb6, 0x8c, 0x4d, 0x05, 0xa3, 0xcf,
|
||||
0x56, 0xe0, 0x15, 0x36, 0xff, 0x7f, 0x3d, 0xad, 0x6d, 0xf2, 0xbc, 0xb6, 0xc9, 0xcb, 0xda, 0x26,
|
||||
0xf7, 0xaf, 0xf6, 0x97, 0xdb, 0xaf, 0xa5, 0xfc, 0x2d, 0x00, 0x00, 0xff, 0xff, 0x9d, 0x5c, 0x08,
|
||||
0xd1, 0x54, 0x03, 0x00, 0x00,
|
||||
}
|
598
vendor/github.com/ericchiang/k8s/client.go
generated
vendored
598
vendor/github.com/ericchiang/k8s/client.go
generated
vendored
|
@ -1,598 +0,0 @@
|
|||
/*
|
||||
Package k8s implements a Kubernetes client.
|
||||
|
||||
c, err := k8s.NewInClusterClient()
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
extensions := c.ExtensionsV1Beta1()
|
||||
|
||||
ingresses, err := extensions.ListIngresses(ctx, c.Namespace)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
|
||||
*/
|
||||
package k8s
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/http2"
|
||||
|
||||
"github.com/ericchiang/k8s/api/unversioned"
|
||||
"github.com/ericchiang/k8s/runtime"
|
||||
"github.com/ericchiang/k8s/watch/versioned"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
// AllNamespaces is given to list and watch operations to signify that the code should
|
||||
// list or watch resources in all namespaces.
|
||||
AllNamespaces = allNamespaces
|
||||
// Actual definition is private in case we want to change it later.
|
||||
allNamespaces = ""
|
||||
|
||||
namespaceDefault = "default"
|
||||
)
|
||||
|
||||
// String returns a pointer to a string. Useful for creating API objects
|
||||
// that take pointers instead of literals.
|
||||
//
|
||||
// cm := &v1.ConfigMap{
|
||||
// Metadata: &v1.ObjectMeta{
|
||||
// Name: k8s.String("myconfigmap"),
|
||||
// Namespace: k8s.String("default"),
|
||||
// },
|
||||
// Data: map[string]string{
|
||||
// "foo": "bar",
|
||||
// },
|
||||
// }
|
||||
//
|
||||
func String(s string) *string { return &s }
|
||||
|
||||
// Int is a convinence for converting an int literal to a pointer to an int.
|
||||
func Int(i int) *int { return &i }
|
||||
|
||||
// Bool is a convinence for converting a bool literal to a pointer to a bool.
|
||||
func Bool(b bool) *bool { return &b }
|
||||
|
||||
const (
|
||||
// Types for watch events.
|
||||
EventAdded = "ADDED"
|
||||
EventDeleted = "DELETED"
|
||||
EventModified = "MODIFIED"
|
||||
EventError = "ERROR"
|
||||
)
|
||||
|
||||
// Client is a Kuberntes client.
|
||||
type Client struct {
|
||||
// The URL of the API server.
|
||||
Endpoint string
|
||||
|
||||
// Default namespaces for objects that don't supply a namespace in
|
||||
// their object metadata.
|
||||
Namespace string
|
||||
|
||||
// SetHeaders provides a hook for modifying the HTTP headers of all requests.
|
||||
//
|
||||
// client, err := k8s.NewClient(config)
|
||||
// if err != nil {
|
||||
// // handle error
|
||||
// }
|
||||
// client.SetHeaders = func(h http.Header) error {
|
||||
// h.Set("Authorization", "Bearer "+mytoken)
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
SetHeaders func(h http.Header) error
|
||||
|
||||
Client *http.Client
|
||||
}
|
||||
|
||||
func (c *Client) newRequest(ctx context.Context, verb, url string, body io.Reader) (*http.Request, error) {
|
||||
req, err := http.NewRequest(verb, url, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if c.SetHeaders != nil {
|
||||
if err := c.SetHeaders(req.Header); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return req.WithContext(ctx), nil
|
||||
}
|
||||
|
||||
// Option represents optional call parameters, such as label selectors.
|
||||
type Option interface {
|
||||
queryParam() (key, val string)
|
||||
}
|
||||
|
||||
type resourceVersionOption string
|
||||
|
||||
func (r resourceVersionOption) queryParam() (string, string) {
|
||||
return "resourceVersion", string(r)
|
||||
}
|
||||
|
||||
// ResourceVersion causes watch operations to only show changes since
|
||||
// a particular version of a resource.
|
||||
func ResourceVersion(resourceVersion string) Option {
|
||||
return resourceVersionOption(resourceVersion)
|
||||
}
|
||||
|
||||
type timeoutSeconds string
|
||||
|
||||
func (t timeoutSeconds) queryParam() (string, string) {
|
||||
return "timeoutSeconds", string(t)
|
||||
}
|
||||
|
||||
// Timeout declares the timeout for list and watch operations. Timeout
|
||||
// is only accurate to the second.
|
||||
func Timeout(d time.Duration) Option {
|
||||
return timeoutSeconds(strconv.FormatInt(int64(d/time.Second), 10))
|
||||
}
|
||||
|
||||
// NewClient initializes a client from a client config.
|
||||
func NewClient(config *Config) (*Client, error) {
|
||||
if len(config.Contexts) == 0 {
|
||||
if config.CurrentContext != "" {
|
||||
return nil, fmt.Errorf("no contexts with name %q", config.CurrentContext)
|
||||
}
|
||||
|
||||
if n := len(config.Clusters); n == 0 {
|
||||
return nil, errors.New("no clusters provided")
|
||||
} else if n > 1 {
|
||||
return nil, errors.New("multiple clusters but no current context")
|
||||
}
|
||||
if n := len(config.AuthInfos); n == 0 {
|
||||
return nil, errors.New("no users provided")
|
||||
} else if n > 1 {
|
||||
return nil, errors.New("multiple users but no current context")
|
||||
}
|
||||
|
||||
return newClient(config.Clusters[0].Cluster, config.AuthInfos[0].AuthInfo, namespaceDefault)
|
||||
}
|
||||
|
||||
var ctx Context
|
||||
if config.CurrentContext == "" {
|
||||
if n := len(config.Contexts); n == 0 {
|
||||
return nil, errors.New("no contexts provided")
|
||||
} else if n > 1 {
|
||||
return nil, errors.New("multiple contexts but no current context")
|
||||
}
|
||||
ctx = config.Contexts[0].Context
|
||||
} else {
|
||||
for _, c := range config.Contexts {
|
||||
if c.Name == config.CurrentContext {
|
||||
ctx = c.Context
|
||||
goto configFound
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("no config named %q", config.CurrentContext)
|
||||
configFound:
|
||||
}
|
||||
|
||||
if ctx.Cluster == "" {
|
||||
return nil, fmt.Errorf("context doesn't have a cluster")
|
||||
}
|
||||
if ctx.AuthInfo == "" {
|
||||
return nil, fmt.Errorf("context doesn't have a user")
|
||||
}
|
||||
var (
|
||||
user AuthInfo
|
||||
cluster Cluster
|
||||
)
|
||||
|
||||
for _, u := range config.AuthInfos {
|
||||
if u.Name == ctx.AuthInfo {
|
||||
user = u.AuthInfo
|
||||
goto userFound
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("no user named %q", ctx.AuthInfo)
|
||||
userFound:
|
||||
|
||||
for _, c := range config.Clusters {
|
||||
if c.Name == ctx.Cluster {
|
||||
cluster = c.Cluster
|
||||
goto clusterFound
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("no cluster named %q", ctx.Cluster)
|
||||
clusterFound:
|
||||
|
||||
namespace := ctx.Namespace
|
||||
if namespace == "" {
|
||||
namespace = namespaceDefault
|
||||
}
|
||||
|
||||
return newClient(cluster, user, namespace)
|
||||
}
|
||||
|
||||
// NewInClusterClient returns a client that uses the service account bearer token mounted
|
||||
// into Kubernetes pods.
|
||||
func NewInClusterClient() (*Client, error) {
|
||||
host, port := os.Getenv("KUBERNETES_SERVICE_HOST"), os.Getenv("KUBERNETES_SERVICE_PORT")
|
||||
if len(host) == 0 || len(port) == 0 {
|
||||
return nil, errors.New("unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined")
|
||||
}
|
||||
namespace, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cluster := Cluster{
|
||||
Server: "https://" + host + ":" + port,
|
||||
CertificateAuthority: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt",
|
||||
}
|
||||
user := AuthInfo{TokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token"}
|
||||
return newClient(cluster, user, string(namespace))
|
||||
}
|
||||
|
||||
func load(filepath string, data []byte) (out []byte, err error) {
|
||||
if filepath != "" {
|
||||
data, err = ioutil.ReadFile(filepath)
|
||||
}
|
||||
return data, err
|
||||
}
|
||||
|
||||
func newClient(cluster Cluster, user AuthInfo, namespace string) (*Client, error) {
|
||||
if cluster.Server == "" {
|
||||
// NOTE: kubectl defaults to localhost:8080, but it's probably better to just
|
||||
// be strict.
|
||||
return nil, fmt.Errorf("no cluster endpoint provided")
|
||||
}
|
||||
|
||||
ca, err := load(cluster.CertificateAuthority, cluster.CertificateAuthorityData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("loading certificate authority: %v", err)
|
||||
}
|
||||
|
||||
clientCert, err := load(user.ClientCertificate, user.ClientCertificateData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load client cert: %v", err)
|
||||
}
|
||||
clientKey, err := load(user.ClientKey, user.ClientKeyData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load client cert: %v", err)
|
||||
}
|
||||
|
||||
// See https://github.com/gtank/cryptopasta
|
||||
tlsConfig := &tls.Config{MinVersion: tls.VersionTLS12}
|
||||
|
||||
if len(ca) != 0 {
|
||||
tlsConfig.RootCAs = x509.NewCertPool()
|
||||
if !tlsConfig.RootCAs.AppendCertsFromPEM(ca) {
|
||||
return nil, errors.New("certificate authority doesn't contain any certificates")
|
||||
}
|
||||
}
|
||||
if len(clientCert) != 0 {
|
||||
cert, err := tls.X509KeyPair(clientCert, clientKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid client cert and key pair: %v", err)
|
||||
}
|
||||
tlsConfig.Certificates = []tls.Certificate{cert}
|
||||
}
|
||||
|
||||
token := user.Token
|
||||
if user.TokenFile != "" {
|
||||
data, err := ioutil.ReadFile(user.TokenFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load token file: %v", err)
|
||||
}
|
||||
token = string(data)
|
||||
}
|
||||
|
||||
transport := &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).DialContext,
|
||||
TLSClientConfig: tlsConfig,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
}
|
||||
if err := http2.ConfigureTransport(transport); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
Endpoint: cluster.Server,
|
||||
Namespace: namespace,
|
||||
Client: &http.Client{
|
||||
Transport: transport,
|
||||
},
|
||||
}
|
||||
|
||||
if token != "" {
|
||||
client.SetHeaders = func(h http.Header) error {
|
||||
h.Set("Authorization", "Bearer "+token)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if user.Username != "" && user.Password != "" {
|
||||
auth := user.Username + ":" + user.Password
|
||||
auth = "Basic " + base64.StdEncoding.EncodeToString([]byte(auth))
|
||||
client.SetHeaders = func(h http.Header) error {
|
||||
h.Set("Authorization", auth)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// APIError is an error from a unexpected status code.
|
||||
type APIError struct {
|
||||
// The status object returned by the Kubernetes API,
|
||||
Status *unversioned.Status
|
||||
|
||||
// Status code returned by the HTTP request.
|
||||
//
|
||||
// NOTE: For some reason the value set in Status.Code
|
||||
// doesn't correspond to the HTTP status code. Possibly
|
||||
// a bug?
|
||||
Code int
|
||||
}
|
||||
|
||||
func (e *APIError) Error() string {
|
||||
if e.Status != nil && e.Status.Message != nil && e.Status.Status != nil {
|
||||
return fmt.Sprintf("kubernetes api: %s %d %s", *e.Status.Status, e.Code, *e.Status.Message)
|
||||
}
|
||||
return fmt.Sprintf("%#v", e)
|
||||
}
|
||||
|
||||
func checkStatusCode(c *codec, statusCode int, body []byte) error {
|
||||
if statusCode/100 == 2 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return newAPIError(c, statusCode, body)
|
||||
}
|
||||
|
||||
func newAPIError(c *codec, statusCode int, body []byte) error {
|
||||
status := new(unversioned.Status)
|
||||
if err := c.unmarshal(body, status); err != nil {
|
||||
return fmt.Errorf("decode error status: %v", err)
|
||||
}
|
||||
return &APIError{status, statusCode}
|
||||
}
|
||||
|
||||
func (c *Client) client() *http.Client {
|
||||
if c.Client == nil {
|
||||
return http.DefaultClient
|
||||
}
|
||||
return c.Client
|
||||
}
|
||||
|
||||
// The following methods hold the logic for interacting with the Kubernetes API. Generated
|
||||
// clients are thin wrappers on top of these methods.
|
||||
//
|
||||
// This client implements specs in the "API Conventions" developer document, which can be
|
||||
// found here:
|
||||
//
|
||||
// https://github.com/kubernetes/kubernetes/blob/master/docs/devel/api-conventions.md
|
||||
|
||||
func (c *Client) urlFor(apiGroup, apiVersion, namespace, resource, name string, options ...Option) string {
|
||||
basePath := "apis/"
|
||||
if apiGroup == "" {
|
||||
basePath = "api/"
|
||||
}
|
||||
|
||||
var p string
|
||||
if namespace != "" {
|
||||
p = path.Join(basePath, apiGroup, apiVersion, "namespaces", namespace, resource, name)
|
||||
} else {
|
||||
p = path.Join(basePath, apiGroup, apiVersion, resource, name)
|
||||
}
|
||||
endpoint := ""
|
||||
if strings.HasSuffix(c.Endpoint, "/") {
|
||||
endpoint = c.Endpoint + p
|
||||
} else {
|
||||
endpoint = c.Endpoint + "/" + p
|
||||
}
|
||||
if len(options) == 0 {
|
||||
return endpoint
|
||||
}
|
||||
|
||||
v := url.Values{}
|
||||
for _, option := range options {
|
||||
key, val := option.queryParam()
|
||||
v.Set(key, val)
|
||||
}
|
||||
return endpoint + "?" + v.Encode()
|
||||
}
|
||||
|
||||
func (c *Client) urlForPath(path string) string {
|
||||
if strings.HasPrefix(path, "/") {
|
||||
path = path[1:]
|
||||
}
|
||||
if strings.HasSuffix(c.Endpoint, "/") {
|
||||
return c.Endpoint + path
|
||||
}
|
||||
return c.Endpoint + "/" + path
|
||||
}
|
||||
|
||||
func (c *Client) create(ctx context.Context, codec *codec, verb, url string, req, resp interface{}) error {
|
||||
body, err := codec.marshal(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := c.newRequest(ctx, verb, url, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Header.Set("Content-Type", codec.contentType)
|
||||
r.Header.Set("Accept", codec.contentType)
|
||||
|
||||
re, err := c.client().Do(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer re.Body.Close()
|
||||
|
||||
respBody, err := ioutil.ReadAll(re.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("read body: %v", err)
|
||||
}
|
||||
|
||||
if err := checkStatusCode(codec, re.StatusCode, respBody); err != nil {
|
||||
return err
|
||||
}
|
||||
return codec.unmarshal(respBody, resp)
|
||||
}
|
||||
|
||||
func (c *Client) delete(ctx context.Context, codec *codec, url string) error {
|
||||
r, err := c.newRequest(ctx, "DELETE", url, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Header.Set("Accept", codec.contentType)
|
||||
|
||||
re, err := c.client().Do(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer re.Body.Close()
|
||||
|
||||
respBody, err := ioutil.ReadAll(re.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("read body: %v", err)
|
||||
}
|
||||
|
||||
if err := checkStatusCode(codec, re.StatusCode, respBody); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// get can be used to either get or list a given resource.
|
||||
func (c *Client) get(ctx context.Context, codec *codec, url string, resp interface{}) error {
|
||||
r, err := c.newRequest(ctx, "GET", url, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Header.Set("Accept", codec.contentType)
|
||||
re, err := c.client().Do(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer re.Body.Close()
|
||||
|
||||
respBody, err := ioutil.ReadAll(re.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("read body: %v", err)
|
||||
}
|
||||
|
||||
if err := checkStatusCode(codec, re.StatusCode, respBody); err != nil {
|
||||
return err
|
||||
}
|
||||
return codec.unmarshal(respBody, resp)
|
||||
}
|
||||
|
||||
var unknownPrefix = []byte{0x6b, 0x38, 0x73, 0x00}
|
||||
|
||||
func parseUnknown(b []byte) (*runtime.Unknown, error) {
|
||||
if !bytes.HasPrefix(b, unknownPrefix) {
|
||||
return nil, errors.New("bytes did not start with expected prefix")
|
||||
}
|
||||
|
||||
var u runtime.Unknown
|
||||
if err := proto.Unmarshal(b[len(unknownPrefix):], &u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &u, nil
|
||||
}
|
||||
|
||||
type event struct {
|
||||
event *versioned.Event
|
||||
unknown *runtime.Unknown
|
||||
}
|
||||
|
||||
type watcher struct {
|
||||
r io.ReadCloser
|
||||
}
|
||||
|
||||
func (w *watcher) Close() error {
|
||||
return w.r.Close()
|
||||
}
|
||||
|
||||
// Decode the next event from a watch stream.
|
||||
//
|
||||
// See: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/protobuf.md#streaming-wire-format
|
||||
func (w *watcher) next() (*versioned.Event, *runtime.Unknown, error) {
|
||||
length := make([]byte, 4)
|
||||
if _, err := io.ReadFull(w.r, length); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
body := make([]byte, int(binary.BigEndian.Uint32(length)))
|
||||
if _, err := io.ReadFull(w.r, body); err != nil {
|
||||
return nil, nil, fmt.Errorf("read frame body: %v", err)
|
||||
}
|
||||
|
||||
var event versioned.Event
|
||||
if err := proto.Unmarshal(body, &event); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if event.Object == nil {
|
||||
return nil, nil, fmt.Errorf("event had no underlying object")
|
||||
}
|
||||
|
||||
unknown, err := parseUnknown(event.Object.Raw)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return &event, unknown, nil
|
||||
}
|
||||
|
||||
func (c *Client) watch(ctx context.Context, url string) (*watcher, error) {
|
||||
if strings.Contains(url, "?") {
|
||||
url = url + "&watch=true"
|
||||
} else {
|
||||
url = url + "?watch=true"
|
||||
}
|
||||
r, err := c.newRequest(ctx, "GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.Header.Set("Accept", "application/vnd.kubernetes.protobuf;type=watch")
|
||||
resp, err := c.client().Do(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode/100 != 2 {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, newAPIError(pbCodec, resp.StatusCode, body)
|
||||
}
|
||||
|
||||
w := &watcher{resp.Body}
|
||||
return w, nil
|
||||
}
|
405
vendor/github.com/ericchiang/k8s/client_test.go
generated
vendored
405
vendor/github.com/ericchiang/k8s/client_test.go
generated
vendored
|
@ -1,405 +0,0 @@
|
|||
package k8s
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ericchiang/k8s/api/v1"
|
||||
metav1 "github.com/ericchiang/k8s/apis/meta/v1"
|
||||
)
|
||||
|
||||
const skipMsg = `
|
||||
warning: this package's test run using the default context of your "kubectl" command,
|
||||
and will create resources on your cluster (mostly configmaps).
|
||||
|
||||
If you wish to continue set the following environment variable:
|
||||
|
||||
export K8S_CLIENT_TEST=1
|
||||
|
||||
To suppress this message, set:
|
||||
|
||||
export K8S_CLIENT_TEST=0
|
||||
`
|
||||
|
||||
func newTestClient(t *testing.T) *Client {
|
||||
if os.Getenv("K8S_CLIENT_TEST") == "0" {
|
||||
t.Skip("")
|
||||
}
|
||||
if os.Getenv("K8S_CLIENT_TEST") != "1" {
|
||||
t.Skip(skipMsg)
|
||||
}
|
||||
|
||||
cmd := exec.Command("kubectl", "config", "view", "-o", "json")
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("'kubectl config view -o json': %v %s", err, out)
|
||||
}
|
||||
|
||||
config := new(Config)
|
||||
if err := json.Unmarshal(out, config); err != nil {
|
||||
t.Fatalf("parse kubeconfig: %v '%s'", err, out)
|
||||
}
|
||||
client, err := NewClient(config)
|
||||
if err != nil {
|
||||
t.Fatalf("new client: %v", err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
func newName() string {
|
||||
b := make([]byte, 12)
|
||||
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return hex.EncodeToString(b)
|
||||
}
|
||||
|
||||
func TestNewTestClient(t *testing.T) {
|
||||
newTestClient(t)
|
||||
}
|
||||
|
||||
func TestHTTP2(t *testing.T) {
|
||||
client := newTestClient(t)
|
||||
req, err := http.NewRequest("GET", client.urlForPath("/api"), nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
resp, err := client.Client.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if !strings.HasPrefix(resp.Proto, "HTTP/2") {
|
||||
t.Errorf("expected proto=HTTP/2.X, got=", resp.Proto)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListNodes(t *testing.T) {
|
||||
client := newTestClient(t)
|
||||
if _, err := client.CoreV1().ListNodes(context.Background()); err != nil {
|
||||
t.Fatal("failed to list nodes: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigMaps(t *testing.T) {
|
||||
client := newTestClient(t).CoreV1()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
name := newName()
|
||||
labelVal := newName()
|
||||
|
||||
cm := &v1.ConfigMap{
|
||||
Metadata: &metav1.ObjectMeta{
|
||||
Name: String(name),
|
||||
Namespace: String("default"),
|
||||
Labels: map[string]string{
|
||||
"testLabel": labelVal,
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
}
|
||||
got, err := client.CreateConfigMap(ctx, cm)
|
||||
if err != nil {
|
||||
t.Fatalf("create config map: %v", err)
|
||||
}
|
||||
got.Data["zam"] = "spam"
|
||||
_, err = client.UpdateConfigMap(ctx, got)
|
||||
if err != nil {
|
||||
t.Fatalf("update config map: %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
labelVal string
|
||||
expNum int
|
||||
}{
|
||||
{labelVal, 1},
|
||||
{newName(), 0},
|
||||
}
|
||||
for _, test := range tests {
|
||||
l := new(LabelSelector)
|
||||
l.Eq("testLabel", test.labelVal)
|
||||
|
||||
configMaps, err := client.ListConfigMaps(ctx, "default", l.Selector())
|
||||
if err != nil {
|
||||
t.Errorf("failed to list configmaps: %v", err)
|
||||
continue
|
||||
}
|
||||
got := len(configMaps.Items)
|
||||
if got != test.expNum {
|
||||
t.Errorf("expected selector to return %d items got %d", test.expNum, got)
|
||||
}
|
||||
}
|
||||
|
||||
if err := client.DeleteConfigMap(ctx, *cm.Metadata.Name, *cm.Metadata.Namespace); err != nil {
|
||||
t.Fatalf("delete config map: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestWatch(t *testing.T) {
|
||||
client := newTestClient(t).CoreV1()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
w, err := client.WatchConfigMaps(ctx, "default")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer w.Close()
|
||||
|
||||
name := newName()
|
||||
labelVal := newName()
|
||||
|
||||
cm := &v1.ConfigMap{
|
||||
Metadata: &metav1.ObjectMeta{
|
||||
Name: String(name),
|
||||
Namespace: String("default"),
|
||||
Labels: map[string]string{
|
||||
"testLabel": labelVal,
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
}
|
||||
got, err := client.CreateConfigMap(ctx, cm)
|
||||
if err != nil {
|
||||
t.Fatalf("create config map: %v", err)
|
||||
}
|
||||
|
||||
if event, gotFromWatch, err := w.Next(); err != nil {
|
||||
t.Errorf("failed to get next watch: %v", err)
|
||||
} else {
|
||||
if *event.Type != EventAdded {
|
||||
t.Errorf("expected event type %q got %q", EventAdded, *event.Type)
|
||||
}
|
||||
if !reflect.DeepEqual(got, gotFromWatch) {
|
||||
t.Errorf("object from add event did not match expected value")
|
||||
}
|
||||
}
|
||||
|
||||
got.Data["zam"] = "spam"
|
||||
got, err = client.UpdateConfigMap(ctx, got)
|
||||
if err != nil {
|
||||
t.Fatalf("update config map: %v", err)
|
||||
}
|
||||
|
||||
if event, gotFromWatch, err := w.Next(); err != nil {
|
||||
t.Errorf("failed to get next watch: %v", err)
|
||||
} else {
|
||||
if *event.Type != EventModified {
|
||||
t.Errorf("expected event type %q got %q", EventModified, *event.Type)
|
||||
}
|
||||
if !reflect.DeepEqual(got, gotFromWatch) {
|
||||
t.Errorf("object from modified event did not match expected value")
|
||||
}
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
labelVal string
|
||||
expNum int
|
||||
}{
|
||||
{labelVal, 1},
|
||||
{newName(), 0},
|
||||
}
|
||||
for _, test := range tests {
|
||||
l := new(LabelSelector)
|
||||
l.Eq("testLabel", test.labelVal)
|
||||
|
||||
configMaps, err := client.ListConfigMaps(ctx, "default", l.Selector())
|
||||
if err != nil {
|
||||
t.Errorf("failed to list configmaps: %v", err)
|
||||
continue
|
||||
}
|
||||
got := len(configMaps.Items)
|
||||
if got != test.expNum {
|
||||
t.Errorf("expected selector to return %d items got %d", test.expNum, got)
|
||||
}
|
||||
}
|
||||
|
||||
if err := client.DeleteConfigMap(ctx, *cm.Metadata.Name, *cm.Metadata.Namespace); err != nil {
|
||||
t.Fatalf("delete config map: %v", err)
|
||||
}
|
||||
if event, gotFromWatch, err := w.Next(); err != nil {
|
||||
t.Errorf("failed to get next watch: %v", err)
|
||||
} else {
|
||||
if *event.Type != EventDeleted {
|
||||
t.Errorf("expected event type %q got %q", EventDeleted, *event.Type)
|
||||
}
|
||||
|
||||
// Resource version will be different after a delete
|
||||
got.Metadata.ResourceVersion = String("")
|
||||
gotFromWatch.Metadata.ResourceVersion = String("")
|
||||
|
||||
if !reflect.DeepEqual(got, gotFromWatch) {
|
||||
t.Errorf("object from deleted event did not match expected value")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestWatchNamespace ensures that creating a configmap in a non-default namespace is not returned while watching the default namespace
|
||||
func TestWatchNamespace(t *testing.T) {
|
||||
client := newTestClient(t).CoreV1()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
defaultWatch, err := client.WatchConfigMaps(ctx, "default")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer defaultWatch.Close()
|
||||
|
||||
allWatch, err := client.WatchConfigMaps(ctx, AllNamespaces)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer allWatch.Close()
|
||||
|
||||
nonDefaultNamespaceName := newName()
|
||||
defaultName := newName()
|
||||
name := newName()
|
||||
labelVal := newName()
|
||||
|
||||
// Create a configmap in the default namespace so the "default" watch has something to return
|
||||
defaultCM := &v1.ConfigMap{
|
||||
Metadata: &metav1.ObjectMeta{
|
||||
Name: String(defaultName),
|
||||
Namespace: String("default"),
|
||||
Labels: map[string]string{
|
||||
"testLabel": labelVal,
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
}
|
||||
defaultGot, err := client.CreateConfigMap(ctx, defaultCM)
|
||||
if err != nil {
|
||||
t.Fatalf("create config map: %v", err)
|
||||
}
|
||||
|
||||
// Create a non-default Namespace
|
||||
ns := &v1.Namespace{
|
||||
Metadata: &metav1.ObjectMeta{
|
||||
Name: String(nonDefaultNamespaceName),
|
||||
},
|
||||
}
|
||||
if _, err := client.CreateNamespace(ctx, ns); err != nil {
|
||||
t.Fatalf("create non-default-namespace: %v", err)
|
||||
}
|
||||
|
||||
// Create a configmap in the non-default namespace
|
||||
nonDefaultCM := &v1.ConfigMap{
|
||||
Metadata: &metav1.ObjectMeta{
|
||||
Name: String(name),
|
||||
Namespace: String(nonDefaultNamespaceName),
|
||||
Labels: map[string]string{
|
||||
"testLabel": labelVal,
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
}
|
||||
nonDefaultGot, err := client.CreateConfigMap(ctx, nonDefaultCM)
|
||||
if err != nil {
|
||||
t.Fatalf("create config map: %v", err)
|
||||
}
|
||||
|
||||
// Watching the default namespace should not return the non-default namespace configmap,
|
||||
// and instead return the previously created configmap in the default namespace
|
||||
if _, gotFromWatch, err := defaultWatch.Next(); err != nil {
|
||||
t.Errorf("failed to get next watch: %v", err)
|
||||
} else {
|
||||
if reflect.DeepEqual(nonDefaultGot, gotFromWatch) {
|
||||
t.Errorf("config map in non-default namespace returned while watching default namespace")
|
||||
}
|
||||
if !reflect.DeepEqual(defaultGot, gotFromWatch) {
|
||||
t.Errorf("object from add event did not match expected value")
|
||||
}
|
||||
}
|
||||
|
||||
// However, watching all-namespaces should contain both the default and non-default namespaced configmaps
|
||||
if _, gotFromWatch, err := allWatch.Next(); err != nil {
|
||||
t.Errorf("failed to get next watch: %v", err)
|
||||
} else {
|
||||
if !reflect.DeepEqual(defaultGot, gotFromWatch) {
|
||||
t.Errorf("watching all namespaces did not return the expected configmap")
|
||||
}
|
||||
}
|
||||
|
||||
if _, gotFromWatch, err := allWatch.Next(); err != nil {
|
||||
t.Errorf("failed to get next watch: %v", err)
|
||||
} else {
|
||||
if !reflect.DeepEqual(nonDefaultGot, gotFromWatch) {
|
||||
t.Errorf("watching all namespaces did not return the expected configmap")
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the config map in the default namespace first, then delete the non-default namespace config map.
|
||||
// Only the former should be noticed by the default-watch.
|
||||
|
||||
if err := client.DeleteConfigMap(ctx, *defaultCM.Metadata.Name, *defaultCM.Metadata.Namespace); err != nil {
|
||||
t.Fatalf("delete config map: %v", err)
|
||||
}
|
||||
if err := client.DeleteConfigMap(ctx, *nonDefaultCM.Metadata.Name, *nonDefaultCM.Metadata.Namespace); err != nil {
|
||||
t.Fatalf("delete config map: %v", err)
|
||||
}
|
||||
|
||||
if event, gotFromWatch, err := defaultWatch.Next(); err != nil {
|
||||
t.Errorf("failed to get next watch: %v", err)
|
||||
} else {
|
||||
if *event.Type != EventDeleted {
|
||||
t.Errorf("expected event type %q got %q", EventDeleted, *event.Type)
|
||||
}
|
||||
|
||||
// Resource version will be different after a delete
|
||||
nonDefaultGot.Metadata.ResourceVersion = String("")
|
||||
gotFromWatch.Metadata.ResourceVersion = String("")
|
||||
|
||||
if reflect.DeepEqual(nonDefaultGot, gotFromWatch) {
|
||||
t.Errorf("should not have received event from non-default namespace while watching default namespace")
|
||||
}
|
||||
}
|
||||
|
||||
if err := client.DeleteNamespace(ctx, nonDefaultNamespaceName); err != nil {
|
||||
t.Fatalf("delete namespace: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultNamespace(t *testing.T) {
|
||||
c := &Config{
|
||||
Clusters: []NamedCluster{
|
||||
{
|
||||
Name: "local",
|
||||
Cluster: Cluster{
|
||||
Server: "http://localhost:8080",
|
||||
},
|
||||
},
|
||||
},
|
||||
AuthInfos: []NamedAuthInfo{
|
||||
{
|
||||
Name: "local",
|
||||
},
|
||||
},
|
||||
}
|
||||
cli, err := NewClient(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if cli.Namespace != "default" {
|
||||
t.Errorf("expected namespace=%q got=%q", "default", cli.Namespace)
|
||||
}
|
||||
}
|
83
vendor/github.com/ericchiang/k8s/codec.go
generated
vendored
83
vendor/github.com/ericchiang/k8s/codec.go
generated
vendored
|
@ -1,83 +0,0 @@
|
|||
package k8s
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/ericchiang/k8s/runtime"
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
type codec struct {
|
||||
contentType string
|
||||
marshal func(interface{}) ([]byte, error)
|
||||
unmarshal func([]byte, interface{}) error
|
||||
}
|
||||
|
||||
var (
|
||||
// Kubernetes implements its own custom protobuf format to allow clients (and possibly
|
||||
// servers) to use either JSON or protocol buffers. The protocol introduces a custom content
|
||||
// type and magic bytes to signal the use of protobufs, and wraps each object with API group,
|
||||
// version and resource data.
|
||||
//
|
||||
// The protocol spec which this client implements can be found here:
|
||||
//
|
||||
// https://github.com/kubernetes/kubernetes/blob/master/docs/proposals/protobuf.md
|
||||
//
|
||||
pbCodec = &codec{
|
||||
contentType: "application/vnd.kubernetes.protobuf",
|
||||
marshal: marshalPB,
|
||||
unmarshal: unmarshalPB,
|
||||
}
|
||||
jsonCodec = &codec{
|
||||
contentType: "application/json",
|
||||
marshal: json.Marshal,
|
||||
unmarshal: json.Unmarshal,
|
||||
}
|
||||
)
|
||||
|
||||
var magicBytes = []byte{0x6b, 0x38, 0x73, 0x00}
|
||||
|
||||
func unmarshalPB(b []byte, obj interface{}) error {
|
||||
message, ok := obj.(proto.Message)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected obj of type proto.Message, got %T", obj)
|
||||
}
|
||||
if len(b) < len(magicBytes) {
|
||||
return errors.New("payload is not a kubernetes protobuf object")
|
||||
}
|
||||
if !bytes.Equal(b[:len(magicBytes)], magicBytes) {
|
||||
return errors.New("payload is not a kubernetes protobuf object")
|
||||
}
|
||||
|
||||
u := new(runtime.Unknown)
|
||||
if err := u.Unmarshal(b[len(magicBytes):]); err != nil {
|
||||
return fmt.Errorf("unmarshal unknown: %v", err)
|
||||
}
|
||||
return proto.Unmarshal(u.Raw, message)
|
||||
}
|
||||
|
||||
func marshalPB(obj interface{}) ([]byte, error) {
|
||||
message, ok := obj.(proto.Message)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected obj of type proto.Message, got %T", obj)
|
||||
}
|
||||
payload, err := proto.Marshal(message)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The URL path informs the API server what the API group, version, and resource
|
||||
// of the object. We don't need to specify it here to talk to the API server.
|
||||
body, err := (&runtime.Unknown{Raw: payload}).Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d := make([]byte, len(magicBytes)+len(body))
|
||||
copy(d[:len(magicBytes)], magicBytes)
|
||||
copy(d[len(magicBytes):], body)
|
||||
return d, nil
|
||||
}
|
170
vendor/github.com/ericchiang/k8s/config.go
generated
vendored
170
vendor/github.com/ericchiang/k8s/config.go
generated
vendored
|
@ -1,170 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package k8s
|
||||
|
||||
import (
|
||||
"github.com/ericchiang/k8s/runtime"
|
||||
)
|
||||
|
||||
// Where possible, json tags match the cli argument names.
|
||||
// Top level config objects and all values required for proper functioning are not "omitempty". Any truly optional piece of config is allowed to be omitted.
|
||||
|
||||
// Config holds the information needed to build connect to remote kubernetes clusters as a given user
|
||||
type Config struct {
|
||||
// Legacy field from pkg/api/types.go TypeMeta.
|
||||
// TODO(jlowdermilk): remove this after eliminating downstream dependencies.
|
||||
// +optional
|
||||
Kind string `json:"kind,omitempty"`
|
||||
// DEPRECATED: APIVersion is the preferred api version for communicating with the kubernetes cluster (v1, v2, etc).
|
||||
// Because a cluster can run multiple API groups and potentially multiple versions of each, it no longer makes sense to specify
|
||||
// a single value for the cluster version.
|
||||
// This field isn't really needed anyway, so we are deprecating it without replacement.
|
||||
// It will be ignored if it is present.
|
||||
// +optional
|
||||
APIVersion string `json:"apiVersion,omitempty"`
|
||||
// Preferences holds general information to be use for cli interactions
|
||||
Preferences Preferences `json:"preferences"`
|
||||
// Clusters is a map of referencable names to cluster configs
|
||||
Clusters []NamedCluster `json:"clusters"`
|
||||
// AuthInfos is a map of referencable names to user configs
|
||||
AuthInfos []NamedAuthInfo `json:"users"`
|
||||
// Contexts is a map of referencable names to context configs
|
||||
Contexts []NamedContext `json:"contexts"`
|
||||
// CurrentContext is the name of the context that you would like to use by default
|
||||
CurrentContext string `json:"current-context"`
|
||||
// Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields
|
||||
// +optional
|
||||
Extensions []NamedExtension `json:"extensions,omitempty"`
|
||||
}
|
||||
|
||||
type Preferences struct {
|
||||
// +optional
|
||||
Colors bool `json:"colors,omitempty"`
|
||||
// Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields
|
||||
// +optional
|
||||
Extensions []NamedExtension `json:"extensions,omitempty"`
|
||||
}
|
||||
|
||||
// Cluster contains information about how to communicate with a kubernetes cluster
|
||||
type Cluster struct {
|
||||
// Server is the address of the kubernetes cluster (https://hostname:port).
|
||||
Server string `json:"server"`
|
||||
// APIVersion is the preferred api version for communicating with the kubernetes cluster (v1, v2, etc).
|
||||
// +optional
|
||||
APIVersion string `json:"api-version,omitempty"`
|
||||
// InsecureSkipTLSVerify skips the validity check for the server's certificate. This will make your HTTPS connections insecure.
|
||||
// +optional
|
||||
InsecureSkipTLSVerify bool `json:"insecure-skip-tls-verify,omitempty"`
|
||||
// CertificateAuthority is the path to a cert file for the certificate authority.
|
||||
// +optional
|
||||
CertificateAuthority string `json:"certificate-authority,omitempty"`
|
||||
// CertificateAuthorityData contains PEM-encoded certificate authority certificates. Overrides CertificateAuthority
|
||||
// +optional
|
||||
CertificateAuthorityData []byte `json:"certificate-authority-data,omitempty"`
|
||||
// Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields
|
||||
// +optional
|
||||
Extensions []NamedExtension `json:"extensions,omitempty"`
|
||||
}
|
||||
|
||||
// AuthInfo contains information that describes identity information. This is use to tell the kubernetes cluster who you are.
|
||||
type AuthInfo struct {
|
||||
// ClientCertificate is the path to a client cert file for TLS.
|
||||
// +optional
|
||||
ClientCertificate string `json:"client-certificate,omitempty"`
|
||||
// ClientCertificateData contains PEM-encoded data from a client cert file for TLS. Overrides ClientCertificate
|
||||
// +optional
|
||||
ClientCertificateData []byte `json:"client-certificate-data,omitempty"`
|
||||
// ClientKey is the path to a client key file for TLS.
|
||||
// +optional
|
||||
ClientKey string `json:"client-key,omitempty"`
|
||||
// ClientKeyData contains PEM-encoded data from a client key file for TLS. Overrides ClientKey
|
||||
// +optional
|
||||
ClientKeyData []byte `json:"client-key-data,omitempty"`
|
||||
// Token is the bearer token for authentication to the kubernetes cluster.
|
||||
// +optional
|
||||
Token string `json:"token,omitempty"`
|
||||
// TokenFile is a pointer to a file that contains a bearer token (as described above). If both Token and TokenFile are present, Token takes precedence.
|
||||
// +optional
|
||||
TokenFile string `json:"tokenFile,omitempty"`
|
||||
// Impersonate is the username to imperonate. The name matches the flag.
|
||||
// +optional
|
||||
Impersonate string `json:"as,omitempty"`
|
||||
// Username is the username for basic authentication to the kubernetes cluster.
|
||||
// +optional
|
||||
Username string `json:"username,omitempty"`
|
||||
// Password is the password for basic authentication to the kubernetes cluster.
|
||||
// +optional
|
||||
Password string `json:"password,omitempty"`
|
||||
// AuthProvider specifies a custom authentication plugin for the kubernetes cluster.
|
||||
// +optional
|
||||
AuthProvider *AuthProviderConfig `json:"auth-provider,omitempty"`
|
||||
// Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields
|
||||
// +optional
|
||||
Extensions []NamedExtension `json:"extensions,omitempty"`
|
||||
}
|
||||
|
||||
// Context is a tuple of references to a cluster (how do I communicate with a kubernetes cluster), a user (how do I identify myself), and a namespace (what subset of resources do I want to work with)
|
||||
type Context struct {
|
||||
// Cluster is the name of the cluster for this context
|
||||
Cluster string `json:"cluster"`
|
||||
// AuthInfo is the name of the authInfo for this context
|
||||
AuthInfo string `json:"user"`
|
||||
// Namespace is the default namespace to use on unspecified requests
|
||||
// +optional
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
// Extensions holds additional information. This is useful for extenders so that reads and writes don't clobber unknown fields
|
||||
// +optional
|
||||
Extensions []NamedExtension `json:"extensions,omitempty"`
|
||||
}
|
||||
|
||||
// NamedCluster relates nicknames to cluster information
|
||||
type NamedCluster struct {
|
||||
// Name is the nickname for this Cluster
|
||||
Name string `json:"name"`
|
||||
// Cluster holds the cluster information
|
||||
Cluster Cluster `json:"cluster"`
|
||||
}
|
||||
|
||||
// NamedContext relates nicknames to context information
|
||||
type NamedContext struct {
|
||||
// Name is the nickname for this Context
|
||||
Name string `json:"name"`
|
||||
// Context holds the context information
|
||||
Context Context `json:"context"`
|
||||
}
|
||||
|
||||
// NamedAuthInfo relates nicknames to auth information
|
||||
type NamedAuthInfo struct {
|
||||
// Name is the nickname for this AuthInfo
|
||||
Name string `json:"name"`
|
||||
// AuthInfo holds the auth information
|
||||
AuthInfo AuthInfo `json:"user"`
|
||||
}
|
||||
|
||||
// NamedExtension relates nicknames to extension information
|
||||
type NamedExtension struct {
|
||||
// Name is the nickname for this Extension
|
||||
Name string `json:"name"`
|
||||
// Extension holds the extension information
|
||||
Extension runtime.RawExtension `json:"extension"`
|
||||
}
|
||||
|
||||
// AuthProviderConfig holds the configuration for a specified auth provider.
|
||||
type AuthProviderConfig struct {
|
||||
Name string `json:"name"`
|
||||
Config map[string]string `json:"config"`
|
||||
}
|
63
vendor/github.com/ericchiang/k8s/discovery.go
generated
vendored
63
vendor/github.com/ericchiang/k8s/discovery.go
generated
vendored
|
@ -1,63 +0,0 @@
|
|||
package k8s
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
|
||||
"github.com/ericchiang/k8s/api/unversioned"
|
||||
)
|
||||
|
||||
type Version struct {
|
||||
Major string `json:"major"`
|
||||
Minor string `json:"minor"`
|
||||
GitVersion string `json:"gitVersion"`
|
||||
GitCommit string `json:"gitCommit"`
|
||||
GitTreeState string `json:"gitTreeState"`
|
||||
BuildDate string `json:"buildDate"`
|
||||
GoVersion string `json:"goVersion"`
|
||||
Compiler string `json:"compiler"`
|
||||
Platform string `json:"platform"`
|
||||
}
|
||||
|
||||
func (c *Client) Discovery() *Discovery {
|
||||
return &Discovery{c}
|
||||
}
|
||||
|
||||
// Discovery is a client used to determine the API version and supported
|
||||
// resources of the server.
|
||||
type Discovery struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (d *Discovery) Version(ctx context.Context) (*Version, error) {
|
||||
var v Version
|
||||
if err := d.client.get(ctx, jsonCodec, d.client.urlForPath("version"), &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &v, nil
|
||||
}
|
||||
|
||||
func (d *Discovery) APIGroups(ctx context.Context) (*unversioned.APIGroupList, error) {
|
||||
var groups unversioned.APIGroupList
|
||||
if err := d.client.get(ctx, pbCodec, d.client.urlForPath("apis"), &groups); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &groups, nil
|
||||
}
|
||||
|
||||
func (d *Discovery) APIGroup(ctx context.Context, name string) (*unversioned.APIGroup, error) {
|
||||
var group unversioned.APIGroup
|
||||
if err := d.client.get(ctx, pbCodec, d.client.urlForPath(path.Join("apis", name)), &group); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &group, nil
|
||||
}
|
||||
|
||||
func (d *Discovery) APIResources(ctx context.Context, groupName, groupVersion string) (*unversioned.APIResourceList, error) {
|
||||
var list unversioned.APIResourceList
|
||||
if err := d.client.get(ctx, pbCodec, d.client.urlForPath(path.Join("apis", groupName, groupVersion)), &list); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &list, nil
|
||||
|
||||
}
|
28
vendor/github.com/ericchiang/k8s/discovery_test.go
generated
vendored
28
vendor/github.com/ericchiang/k8s/discovery_test.go
generated
vendored
|
@ -1,28 +0,0 @@
|
|||
package k8s
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDiscovery(t *testing.T) {
|
||||
client := newTestClient(t).Discovery()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
if _, err := client.Version(ctx); err != nil {
|
||||
t.Errorf("list version: %v", err)
|
||||
}
|
||||
|
||||
if _, err := client.APIGroups(ctx); err != nil {
|
||||
t.Errorf("list api groups: %v", err)
|
||||
}
|
||||
|
||||
if _, err := client.APIGroup(ctx, "extensions"); err != nil {
|
||||
t.Errorf("list api group: %v", err)
|
||||
}
|
||||
|
||||
if _, err := client.APIResources(ctx, "extensions", "v1beta1"); err != nil {
|
||||
t.Errorf("list api group resources: %v", err)
|
||||
}
|
||||
}
|
38
vendor/github.com/ericchiang/k8s/examples/api-errors.go
generated
vendored
38
vendor/github.com/ericchiang/k8s/examples/api-errors.go
generated
vendored
|
@ -1,38 +0,0 @@
|
|||
// +build ignore
|
||||
|
||||
package configmaps
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/ericchiang/k8s"
|
||||
"github.com/ericchiang/k8s/api/v1"
|
||||
metav1 "github.com/ericchiang/k8s/apis/meta/v1"
|
||||
)
|
||||
|
||||
// createConfigMap creates a configmap in the client's default namespace
|
||||
// but does not return an error if a configmap of the same name already
|
||||
// exists.
|
||||
func createConfigMap(client *k8s.Client, name string, values map[string]string) error {
|
||||
cm := &v1.ConfigMap{
|
||||
Metadata: &metav1.ObjectMeta{
|
||||
Name: &name,
|
||||
Namespace: &client.Namespace,
|
||||
},
|
||||
Data: values,
|
||||
}
|
||||
|
||||
_, err := client.CoreV1().CreateConfigMap(context.TODO(), cm)
|
||||
|
||||
// If an HTTP error was returned by the API server, it will be of type
|
||||
// *k8s.APIError. This can be used to inspect the status code.
|
||||
if apiErr, ok := err.(*k8s.APIError); ok {
|
||||
// Resource already exists. Carry on.
|
||||
if apiErr.Code == http.StatusConflict {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("create configmap: %v", err)
|
||||
}
|
24
vendor/github.com/ericchiang/k8s/examples/create-resource.go
generated
vendored
24
vendor/github.com/ericchiang/k8s/examples/create-resource.go
generated
vendored
|
@ -1,24 +0,0 @@
|
|||
// +build ignore
|
||||
|
||||
package configmaps
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ericchiang/k8s"
|
||||
"github.com/ericchiang/k8s/api/v1"
|
||||
metav1 "github.com/ericchiang/k8s/apis/meta/v1"
|
||||
)
|
||||
|
||||
func createConfigMap(client *k8s.Client, name string, values map[string]string) error {
|
||||
cm := &v1.ConfigMap{
|
||||
Metadata: &metav1.ObjectMeta{
|
||||
Name: &name,
|
||||
Namespace: &client.Namespace,
|
||||
},
|
||||
Data: values,
|
||||
}
|
||||
// Will return the created configmap as well.
|
||||
_, err := client.CoreV1().CreateConfigMap(context.TODO(), cm)
|
||||
return err
|
||||
}
|
26
vendor/github.com/ericchiang/k8s/examples/in-cluster-client.go
generated
vendored
26
vendor/github.com/ericchiang/k8s/examples/in-cluster-client.go
generated
vendored
|
@ -1,26 +0,0 @@
|
|||
// +build ignore
|
||||
|
||||
package nodes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/ericchiang/k8s"
|
||||
)
|
||||
|
||||
func listNodes() {
|
||||
client, err := k8s.NewInClusterClient()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
nodes, err := client.CoreV1().ListNodes(context.Background())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
for _, node := range nodes.Items {
|
||||
fmt.Printf("name=%q schedulable=%t\n", *node.Metadata.Name, !*node.Spec.Unschedulable)
|
||||
}
|
||||
}
|
28
vendor/github.com/ericchiang/k8s/examples/out-of-cluster-client.go
generated
vendored
28
vendor/github.com/ericchiang/k8s/examples/out-of-cluster-client.go
generated
vendored
|
@ -1,28 +0,0 @@
|
|||
// +build ignore
|
||||
|
||||
package kubeconfig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/ericchiang/k8s"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
)
|
||||
|
||||
// loadClient parses a kubeconfig from a file and returns a Kubernetes
|
||||
// client. It does not support extensions or client auth providers.
|
||||
func loadClient(kubeconfigPath string) (*k8s.Client, error) {
|
||||
data, err := ioutil.ReadFile(kubeconfigPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read kubeconfig: %v", err)
|
||||
}
|
||||
|
||||
// Unmarshal YAML into a Kubernetes config object.
|
||||
var config k8s.Config
|
||||
if err := yaml.Unmarshal(data, &config); err != nil {
|
||||
return nil, fmt.Errorf("unmarshal kubeconfig: %v", err)
|
||||
}
|
||||
return k8s.NewClient(&config)
|
||||
}
|
382
vendor/github.com/ericchiang/k8s/gen.go
generated
vendored
382
vendor/github.com/ericchiang/k8s/gen.go
generated
vendored
|
@ -1,382 +0,0 @@
|
|||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"golang.org/x/tools/go/loader"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := load(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
func isInterface(obj interface{}) (*types.Interface, bool) {
|
||||
switch obj := obj.(type) {
|
||||
case *types.TypeName:
|
||||
return isInterface(obj.Type())
|
||||
case *types.Named:
|
||||
return isInterface(obj.Underlying())
|
||||
case *types.Interface:
|
||||
return obj, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
type Resource struct {
|
||||
Name string
|
||||
Namespaced bool
|
||||
HasList bool
|
||||
Pluralized string
|
||||
}
|
||||
|
||||
type byName []Resource
|
||||
|
||||
func (n byName) Len() int { return len(n) }
|
||||
func (n byName) Swap(i, j int) { n[i], n[j] = n[j], n[i] }
|
||||
func (n byName) Less(i, j int) bool { return n[i].Name < n[j].Name }
|
||||
|
||||
type Package struct {
|
||||
Name string
|
||||
APIGroup string
|
||||
APIVersion string
|
||||
ImportPath string
|
||||
ImportName string
|
||||
Resources []Resource
|
||||
}
|
||||
|
||||
type byGroup []Package
|
||||
|
||||
func (r byGroup) Len() int { return len(r) }
|
||||
func (r byGroup) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
||||
|
||||
func (r byGroup) Less(i, j int) bool {
|
||||
if r[i].APIGroup != r[j].APIGroup {
|
||||
return r[i].APIGroup < r[j].APIGroup
|
||||
}
|
||||
return r[i].APIVersion < r[j].APIVersion
|
||||
}
|
||||
|
||||
// Incorrect but this is basically what Kubernetes does.
|
||||
func pluralize(s string) string {
|
||||
switch {
|
||||
case strings.HasSuffix(s, "points"):
|
||||
// NOTE: the k8s "endpoints" resource is already pluralized
|
||||
return s
|
||||
case strings.HasSuffix(s, "s"):
|
||||
return s + "es"
|
||||
case strings.HasSuffix(s, "y"):
|
||||
return s[:len(s)-1] + "ies"
|
||||
default:
|
||||
return s + "s"
|
||||
}
|
||||
}
|
||||
|
||||
var tmpl = template.Must(template.New("").Funcs(template.FuncMap{
|
||||
"pluralize": pluralize,
|
||||
}).Parse(`
|
||||
// {{ .Name }} returns a client for interacting with the {{ .APIGroup }}/{{ .APIVersion }} API group.
|
||||
func (c *Client) {{ .Name }}() *{{ .Name }} {
|
||||
return &{{ .Name }}{c}
|
||||
}
|
||||
|
||||
// {{ .Name }} is a client for interacting with the {{ .APIGroup }}/{{ .APIVersion }} API group.
|
||||
type {{ .Name }} struct {
|
||||
client *Client
|
||||
}
|
||||
{{ range $i, $r := .Resources }}
|
||||
func (c *{{ $.Name }}) Create{{ $r.Name }}(ctx context.Context, obj *{{ $.ImportName }}.{{ $r.Name }}) (*{{ $.ImportName }}.{{ $r.Name }}, error) {
|
||||
md := obj.GetMetadata()
|
||||
if md.Name != nil && *md.Name == "" {
|
||||
return nil, fmt.Errorf("no name for given object")
|
||||
}
|
||||
|
||||
ns := ""
|
||||
if md.Namespace != nil {
|
||||
ns = *md.Namespace
|
||||
}
|
||||
if !{{ $r.Namespaced }} && ns != ""{
|
||||
return nil, fmt.Errorf("resource isn't namespaced")
|
||||
}
|
||||
|
||||
if {{ $r.Namespaced }} {
|
||||
if ns == "" {
|
||||
return nil, fmt.Errorf("no resource namespace provided")
|
||||
}
|
||||
md.Namespace = &ns
|
||||
}
|
||||
url := c.client.urlFor("{{ $.APIGroup }}", "{{ $.APIVersion }}", ns, "{{ $r.Pluralized }}", "")
|
||||
resp := new({{ $.ImportName }}.{{ $r.Name }})
|
||||
err := c.client.create(ctx, pbCodec, "POST", url, obj, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *{{ $.Name }}) Update{{ $r.Name }}(ctx context.Context, obj *{{ $.ImportName }}.{{ $r.Name }}) (*{{ $.ImportName }}.{{ $r.Name }}, error) {
|
||||
md := obj.GetMetadata()
|
||||
if md.Name != nil && *md.Name == "" {
|
||||
return nil, fmt.Errorf("no name for given object")
|
||||
}
|
||||
|
||||
ns := ""
|
||||
if md.Namespace != nil {
|
||||
ns = *md.Namespace
|
||||
}
|
||||
if !{{ $r.Namespaced }} && ns != "" {
|
||||
return nil, fmt.Errorf("resource isn't namespaced")
|
||||
}
|
||||
|
||||
if {{ $r.Namespaced }} {
|
||||
if ns == "" {
|
||||
return nil, fmt.Errorf("no resource namespace provided")
|
||||
}
|
||||
md.Namespace = &ns
|
||||
}
|
||||
url := c.client.urlFor("{{ $.APIGroup }}", "{{ $.APIVersion }}", *md.Namespace, "{{ $r.Pluralized }}", *md.Name)
|
||||
resp := new({{ $.ImportName }}.{{ $r.Name }})
|
||||
err := c.client.create(ctx, pbCodec, "PUT", url, obj, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *{{ $.Name }}) Delete{{ $r.Name }}(ctx context.Context, name string{{ if $r.Namespaced }}, namespace string{{ end }}) error {
|
||||
if name == "" {
|
||||
return fmt.Errorf("create: no name for given object")
|
||||
}
|
||||
url := c.client.urlFor("{{ $.APIGroup }}", "{{ $.APIVersion }}", {{ if $r.Namespaced }}namespace{{ else }}AllNamespaces{{ end }}, "{{ $r.Pluralized }}", name)
|
||||
return c.client.delete(ctx, pbCodec, url)
|
||||
}
|
||||
|
||||
func (c *{{ $.Name }}) Get{{ $r.Name }}(ctx context.Context, name{{ if $r.Namespaced }}, namespace{{ end }} string) (*{{ $.ImportName }}.{{ $r.Name }}, error) {
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("create: no name for given object")
|
||||
}
|
||||
url := c.client.urlFor("{{ $.APIGroup }}", "{{ $.APIVersion }}", {{ if $r.Namespaced }}namespace{{ else }}AllNamespaces{{ end }}, "{{ $r.Pluralized }}", name)
|
||||
resp := new({{ $.ImportName }}.{{ $r.Name }})
|
||||
if err := c.client.get(ctx, pbCodec, url, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
{{- if $r.HasList }}
|
||||
|
||||
type {{ $.Name }}{{ $r.Name }}Watcher struct {
|
||||
watcher *watcher
|
||||
}
|
||||
|
||||
func (w *{{ $.Name }}{{ $r.Name }}Watcher) Next() (*versioned.Event, *{{ $.ImportName }}.{{ $r.Name }}, error) {
|
||||
event, unknown, err := w.watcher.next()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
resp := new({{ $.ImportName }}.{{ $r.Name }})
|
||||
if err := proto.Unmarshal(unknown.Raw, resp); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return event, resp, nil
|
||||
}
|
||||
|
||||
func (w *{{ $.Name }}{{ $r.Name }}Watcher) Close() error {
|
||||
return w.watcher.Close()
|
||||
}
|
||||
|
||||
func (c *{{ $.Name }}) Watch{{ $r.Name | pluralize }}(ctx context.Context{{ if $r.Namespaced }}, namespace string{{ end }}, options ...Option) (*{{ $.Name }}{{ $r.Name }}Watcher, error) {
|
||||
url := c.client.urlFor("{{ $.APIGroup }}", "{{ $.APIVersion }}", {{ if $r.Namespaced }}namespace{{ else }}AllNamespaces{{ end }}, "{{ $r.Pluralized }}", "", options...)
|
||||
watcher, err := c.client.watch(ctx, url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &{{ $.Name }}{{ $r.Name }}Watcher{watcher}, nil
|
||||
}
|
||||
|
||||
func (c *{{ $.Name }}) List{{ $r.Name | pluralize }}(ctx context.Context{{ if $r.Namespaced }}, namespace string{{ end }}, options ...Option) (*{{ $.ImportName }}.{{ $r.Name }}List, error) {
|
||||
url := c.client.urlFor("{{ $.APIGroup }}", "{{ $.APIVersion }}", {{ if $r.Namespaced }}namespace{{ else }}AllNamespaces{{ end }}, "{{ $r.Pluralized }}", "", options...)
|
||||
resp := new({{ $.ImportName }}.{{ $r.Name }}List)
|
||||
if err := c.client.get(ctx, pbCodec, url, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}{{ end }}
|
||||
{{ end }}
|
||||
`))
|
||||
|
||||
var (
|
||||
apiGroupName = map[string]string{
|
||||
"authentication": "authentication.k8s.io",
|
||||
"authorization": "authorization.k8s.io",
|
||||
"certificates": "certificates.k8s.io",
|
||||
"rbac": "rbac.authorization.k8s.io",
|
||||
"storage": "storage.k8s.io",
|
||||
}
|
||||
notNamespaced = map[string]bool{
|
||||
"ClusterRole": true,
|
||||
"ClusterRoleBinding": true,
|
||||
|
||||
"ComponentStatus": true,
|
||||
"Node": true,
|
||||
"Namespace": true,
|
||||
"PersistentVolume": true,
|
||||
|
||||
"PodSecurityPolicy": true,
|
||||
"ThirdPartyResource": true,
|
||||
|
||||
"CertificateSigningRequest": true,
|
||||
|
||||
"TokenReview": true,
|
||||
|
||||
"SubjectAccessReview": true,
|
||||
"SelfSubjectAccessReview": true,
|
||||
|
||||
"ImageReview": true,
|
||||
|
||||
"StorageClass": true,
|
||||
}
|
||||
)
|
||||
|
||||
func clientName(apiGroup, apiVersion string) string {
|
||||
switch apiGroup {
|
||||
case "":
|
||||
apiGroup = "Core"
|
||||
case "rbac":
|
||||
apiGroup = "RBAC"
|
||||
default:
|
||||
apiGroup = strings.Title(apiGroup)
|
||||
}
|
||||
r := strings.NewReplacer("alpha", "Alpha", "beta", "Beta")
|
||||
return apiGroup + r.Replace(strings.Title(apiVersion))
|
||||
}
|
||||
|
||||
func load() error {
|
||||
out, err := exec.Command("go", "list", "./...").CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("go list: %v %s", err, out)
|
||||
}
|
||||
|
||||
var conf loader.Config
|
||||
if _, err := conf.FromArgs(strings.Fields(string(out)), false); err != nil {
|
||||
return fmt.Errorf("from args: %v", err)
|
||||
}
|
||||
|
||||
prog, err := conf.Load()
|
||||
if err != nil {
|
||||
return fmt.Errorf("load: %v", err)
|
||||
}
|
||||
thisPkg, ok := prog.Imported["github.com/ericchiang/k8s"]
|
||||
if !ok {
|
||||
return errors.New("could not find this package")
|
||||
}
|
||||
|
||||
// Types defined in tpr.go. It's hacky, but to "load" interfaces as their
|
||||
// go/types equilvalent, we either have to:
|
||||
//
|
||||
// * Define them in code somewhere (what we're doing here).
|
||||
// * Manually construct them using go/types (blah).
|
||||
// * Parse them from an inlined string (doesn't work in combination with other pkgs).
|
||||
//
|
||||
var interfaces []*types.Interface
|
||||
for _, s := range []string{"object", "after16Object"} {
|
||||
obj := thisPkg.Pkg.Scope().Lookup(s)
|
||||
if obj == nil {
|
||||
return errors.New("failed to lookup object interface")
|
||||
}
|
||||
intr, ok := isInterface(obj)
|
||||
if !ok {
|
||||
return errors.New("failed to convert to interface")
|
||||
}
|
||||
interfaces = append(interfaces, intr)
|
||||
}
|
||||
|
||||
var pkgs []Package
|
||||
for name, pkgInfo := range prog.Imported {
|
||||
pkg := Package{
|
||||
APIVersion: path.Base(name),
|
||||
APIGroup: path.Base(path.Dir(name)),
|
||||
ImportPath: name,
|
||||
}
|
||||
pkg.ImportName = pkg.APIGroup + pkg.APIVersion
|
||||
|
||||
if pkg.APIGroup == "api" {
|
||||
pkg.APIGroup = ""
|
||||
}
|
||||
|
||||
pkg.Name = clientName(pkg.APIGroup, pkg.APIVersion)
|
||||
if name, ok := apiGroupName[pkg.APIGroup]; ok {
|
||||
pkg.APIGroup = name
|
||||
}
|
||||
|
||||
for _, obj := range pkgInfo.Defs {
|
||||
tn, ok := obj.(*types.TypeName)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
impl := false
|
||||
for _, intr := range interfaces {
|
||||
impl = impl || types.Implements(types.NewPointer(tn.Type()), intr)
|
||||
}
|
||||
if !impl {
|
||||
continue
|
||||
}
|
||||
if tn.Name() == "JobTemplateSpec" {
|
||||
continue
|
||||
}
|
||||
|
||||
pkg.Resources = append(pkg.Resources, Resource{
|
||||
Name: tn.Name(),
|
||||
Pluralized: pluralize(strings.ToLower(tn.Name())),
|
||||
HasList: pkgInfo.Pkg.Scope().Lookup(tn.Name()+"List") != nil,
|
||||
Namespaced: !notNamespaced[tn.Name()],
|
||||
})
|
||||
}
|
||||
pkgs = append(pkgs, pkg)
|
||||
}
|
||||
|
||||
sort.Sort(byGroup(pkgs))
|
||||
|
||||
buff := new(bytes.Buffer)
|
||||
buff.WriteString("package k8s\n\n")
|
||||
buff.WriteString("import (\n")
|
||||
buff.WriteString("\t\"context\"\n")
|
||||
buff.WriteString("\t\"fmt\"\n\n")
|
||||
for _, pkg := range pkgs {
|
||||
if len(pkg.Resources) == 0 {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(buff, "\t%s \"%s\"\n", pkg.ImportName, pkg.ImportPath)
|
||||
}
|
||||
fmt.Fprintf(buff, "\t%q\n", "github.com/ericchiang/k8s/watch/versioned")
|
||||
fmt.Fprintf(buff, "\t%q\n", "github.com/golang/protobuf/proto")
|
||||
buff.WriteString(")\n")
|
||||
|
||||
for _, pkg := range pkgs {
|
||||
sort.Sort(byName(pkg.Resources))
|
||||
for _, resource := range pkg.Resources {
|
||||
fmt.Println(pkg.APIGroup, pkg.APIVersion, resource.Name)
|
||||
}
|
||||
if len(pkg.Resources) != 0 {
|
||||
if err := tmpl.Execute(buff, pkg); err != nil {
|
||||
return fmt.Errorf("execute: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ioutil.WriteFile("types.go", buff.Bytes(), 0644)
|
||||
}
|
110
vendor/github.com/ericchiang/k8s/gen.sh
generated
vendored
110
vendor/github.com/ericchiang/k8s/gen.sh
generated
vendored
|
@ -1,110 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
# Clean up any existing build.
|
||||
rm -rf assets/k8s.io
|
||||
mkdir -p assets/k8s.io/kubernetes
|
||||
|
||||
VERSIONS=( "1.4.7" "1.5.1" "1.6.0-rc.1" )
|
||||
|
||||
for VERSION in ${VERSIONS[@]}; do
|
||||
if [ ! -f assets/v${VERSION}.zip ]; then
|
||||
wget https://github.com/kubernetes/kubernetes/archive/v${VERSION}.zip -O assets/v${VERSION}.zip
|
||||
fi
|
||||
|
||||
# Copy source tree to assets/k8s.io/kubernetes. Newer versions overwrite existing ones.
|
||||
unzip -q assets/v${VERSION}.zip -d assets/
|
||||
cp -r assets/kubernetes-${VERSION}/* assets/k8s.io/kubernetes
|
||||
rm -rf assets/kubernetes-${VERSION}
|
||||
done
|
||||
|
||||
# Rewrite API machinery files to their equivalent.
|
||||
apimachinery=assets/k8s.io/kubernetes/staging/src/k8s.io/apimachinery/
|
||||
for file in $( find $apimachinery -type f -name '*.proto' ); do
|
||||
path=assets/k8s.io/kubernetes/${file#$apimachinery}
|
||||
mkdir -p $(dirname $path)
|
||||
mv $file $path
|
||||
done
|
||||
|
||||
# Remove any existing generated code.
|
||||
rm -rf api apis config.go runtime util types.go watch
|
||||
|
||||
# Generate Go code from proto definitions.
|
||||
PKG=$PWD
|
||||
cd assets
|
||||
|
||||
protobuf=$( find k8s.io/kubernetes/pkg/{api,apis,util,runtime,watch} -name '*.proto' )
|
||||
|
||||
# Remote this ununused import:
|
||||
# https://github.com/kubernetes/kubernetes/blob/v1.6.0-rc.1/pkg/api/v1/generated.proto#L29
|
||||
sed -i '/"k8s\.io\/apiserver\/pkg\/apis\/example\/v1\/generated.proto"/d' $protobuf
|
||||
|
||||
# Rewrite all of the API machineary out of staging.
|
||||
sed -i 's|"k8s.io/apimachinery/|"k8s.io/kubernetes/|g' $protobuf
|
||||
sed -i 's/k8s\.io.apimachinery/k8s\.io.kubernetes/g' $protobuf
|
||||
|
||||
for file in $protobuf; do
|
||||
echo $file
|
||||
# Generate protoc definitions at the base of this repo.
|
||||
protoc --gofast_out=$PKG $file
|
||||
done
|
||||
|
||||
cd -
|
||||
|
||||
mv k8s.io/kubernetes/pkg/* .
|
||||
rm -rf k8s.io
|
||||
|
||||
# Copy kubeconfig structs.
|
||||
client_dir="client/unversioned/clientcmd/api/v1"
|
||||
cp assets/k8s.io/kubernetes/pkg/${client_dir}/types.go config.go
|
||||
sed -i 's|package v1|package k8s|g' config.go
|
||||
|
||||
# Rewrite imports for the generated fiels.
|
||||
sed -i 's|"k8s.io/kubernetes/pkg|"github.com/ericchiang/k8s|g' $( find {api,apis,config.go,util,runtime,watch} -name '*.go' )
|
||||
sed -i 's|"k8s.io.kubernetes.pkg.|"github.com/ericchiang.k8s.|g' $( find {api,apis,config.go,util,runtime,watch} -name '*.go' )
|
||||
|
||||
# Clean up assets.
|
||||
rm -rf assets/k8s.io
|
||||
|
||||
# Generate HTTP clients from Go structs.
|
||||
go run gen.go
|
||||
|
||||
# Fix JSON marshaling for types need by third party resources.
|
||||
cat << EOF >> api/unversioned/time.go
|
||||
package unversioned
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
// JSON marshaling logic for the Time type. Need to make
|
||||
// third party resources JSON work.
|
||||
|
||||
func (t Time) MarshalJSON() ([]byte, error) {
|
||||
var seconds, nanos int64
|
||||
if t.Seconds != nil {
|
||||
seconds = *t.Seconds
|
||||
}
|
||||
if t.Nanos != nil {
|
||||
nanos = int64(*t.Nanos)
|
||||
}
|
||||
return json.Marshal(time.Unix(seconds, nanos))
|
||||
}
|
||||
|
||||
func (t *Time) UnmarshalJSON(p []byte) error {
|
||||
var t1 time.Time
|
||||
if err := json.Unmarshal(p, &t1); err != nil {
|
||||
return err
|
||||
}
|
||||
seconds := t1.Unix()
|
||||
nanos := int32(t1.UnixNano())
|
||||
t.Seconds = &seconds
|
||||
t.Nanos = &nanos
|
||||
return nil
|
||||
}
|
||||
EOF
|
||||
gofmt -w api/unversioned/time.go
|
||||
cp api/unversioned/time.go apis/meta/v1
|
||||
sed -i 's|package unversioned|package v1|g' apis/meta/v1/time.go
|
93
vendor/github.com/ericchiang/k8s/labels.go
generated
vendored
93
vendor/github.com/ericchiang/k8s/labels.go
generated
vendored
|
@ -1,93 +0,0 @@
|
|||
package k8s
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
qnameCharFmt string = "[A-Za-z0-9]"
|
||||
qnameExtCharFmt string = "[-A-Za-z0-9_./]"
|
||||
qualifiedNameFmt string = "(" + qnameCharFmt + qnameExtCharFmt + "*)?" + qnameCharFmt
|
||||
qualifiedNameMaxLength int = 63
|
||||
labelValueFmt string = "(" + qualifiedNameFmt + ")?"
|
||||
)
|
||||
|
||||
var labelValueRegexp = regexp.MustCompile("^" + labelValueFmt + "$")
|
||||
|
||||
// LabelSelector represents a Kubernetes label selector.
|
||||
//
|
||||
// Any values that don't conform to Kubernetes label value restrictions
|
||||
// will be silently dropped.
|
||||
//
|
||||
// l := new(k8s.LabelSelector)
|
||||
// l.Eq("component", "frontend")
|
||||
// l.In("type", "prod", "staging")
|
||||
//
|
||||
type LabelSelector struct {
|
||||
stmts []string
|
||||
}
|
||||
|
||||
type labelSelectorOption string
|
||||
|
||||
func (l labelSelectorOption) queryParam() (string, string) {
|
||||
return "labelSelector", string(l)
|
||||
}
|
||||
|
||||
func (l *LabelSelector) Selector() Option {
|
||||
return labelSelectorOption(l.encode())
|
||||
}
|
||||
|
||||
func (l *LabelSelector) encode() string {
|
||||
return strings.Join(l.stmts, ",")
|
||||
}
|
||||
|
||||
func validLabelValue(s string) bool {
|
||||
if len(s) > 63 || len(s) == 0 {
|
||||
return false
|
||||
}
|
||||
return labelValueRegexp.MatchString(s)
|
||||
}
|
||||
|
||||
// Eq selects labels which have the key and the key has the provide value.
|
||||
func (l *LabelSelector) Eq(key, val string) {
|
||||
if !validLabelValue(key) || !validLabelValue(val) {
|
||||
return
|
||||
}
|
||||
l.stmts = append(l.stmts, key+"="+val)
|
||||
}
|
||||
|
||||
// NotEq selects labels where the key is present and has a different value
|
||||
// than the value provided.
|
||||
func (l *LabelSelector) NotEq(key, val string) {
|
||||
if !validLabelValue(key) || !validLabelValue(val) {
|
||||
return
|
||||
}
|
||||
l.stmts = append(l.stmts, key+"!="+val)
|
||||
}
|
||||
|
||||
// In selects labels which have the key and the key has one of the provided values.
|
||||
func (l *LabelSelector) In(key string, vals ...string) {
|
||||
if !validLabelValue(key) || len(vals) == 0 {
|
||||
return
|
||||
}
|
||||
for _, val := range vals {
|
||||
if !validLabelValue(val) {
|
||||
return
|
||||
}
|
||||
}
|
||||
l.stmts = append(l.stmts, key+" in ("+strings.Join(vals, ", ")+")")
|
||||
}
|
||||
|
||||
// NotIn selects labels which have the key and the key is not one of the provided values.
|
||||
func (l *LabelSelector) NotIn(key string, vals ...string) {
|
||||
if !validLabelValue(key) || len(vals) == 0 {
|
||||
return
|
||||
}
|
||||
for _, val := range vals {
|
||||
if !validLabelValue(val) {
|
||||
return
|
||||
}
|
||||
}
|
||||
l.stmts = append(l.stmts, key+" notin ("+strings.Join(vals, ", ")+")")
|
||||
}
|
52
vendor/github.com/ericchiang/k8s/labels_test.go
generated
vendored
52
vendor/github.com/ericchiang/k8s/labels_test.go
generated
vendored
|
@ -1,52 +0,0 @@
|
|||
package k8s
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestLabelSelector(t *testing.T) {
|
||||
tests := []struct {
|
||||
f func(l *LabelSelector)
|
||||
want string
|
||||
}{
|
||||
{
|
||||
f: func(l *LabelSelector) {
|
||||
l.Eq("component", "frontend")
|
||||
},
|
||||
want: "component=frontend",
|
||||
},
|
||||
{
|
||||
f: func(l *LabelSelector) {
|
||||
l.Eq("kubernetes.io/role", "master")
|
||||
},
|
||||
want: "kubernetes.io/role=master",
|
||||
},
|
||||
{
|
||||
f: func(l *LabelSelector) {
|
||||
l.In("type", "prod", "staging")
|
||||
l.Eq("component", "frontend")
|
||||
},
|
||||
want: "type in (prod, staging),component=frontend",
|
||||
},
|
||||
{
|
||||
f: func(l *LabelSelector) {
|
||||
l.NotIn("type", "prod", "staging")
|
||||
l.NotEq("component", "frontend")
|
||||
},
|
||||
want: "type notin (prod, staging),component!=frontend",
|
||||
},
|
||||
{
|
||||
f: func(l *LabelSelector) {
|
||||
l.Eq("foo", "I am not a valid label value")
|
||||
},
|
||||
want: "",
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
l := new(LabelSelector)
|
||||
test.f(l)
|
||||
got := l.encode()
|
||||
if test.want != got {
|
||||
t.Errorf("case %d: want=%q, got=%q", i, test.want, got)
|
||||
}
|
||||
}
|
||||
}
|
905
vendor/github.com/ericchiang/k8s/runtime/generated.pb.go
generated
vendored
905
vendor/github.com/ericchiang/k8s/runtime/generated.pb.go
generated
vendored
|
@ -1,905 +0,0 @@
|
|||
// Code generated by protoc-gen-gogo.
|
||||
// source: k8s.io/kubernetes/pkg/runtime/generated.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package runtime is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
k8s.io/kubernetes/pkg/runtime/generated.proto
|
||||
|
||||
It has these top-level messages:
|
||||
RawExtension
|
||||
TypeMeta
|
||||
Unknown
|
||||
*/
|
||||
package runtime
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import _ "github.com/ericchiang/k8s/util/intstr"
|
||||
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// RawExtension is used to hold extensions in external versions.
|
||||
//
|
||||
// To use this, make a field which has RawExtension as its type in your external, versioned
|
||||
// struct, and Object in your internal struct. You also need to register your
|
||||
// various plugin types.
|
||||
//
|
||||
// // Internal package:
|
||||
// type MyAPIObject struct {
|
||||
// runtime.TypeMeta `json:",inline"`
|
||||
// MyPlugin runtime.Object `json:"myPlugin"`
|
||||
// }
|
||||
// type PluginA struct {
|
||||
// AOption string `json:"aOption"`
|
||||
// }
|
||||
//
|
||||
// // External package:
|
||||
// type MyAPIObject struct {
|
||||
// runtime.TypeMeta `json:",inline"`
|
||||
// MyPlugin runtime.RawExtension `json:"myPlugin"`
|
||||
// }
|
||||
// type PluginA struct {
|
||||
// AOption string `json:"aOption"`
|
||||
// }
|
||||
//
|
||||
// // On the wire, the JSON will look something like this:
|
||||
// {
|
||||
// "kind":"MyAPIObject",
|
||||
// "apiVersion":"v1",
|
||||
// "myPlugin": {
|
||||
// "kind":"PluginA",
|
||||
// "aOption":"foo",
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// So what happens? Decode first uses json or yaml to unmarshal the serialized data into
|
||||
// your external MyAPIObject. That causes the raw JSON to be stored, but not unpacked.
|
||||
// The next step is to copy (using pkg/conversion) into the internal struct. The runtime
|
||||
// package's DefaultScheme has conversion functions installed which will unpack the
|
||||
// JSON stored in RawExtension, turning it into the correct object type, and storing it
|
||||
// in the Object. (TODO: In the case where the object is of an unknown type, a
|
||||
// runtime.Unknown object will be created and stored.)
|
||||
//
|
||||
// +k8s:deepcopy-gen=true
|
||||
// +protobuf=true
|
||||
// +k8s:openapi-gen=true
|
||||
type RawExtension struct {
|
||||
// Raw is the underlying serialization of this object.
|
||||
//
|
||||
// TODO: Determine how to detect ContentType and ContentEncoding of 'Raw' data.
|
||||
Raw []byte `protobuf:"bytes,1,opt,name=raw" json:"raw,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *RawExtension) Reset() { *m = RawExtension{} }
|
||||
func (m *RawExtension) String() string { return proto.CompactTextString(m) }
|
||||
func (*RawExtension) ProtoMessage() {}
|
||||
func (*RawExtension) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} }
|
||||
|
||||
func (m *RawExtension) GetRaw() []byte {
|
||||
if m != nil {
|
||||
return m.Raw
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TypeMeta is shared by all top level objects. The proper way to use it is to inline it in your type,
|
||||
// like this:
|
||||
// type MyAwesomeAPIObject struct {
|
||||
// runtime.TypeMeta `json:",inline"`
|
||||
// ... // other fields
|
||||
// }
|
||||
// func (obj *MyAwesomeAPIObject) SetGroupVersionKind(gvk *metav1.GroupVersionKind) { metav1.UpdateTypeMeta(obj,gvk) }; GroupVersionKind() *GroupVersionKind
|
||||
//
|
||||
// TypeMeta is provided here for convenience. You may use it directly from this package or define
|
||||
// your own with the same fields.
|
||||
//
|
||||
// +k8s:deepcopy-gen=true
|
||||
// +protobuf=true
|
||||
// +k8s:openapi-gen=true
|
||||
type TypeMeta struct {
|
||||
// +optional
|
||||
ApiVersion *string `protobuf:"bytes,1,opt,name=apiVersion" json:"apiVersion,omitempty"`
|
||||
// +optional
|
||||
Kind *string `protobuf:"bytes,2,opt,name=kind" json:"kind,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *TypeMeta) Reset() { *m = TypeMeta{} }
|
||||
func (m *TypeMeta) String() string { return proto.CompactTextString(m) }
|
||||
func (*TypeMeta) ProtoMessage() {}
|
||||
func (*TypeMeta) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{1} }
|
||||
|
||||
func (m *TypeMeta) GetApiVersion() string {
|
||||
if m != nil && m.ApiVersion != nil {
|
||||
return *m.ApiVersion
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *TypeMeta) GetKind() string {
|
||||
if m != nil && m.Kind != nil {
|
||||
return *m.Kind
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Unknown allows api objects with unknown types to be passed-through. This can be used
|
||||
// to deal with the API objects from a plug-in. Unknown objects still have functioning
|
||||
// TypeMeta features-- kind, version, etc.
|
||||
// TODO: Make this object have easy access to field based accessors and settors for
|
||||
// metadata and field mutatation.
|
||||
//
|
||||
// +k8s:deepcopy-gen=true
|
||||
// +protobuf=true
|
||||
// +k8s:openapi-gen=true
|
||||
type Unknown struct {
|
||||
TypeMeta *TypeMeta `protobuf:"bytes,1,opt,name=typeMeta" json:"typeMeta,omitempty"`
|
||||
// Raw will hold the complete serialized object which couldn't be matched
|
||||
// with a registered type. Most likely, nothing should be done with this
|
||||
// except for passing it through the system.
|
||||
Raw []byte `protobuf:"bytes,2,opt,name=raw" json:"raw,omitempty"`
|
||||
// ContentEncoding is encoding used to encode 'Raw' data.
|
||||
// Unspecified means no encoding.
|
||||
ContentEncoding *string `protobuf:"bytes,3,opt,name=contentEncoding" json:"contentEncoding,omitempty"`
|
||||
// ContentType is serialization method used to serialize 'Raw'.
|
||||
// Unspecified means ContentTypeJSON.
|
||||
ContentType *string `protobuf:"bytes,4,opt,name=contentType" json:"contentType,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Unknown) Reset() { *m = Unknown{} }
|
||||
func (m *Unknown) String() string { return proto.CompactTextString(m) }
|
||||
func (*Unknown) ProtoMessage() {}
|
||||
func (*Unknown) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{2} }
|
||||
|
||||
func (m *Unknown) GetTypeMeta() *TypeMeta {
|
||||
if m != nil {
|
||||
return m.TypeMeta
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Unknown) GetRaw() []byte {
|
||||
if m != nil {
|
||||
return m.Raw
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Unknown) GetContentEncoding() string {
|
||||
if m != nil && m.ContentEncoding != nil {
|
||||
return *m.ContentEncoding
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Unknown) GetContentType() string {
|
||||
if m != nil && m.ContentType != nil {
|
||||
return *m.ContentType
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*RawExtension)(nil), "github.com/ericchiang.k8s.runtime.RawExtension")
|
||||
proto.RegisterType((*TypeMeta)(nil), "github.com/ericchiang.k8s.runtime.TypeMeta")
|
||||
proto.RegisterType((*Unknown)(nil), "github.com/ericchiang.k8s.runtime.Unknown")
|
||||
}
|
||||
func (m *RawExtension) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *RawExtension) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Raw != nil {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Raw)))
|
||||
i += copy(dAtA[i:], m.Raw)
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *TypeMeta) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *TypeMeta) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.ApiVersion != nil {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(*m.ApiVersion)))
|
||||
i += copy(dAtA[i:], *m.ApiVersion)
|
||||
}
|
||||
if m.Kind != nil {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(*m.Kind)))
|
||||
i += copy(dAtA[i:], *m.Kind)
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *Unknown) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Unknown) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.TypeMeta != nil {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(m.TypeMeta.Size()))
|
||||
n1, err := m.TypeMeta.MarshalTo(dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n1
|
||||
}
|
||||
if m.Raw != nil {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Raw)))
|
||||
i += copy(dAtA[i:], m.Raw)
|
||||
}
|
||||
if m.ContentEncoding != nil {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(*m.ContentEncoding)))
|
||||
i += copy(dAtA[i:], *m.ContentEncoding)
|
||||
}
|
||||
if m.ContentType != nil {
|
||||
dAtA[i] = 0x22
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(*m.ContentType)))
|
||||
i += copy(dAtA[i:], *m.ContentType)
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
dAtA[offset+2] = uint8(v >> 16)
|
||||
dAtA[offset+3] = uint8(v >> 24)
|
||||
dAtA[offset+4] = uint8(v >> 32)
|
||||
dAtA[offset+5] = uint8(v >> 40)
|
||||
dAtA[offset+6] = uint8(v >> 48)
|
||||
dAtA[offset+7] = uint8(v >> 56)
|
||||
return offset + 8
|
||||
}
|
||||
func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
dAtA[offset+2] = uint8(v >> 16)
|
||||
dAtA[offset+3] = uint8(v >> 24)
|
||||
return offset + 4
|
||||
}
|
||||
func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *RawExtension) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.Raw != nil {
|
||||
l = len(m.Raw)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *TypeMeta) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.ApiVersion != nil {
|
||||
l = len(*m.ApiVersion)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if m.Kind != nil {
|
||||
l = len(*m.Kind)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *Unknown) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.TypeMeta != nil {
|
||||
l = m.TypeMeta.Size()
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if m.Raw != nil {
|
||||
l = len(m.Raw)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if m.ContentEncoding != nil {
|
||||
l = len(*m.ContentEncoding)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if m.ContentType != nil {
|
||||
l = len(*m.ContentType)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovGenerated(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozGenerated(x uint64) (n int) {
|
||||
return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *RawExtension) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: RawExtension: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: RawExtension: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Raw", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Raw = append(m.Raw[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.Raw == nil {
|
||||
m.Raw = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *TypeMeta) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: TypeMeta: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: TypeMeta: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ApiVersion", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.ApiVersion = &s
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Kind", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Kind = &s
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Unknown) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Unknown: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Unknown: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field TypeMeta", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.TypeMeta == nil {
|
||||
m.TypeMeta = &TypeMeta{}
|
||||
}
|
||||
if err := m.TypeMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Raw", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Raw = append(m.Raw[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.Raw == nil {
|
||||
m.Raw = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ContentEncoding", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.ContentEncoding = &s
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ContentType", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.ContentType = &s
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipGenerated(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthGenerated
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipGenerated(dAtA[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/ericchiang/k8s/runtime/generated.proto", fileDescriptorGenerated)
|
||||
}
|
||||
|
||||
var fileDescriptorGenerated = []byte{
|
||||
// 275 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x7c, 0x8f, 0xc1, 0x4a, 0xc3, 0x40,
|
||||
0x10, 0x86, 0xdd, 0xb6, 0xd0, 0x3a, 0x2d, 0x28, 0x7b, 0x8a, 0x82, 0x21, 0xe4, 0x62, 0x2f, 0x6e,
|
||||
0xd0, 0x93, 0x27, 0x0f, 0x4a, 0x8f, 0x5e, 0x82, 0x7a, 0xf0, 0x16, 0x9b, 0x21, 0x2c, 0xab, 0xb3,
|
||||
0x61, 0x33, 0x21, 0xfa, 0x26, 0x3e, 0x84, 0x0f, 0xe2, 0xd1, 0x47, 0x90, 0xf8, 0x22, 0x92, 0x35,
|
||||
0xad, 0xa5, 0x88, 0xb7, 0xe1, 0xdf, 0x6f, 0xfe, 0xfd, 0x06, 0x4e, 0xcc, 0x79, 0xa5, 0xb4, 0x4d,
|
||||
0x4c, 0xfd, 0x80, 0x8e, 0x90, 0xb1, 0x4a, 0x4a, 0x53, 0x24, 0xae, 0x26, 0xd6, 0x4f, 0x98, 0x14,
|
||||
0x48, 0xe8, 0x32, 0xc6, 0x5c, 0x95, 0xce, 0xb2, 0x95, 0x47, 0x3f, 0xb8, 0xfa, 0xc5, 0x55, 0x69,
|
||||
0x0a, 0xd5, 0xe3, 0x87, 0xa7, 0x7f, 0xb7, 0xd5, 0xac, 0x1f, 0x13, 0x4d, 0x5c, 0xb1, 0xdb, 0x6e,
|
||||
0x8c, 0x23, 0x98, 0xa5, 0x59, 0xb3, 0x78, 0x66, 0xa4, 0x4a, 0x5b, 0x92, 0xfb, 0x30, 0x74, 0x59,
|
||||
0x13, 0x88, 0x48, 0xcc, 0x67, 0x69, 0x37, 0xc6, 0x17, 0x30, 0xb9, 0x79, 0x29, 0xf1, 0x1a, 0x39,
|
||||
0x93, 0x21, 0x40, 0x56, 0xea, 0x3b, 0x74, 0x1d, 0xeb, 0xa1, 0xdd, 0x74, 0x23, 0x91, 0x12, 0x46,
|
||||
0x46, 0x53, 0x1e, 0x0c, 0xfc, 0x8b, 0x9f, 0xe3, 0x37, 0x01, 0xe3, 0x5b, 0x32, 0x64, 0x1b, 0x92,
|
||||
0x57, 0x30, 0xe1, 0xbe, 0xcb, 0x6f, 0x4f, 0xcf, 0x8e, 0xd5, 0xbf, 0x27, 0xa9, 0xd5, 0xd7, 0xe9,
|
||||
0x7a, 0x71, 0xa5, 0x38, 0x58, 0x2b, 0xca, 0x39, 0xec, 0x2d, 0x2d, 0x31, 0x12, 0x2f, 0x68, 0x69,
|
||||
0x73, 0x4d, 0x45, 0x30, 0xf4, 0x06, 0xdb, 0xb1, 0x8c, 0x60, 0xda, 0x47, 0x5d, 0x71, 0x30, 0xf2,
|
||||
0xd4, 0x66, 0x74, 0x79, 0xf0, 0xde, 0x86, 0xe2, 0xa3, 0x0d, 0xc5, 0x67, 0x1b, 0x8a, 0xd7, 0xaf,
|
||||
0x70, 0xe7, 0x7e, 0xdc, 0xbb, 0x7c, 0x07, 0x00, 0x00, 0xff, 0xff, 0x56, 0xe9, 0xf9, 0xae, 0xad,
|
||||
0x01, 0x00, 0x00,
|
||||
}
|
46
vendor/github.com/ericchiang/k8s/runtime/schema/generated.pb.go
generated
vendored
46
vendor/github.com/ericchiang/k8s/runtime/schema/generated.pb.go
generated
vendored
|
@ -1,46 +0,0 @@
|
|||
// Code generated by protoc-gen-gogo.
|
||||
// source: k8s.io/kubernetes/pkg/runtime/schema/generated.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package schema is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
k8s.io/kubernetes/pkg/runtime/schema/generated.proto
|
||||
|
||||
It has these top-level messages:
|
||||
*/
|
||||
package schema
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import _ "github.com/ericchiang/k8s/util/intstr"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/ericchiang/k8s/runtime/schema/generated.proto", fileDescriptorGenerated)
|
||||
}
|
||||
|
||||
var fileDescriptorGenerated = []byte{
|
||||
// 136 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x32, 0xc9, 0xb6, 0x28, 0xd6,
|
||||
0xcb, 0xcc, 0xd7, 0xcf, 0x2e, 0x4d, 0x4a, 0x2d, 0xca, 0x4b, 0x2d, 0x49, 0x2d, 0xd6, 0x2f, 0xc8,
|
||||
0x4e, 0xd7, 0x2f, 0x2a, 0xcd, 0x2b, 0xc9, 0xcc, 0x4d, 0xd5, 0x2f, 0x4e, 0xce, 0x48, 0xcd, 0x4d,
|
||||
0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0x4a, 0x2c, 0x49, 0x4d, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9,
|
||||
0x17, 0x52, 0x81, 0xe8, 0xd2, 0x43, 0xe8, 0xd2, 0x2b, 0xc8, 0x4e, 0xd7, 0x83, 0xea, 0xd2, 0x83,
|
||||
0xe8, 0x92, 0x32, 0xc4, 0x6e, 0x76, 0x69, 0x49, 0x66, 0x8e, 0x7e, 0x66, 0x5e, 0x49, 0x71, 0x49,
|
||||
0x11, 0xba, 0xc1, 0x4e, 0x12, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91,
|
||||
0x1c, 0xe3, 0x8c, 0xc7, 0x72, 0x0c, 0x51, 0x6c, 0x10, 0xc3, 0x00, 0x01, 0x00, 0x00, 0xff, 0xff,
|
||||
0xea, 0x33, 0x0e, 0xbb, 0xa9, 0x00, 0x00, 0x00,
|
||||
}
|
166
vendor/github.com/ericchiang/k8s/tprs.go
generated
vendored
166
vendor/github.com/ericchiang/k8s/tprs.go
generated
vendored
|
@ -1,166 +0,0 @@
|
|||
package k8s
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/ericchiang/k8s/api/v1"
|
||||
metav1 "github.com/ericchiang/k8s/apis/meta/v1"
|
||||
)
|
||||
|
||||
// ThirdPartyResources is a client used for interacting with user
|
||||
// defined API groups. It uses JSON encoding instead of protobufs
|
||||
// which are unsupported for these APIs.
|
||||
//
|
||||
// Users are expected to define their own third party resources.
|
||||
//
|
||||
// const metricsResource = "metrics"
|
||||
//
|
||||
// // First, define a third party resources with TypeMeta
|
||||
// // and ObjectMeta fields.
|
||||
// type Metric struct {
|
||||
// *unversioned.TypeMeta `json:",inline"`
|
||||
// *v1.ObjectMeta `json:"metadata,omitempty"`
|
||||
//
|
||||
// Timestamp time.Time `json:"timestamp"`
|
||||
// Value []byte `json:"value"`
|
||||
// }
|
||||
//
|
||||
// // Define a list wrapper.
|
||||
// type MetricsList struct {
|
||||
// *unversioned.TypeMeta `json:",inline"`
|
||||
// *unversioned.ListMeta `json:"metadata,omitempty"`
|
||||
//
|
||||
// Items []Metric `json:"items"`
|
||||
// }
|
||||
//
|
||||
// Register the new resource by creating a ThirdPartyResource type.
|
||||
//
|
||||
// // Create a ThirdPartyResource
|
||||
// tpr := &v1beta1.ThirdPartyResource{
|
||||
// Metadata: &v1.ObjectMeta{
|
||||
// Name: k8s.String("metric.metrics.example.com"),
|
||||
// },
|
||||
// Description: k8s.String("A custom third party resource"),
|
||||
// Versions: []*v1beta1.APIVersion{
|
||||
// {Name: k8s.String("v1")},
|
||||
// },
|
||||
// }
|
||||
// _, err := client.ExtensionsV1Beta1().CreateThirdPartyResource(ctx, trp)
|
||||
// if err != nil {
|
||||
// // handle error
|
||||
// }
|
||||
//
|
||||
// After creating the resource type, create a ThirdPartyResources client then
|
||||
// use interact with it like any other API group. For example to create a third
|
||||
// party resource:
|
||||
//
|
||||
// metricsClient := client.ThirdPartyResources("metrics.example.com", "v1")
|
||||
//
|
||||
// metric := &Metric{
|
||||
// ObjectMeta: &v1.ObjectMeta{
|
||||
// Name: k8s.String("foo"),
|
||||
// },
|
||||
// Timestamp: time.Now(),
|
||||
// Value: 42,
|
||||
// }
|
||||
//
|
||||
// err = metricsClient.Create(ctx, metricsResource, client.Namespace, metric, metric)
|
||||
// if err != nil {
|
||||
// // handle error
|
||||
// }
|
||||
//
|
||||
// List a set of third party resources:
|
||||
//
|
||||
// var metrics MetricsList
|
||||
// metricsClient.List(ctx, metricsResource, &metrics)
|
||||
//
|
||||
// Or delete:
|
||||
//
|
||||
// tprClient.Delete(ctx, metricsResource, client.Namespace, *metric.Name)
|
||||
//
|
||||
type ThirdPartyResources struct {
|
||||
c *Client
|
||||
|
||||
apiGroup string
|
||||
apiVersion string
|
||||
}
|
||||
|
||||
// ThirdPartyResources returns a client for interacting with a ThirdPartyResource
|
||||
// API group.
|
||||
func (c *Client) ThirdPartyResources(apiGroup, apiVersion string) *ThirdPartyResources {
|
||||
return &ThirdPartyResources{c, apiGroup, apiVersion}
|
||||
}
|
||||
|
||||
func checkResource(apiGroup, apiVersion, resource, namespace, name string) error {
|
||||
if apiGroup == "" {
|
||||
return errors.New("no api group provided")
|
||||
}
|
||||
if apiVersion == "" {
|
||||
return errors.New("no api version provided")
|
||||
}
|
||||
if resource == "" {
|
||||
return errors.New("no resource version provided")
|
||||
}
|
||||
if namespace == "" {
|
||||
return errors.New("no namespace provided")
|
||||
}
|
||||
if name == "" {
|
||||
return errors.New("no resource name provided")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// object and after16Object are used by go/types to detect types that are likely
|
||||
// to be Kubernetes resources. Types that implement this resources are likely
|
||||
// resource.
|
||||
//
|
||||
// They're defined here but only used in gen.go.
|
||||
type object interface {
|
||||
GetMetadata() *v1.ObjectMeta
|
||||
}
|
||||
|
||||
// after16Object uses the new ObjectMeta's home.
|
||||
type after16Object interface {
|
||||
GetMetadata() *metav1.ObjectMeta
|
||||
}
|
||||
|
||||
func (t *ThirdPartyResources) Create(ctx context.Context, resource, namespace string, req, resp interface{}) error {
|
||||
if err := checkResource(t.apiGroup, t.apiVersion, resource, namespace, "not required"); err != nil {
|
||||
return err
|
||||
}
|
||||
url := t.c.urlFor(t.apiGroup, t.apiVersion, namespace, resource, "")
|
||||
return t.c.create(ctx, jsonCodec, "POST", url, req, resp)
|
||||
}
|
||||
|
||||
func (t *ThirdPartyResources) Update(ctx context.Context, resource, namespace, name string, req, resp interface{}) error {
|
||||
if err := checkResource(t.apiGroup, t.apiVersion, resource, namespace, "not required"); err != nil {
|
||||
return err
|
||||
}
|
||||
url := t.c.urlFor(t.apiGroup, t.apiVersion, namespace, resource, name)
|
||||
return t.c.create(ctx, jsonCodec, "PUT", url, req, resp)
|
||||
}
|
||||
|
||||
func (t *ThirdPartyResources) Get(ctx context.Context, resource, namespace, name string, resp interface{}) error {
|
||||
if err := checkResource(t.apiGroup, t.apiVersion, resource, namespace, name); err != nil {
|
||||
return err
|
||||
}
|
||||
url := t.c.urlFor(t.apiGroup, t.apiVersion, namespace, resource, name)
|
||||
return t.c.get(ctx, jsonCodec, url, resp)
|
||||
}
|
||||
|
||||
func (t *ThirdPartyResources) Delete(ctx context.Context, resource, namespace, name string) error {
|
||||
if err := checkResource(t.apiGroup, t.apiVersion, resource, namespace, name); err != nil {
|
||||
return err
|
||||
}
|
||||
url := t.c.urlFor(t.apiGroup, t.apiVersion, namespace, resource, name)
|
||||
return t.c.delete(ctx, jsonCodec, url)
|
||||
}
|
||||
|
||||
func (t *ThirdPartyResources) List(ctx context.Context, resource, namespace string, resp interface{}) error {
|
||||
if err := checkResource(t.apiGroup, t.apiVersion, resource, namespace, "name not required"); err != nil {
|
||||
return err
|
||||
}
|
||||
url := t.c.urlFor(t.apiGroup, t.apiVersion, namespace, resource, "")
|
||||
return t.c.get(ctx, jsonCodec, url, resp)
|
||||
}
|
74
vendor/github.com/ericchiang/k8s/tprs_test.go
generated
vendored
74
vendor/github.com/ericchiang/k8s/tprs_test.go
generated
vendored
|
@ -1,74 +0,0 @@
|
|||
package k8s
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ericchiang/k8s/api/unversioned"
|
||||
"github.com/ericchiang/k8s/apis/extensions/v1beta1"
|
||||
metav1 "github.com/ericchiang/k8s/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestTPRs(t *testing.T) {
|
||||
client := newTestClient(t)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
type Metric struct {
|
||||
*unversioned.TypeMeta `json:",inline"`
|
||||
*metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Value int64 `json:"value"`
|
||||
}
|
||||
|
||||
type MetricsList struct {
|
||||
*unversioned.TypeMeta `json:",inline"`
|
||||
*unversioned.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
Items []Metric `json:"items"`
|
||||
}
|
||||
|
||||
// Create a ThirdPartyResource
|
||||
tpr := &v1beta1.ThirdPartyResource{
|
||||
Metadata: &metav1.ObjectMeta{
|
||||
Name: String("metric.example.com"),
|
||||
},
|
||||
Description: String("A value and a timestamp"),
|
||||
Versions: []*v1beta1.APIVersion{
|
||||
{Name: String("v1")},
|
||||
},
|
||||
}
|
||||
_, err := client.ExtensionsV1Beta1().CreateThirdPartyResource(ctx, tpr)
|
||||
if err != nil {
|
||||
if apiErr, ok := err.(*APIError); !ok || apiErr.Code != http.StatusConflict {
|
||||
t.Fatalf("create third party resource: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
metric := &Metric{
|
||||
ObjectMeta: &metav1.ObjectMeta{
|
||||
Name: String("foo"),
|
||||
},
|
||||
Timestamp: time.Now(),
|
||||
Value: 42,
|
||||
}
|
||||
|
||||
myClient := client.ThirdPartyResources("example.com", "v1")
|
||||
err = myClient.Create(ctx, "metrics", "default", metric, metric)
|
||||
if err != nil {
|
||||
t.Errorf("create third party resource: %v", err)
|
||||
}
|
||||
|
||||
var metrics MetricsList
|
||||
if err := myClient.List(ctx, "metrics", "default", &metrics); err != nil {
|
||||
t.Errorf("list third party resource: %v", err)
|
||||
}
|
||||
|
||||
if err := myClient.Delete(ctx, "metrics", "default", "foo"); err != nil {
|
||||
t.Fatalf("delete tpr: %v", err)
|
||||
}
|
||||
}
|
7091
vendor/github.com/ericchiang/k8s/types.go
generated
vendored
7091
vendor/github.com/ericchiang/k8s/types.go
generated
vendored
File diff suppressed because it is too large
Load diff
418
vendor/github.com/ericchiang/k8s/util/intstr/generated.pb.go
generated
vendored
418
vendor/github.com/ericchiang/k8s/util/intstr/generated.pb.go
generated
vendored
|
@ -1,418 +0,0 @@
|
|||
// Code generated by protoc-gen-gogo.
|
||||
// source: k8s.io/kubernetes/pkg/util/intstr/generated.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package intstr is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
k8s.io/kubernetes/pkg/util/intstr/generated.proto
|
||||
|
||||
It has these top-level messages:
|
||||
IntOrString
|
||||
*/
|
||||
package intstr
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// IntOrString is a type that can hold an int32 or a string. When used in
|
||||
// JSON or YAML marshalling and unmarshalling, it produces or consumes the
|
||||
// inner type. This allows you to have, for example, a JSON field that can
|
||||
// accept a name or number.
|
||||
// TODO: Rename to Int32OrString
|
||||
//
|
||||
// +protobuf=true
|
||||
// +protobuf.options.(gogoproto.goproto_stringer)=false
|
||||
// +k8s:openapi-gen=true
|
||||
type IntOrString struct {
|
||||
Type *int64 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"`
|
||||
IntVal *int32 `protobuf:"varint,2,opt,name=intVal" json:"intVal,omitempty"`
|
||||
StrVal *string `protobuf:"bytes,3,opt,name=strVal" json:"strVal,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *IntOrString) Reset() { *m = IntOrString{} }
|
||||
func (m *IntOrString) String() string { return proto.CompactTextString(m) }
|
||||
func (*IntOrString) ProtoMessage() {}
|
||||
func (*IntOrString) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} }
|
||||
|
||||
func (m *IntOrString) GetType() int64 {
|
||||
if m != nil && m.Type != nil {
|
||||
return *m.Type
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *IntOrString) GetIntVal() int32 {
|
||||
if m != nil && m.IntVal != nil {
|
||||
return *m.IntVal
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *IntOrString) GetStrVal() string {
|
||||
if m != nil && m.StrVal != nil {
|
||||
return *m.StrVal
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*IntOrString)(nil), "github.com/ericchiang.k8s.util.intstr.IntOrString")
|
||||
}
|
||||
func (m *IntOrString) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *IntOrString) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Type != nil {
|
||||
dAtA[i] = 0x8
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(*m.Type))
|
||||
}
|
||||
if m.IntVal != nil {
|
||||
dAtA[i] = 0x10
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(*m.IntVal))
|
||||
}
|
||||
if m.StrVal != nil {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(*m.StrVal)))
|
||||
i += copy(dAtA[i:], *m.StrVal)
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
dAtA[offset+2] = uint8(v >> 16)
|
||||
dAtA[offset+3] = uint8(v >> 24)
|
||||
dAtA[offset+4] = uint8(v >> 32)
|
||||
dAtA[offset+5] = uint8(v >> 40)
|
||||
dAtA[offset+6] = uint8(v >> 48)
|
||||
dAtA[offset+7] = uint8(v >> 56)
|
||||
return offset + 8
|
||||
}
|
||||
func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
dAtA[offset+2] = uint8(v >> 16)
|
||||
dAtA[offset+3] = uint8(v >> 24)
|
||||
return offset + 4
|
||||
}
|
||||
func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *IntOrString) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.Type != nil {
|
||||
n += 1 + sovGenerated(uint64(*m.Type))
|
||||
}
|
||||
if m.IntVal != nil {
|
||||
n += 1 + sovGenerated(uint64(*m.IntVal))
|
||||
}
|
||||
if m.StrVal != nil {
|
||||
l = len(*m.StrVal)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovGenerated(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozGenerated(x uint64) (n int) {
|
||||
return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *IntOrString) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: IntOrString: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: IntOrString: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
|
||||
}
|
||||
var v int64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= (int64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Type = &v
|
||||
case 2:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field IntVal", wireType)
|
||||
}
|
||||
var v int32
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= (int32(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.IntVal = &v
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field StrVal", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.StrVal = &s
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipGenerated(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthGenerated
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipGenerated(dAtA[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/ericchiang/k8s/util/intstr/generated.proto", fileDescriptorGenerated)
|
||||
}
|
||||
|
||||
var fileDescriptorGenerated = []byte{
|
||||
// 180 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x32, 0xcc, 0xb6, 0x28, 0xd6,
|
||||
0xcb, 0xcc, 0xd7, 0xcf, 0x2e, 0x4d, 0x4a, 0x2d, 0xca, 0x4b, 0x2d, 0x49, 0x2d, 0xd6, 0x2f, 0xc8,
|
||||
0x4e, 0xd7, 0x2f, 0x2d, 0xc9, 0xcc, 0xd1, 0xcf, 0xcc, 0x2b, 0x29, 0x2e, 0x29, 0xd2, 0x4f, 0x4f,
|
||||
0xcd, 0x4b, 0x2d, 0x4a, 0x2c, 0x49, 0x4d, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0x84,
|
||||
0x68, 0xd1, 0x43, 0x68, 0xd1, 0x2b, 0xc8, 0x4e, 0xd7, 0x03, 0x69, 0xd1, 0x83, 0x68, 0x51, 0x0a,
|
||||
0xe4, 0xe2, 0xf6, 0xcc, 0x2b, 0xf1, 0x2f, 0x0a, 0x2e, 0x29, 0xca, 0xcc, 0x4b, 0x17, 0x12, 0xe2,
|
||||
0x62, 0x29, 0xa9, 0x2c, 0x48, 0x95, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x0e, 0x02, 0xb3, 0x85, 0xc4,
|
||||
0xb8, 0xd8, 0x32, 0xf3, 0x4a, 0xc2, 0x12, 0x73, 0x24, 0x98, 0x14, 0x18, 0x35, 0x58, 0x83, 0xa0,
|
||||
0x3c, 0x90, 0x78, 0x71, 0x49, 0x11, 0x48, 0x9c, 0x59, 0x81, 0x51, 0x83, 0x33, 0x08, 0xca, 0x73,
|
||||
0x92, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x67, 0x3c,
|
||||
0x96, 0x63, 0x88, 0x62, 0x83, 0x58, 0x06, 0x08, 0x00, 0x00, 0xff, 0xff, 0xcd, 0x20, 0xf2, 0x02,
|
||||
0xc3, 0x00, 0x00, 0x00,
|
||||
}
|
405
vendor/github.com/ericchiang/k8s/watch/versioned/generated.pb.go
generated
vendored
405
vendor/github.com/ericchiang/k8s/watch/versioned/generated.pb.go
generated
vendored
|
@ -1,405 +0,0 @@
|
|||
// Code generated by protoc-gen-gogo.
|
||||
// source: k8s.io/kubernetes/pkg/watch/versioned/generated.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package versioned is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
k8s.io/kubernetes/pkg/watch/versioned/generated.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Event
|
||||
*/
|
||||
package versioned
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import k8s_io_kubernetes_pkg_runtime "github.com/ericchiang/k8s/runtime"
|
||||
import _ "github.com/ericchiang/k8s/util/intstr"
|
||||
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// Event represents a single event to a watched resource.
|
||||
//
|
||||
// +protobuf=true
|
||||
// +k8s:openapi-gen=true
|
||||
type Event struct {
|
||||
Type *string `protobuf:"bytes,1,opt,name=type" json:"type,omitempty"`
|
||||
// Object is:
|
||||
// * If Type is Added or Modified: the new state of the object.
|
||||
// * If Type is Deleted: the state of the object immediately before deletion.
|
||||
// * If Type is Error: *api.Status is recommended; other types may make sense
|
||||
// depending on context.
|
||||
Object *k8s_io_kubernetes_pkg_runtime.RawExtension `protobuf:"bytes,2,opt,name=object" json:"object,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Event) Reset() { *m = Event{} }
|
||||
func (m *Event) String() string { return proto.CompactTextString(m) }
|
||||
func (*Event) ProtoMessage() {}
|
||||
func (*Event) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} }
|
||||
|
||||
func (m *Event) GetType() string {
|
||||
if m != nil && m.Type != nil {
|
||||
return *m.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Event) GetObject() *k8s_io_kubernetes_pkg_runtime.RawExtension {
|
||||
if m != nil {
|
||||
return m.Object
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Event)(nil), "github.com/ericchiang.k8s.watch.versioned.Event")
|
||||
}
|
||||
func (m *Event) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Event) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Type != nil {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(*m.Type)))
|
||||
i += copy(dAtA[i:], *m.Type)
|
||||
}
|
||||
if m.Object != nil {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(m.Object.Size()))
|
||||
n1, err := m.Object.MarshalTo(dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n1
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
dAtA[offset+2] = uint8(v >> 16)
|
||||
dAtA[offset+3] = uint8(v >> 24)
|
||||
dAtA[offset+4] = uint8(v >> 32)
|
||||
dAtA[offset+5] = uint8(v >> 40)
|
||||
dAtA[offset+6] = uint8(v >> 48)
|
||||
dAtA[offset+7] = uint8(v >> 56)
|
||||
return offset + 8
|
||||
}
|
||||
func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
dAtA[offset+2] = uint8(v >> 16)
|
||||
dAtA[offset+3] = uint8(v >> 24)
|
||||
return offset + 4
|
||||
}
|
||||
func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *Event) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.Type != nil {
|
||||
l = len(*m.Type)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if m.Object != nil {
|
||||
l = m.Object.Size()
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovGenerated(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozGenerated(x uint64) (n int) {
|
||||
return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *Event) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Event: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Event: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.Type = &s
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Object", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Object == nil {
|
||||
m.Object = &k8s_io_kubernetes_pkg_runtime.RawExtension{}
|
||||
}
|
||||
if err := m.Object.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipGenerated(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthGenerated
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipGenerated(dAtA[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("github.com/ericchiang/k8s/watch/versioned/generated.proto", fileDescriptorGenerated)
|
||||
}
|
||||
|
||||
var fileDescriptorGenerated = []byte{
|
||||
// 214 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x32, 0xcd, 0xb6, 0x28, 0xd6,
|
||||
0xcb, 0xcc, 0xd7, 0xcf, 0x2e, 0x4d, 0x4a, 0x2d, 0xca, 0x4b, 0x2d, 0x49, 0x2d, 0xd6, 0x2f, 0xc8,
|
||||
0x4e, 0xd7, 0x2f, 0x4f, 0x2c, 0x49, 0xce, 0xd0, 0x2f, 0x4b, 0x2d, 0x2a, 0xce, 0xcc, 0xcf, 0x4b,
|
||||
0x4d, 0xd1, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0x4a, 0x2c, 0x49, 0x4d, 0xd1, 0x2b, 0x28, 0xca, 0x2f,
|
||||
0xc9, 0x17, 0x52, 0x85, 0x68, 0xd3, 0x43, 0x68, 0xd3, 0x2b, 0xc8, 0x4e, 0xd7, 0x03, 0x6b, 0xd3,
|
||||
0x83, 0x6b, 0x93, 0xd2, 0xc5, 0x6e, 0x7a, 0x51, 0x69, 0x5e, 0x49, 0x66, 0x6e, 0x2a, 0xba, 0xa9,
|
||||
0x52, 0x86, 0xd8, 0x95, 0x97, 0x96, 0x64, 0xe6, 0xe8, 0x67, 0xe6, 0x95, 0x14, 0x97, 0x14, 0xa1,
|
||||
0x6b, 0x51, 0x4a, 0xe0, 0x62, 0x75, 0x2d, 0x4b, 0xcd, 0x2b, 0x11, 0x12, 0xe2, 0x62, 0x29, 0xa9,
|
||||
0x2c, 0x48, 0x95, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0xb3, 0x85, 0x9c, 0xb9, 0xd8, 0xf2,
|
||||
0x93, 0xb2, 0x52, 0x93, 0x4b, 0x24, 0x98, 0x14, 0x18, 0x35, 0xb8, 0x8d, 0xb4, 0xf5, 0xb0, 0x3b,
|
||||
0x1b, 0xea, 0x1e, 0xbd, 0xa0, 0xc4, 0x72, 0xd7, 0x8a, 0x92, 0xd4, 0x3c, 0x90, 0xeb, 0x83, 0xa0,
|
||||
0x5a, 0x9d, 0xa4, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6,
|
||||
0x19, 0x8f, 0xe5, 0x18, 0xa2, 0x38, 0xe1, 0x1e, 0x04, 0x04, 0x00, 0x00, 0xff, 0xff, 0xb4, 0x05,
|
||||
0x8c, 0x51, 0x3f, 0x01, 0x00, 0x00,
|
||||
}
|
6
vendor/github.com/kylelemons/godebug/.travis.yml
generated
vendored
Normal file
6
vendor/github.com/kylelemons/godebug/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.7
|
||||
- 1.8
|
||||
- tip
|
64
vendor/github.com/kylelemons/godebug/README.md
generated
vendored
Normal file
64
vendor/github.com/kylelemons/godebug/README.md
generated
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
Pretty Printing for Go
|
||||
======================
|
||||
|
||||
[![godebug build status][ciimg]][ci]
|
||||
|
||||
Have you ever wanted to get a pretty-printed version of a Go data structure,
|
||||
complete with indentation? I have found this especially useful in unit tests
|
||||
and in debugging my code, and thus godebug was born!
|
||||
|
||||
[ciimg]: https://travis-ci.org/kylelemons/godebug.svg?branch=master
|
||||
[ci]: https://travis-ci.org/kylelemons/godebug
|
||||
|
||||
Quick Examples
|
||||
--------------
|
||||
|
||||
By default, pretty will write out a very compact representation of a data structure.
|
||||
From the [Print example][printex]:
|
||||
|
||||
```
|
||||
{Name: "Spaceship Heart of Gold",
|
||||
Crew: {Arthur Dent: "Along for the Ride",
|
||||
Ford Prefect: "A Hoopy Frood",
|
||||
Trillian: "Human",
|
||||
Zaphod Beeblebrox: "Galactic President"},
|
||||
Androids: 1,
|
||||
Stolen: true}
|
||||
```
|
||||
|
||||
It can also produce a much more verbose, one-item-per-line representation suitable for
|
||||
[computing diffs][diffex]. See the documentation for more examples and customization.
|
||||
|
||||
[printex]: https://godoc.org/github.com/kylelemons/godebug/pretty#example-Print
|
||||
[diffex]: https://godoc.org/github.com/kylelemons/godebug/pretty#example-Compare
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
Documentation for this package is available at [godoc.org][doc]:
|
||||
|
||||
* Pretty: [![godoc for godebug/pretty][prettyimg]][prettydoc]
|
||||
* Diff: [![godoc for godebug/diff][diffimg]][diffdoc]
|
||||
|
||||
[doc]: https://godoc.org/
|
||||
[prettyimg]: https://godoc.org/github.com/kylelemons/godebug/pretty?status.png
|
||||
[prettydoc]: https://godoc.org/github.com/kylelemons/godebug/pretty
|
||||
[diffimg]: https://godoc.org/github.com/kylelemons/godebug/diff?status.png
|
||||
[diffdoc]: https://godoc.org/github.com/kylelemons/godebug/diff
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
These packages are available via `go get`:
|
||||
|
||||
```bash
|
||||
$ go get -u github.com/kylelemons/godebug/{pretty,diff}
|
||||
```
|
||||
|
||||
Other Packages
|
||||
--------------
|
||||
|
||||
If `godebug/pretty` is not granular enough, I highly recommend
|
||||
checking out [go-spew][spew].
|
||||
|
||||
[spew]: http://godoc.org/github.com/davecgh/go-spew/spew
|
186
vendor/github.com/kylelemons/godebug/diff/diff.go
generated
vendored
Normal file
186
vendor/github.com/kylelemons/godebug/diff/diff.go
generated
vendored
Normal file
|
@ -0,0 +1,186 @@
|
|||
// Copyright 2013 Google Inc. All rights reserved.
|
||||
//
|
||||
// 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 diff implements a linewise diff algorithm.
|
||||
package diff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Chunk represents a piece of the diff. A chunk will not have both added and
|
||||
// deleted lines. Equal lines are always after any added or deleted lines.
|
||||
// A Chunk may or may not have any lines in it, especially for the first or last
|
||||
// chunk in a computation.
|
||||
type Chunk struct {
|
||||
Added []string
|
||||
Deleted []string
|
||||
Equal []string
|
||||
}
|
||||
|
||||
func (c *Chunk) empty() bool {
|
||||
return len(c.Added) == 0 && len(c.Deleted) == 0 && len(c.Equal) == 0
|
||||
}
|
||||
|
||||
// Diff returns a string containing a line-by-line unified diff of the linewise
|
||||
// changes required to make A into B. Each line is prefixed with '+', '-', or
|
||||
// ' ' to indicate if it should be added, removed, or is correct respectively.
|
||||
func Diff(A, B string) string {
|
||||
aLines := strings.Split(A, "\n")
|
||||
bLines := strings.Split(B, "\n")
|
||||
|
||||
chunks := DiffChunks(aLines, bLines)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
for _, c := range chunks {
|
||||
for _, line := range c.Added {
|
||||
fmt.Fprintf(buf, "+%s\n", line)
|
||||
}
|
||||
for _, line := range c.Deleted {
|
||||
fmt.Fprintf(buf, "-%s\n", line)
|
||||
}
|
||||
for _, line := range c.Equal {
|
||||
fmt.Fprintf(buf, " %s\n", line)
|
||||
}
|
||||
}
|
||||
return strings.TrimRight(buf.String(), "\n")
|
||||
}
|
||||
|
||||
// DiffChunks uses an O(D(N+M)) shortest-edit-script algorithm
|
||||
// to compute the edits required from A to B and returns the
|
||||
// edit chunks.
|
||||
func DiffChunks(a, b []string) []Chunk {
|
||||
// algorithm: http://www.xmailserver.org/diff2.pdf
|
||||
|
||||
// We'll need these quantities a lot.
|
||||
alen, blen := len(a), len(b) // M, N
|
||||
|
||||
// At most, it will require len(a) deletions and len(b) additions
|
||||
// to transform a into b.
|
||||
maxPath := alen + blen // MAX
|
||||
if maxPath == 0 {
|
||||
// degenerate case: two empty lists are the same
|
||||
return nil
|
||||
}
|
||||
|
||||
// Store the endpoint of the path for diagonals.
|
||||
// We store only the a index, because the b index on any diagonal
|
||||
// (which we know during the loop below) is aidx-diag.
|
||||
// endpoint[maxPath] represents the 0 diagonal.
|
||||
//
|
||||
// Stated differently:
|
||||
// endpoint[d] contains the aidx of a furthest reaching path in diagonal d
|
||||
endpoint := make([]int, 2*maxPath+1) // V
|
||||
|
||||
saved := make([][]int, 0, 8) // Vs
|
||||
save := func() {
|
||||
dup := make([]int, len(endpoint))
|
||||
copy(dup, endpoint)
|
||||
saved = append(saved, dup)
|
||||
}
|
||||
|
||||
var editDistance int // D
|
||||
dLoop:
|
||||
for editDistance = 0; editDistance <= maxPath; editDistance++ {
|
||||
// The 0 diag(onal) represents equality of a and b. Each diagonal to
|
||||
// the left is numbered one lower, to the right is one higher, from
|
||||
// -alen to +blen. Negative diagonals favor differences from a,
|
||||
// positive diagonals favor differences from b. The edit distance to a
|
||||
// diagonal d cannot be shorter than d itself.
|
||||
//
|
||||
// The iterations of this loop cover either odds or evens, but not both,
|
||||
// If odd indices are inputs, even indices are outputs and vice versa.
|
||||
for diag := -editDistance; diag <= editDistance; diag += 2 { // k
|
||||
var aidx int // x
|
||||
switch {
|
||||
case diag == -editDistance:
|
||||
// This is a new diagonal; copy from previous iter
|
||||
aidx = endpoint[maxPath-editDistance+1] + 0
|
||||
case diag == editDistance:
|
||||
// This is a new diagonal; copy from previous iter
|
||||
aidx = endpoint[maxPath+editDistance-1] + 1
|
||||
case endpoint[maxPath+diag+1] > endpoint[maxPath+diag-1]:
|
||||
// diagonal d+1 was farther along, so use that
|
||||
aidx = endpoint[maxPath+diag+1] + 0
|
||||
default:
|
||||
// diagonal d-1 was farther (or the same), so use that
|
||||
aidx = endpoint[maxPath+diag-1] + 1
|
||||
}
|
||||
// On diagonal d, we can compute bidx from aidx.
|
||||
bidx := aidx - diag // y
|
||||
// See how far we can go on this diagonal before we find a difference.
|
||||
for aidx < alen && bidx < blen && a[aidx] == b[bidx] {
|
||||
aidx++
|
||||
bidx++
|
||||
}
|
||||
// Store the end of the current edit chain.
|
||||
endpoint[maxPath+diag] = aidx
|
||||
// If we've found the end of both inputs, we're done!
|
||||
if aidx >= alen && bidx >= blen {
|
||||
save() // save the final path
|
||||
break dLoop
|
||||
}
|
||||
}
|
||||
save() // save the current path
|
||||
}
|
||||
if editDistance == 0 {
|
||||
return nil
|
||||
}
|
||||
chunks := make([]Chunk, editDistance+1)
|
||||
|
||||
x, y := alen, blen
|
||||
for d := editDistance; d > 0; d-- {
|
||||
endpoint := saved[d]
|
||||
diag := x - y
|
||||
insert := diag == -d || (diag != d && endpoint[maxPath+diag-1] < endpoint[maxPath+diag+1])
|
||||
|
||||
x1 := endpoint[maxPath+diag]
|
||||
var x0, xM, kk int
|
||||
if insert {
|
||||
kk = diag + 1
|
||||
x0 = endpoint[maxPath+kk]
|
||||
xM = x0
|
||||
} else {
|
||||
kk = diag - 1
|
||||
x0 = endpoint[maxPath+kk]
|
||||
xM = x0 + 1
|
||||
}
|
||||
y0 := x0 - kk
|
||||
|
||||
var c Chunk
|
||||
if insert {
|
||||
c.Added = b[y0:][:1]
|
||||
} else {
|
||||
c.Deleted = a[x0:][:1]
|
||||
}
|
||||
if xM < x1 {
|
||||
c.Equal = a[xM:][:x1-xM]
|
||||
}
|
||||
|
||||
x, y = x0, y0
|
||||
chunks[d] = c
|
||||
}
|
||||
if x > 0 {
|
||||
chunks[0].Equal = a[:x]
|
||||
}
|
||||
if chunks[0].empty() {
|
||||
chunks = chunks[1:]
|
||||
}
|
||||
if len(chunks) == 0 {
|
||||
return nil
|
||||
}
|
||||
return chunks
|
||||
}
|
166
vendor/github.com/kylelemons/godebug/diff/diff_test.go
generated
vendored
Normal file
166
vendor/github.com/kylelemons/godebug/diff/diff_test.go
generated
vendored
Normal file
|
@ -0,0 +1,166 @@
|
|||
// Copyright 2013 Google Inc. All rights reserved.
|
||||
//
|
||||
// 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 diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDiff(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
A, B []string
|
||||
chunks []Chunk
|
||||
}{
|
||||
{
|
||||
desc: "nil",
|
||||
},
|
||||
{
|
||||
desc: "empty",
|
||||
A: []string{},
|
||||
B: []string{},
|
||||
},
|
||||
{
|
||||
desc: "same",
|
||||
A: []string{"foo"},
|
||||
B: []string{"foo"},
|
||||
},
|
||||
{
|
||||
desc: "a empty",
|
||||
A: []string{},
|
||||
},
|
||||
{
|
||||
desc: "b empty",
|
||||
B: []string{},
|
||||
},
|
||||
{
|
||||
desc: "b nil",
|
||||
A: []string{"foo"},
|
||||
chunks: []Chunk{
|
||||
0: {Deleted: []string{"foo"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "a nil",
|
||||
B: []string{"foo"},
|
||||
chunks: []Chunk{
|
||||
0: {Added: []string{"foo"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "start with change",
|
||||
A: []string{"a", "b", "c"},
|
||||
B: []string{"A", "b", "c"},
|
||||
chunks: []Chunk{
|
||||
0: {Deleted: []string{"a"}},
|
||||
1: {Added: []string{"A"}, Equal: []string{"b", "c"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "constitution",
|
||||
A: []string{
|
||||
"We the People of the United States, in Order to form a more perfect Union,",
|
||||
"establish Justice, insure domestic Tranquility, provide for the common defence,",
|
||||
"and secure the Blessings of Liberty to ourselves",
|
||||
"and our Posterity, do ordain and establish this Constitution for the United",
|
||||
"States of America.",
|
||||
},
|
||||
B: []string{
|
||||
"We the People of the United States, in Order to form a more perfect Union,",
|
||||
"establish Justice, insure domestic Tranquility, provide for the common defence,",
|
||||
"promote the general Welfare, and secure the Blessings of Liberty to ourselves",
|
||||
"and our Posterity, do ordain and establish this Constitution for the United",
|
||||
"States of America.",
|
||||
},
|
||||
chunks: []Chunk{
|
||||
0: {
|
||||
Equal: []string{
|
||||
"We the People of the United States, in Order to form a more perfect Union,",
|
||||
"establish Justice, insure domestic Tranquility, provide for the common defence,",
|
||||
},
|
||||
},
|
||||
1: {
|
||||
Deleted: []string{
|
||||
"and secure the Blessings of Liberty to ourselves",
|
||||
},
|
||||
},
|
||||
2: {
|
||||
Added: []string{
|
||||
"promote the general Welfare, and secure the Blessings of Liberty to ourselves",
|
||||
},
|
||||
Equal: []string{
|
||||
"and our Posterity, do ordain and establish this Constitution for the United",
|
||||
"States of America.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
got := DiffChunks(test.A, test.B)
|
||||
if got, want := len(got), len(test.chunks); got != want {
|
||||
t.Errorf("edit distance = %v, want %v", got-1, want-1)
|
||||
return
|
||||
}
|
||||
for i := range got {
|
||||
got, want := got[i], test.chunks[i]
|
||||
if got, want := got.Added, want.Added; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("chunks[%d]: Added = %v, want %v", i, got, want)
|
||||
}
|
||||
if got, want := got.Deleted, want.Deleted; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("chunks[%d]: Deleted = %v, want %v", i, got, want)
|
||||
}
|
||||
if got, want := got.Equal, want.Equal; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("chunks[%d]: Equal = %v, want %v", i, got, want)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleDiff() {
|
||||
constitution := strings.TrimSpace(`
|
||||
We the People of the United States, in Order to form a more perfect Union,
|
||||
establish Justice, insure domestic Tranquility, provide for the common defence,
|
||||
promote the general Welfare, and secure the Blessings of Liberty to ourselves
|
||||
and our Posterity, do ordain and establish this Constitution for the United
|
||||
States of America.
|
||||
`)
|
||||
|
||||
got := strings.TrimSpace(`
|
||||
:wq
|
||||
We the People of the United States, in Order to form a more perfect Union,
|
||||
establish Justice, insure domestic Tranquility, provide for the common defence,
|
||||
and secure the Blessings of Liberty to ourselves
|
||||
and our Posterity, do ordain and establish this Constitution for the United
|
||||
States of America.
|
||||
`)
|
||||
|
||||
fmt.Println(Diff(got, constitution))
|
||||
|
||||
// Output:
|
||||
// -:wq
|
||||
// We the People of the United States, in Order to form a more perfect Union,
|
||||
// establish Justice, insure domestic Tranquility, provide for the common defence,
|
||||
// -and secure the Blessings of Liberty to ourselves
|
||||
// +promote the general Welfare, and secure the Blessings of Liberty to ourselves
|
||||
// and our Posterity, do ordain and establish this Constitution for the United
|
||||
// States of America.
|
||||
}
|
5
vendor/github.com/kylelemons/godebug/pretty/.gitignore
generated
vendored
Normal file
5
vendor/github.com/kylelemons/godebug/pretty/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
*.test
|
||||
*.bench
|
||||
*.golden
|
||||
*.txt
|
||||
*.prof
|
25
vendor/github.com/kylelemons/godebug/pretty/doc.go
generated
vendored
Normal file
25
vendor/github.com/kylelemons/godebug/pretty/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2013 Google Inc. All rights reserved.
|
||||
//
|
||||
// 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 pretty pretty-prints Go structures.
|
||||
//
|
||||
// This package uses reflection to examine a Go value and can
|
||||
// print out in a nice, aligned fashion. It supports three
|
||||
// modes (normal, compact, and extended) for advanced use.
|
||||
//
|
||||
// See the Reflect and Print examples for what the output looks like.
|
||||
package pretty
|
||||
|
||||
// TODO:
|
||||
// - Catch cycles
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue