diff --git a/assets/gateway-api/gateway.networking.k8s.io_gatewayclasses.yaml b/assets/gateway-api/gateway.networking.k8s.io_gatewayclasses.yaml new file mode 100644 index 0000000000..012e5b04bc --- /dev/null +++ b/assets/gateway-api/gateway.networking.k8s.io_gatewayclasses.yaml @@ -0,0 +1,430 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/1086 + gateway.networking.k8s.io/bundle-version: v0.6.0-dev + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: gatewayclasses.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: GatewayClass + listKind: GatewayClassList + plural: gatewayclasses + shortNames: + - gc + singular: gatewayclass + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.controllerName + name: Controller + type: string + - jsonPath: .status.conditions[?(@.type=="Accepted")].status + name: Accepted + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.description + name: Description + priority: 1 + type: string + name: v1alpha2 + schema: + openAPIV3Schema: + description: "GatewayClass describes a class of Gateways available to the + user for creating Gateway resources. \n It is recommended that this resource + be used as a template for Gateways. This means that a Gateway is based on + the state of the GatewayClass at the time it was created and changes to + the GatewayClass or associated parameters are not propagated down to existing + Gateways. This recommendation is intended to limit the blast radius of changes + to GatewayClass or associated parameters. If implementations choose to propagate + GatewayClass changes to existing Gateways, that MUST be clearly documented + by the implementation. \n Whenever one or more Gateways are using a GatewayClass, + implementations MUST add the `gateway-exists-finalizer.gateway.networking.k8s.io` + finalizer on the associated GatewayClass. This ensures that a GatewayClass + associated with a Gateway is not deleted while in use. \n GatewayClass is + a Cluster level resource." + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of GatewayClass. + properties: + controllerName: + description: "ControllerName is the name of the controller that is + managing Gateways of this class. The value of this field MUST be + a domain prefixed path. \n Example: \"example.net/gateway-controller\". + \n This field is not mutable and cannot be empty. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + description: + description: Description helps describe a GatewayClass with more details. + maxLength: 64 + type: string + parametersRef: + description: "ParametersRef is a reference to a resource that contains + the configuration parameters corresponding to the GatewayClass. + This is optional if the controller does not require any additional + configuration. \n ParametersRef can reference a standard Kubernetes + resource, i.e. ConfigMap, or an implementation-specific custom resource. + The resource can be cluster-scoped or namespace-scoped. \n If the + referent cannot be found, the GatewayClass's \"InvalidParameters\" + status condition will be true. \n Support: Custom" + properties: + group: + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. This + field is required when referring to a Namespace-scoped resource + and MUST be unset when referring to a Cluster-scoped resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + required: + - controllerName + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Waiting + status: Unknown + type: Accepted + description: Status defines the current state of GatewayClass. + properties: + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Waiting + status: Unknown + type: Accepted + description: "Conditions is the current status from the controller + for this GatewayClass. \n Controllers should prefer to publish conditions + using values of GatewayClassConditionType for the type of each Condition." + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: + \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // +listMapKey=type + \ Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: false + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.controllerName + name: Controller + type: string + - jsonPath: .status.conditions[?(@.type=="Accepted")].status + name: Accepted + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.description + name: Description + priority: 1 + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: "GatewayClass describes a class of Gateways available to the + user for creating Gateway resources. \n It is recommended that this resource + be used as a template for Gateways. This means that a Gateway is based on + the state of the GatewayClass at the time it was created and changes to + the GatewayClass or associated parameters are not propagated down to existing + Gateways. This recommendation is intended to limit the blast radius of changes + to GatewayClass or associated parameters. If implementations choose to propagate + GatewayClass changes to existing Gateways, that MUST be clearly documented + by the implementation. \n Whenever one or more Gateways are using a GatewayClass, + implementations MUST add the `gateway-exists-finalizer.gateway.networking.k8s.io` + finalizer on the associated GatewayClass. This ensures that a GatewayClass + associated with a Gateway is not deleted while in use. \n GatewayClass is + a Cluster level resource." + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of GatewayClass. + properties: + controllerName: + description: "ControllerName is the name of the controller that is + managing Gateways of this class. The value of this field MUST be + a domain prefixed path. \n Example: \"example.net/gateway-controller\". + \n This field is not mutable and cannot be empty. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + description: + description: Description helps describe a GatewayClass with more details. + maxLength: 64 + type: string + parametersRef: + description: "ParametersRef is a reference to a resource that contains + the configuration parameters corresponding to the GatewayClass. + This is optional if the controller does not require any additional + configuration. \n ParametersRef can reference a standard Kubernetes + resource, i.e. ConfigMap, or an implementation-specific custom resource. + The resource can be cluster-scoped or namespace-scoped. \n If the + referent cannot be found, the GatewayClass's \"InvalidParameters\" + status condition will be true. \n Support: Custom" + properties: + group: + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. This + field is required when referring to a Namespace-scoped resource + and MUST be unset when referring to a Cluster-scoped resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + required: + - controllerName + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Waiting + status: Unknown + type: Accepted + description: Status defines the current state of GatewayClass. + properties: + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Waiting + status: Unknown + type: Accepted + description: "Conditions is the current status from the controller + for this GatewayClass. \n Controllers should prefer to publish conditions + using values of GatewayClassConditionType for the type of each Condition." + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: + \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // +listMapKey=type + \ Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/assets/gateway-api/gateway.networking.k8s.io_gateways.yaml b/assets/gateway-api/gateway.networking.k8s.io_gateways.yaml new file mode 100644 index 0000000000..1571ae652c --- /dev/null +++ b/assets/gateway-api/gateway.networking.k8s.io_gateways.yaml @@ -0,0 +1,1416 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/1086 + gateway.networking.k8s.io/bundle-version: v0.6.0-dev + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: gateways.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: Gateway + listKind: GatewayList + plural: gateways + shortNames: + - gtw + singular: gateway + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.gatewayClassName + name: Class + type: string + - jsonPath: .status.addresses[*].value + name: Address + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: Gateway represents an instance of a service-traffic handling + infrastructure by binding Listeners to a set of IP addresses. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of Gateway. + properties: + addresses: + description: "Addresses requested for this Gateway. This is optional + and behavior can depend on the implementation. If a value is set + in the spec and the requested address is invalid or unavailable, + the implementation MUST indicate this in the associated entry in + GatewayStatus.Addresses. \n The Addresses field represents a request + for the address(es) on the \"outside of the Gateway\", that traffic + bound for this Gateway will use. This could be the IP address or + hostname of an external load balancer or other networking infrastructure, + or some other address that traffic will be sent to. \n The .listener.hostname + field is used to route traffic that has already arrived at the Gateway + to the correct in-cluster destination. \n If no Addresses are specified, + the implementation MAY schedule the Gateway in an implementation-specific + manner, assigning an appropriate set of Addresses. \n The implementation + MUST bind all Listeners to every GatewayAddress that it assigns + to the Gateway and add a corresponding entry in GatewayStatus.Addresses. + \n Support: Extended" + items: + description: GatewayAddress describes an address that can be bound + to a Gateway. + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: "Value of the address. The validity of the values + will depend on the type and support by the controller. \n + Examples: `1.2.3.4`, `128::1`, `my-ip-address`." + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + maxItems: 16 + type: array + gatewayClassName: + description: GatewayClassName used for this Gateway. This is the name + of a GatewayClass resource. + maxLength: 253 + minLength: 1 + type: string + listeners: + description: "Listeners associated with this Gateway. Listeners define + logical endpoints that are bound on this Gateway's addresses. At + least one Listener MUST be specified. \n Each listener in a Gateway + must have a unique combination of Hostname, Port, and Protocol. + \n An implementation MAY group Listeners by Port and then collapse + each group of Listeners into a single Listener if the implementation + determines that the Listeners in the group are \"compatible\". An + implementation MAY also group together and collapse compatible Listeners + belonging to different Gateways. \n For example, an implementation + might consider Listeners to be compatible with each other if all + of the following conditions are met: \n 1. Either each Listener + within the group specifies the \"HTTP\" Protocol or each Listener + within the group specifies either the \"HTTPS\" or \"TLS\" Protocol. + \n 2. Each Listener within the group specifies a Hostname that is + unique within the group. \n 3. As a special case, one Listener + within a group may omit Hostname, in which case this Listener + matches when no other Listener matches. \n If the implementation + does collapse compatible Listeners, the hostname provided in the + incoming client request MUST be matched to a Listener to find the + correct set of Routes. The incoming hostname MUST be matched using + the Hostname field for each Listener in order of most to least specific. + That is, exact matches must be processed before wildcard matches. + \n If this field specifies multiple Listeners that have the same + Port value but are not compatible, the implementation must raise + a \"Conflicted\" condition in the Listener status. \n Support: Core" + items: + description: Listener embodies the concept of a logical endpoint + where a Gateway accepts network connections. + properties: + allowedRoutes: + default: + namespaces: + from: Same + description: "AllowedRoutes defines the types of routes that + MAY be attached to a Listener and the trusted namespaces where + those Route resources MAY be present. \n Although a client + request may match multiple route rules, only one rule may + ultimately receive the request. Matching precedence MUST be + determined in order of the following criteria: \n * The most + specific match as defined by the Route type. * The oldest + Route based on creation timestamp. For example, a Route with + \ a creation timestamp of \"2020-09-08 01:02:03\" is given + precedence over a Route with a creation timestamp of \"2020-09-08 + 01:02:04\". * If everything else is equivalent, the Route + appearing first in alphabetical order (namespace/name) should + be given precedence. For example, foo/bar is given precedence + over foo/baz. \n All valid rules within a Route attached to + this Listener should be implemented. Invalid Route rules can + be ignored (sometimes that will mean the full Route). If a + Route rule transitions from valid to invalid, support for + that Route rule should be dropped to ensure consistency. For + example, even if a filter specified by a Route rule is invalid, + the rest of the rules within that Route should still be supported. + \n Support: Core" + properties: + kinds: + description: "Kinds specifies the groups and kinds of Routes + that are allowed to bind to this Gateway Listener. When + unspecified or empty, the kinds of Routes selected are + determined using the Listener protocol. \n A RouteGroupKind + MUST correspond to kinds of Routes that are compatible + with the application protocol specified in the Listener's + Protocol field. If an implementation does not support + or recognize this resource type, it MUST set the \"ResolvedRefs\" + condition to False for this Listener with the \"InvalidRouteKinds\" + reason. \n Support: Core" + items: + description: RouteGroupKind indicates the group and kind + of a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + namespaces: + default: + from: Same + description: "Namespaces indicates namespaces from which + Routes may be attached to this Listener. This is restricted + to the namespace of this Gateway by default. \n Support: + Core" + properties: + from: + default: Same + description: "From indicates where Routes will be selected + for this Gateway. Possible values are: * All: Routes + in all namespaces may be used by this Gateway. * Selector: + Routes in namespaces selected by the selector may + be used by this Gateway. * Same: Only Routes in + the same namespace may be used by this Gateway. \n + Support: Core" + enum: + - All + - Selector + - Same + type: string + selector: + description: "Selector must be specified when From is + set to \"Selector\". In that case, only Routes in + Namespaces matching this Selector will be selected + by this Gateway. This field is ignored for other values + of \"From\". \n Support: Core" + 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: object + type: array + matchLabels: + additionalProperties: + type: string + 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 + type: object + type: object + type: object + hostname: + description: "Hostname specifies the virtual hostname to match + for protocol types that define this concept. When unspecified, + all hostnames are matched. This field is ignored for protocols + that don't require hostname based matching. \n Implementations + MUST apply Hostname matching appropriately for each of the + following protocols: \n * TLS: The Listener Hostname MUST + match the SNI. * HTTP: The Listener Hostname MUST match the + Host header of the request. * HTTPS: The Listener Hostname + SHOULD match at both the TLS and HTTP protocol layers as + described above. If an implementation does not ensure that + both the SNI and Host header match the Listener hostname, + \ it MUST clearly document that. \n For HTTPRoute and TLSRoute + resources, there is an interaction with the `spec.hostnames` + array. When both listener and route specify hostnames, there + MUST be an intersection between the values for a Route to + be accepted. For more information, refer to the Route specific + Hostnames documentation. \n Hostnames that are prefixed with + a wildcard label (`*.`) are interpreted as a suffix match. + That means that a match for `*.example.com` would match both + `test.example.com`, and `foo.test.example.com`, but not `example.com`. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + name: + description: "Name is the name of the Listener. This name MUST + be unique within a Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + port: + description: "Port is the network port. Multiple listeners may + use the same port, subject to the Listener compatibility rules. + \n Support: Core" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + description: "Protocol specifies the network protocol this listener + expects to receive. \n Support: Core" + maxLength: 255 + minLength: 1 + pattern: ^[a-zA-Z0-9]([-a-zSA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$ + type: string + tls: + description: "TLS is the TLS configuration for the Listener. + This field is required if the Protocol field is \"HTTPS\" + or \"TLS\". It is invalid to set this field if the Protocol + field is \"HTTP\", \"TCP\", or \"UDP\". \n The association + of SNIs to Certificate defined in GatewayTLSConfig is defined + based on the Hostname field for this listener. \n The GatewayClass + MUST use the longest matching SNI out of all available certificates + for any TLS handshake. \n Support: Core" + properties: + certificateRefs: + description: "CertificateRefs contains a series of references + to Kubernetes objects that contains TLS certificates and + private keys. These certificates are used to establish + a TLS handshake for requests that match the hostname of + the associated listener. \n A single CertificateRef to + a Kubernetes Secret has \"Core\" support. Implementations + MAY choose to support attaching multiple certificates + to a Listener, but this behavior is implementation-specific. + \n References to a resource in different namespace are + invalid UNLESS there is a ReferenceGrant in the target + namespace that allows the certificate to be attached. + If a ReferenceGrant does not allow this reference, the + \"ResolvedRefs\" condition MUST be set to False for this + listener with the \"InvalidCertificateRef\" reason. \n + This field is required to have at least one element when + the mode is set to \"Terminate\" (default) and is optional + otherwise. \n CertificateRefs can reference to standard + Kubernetes resources, i.e. Secret, or implementation-specific + custom resources. \n Support: Core - A single reference + to a Kubernetes Secret of type kubernetes.io/tls \n Support: + Implementation-specific (More than one reference or other + resource types)" + items: + description: "SecretObjectReference identifies an API + object including its namespace, defaulting to Secret. + \n The API object must be valid in the cluster; the + Group and Kind must be registered in the cluster for + this reference to be valid. \n References to objects + with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate + Conditions set on the containing object." + properties: + group: + default: "" + description: Group is the group of the referent. For + example, "networking.k8s.io". When unspecified (empty + string), core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Secret + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. + \n Note that when a namespace is specified, a ReferenceGrant + object is required in the referent namespace to + allow that namespace's owner to accept the reference. + See the ReferenceGrant documentation for details. + \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + maxItems: 64 + type: array + mode: + default: Terminate + description: "Mode defines the TLS behavior for the TLS + session initiated by the client. There are two possible + modes: \n - Terminate: The TLS session between the downstream + client and the Gateway is terminated at the Gateway. + This mode requires certificateRefs to be set and contain + at least one element. - Passthrough: The TLS session is + NOT terminated by the Gateway. This implies that the + Gateway can't decipher the TLS stream except for the + ClientHello message of the TLS protocol. CertificateRefs + field is ignored in this mode. \n Support: Core" + enum: + - Terminate + - Passthrough + type: string + options: + additionalProperties: + description: AnnotationValue is the value of an annotation + in Gateway API. This is used for validation of maps + such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation + in that case is based on the entire size of the annotations + struct. + maxLength: 4096 + minLength: 0 + type: string + description: "Options are a list of key/value pairs to enable + extended TLS configuration for each implementation. For + example, configuring the minimum TLS version or supported + cipher suites. \n A set of common keys MAY be defined + by the API in the future. To avoid any ambiguity, implementation-specific + definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. + Un-prefixed names are reserved for key names defined by + Gateway API. \n Support: Implementation-specific" + maxProperties: 16 + type: object + type: object + required: + - name + - port + - protocol + type: object + maxItems: 64 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + required: + - gatewayClassName + - listeners + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: NotReconciled + status: Unknown + type: Scheduled + description: Status defines the current state of Gateway. + properties: + addresses: + description: Addresses lists the IP addresses that have actually been + bound to the Gateway. These addresses may differ from the addresses + in the Spec, e.g. if the Gateway automatically assigns an address + from a reserved pool. + items: + description: GatewayAddress describes an address that can be bound + to a Gateway. + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: "Value of the address. The validity of the values + will depend on the type and support by the controller. \n + Examples: `1.2.3.4`, `128::1`, `my-ip-address`." + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + maxItems: 16 + type: array + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: NotReconciled + status: Unknown + type: Scheduled + description: "Conditions describe the current conditions of the Gateway. + \n Implementations should prefer to express Gateway conditions using + the `GatewayConditionType` and `GatewayConditionReason` constants + so that operators and tools can converge on a common vocabulary + to describe Gateway state. \n Known condition types are: \n * \"Scheduled\" + * \"Ready\"" + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: + \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // +listMapKey=type + \ Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + listeners: + description: Listeners provide status for each unique listener port + defined in the Spec. + items: + description: ListenerStatus is the status associated with a Listener. + properties: + attachedRoutes: + description: AttachedRoutes represents the total number of Routes + that have been successfully attached to this Listener. + format: int32 + type: integer + conditions: + description: Conditions describe the current condition of this + listener. + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + name: + description: Name is the name of the Listener that this status + corresponds to. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + supportedKinds: + description: "SupportedKinds is the list indicating the Kinds + supported by this listener. This MUST represent the kinds + an implementation supports for that Listener configuration. + \n If kinds are specified in Spec that are not supported, + they MUST NOT appear in this list and an implementation MUST + set the \"ResolvedRefs\" condition to \"False\" with the \"InvalidRouteKinds\" + reason. If both valid and invalid Route kinds are specified, + the implementation MUST reference the valid Route kinds that + have been specified." + items: + description: RouteGroupKind indicates the group and kind of + a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + required: + - attachedRoutes + - conditions + - name + - supportedKinds + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: false + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.gatewayClassName + name: Class + type: string + - jsonPath: .status.addresses[*].value + name: Address + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: Gateway represents an instance of a service-traffic handling + infrastructure by binding Listeners to a set of IP addresses. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of Gateway. + properties: + addresses: + description: "Addresses requested for this Gateway. This is optional + and behavior can depend on the implementation. If a value is set + in the spec and the requested address is invalid or unavailable, + the implementation MUST indicate this in the associated entry in + GatewayStatus.Addresses. \n The Addresses field represents a request + for the address(es) on the \"outside of the Gateway\", that traffic + bound for this Gateway will use. This could be the IP address or + hostname of an external load balancer or other networking infrastructure, + or some other address that traffic will be sent to. \n The .listener.hostname + field is used to route traffic that has already arrived at the Gateway + to the correct in-cluster destination. \n If no Addresses are specified, + the implementation MAY schedule the Gateway in an implementation-specific + manner, assigning an appropriate set of Addresses. \n The implementation + MUST bind all Listeners to every GatewayAddress that it assigns + to the Gateway and add a corresponding entry in GatewayStatus.Addresses. + \n Support: Extended" + items: + description: GatewayAddress describes an address that can be bound + to a Gateway. + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: "Value of the address. The validity of the values + will depend on the type and support by the controller. \n + Examples: `1.2.3.4`, `128::1`, `my-ip-address`." + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + maxItems: 16 + type: array + gatewayClassName: + description: GatewayClassName used for this Gateway. This is the name + of a GatewayClass resource. + maxLength: 253 + minLength: 1 + type: string + listeners: + description: "Listeners associated with this Gateway. Listeners define + logical endpoints that are bound on this Gateway's addresses. At + least one Listener MUST be specified. \n Each listener in a Gateway + must have a unique combination of Hostname, Port, and Protocol. + \n An implementation MAY group Listeners by Port and then collapse + each group of Listeners into a single Listener if the implementation + determines that the Listeners in the group are \"compatible\". An + implementation MAY also group together and collapse compatible Listeners + belonging to different Gateways. \n For example, an implementation + might consider Listeners to be compatible with each other if all + of the following conditions are met: \n 1. Either each Listener + within the group specifies the \"HTTP\" Protocol or each Listener + within the group specifies either the \"HTTPS\" or \"TLS\" Protocol. + \n 2. Each Listener within the group specifies a Hostname that is + unique within the group. \n 3. As a special case, one Listener + within a group may omit Hostname, in which case this Listener + matches when no other Listener matches. \n If the implementation + does collapse compatible Listeners, the hostname provided in the + incoming client request MUST be matched to a Listener to find the + correct set of Routes. The incoming hostname MUST be matched using + the Hostname field for each Listener in order of most to least specific. + That is, exact matches must be processed before wildcard matches. + \n If this field specifies multiple Listeners that have the same + Port value but are not compatible, the implementation must raise + a \"Conflicted\" condition in the Listener status. \n Support: Core" + items: + description: Listener embodies the concept of a logical endpoint + where a Gateway accepts network connections. + properties: + allowedRoutes: + default: + namespaces: + from: Same + description: "AllowedRoutes defines the types of routes that + MAY be attached to a Listener and the trusted namespaces where + those Route resources MAY be present. \n Although a client + request may match multiple route rules, only one rule may + ultimately receive the request. Matching precedence MUST be + determined in order of the following criteria: \n * The most + specific match as defined by the Route type. * The oldest + Route based on creation timestamp. For example, a Route with + \ a creation timestamp of \"2020-09-08 01:02:03\" is given + precedence over a Route with a creation timestamp of \"2020-09-08 + 01:02:04\". * If everything else is equivalent, the Route + appearing first in alphabetical order (namespace/name) should + be given precedence. For example, foo/bar is given precedence + over foo/baz. \n All valid rules within a Route attached to + this Listener should be implemented. Invalid Route rules can + be ignored (sometimes that will mean the full Route). If a + Route rule transitions from valid to invalid, support for + that Route rule should be dropped to ensure consistency. For + example, even if a filter specified by a Route rule is invalid, + the rest of the rules within that Route should still be supported. + \n Support: Core" + properties: + kinds: + description: "Kinds specifies the groups and kinds of Routes + that are allowed to bind to this Gateway Listener. When + unspecified or empty, the kinds of Routes selected are + determined using the Listener protocol. \n A RouteGroupKind + MUST correspond to kinds of Routes that are compatible + with the application protocol specified in the Listener's + Protocol field. If an implementation does not support + or recognize this resource type, it MUST set the \"ResolvedRefs\" + condition to False for this Listener with the \"InvalidRouteKinds\" + reason. \n Support: Core" + items: + description: RouteGroupKind indicates the group and kind + of a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + namespaces: + default: + from: Same + description: "Namespaces indicates namespaces from which + Routes may be attached to this Listener. This is restricted + to the namespace of this Gateway by default. \n Support: + Core" + properties: + from: + default: Same + description: "From indicates where Routes will be selected + for this Gateway. Possible values are: * All: Routes + in all namespaces may be used by this Gateway. * Selector: + Routes in namespaces selected by the selector may + be used by this Gateway. * Same: Only Routes in + the same namespace may be used by this Gateway. \n + Support: Core" + enum: + - All + - Selector + - Same + type: string + selector: + description: "Selector must be specified when From is + set to \"Selector\". In that case, only Routes in + Namespaces matching this Selector will be selected + by this Gateway. This field is ignored for other values + of \"From\". \n Support: Core" + 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: object + type: array + matchLabels: + additionalProperties: + type: string + 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 + type: object + type: object + type: object + hostname: + description: "Hostname specifies the virtual hostname to match + for protocol types that define this concept. When unspecified, + all hostnames are matched. This field is ignored for protocols + that don't require hostname based matching. \n Implementations + MUST apply Hostname matching appropriately for each of the + following protocols: \n * TLS: The Listener Hostname MUST + match the SNI. * HTTP: The Listener Hostname MUST match the + Host header of the request. * HTTPS: The Listener Hostname + SHOULD match at both the TLS and HTTP protocol layers as + described above. If an implementation does not ensure that + both the SNI and Host header match the Listener hostname, + \ it MUST clearly document that. \n For HTTPRoute and TLSRoute + resources, there is an interaction with the `spec.hostnames` + array. When both listener and route specify hostnames, there + MUST be an intersection between the values for a Route to + be accepted. For more information, refer to the Route specific + Hostnames documentation. \n Hostnames that are prefixed with + a wildcard label (`*.`) are interpreted as a suffix match. + That means that a match for `*.example.com` would match both + `test.example.com`, and `foo.test.example.com`, but not `example.com`. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + name: + description: "Name is the name of the Listener. This name MUST + be unique within a Gateway. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + port: + description: "Port is the network port. Multiple listeners may + use the same port, subject to the Listener compatibility rules. + \n Support: Core" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + protocol: + description: "Protocol specifies the network protocol this listener + expects to receive. \n Support: Core" + maxLength: 255 + minLength: 1 + pattern: ^[a-zA-Z0-9]([-a-zSA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$ + type: string + tls: + description: "TLS is the TLS configuration for the Listener. + This field is required if the Protocol field is \"HTTPS\" + or \"TLS\". It is invalid to set this field if the Protocol + field is \"HTTP\", \"TCP\", or \"UDP\". \n The association + of SNIs to Certificate defined in GatewayTLSConfig is defined + based on the Hostname field for this listener. \n The GatewayClass + MUST use the longest matching SNI out of all available certificates + for any TLS handshake. \n Support: Core" + properties: + certificateRefs: + description: "CertificateRefs contains a series of references + to Kubernetes objects that contains TLS certificates and + private keys. These certificates are used to establish + a TLS handshake for requests that match the hostname of + the associated listener. \n A single CertificateRef to + a Kubernetes Secret has \"Core\" support. Implementations + MAY choose to support attaching multiple certificates + to a Listener, but this behavior is implementation-specific. + \n References to a resource in different namespace are + invalid UNLESS there is a ReferenceGrant in the target + namespace that allows the certificate to be attached. + If a ReferenceGrant does not allow this reference, the + \"ResolvedRefs\" condition MUST be set to False for this + listener with the \"InvalidCertificateRef\" reason. \n + This field is required to have at least one element when + the mode is set to \"Terminate\" (default) and is optional + otherwise. \n CertificateRefs can reference to standard + Kubernetes resources, i.e. Secret, or implementation-specific + custom resources. \n Support: Core - A single reference + to a Kubernetes Secret of type kubernetes.io/tls \n Support: + Implementation-specific (More than one reference or other + resource types)" + items: + description: "SecretObjectReference identifies an API + object including its namespace, defaulting to Secret. + \n The API object must be valid in the cluster; the + Group and Kind must be registered in the cluster for + this reference to be valid. \n References to objects + with invalid Group and Kind are not valid, and must + be rejected by the implementation, with appropriate + Conditions set on the containing object." + properties: + group: + default: "" + description: Group is the group of the referent. For + example, "networking.k8s.io". When unspecified (empty + string), core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Secret + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. + \n Note that when a namespace is specified, a ReferenceGrant + object is required in the referent namespace to + allow that namespace's owner to accept the reference. + See the ReferenceGrant documentation for details. + \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + maxItems: 64 + type: array + mode: + default: Terminate + description: "Mode defines the TLS behavior for the TLS + session initiated by the client. There are two possible + modes: \n - Terminate: The TLS session between the downstream + client and the Gateway is terminated at the Gateway. + This mode requires certificateRefs to be set and contain + at least one element. - Passthrough: The TLS session is + NOT terminated by the Gateway. This implies that the + Gateway can't decipher the TLS stream except for the + ClientHello message of the TLS protocol. CertificateRefs + field is ignored in this mode. \n Support: Core" + enum: + - Terminate + - Passthrough + type: string + options: + additionalProperties: + description: AnnotationValue is the value of an annotation + in Gateway API. This is used for validation of maps + such as TLS options. This roughly matches Kubernetes + annotation validation, although the length validation + in that case is based on the entire size of the annotations + struct. + maxLength: 4096 + minLength: 0 + type: string + description: "Options are a list of key/value pairs to enable + extended TLS configuration for each implementation. For + example, configuring the minimum TLS version or supported + cipher suites. \n A set of common keys MAY be defined + by the API in the future. To avoid any ambiguity, implementation-specific + definitions MUST use domain-prefixed names, such as `example.com/my-custom-option`. + Un-prefixed names are reserved for key names defined by + Gateway API. \n Support: Implementation-specific" + maxProperties: 16 + type: object + type: object + required: + - name + - port + - protocol + type: object + maxItems: 64 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + required: + - gatewayClassName + - listeners + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: NotReconciled + status: Unknown + type: Scheduled + description: Status defines the current state of Gateway. + properties: + addresses: + description: Addresses lists the IP addresses that have actually been + bound to the Gateway. These addresses may differ from the addresses + in the Spec, e.g. if the Gateway automatically assigns an address + from a reserved pool. + items: + description: GatewayAddress describes an address that can be bound + to a Gateway. + properties: + type: + default: IPAddress + description: Type of the address. + maxLength: 253 + minLength: 1 + pattern: ^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + value: + description: "Value of the address. The validity of the values + will depend on the type and support by the controller. \n + Examples: `1.2.3.4`, `128::1`, `my-ip-address`." + maxLength: 253 + minLength: 1 + type: string + required: + - value + type: object + maxItems: 16 + type: array + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: NotReconciled + status: Unknown + type: Scheduled + description: "Conditions describe the current conditions of the Gateway. + \n Implementations should prefer to express Gateway conditions using + the `GatewayConditionType` and `GatewayConditionReason` constants + so that operators and tools can converge on a common vocabulary + to describe Gateway state. \n Known condition types are: \n * \"Scheduled\" + * \"Ready\"" + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: + \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // +listMapKey=type + \ Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + listeners: + description: Listeners provide status for each unique listener port + defined in the Spec. + items: + description: ListenerStatus is the status associated with a Listener. + properties: + attachedRoutes: + description: AttachedRoutes represents the total number of Routes + that have been successfully attached to this Listener. + format: int32 + type: integer + conditions: + description: Conditions describe the current condition of this + listener. + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + name: + description: Name is the name of the Listener that this status + corresponds to. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + supportedKinds: + description: "SupportedKinds is the list indicating the Kinds + supported by this listener. This MUST represent the kinds + an implementation supports for that Listener configuration. + \n If kinds are specified in Spec that are not supported, + they MUST NOT appear in this list and an implementation MUST + set the \"ResolvedRefs\" condition to \"False\" with the \"InvalidRouteKinds\" + reason. If both valid and invalid Route kinds are specified, + the implementation MUST reference the valid Route kinds that + have been specified." + items: + description: RouteGroupKind indicates the group and kind of + a Route resource. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the Route. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is the kind of the Route. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + required: + - kind + type: object + maxItems: 8 + type: array + required: + - attachedRoutes + - conditions + - name + - supportedKinds + type: object + maxItems: 64 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/assets/gateway-api/gateway.networking.k8s.io_httproutes.yaml b/assets/gateway-api/gateway.networking.k8s.io_httproutes.yaml new file mode 100644 index 0000000000..67bebbc91b --- /dev/null +++ b/assets/gateway-api/gateway.networking.k8s.io_httproutes.yaml @@ -0,0 +1,3252 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/1086 + gateway.networking.k8s.io/bundle-version: v0.6.0-dev + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: httproutes.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: HTTPRoute + listKind: HTTPRouteList + plural: httproutes + singular: httproute + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: HTTPRoute provides a way to route HTTP requests. This includes + the capability to match requests by hostname, path, header, or query param. + Filters can be used to specify additional processing steps. Backends specify + where matching requests should be routed. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of HTTPRoute. + properties: + hostnames: + description: "Hostnames defines a set of hostname that should match + against the HTTP Host header to select a HTTPRoute to process the + request. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may + be prefixed with a wildcard label (`*.`). The wildcard label + must appear by itself as the first label. \n If a hostname is specified + by both the Listener and HTTPRoute, there must be at least one intersecting + hostname for the HTTPRoute to be attached to the Listener. For example: + \n * A Listener with `test.example.com` as the hostname matches + HTTPRoutes that have either not specified any hostnames, or have + specified at least one of `test.example.com` or `*.example.com`. + * A Listener with `*.example.com` as the hostname matches HTTPRoutes + \ that have either not specified any hostnames or have specified + at least one hostname that matches the Listener hostname. For + example, `*.example.com`, `test.example.com`, and `foo.test.example.com` + would all match. On the other hand, `example.com` and `test.example.net` + would not match. \n Hostnames that are prefixed with a wildcard + label (`*.`) are interpreted as a suffix match. That means that + a match for `*.example.com` would match both `test.example.com`, + and `foo.test.example.com`, but not `example.com`. \n If both the + Listener and HTTPRoute have specified hostnames, any HTTPRoute hostnames + that do not match the Listener hostname MUST be ignored. For example, + if a Listener specified `*.example.com`, and the HTTPRoute specified + `test.example.com` and `test.example.net`, `test.example.net` must + not be considered for a match. \n If both the Listener and HTTPRoute + have specified hostnames, and none match with the criteria above, + then the HTTPRoute is not accepted. The implementation must raise + an 'Accepted' Condition with a status of `False` in the corresponding + RouteParentStatus. \n Support: Core" + items: + description: "Hostname is the fully qualified domain name of a network + host. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname + may be prefixed with a wildcard label (`*.`). The wildcard label + must appear by itself as the first label. \n Hostname can be \"precise\" + which is a domain name without the terminating dot of a network + host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain + name prefixed with a single wildcard label (e.g. `*.example.com`). + \n Note that as per RFC1035 and RFC1123, a *label* must consist + of lower case alphanumeric characters or '-', and must start and + end with an alphanumeric character. No other punctuation is allowed." + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: "ParentRefs references the resources (usually Gateways) + that a Route wants to be attached to. Note that the referenced parent + resource needs to allow this for the attachment to be complete. + For Gateways, that means the Gateway needs to allow attachment from + Routes of this kind and namespace. \n The only kind of parent resource + with \"Core\" support is Gateway. This API may be extended in the + future to support additional kinds of parent resources such as one + of the route kinds. \n It is invalid to reference an identical parent + more than once. It is valid to reference multiple distinct sections + within the same parent resource, such as 2 Listeners within a Gateway. + \n It is possible to separately reference multiple distinct objects + that may be collapsed by an implementation. For example, some implementations + may choose to merge compatible Gateway Listeners together. If that + is the case, the list of routes attached to those resources should + also be merged." + items: + description: "ParentReference identifies an API object (usually + a Gateway) that can be considered a parent of this resource (usually + a route). The only kind of parent resource with \"Core\" support + is Gateway. This API may be extended in the future to support + additional kinds of parent resources, such as HTTPRoute. \n The + API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n Support: Core + (Gateway) \n Support: Custom (Other Resources)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified, this refers to the local namespace of the Route. + \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It + can be interpreted differently based on the type of parent + resource. \n When the parent resource is a Gateway, this targets + all listeners listening on the specified port that also support + this kind of Route(and select this Route). It's not recommended + to set `Port` unless the networking behaviors specified in + a Route must apply to a specific port as opposed to a listener(s) + whose port(s) may be changed. When both Port and SectionName + are specified, the name and port of the selected listener + must match both specified values. \n Implementations MAY choose + to support other parent resources. Implementations supporting + other types of parent resources MUST clearly document how/if + Port is interpreted. \n For the purpose of status, an attachment + is considered successful as long as the parent resource accepts + it partially. For example, Gateway listeners can restrict + which Routes can attach to them by Route kind, namespace, + or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this + Route, the Route MUST be considered detached from the Gateway. + \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match both + specified values. \n Implementations MAY choose to support + attaching Routes to other resources. If that is the case, + they MUST clearly document how SectionName is interpreted. + \n When unspecified (empty string), this will reference the + entire resource. For the purpose of status, an attachment + is considered successful if at least one section in the parent + resource accepts it. For example, Gateway listeners can restrict + which Routes can attach to them by Route kind, namespace, + or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this + Route, the Route MUST be considered detached from the Gateway. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + rules: + default: + - matches: + - path: + type: PathPrefix + value: / + description: Rules are a list of HTTP matchers, filters and actions. + items: + description: HTTPRouteRule defines semantics for matching an HTTP + request based on conditions (matches), processing it (filters), + and forwarding the request to an API object (backendRefs). + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching + requests should be sent. \n Failure behavior here depends + on how many BackendRefs are specified and how many are invalid. + \n If *all* entries in BackendRefs are invalid, and there + are also no filters specified in this route rule, *all* traffic + which matches this rule MUST receive a 500 status code. \n + See the HTTPBackendRef definition for the rules about what + makes a single HTTPBackendRef invalid. \n When a HTTPBackendRef + is invalid, 500 status codes MUST be returned for requests + that would have otherwise been routed to an invalid backend. + If multiple backends are specified, and some are invalid, + the proportion of requests that would otherwise have been + routed to an invalid backend MUST receive a 500 status code. + \n For example, if two backends are specified with equal weights, + and one is invalid, 50 percent of traffic must receive a 500. + Implementations may choose how that 50 percent is determined. + \n Support: Core for Kubernetes Service \n Support: Custom + for any other resource \n Support for weight: Core" + items: + description: HTTPBackendRef defines how a HTTPRoute should + forward an HTTP request. + properties: + filters: + description: "Filters defined at this level should be + executed if and only if the request is being forwarded + to the backend defined here. \n Support: Custom (For + broader support of filters, use the Filters field in + HTTPRouteRule.)" + items: + description: HTTPRouteFilter defines processing steps + that must be completed during the request or response + lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway + implementations. Some examples include request or + response modification, implementing authentication + strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type + of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific + extension to the \"filter\" behavior. For example, + resource \"myroutefilter\" in group \"networking.example.net\"). + ExtensionRef MUST NOT be used for core and extended + filters. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. + For example, "networking.k8s.io". When unspecified + (empty string), core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For + example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema + for a filter that modifies request headers. \n + Support: Core" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It + appends to any existing values associated + with the header name. \n Input: GET /foo + HTTP/1.1 my-header: foo \n Config: add: + \ - name: \"my-header\" value: \"bar\" + \n Output: GET /foo HTTP/1.1 my-header: + foo my-header: bar" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from + the HTTP request before the action. The value + of Remove is a list of HTTP header names. + Note that the header names are case-insensitive + (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: + foo my-header2: bar my-header3: baz \n + Config: remove: [\"my-header1\", \"my-header3\"] + \n Output: GET /foo HTTP/1.1 my-header2: + bar" + items: + type: string + maxItems: 16 + type: array + set: + description: "Set overwrites the request with + the given header (name, value) before the + action. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: set: - name: \"my-header\" + \ value: \"bar\" \n Output: GET /foo + HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for + a filter that mirrors requests. Requests are sent + to the specified destination, but responses from + that destination are ignored. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource + where mirrored requests are sent. \n If the + referent cannot be found, this BackendRef + is invalid and must be dropped from the Gateway. + The controller must ensure the \"ResolvedRefs\" + condition on the Route status is set to `status: + False` and not configure this backend in the + underlying implementation. \n If there is + a cross-namespace reference to an *existing* + object that is not allowed by a ReferenceGrant, + the controller must ensure the \"ResolvedRefs\" + \ condition on the Route is set to `status: + False`, with the \"RefNotPermitted\" reason + and not configure this backend in the underlying + implementation. \n In either error case, the + Message of the `ResolvedRefs` Condition should + be used to provide more detail about the problem. + \n Support: Extended for Kubernetes Service + \n Support: Custom for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "networking.k8s.io". When + unspecified (empty string), core API group + is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: Kind is kind of the referent. + For example "HTTPRoute" or "Service". + Defaults to "Service" when not specified. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace + of the backend. When unspecified, the + local namespace is inferred. \n Note that + when a namespace is specified, a ReferenceGrant + object is required in the referent namespace + to allow that namespace's owner to accept + the reference. See the ReferenceGrant + documentation for details. \n Support: + Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination + port number to use for this resource. + Port is required when the referent is + a Kubernetes Service. In this case, the + port number is the service port number, + not the target port. For other resources, + destination port might be derived from + the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for + a filter that responds to the request with an + HTTP redirection. \n Support: Core" + properties: + hostname: + description: "Hostname is the hostname to be + used in the value of the `Location` header + in the response. When empty, the hostname + of the request is used. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines parameters used to + modify the path of the incoming request. The + modified path is then used to construct the + `Location` header. When empty, the request + path is used as-is. \n Support: Extended \n + " + properties: + replaceFullPath: + description: "ReplaceFullPath specifies + the value with which to replace the full + path of a request during a rewrite or + redirect. \n " + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies + the value with which to replace the prefix + match of a request during a rewrite or + redirect. For example, a request to \"/foo/bar\" + with a prefix match of \"/foo\" would + be modified to \"/bar\". \n Note that + this matches the behavior of the PathPrefix + match type. This matches full path elements. + A path element refers to the list of labels + in the path split by the `/` separator. + When specified, a trailing `/` is ignored. + For example, the paths `/abc`, `/abc/`, + and `/abc/def` would all match the prefix + `/abc`, but the path `/abcd` would not. + \n " + maxLength: 1024 + type: string + type: + description: "Type defines the type of path + modifier. Additional types may be added + in a future release of the API. \n Note + that values may be added to this enum, + implementations must ensure that unknown + values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Attached Condition for the + Route to `status: False`, with a Reason + of `UnsupportedValue`. \n " + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + port: + description: "Port is the port to be used in + the value of the `Location` header in the + response. When empty, port (if specified) + of the request is used. \n Support: Extended" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: "Scheme is the scheme to be used + in the value of the `Location` header in the + response. When empty, the scheme of the request + is used. \n Support: Extended \n Note that + values may be added to this enum, implementations + must ensure that unknown values will not cause + a crash. \n Unknown values here must result + in the implementation setting the Attached + Condition for the Route to `status: False`, + with a Reason of `UnsupportedValue`." + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status + code to be used in response. \n Support: Core + \n Note that values may be added to this enum, + implementations must ensure that unknown values + will not cause a crash. \n Unknown values + here must result in the implementation setting + the Attached Condition for the Route to `status: + False`, with a Reason of `UnsupportedValue`." + enum: + - 301 + - 302 + type: integer + type: object + type: + description: "Type identifies the type of filter + to apply. As with other API fields, types are + classified into three conformance levels: \n - + Core: Filter types and their corresponding configuration + defined by \"Support: Core\" in this package, + e.g. \"RequestHeaderModifier\". All implementations + must support core filters. \n - Extended: Filter + types and their corresponding configuration defined + by \"Support: Extended\" in this package, e.g. + \"RequestMirror\". Implementers are encouraged + to support extended filters. \n - Custom: Filters + that are defined and supported by specific vendors. + \ In the future, filters showing convergence + in behavior across multiple implementations + will be considered for inclusion in extended or + core conformance levels. Filter-specific configuration + for such filters is specified using the ExtensionRef + field. `Type` should be set to \"ExtensionRef\" + for custom filters. \n Implementers are encouraged + to define custom implementation types to extend + the core API with implementation-specific behavior. + \n If a reference to a custom filter type cannot + be resolved, the filter MUST NOT be skipped. Instead, + requests that would have been processed by that + filter MUST receive a HTTP error response. \n + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause + a crash. \n Unknown values here must result in + the implementation setting the Attached Condition + for the Route to `status: False`, with a Reason + of `UnsupportedValue`. \n " + enum: + - RequestHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: "URLRewrite defines a schema for a + filter that modifies a request during forwarding. + \n Support: Extended \n " + properties: + hostname: + description: "Hostname is the value to be used + to replace the Host header value during forwarding. + \n Support: Extended \n " + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines a path rewrite. \n + Support: Extended \n " + properties: + replaceFullPath: + description: "ReplaceFullPath specifies + the value with which to replace the full + path of a request during a rewrite or + redirect. \n " + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies + the value with which to replace the prefix + match of a request during a rewrite or + redirect. For example, a request to \"/foo/bar\" + with a prefix match of \"/foo\" would + be modified to \"/bar\". \n Note that + this matches the behavior of the PathPrefix + match type. This matches full path elements. + A path element refers to the list of labels + in the path split by the `/` separator. + When specified, a trailing `/` is ignored. + For example, the paths `/abc`, `/abc/`, + and `/abc/def` would all match the prefix + `/abc`, but the path `/abcd` would not. + \n " + maxLength: 1024 + type: string + type: + description: "Type defines the type of path + modifier. Additional types may be added + in a future release of the API. \n Note + that values may be added to this enum, + implementations must ensure that unknown + values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Attached Condition for the + Route to `status: False`, with a Reason + of `UnsupportedValue`. \n " + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + type: object + required: + - type + type: object + maxItems: 16 + type: array + group: + default: "" + description: Group is the group of the referent. For example, + "networking.k8s.io". When unspecified (empty string), + core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". Defaults to "Service" when + not specified. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace is specified, a ReferenceGrant + object is required in the referent namespace to allow + that namespace's owner to accept the reference. See + the ReferenceGrant documentation for details. \n Support: + Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number + to use for this resource. Port is required when the + referent is a Kubernetes Service. In this case, the + port number is the service port number, not the target + port. For other resources, destination port might be + derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests + forwarded to the referenced backend. This is computed + as weight/(sum of all weights in this BackendRefs list). + For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision + an implementation supports. Weight is not a percentage + and the sum of weights does not need to equal 100. \n + If only one backend is specified and it has a weight + greater than 0, 100% of the traffic is forwarded to + that backend. If weight is set to 0, no traffic should + be forwarded for this entry. If unspecified, weight + defaults to 1. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + maxItems: 16 + type: array + filters: + description: "Filters define the filters that are applied to + requests that match this rule. \n The effects of ordering + of multiple behaviors are currently unspecified. This can + change in the future based on feedback during the alpha stage. + \n Conformance-levels at this level are defined based on the + type of filter: \n - ALL core filters MUST be supported by + all implementations. - Implementers are encouraged to support + extended filters. - Implementation-specific custom filters + have no API guarantees across implementations. \n Specifying + a core filter multiple times has unspecified or custom conformance. + \n All filters are expected to be compatible with each other + except for the URLRewrite and RequestRedirect filters, which + may not be combined. If an implementation can not support + other combinations of filters, they must clearly document + that limitation. In all cases where incompatible or unsupported + filters are specified, implementations MUST add a warning + condition to status. \n Support: Core" + items: + description: HTTPRouteFilter defines processing steps that + must be completed during the request or response lifecycle. + HTTPRouteFilters are meant as an extension point to express + processing that may be done in Gateway implementations. + Some examples include request or response modification, + implementing authentication strategies, rate-limiting, and + traffic shaping. API guarantee/conformance is defined based + on the type of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific + extension to the \"filter\" behavior. For example, + resource \"myroutefilter\" in group \"networking.example.net\"). + ExtensionRef MUST NOT be used for core and extended + filters. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. For + example, "networking.k8s.io". When unspecified (empty + string), core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema for + a filter that modifies request headers. \n Support: + Core" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It appends + to any existing values associated with the header + name. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: add: - name: \"my-header\" value: + \"bar\" \n Output: GET /foo HTTP/1.1 my-header: + foo my-header: bar" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the + HTTP request before the action. The value of Remove + is a list of HTTP header names. Note that the header + names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo + \ my-header2: bar my-header3: baz \n Config: + \ remove: [\"my-header1\", \"my-header3\"] \n Output: + \ GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + set: + description: "Set overwrites the request with the + given header (name, value) before the action. \n + Input: GET /foo HTTP/1.1 my-header: foo \n Config: + \ set: - name: \"my-header\" value: \"bar\" + \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for a filter + that mirrors requests. Requests are sent to the specified + destination, but responses from that destination are + ignored. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource where + mirrored requests are sent. \n If the referent cannot + be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure + the \"ResolvedRefs\" condition on the Route status + is set to `status: False` and not configure this + backend in the underlying implementation. \n If + there is a cross-namespace reference to an *existing* + object that is not allowed by a ReferenceGrant, + the controller must ensure the \"ResolvedRefs\" + \ condition on the Route is set to `status: False`, + with the \"RefNotPermitted\" reason and not configure + this backend in the underlying implementation. \n + In either error case, the Message of the `ResolvedRefs` + Condition should be used to provide more detail + about the problem. \n Support: Extended for Kubernetes + Service \n Support: Custom for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "networking.k8s.io". When unspecified + (empty string), core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: Kind is kind of the referent. For + example "HTTPRoute" or "Service". Defaults to + "Service" when not specified. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the + backend. When unspecified, the local namespace + is inferred. \n Note that when a namespace is + specified, a ReferenceGrant object is required + in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port + number to use for this resource. Port is required + when the referent is a Kubernetes Service. In + this case, the port number is the service port + number, not the target port. For other resources, + destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for a filter + that responds to the request with an HTTP redirection. + \n Support: Core" + properties: + hostname: + description: "Hostname is the hostname to be used + in the value of the `Location` header in the response. + When empty, the hostname of the request is used. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines parameters used to modify + the path of the incoming request. The modified path + is then used to construct the `Location` header. + When empty, the request path is used as-is. \n Support: + Extended \n " + properties: + replaceFullPath: + description: "ReplaceFullPath specifies the value + with which to replace the full path of a request + during a rewrite or redirect. \n " + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the + value with which to replace the prefix match + of a request during a rewrite or redirect. For + example, a request to \"/foo/bar\" with a prefix + match of \"/foo\" would be modified to \"/bar\". + \n Note that this matches the behavior of the + PathPrefix match type. This matches full path + elements. A path element refers to the list + of labels in the path split by the `/` separator. + When specified, a trailing `/` is ignored. For + example, the paths `/abc`, `/abc/`, and `/abc/def` + would all match the prefix `/abc`, but the path + `/abcd` would not. \n " + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. + Additional types may be added in a future release + of the API. \n Note that values may be added + to this enum, implementations must ensure that + unknown values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Attached Condition for the Route + to `status: False`, with a Reason of `UnsupportedValue`. + \n " + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + port: + description: "Port is the port to be used in the value + of the `Location` header in the response. When empty, + port (if specified) of the request is used. \n Support: + Extended" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: "Scheme is the scheme to be used in the + value of the `Location` header in the response. + When empty, the scheme of the request is used. \n + Support: Extended \n Note that values may be added + to this enum, implementations must ensure that unknown + values will not cause a crash. \n Unknown values + here must result in the implementation setting the + Attached Condition for the Route to `status: False`, + with a Reason of `UnsupportedValue`." + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status code to + be used in response. \n Support: Core \n Note that + values may be added to this enum, implementations + must ensure that unknown values will not cause a + crash. \n Unknown values here must result in the + implementation setting the Attached Condition for + the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - 301 + - 302 + type: integer + type: object + type: + description: "Type identifies the type of filter to apply. + As with other API fields, types are classified into + three conformance levels: \n - Core: Filter types and + their corresponding configuration defined by \"Support: + Core\" in this package, e.g. \"RequestHeaderModifier\". + All implementations must support core filters. \n + - Extended: Filter types and their corresponding configuration + defined by \"Support: Extended\" in this package, + e.g. \"RequestMirror\". Implementers are encouraged + to support extended filters. \n - Custom: Filters that + are defined and supported by specific vendors. In + the future, filters showing convergence in behavior + across multiple implementations will be considered + for inclusion in extended or core conformance levels. + Filter-specific configuration for such filters is + specified using the ExtensionRef field. `Type` should + be set to \"ExtensionRef\" for custom filters. \n + Implementers are encouraged to define custom implementation + types to extend the core API with implementation-specific + behavior. \n If a reference to a custom filter type + cannot be resolved, the filter MUST NOT be skipped. + Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. \n Note + that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + \n Unknown values here must result in the implementation + setting the Attached Condition for the Route to `status: + False`, with a Reason of `UnsupportedValue`. \n " + enum: + - RequestHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: "URLRewrite defines a schema for a filter + that modifies a request during forwarding. \n Support: + Extended \n " + properties: + hostname: + description: "Hostname is the value to be used to + replace the Host header value during forwarding. + \n Support: Extended \n " + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines a path rewrite. \n Support: + Extended \n " + properties: + replaceFullPath: + description: "ReplaceFullPath specifies the value + with which to replace the full path of a request + during a rewrite or redirect. \n " + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the + value with which to replace the prefix match + of a request during a rewrite or redirect. For + example, a request to \"/foo/bar\" with a prefix + match of \"/foo\" would be modified to \"/bar\". + \n Note that this matches the behavior of the + PathPrefix match type. This matches full path + elements. A path element refers to the list + of labels in the path split by the `/` separator. + When specified, a trailing `/` is ignored. For + example, the paths `/abc`, `/abc/`, and `/abc/def` + would all match the prefix `/abc`, but the path + `/abcd` would not. \n " + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. + Additional types may be added in a future release + of the API. \n Note that values may be added + to this enum, implementations must ensure that + unknown values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Attached Condition for the Route + to `status: False`, with a Reason of `UnsupportedValue`. + \n " + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + type: object + required: + - type + type: object + maxItems: 16 + type: array + matches: + default: + - path: + type: PathPrefix + value: / + description: "Matches define conditions used for matching the + rule against incoming HTTP requests. Each match is independent, + i.e. this rule will be matched if **any** one of the matches + is satisfied. \n For example, take the following matches configuration: + \n ``` matches: - path: value: \"/foo\" headers: - + name: \"version\" value: \"v2\" - path: value: \"/v2/foo\" + ``` \n For a request to match against this rule, a request + must satisfy EITHER of the two conditions: \n - path prefixed + with `/foo` AND contains the header `version: v2` - path prefix + of `/v2/foo` \n See the documentation for HTTPRouteMatch on + how to specify multiple match conditions that should be ANDed + together. \n If no matches are specified, the default is a + prefix path match on \"/\", which has the effect of matching + every HTTP request. \n Proxy or Load Balancer routing configuration + generated from HTTPRoutes MUST prioritize rules based on the + following criteria, continuing on ties. Precedence must be + given to the Rule with the largest number of: \n * Characters + in a matching non-wildcard hostname. * Characters in a matching + hostname. * Characters in a matching path. * Header matches. + * Query param matches. \n If ties still exist across multiple + Routes, matching precedence MUST be determined in order of + the following criteria, continuing on ties: \n * The oldest + Route based on creation timestamp. * The Route appearing first + in alphabetical order by \"{namespace}/{name}\". \n If ties + still exist within the Route that has been given precedence, + matching precedence MUST be granted to the FIRST matching + rule (in list order) meeting the above criteria. \n When no + rules matching a request have been successfully attached to + the parent a request is coming from, a HTTP 404 status code + MUST be returned." + items: + description: "HTTPRouteMatch defines the predicate used to + match requests to a given action. Multiple match types are + ANDed together, i.e. the match will evaluate to true only + if all conditions are satisfied. \n For example, the match + below will match a HTTP request only if its path starts + with `/foo` AND it contains the `version: v1` header: \n + ``` match: path: value: \"/foo\" headers: - name: + \"version\" value \"v1\" ```" + properties: + headers: + description: Headers specifies HTTP request header matchers. + Multiple match values are ANDed together, meaning, a + request must match all the specified headers to select + the route. + items: + description: HTTPHeaderMatch describes how to select + a HTTP route by matching HTTP request headers. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case insensitive. + (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent header + names, only the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be + ignored. Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered equivalent. + \n When a header is repeated in an HTTP request, + it is implementation-specific behavior as to how + this is represented. Generally, proxies should + follow the guidance from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 + regarding processing a repeated header, with special + handling for \"Set-Cookie\"." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: "Type specifies how to match against + the value of the header. \n Support: Core (Exact) + \n Support: Custom (RegularExpression) \n Since + RegularExpression HeaderMatchType has custom conformance, + implementations can support POSIX, PCRE or any + other dialects of regular expressions. Please + read the implementation's documentation to determine + the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to + be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: "Method specifies HTTP method matcher. When + specified, this route will be matched only if the request + has the specified method. \n Support: Extended" + enum: + - GET + - HEAD + - POST + - PUT + - DELETE + - CONNECT + - OPTIONS + - TRACE + - PATCH + type: string + path: + default: + type: PathPrefix + value: / + description: Path specifies a HTTP request path matcher. + If this field is not specified, a default prefix match + on the "/" path is provided. + properties: + type: + default: PathPrefix + description: "Type specifies how to match against + the path Value. \n Support: Core (Exact, PathPrefix) + \n Support: Custom (RegularExpression)" + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + queryParams: + description: QueryParams specifies HTTP query parameter + matchers. Multiple match values are ANDed together, + meaning, a request must match all the specified query + parameters to select the route. + items: + description: HTTPQueryParamMatch describes how to select + a HTTP route by matching HTTP query parameters. + properties: + name: + description: "Name is the name of the HTTP query + param to be matched. This must be an exact string + match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). + \n If multiple entries specify equivalent query + param names, only the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST + be ignored. \n If a query param is repeated in + an HTTP request, the behavior is purposely left + undefined, since different data planes have different + capabilities. However, it's *recommended* that + implementations should match against the first + value of the param if the data plane supports + it, as this behavior is expected in other load + balancing contexts outside of the Gateway API. + Users should not route traffic based on repeated + query params to guard themselves against potential + differences in the implementations." + maxLength: 256 + minLength: 1 + type: string + type: + default: Exact + description: "Type specifies how to match against + the value of the query parameter. \n Support: + Extended (Exact) \n Support: Custom (RegularExpression) + \n Since RegularExpression QueryParamMatchType + has custom conformance, implementations can support + POSIX, PCRE or any other dialects of regular expressions. + Please read the implementation's documentation + to determine the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param + to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + type: object + maxItems: 16 + type: array + type: object + status: + description: Status defines the current state of HTTPRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) + that are associated with the route, and the status of the route + with respect to each parent. When this route attaches to a parent, + the controller that manages the parent must add an entry to this + list when the controller first sees the route and should update + the entry as appropriate when the route or gateway is modified. + \n Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this + API can only populate Route status for the Gateways/parent resources + they are responsible for. \n A maximum of 32 Gateways will be represented + in this list. An empty list means the route has not been attached + to any Gateway." + items: + description: RouteParentStatus describes the status of a route with + respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with + respect to the Gateway. Note that the route's availability + is also subject to the Gateway's own status conditions and + listener status. \n If the Route's ParentRef specifies an + existing Gateway that supports Routes of this kind AND that + Gateway's controller has sufficient access, then that Gateway's + controller MUST set the \"Accepted\" condition on the Route, + to indicate whether the route has been accepted or rejected + by the Gateway, and why. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates + the name of the controller that wrote this status. This corresponds + with the controllerName field on GatewayClass. \n Example: + \"example.net/gateway-controller\". \n The format of this + field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + \n Controllers MUST populate this field when writing status. + Controllers should ensure that entries to status populated + with their ControllerName are cleaned up when they are no + longer necessary." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec + that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n Support: + Core (Gateway) \n Support: Custom (Other Resources)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified, this refers to the local namespace of + the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. + It can be interpreted differently based on the type of + parent resource. \n When the parent resource is a Gateway, + this targets all listeners listening on the specified + port that also support this kind of Route(and select this + Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to + a specific port as opposed to a listener(s) whose port(s) + may be changed. When both Port and SectionName are specified, + the name and port of the selected listener must match + both specified values. \n Implementations MAY choose to + support other parent resources. Implementations supporting + other types of parent resources MUST clearly document + how/if Port is interpreted. \n For the purpose of status, + an attachment is considered successful as long as the + parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them + by Route kind, namespace, or hostname. If 1 of 2 Gateway + listeners accept attachment from the referencing Route, + the Route MUST be considered successfully attached. If + no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name. When both Port (experimental) and SectionName are + specified, the name and port of the selected listener + must match both specified values. \n Implementations MAY + choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this + will reference the entire resource. For the purpose of + status, an attachment is considered successful if at least + one section in the parent resource accepts it. For example, + Gateway listeners can restrict which Routes can attach + to them by Route kind, namespace, or hostname. If 1 of + 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: false + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.hostnames + name: Hostnames + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: HTTPRoute provides a way to route HTTP requests. This includes + the capability to match requests by hostname, path, header, or query param. + Filters can be used to specify additional processing steps. Backends specify + where matching requests should be routed. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of HTTPRoute. + properties: + hostnames: + description: "Hostnames defines a set of hostname that should match + against the HTTP Host header to select a HTTPRoute to process the + request. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may + be prefixed with a wildcard label (`*.`). The wildcard label + must appear by itself as the first label. \n If a hostname is specified + by both the Listener and HTTPRoute, there must be at least one intersecting + hostname for the HTTPRoute to be attached to the Listener. For example: + \n * A Listener with `test.example.com` as the hostname matches + HTTPRoutes that have either not specified any hostnames, or have + specified at least one of `test.example.com` or `*.example.com`. + * A Listener with `*.example.com` as the hostname matches HTTPRoutes + \ that have either not specified any hostnames or have specified + at least one hostname that matches the Listener hostname. For + example, `*.example.com`, `test.example.com`, and `foo.test.example.com` + would all match. On the other hand, `example.com` and `test.example.net` + would not match. \n Hostnames that are prefixed with a wildcard + label (`*.`) are interpreted as a suffix match. That means that + a match for `*.example.com` would match both `test.example.com`, + and `foo.test.example.com`, but not `example.com`. \n If both the + Listener and HTTPRoute have specified hostnames, any HTTPRoute hostnames + that do not match the Listener hostname MUST be ignored. For example, + if a Listener specified `*.example.com`, and the HTTPRoute specified + `test.example.com` and `test.example.net`, `test.example.net` must + not be considered for a match. \n If both the Listener and HTTPRoute + have specified hostnames, and none match with the criteria above, + then the HTTPRoute is not accepted. The implementation must raise + an 'Accepted' Condition with a status of `False` in the corresponding + RouteParentStatus. \n Support: Core" + items: + description: "Hostname is the fully qualified domain name of a network + host. This matches the RFC 1123 definition of a hostname with + 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname + may be prefixed with a wildcard label (`*.`). The wildcard label + must appear by itself as the first label. \n Hostname can be \"precise\" + which is a domain name without the terminating dot of a network + host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain + name prefixed with a single wildcard label (e.g. `*.example.com`). + \n Note that as per RFC1035 and RFC1123, a *label* must consist + of lower case alphanumeric characters or '-', and must start and + end with an alphanumeric character. No other punctuation is allowed." + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + description: "ParentRefs references the resources (usually Gateways) + that a Route wants to be attached to. Note that the referenced parent + resource needs to allow this for the attachment to be complete. + For Gateways, that means the Gateway needs to allow attachment from + Routes of this kind and namespace. \n The only kind of parent resource + with \"Core\" support is Gateway. This API may be extended in the + future to support additional kinds of parent resources such as one + of the route kinds. \n It is invalid to reference an identical parent + more than once. It is valid to reference multiple distinct sections + within the same parent resource, such as 2 Listeners within a Gateway. + \n It is possible to separately reference multiple distinct objects + that may be collapsed by an implementation. For example, some implementations + may choose to merge compatible Gateway Listeners together. If that + is the case, the list of routes attached to those resources should + also be merged." + items: + description: "ParentReference identifies an API object (usually + a Gateway) that can be considered a parent of this resource (usually + a route). The only kind of parent resource with \"Core\" support + is Gateway. This API may be extended in the future to support + additional kinds of parent resources, such as HTTPRoute. \n The + API object must be valid in the cluster; the Group and Kind must + be registered in the cluster for this reference to be valid." + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n Support: Core + (Gateway) \n Support: Custom (Other Resources)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. When + unspecified, this refers to the local namespace of the Route. + \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. It + can be interpreted differently based on the type of parent + resource. \n When the parent resource is a Gateway, this targets + all listeners listening on the specified port that also support + this kind of Route(and select this Route). It's not recommended + to set `Port` unless the networking behaviors specified in + a Route must apply to a specific port as opposed to a listener(s) + whose port(s) may be changed. When both Port and SectionName + are specified, the name and port of the selected listener + must match both specified values. \n Implementations MAY choose + to support other parent resources. Implementations supporting + other types of parent resources MUST clearly document how/if + Port is interpreted. \n For the purpose of status, an attachment + is considered successful as long as the parent resource accepts + it partially. For example, Gateway listeners can restrict + which Routes can attach to them by Route kind, namespace, + or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this + Route, the Route MUST be considered detached from the Gateway. + \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within the + target resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match both + specified values. \n Implementations MAY choose to support + attaching Routes to other resources. If that is the case, + they MUST clearly document how SectionName is interpreted. + \n When unspecified (empty string), this will reference the + entire resource. For the purpose of status, an attachment + is considered successful if at least one section in the parent + resource accepts it. For example, Gateway listeners can restrict + which Routes can attach to them by Route kind, namespace, + or hostname. If 1 of 2 Gateway listeners accept attachment + from the referencing Route, the Route MUST be considered successfully + attached. If no Gateway listeners accept attachment from this + Route, the Route MUST be considered detached from the Gateway. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + rules: + default: + - matches: + - path: + type: PathPrefix + value: / + description: Rules are a list of HTTP matchers, filters and actions. + items: + description: HTTPRouteRule defines semantics for matching an HTTP + request based on conditions (matches), processing it (filters), + and forwarding the request to an API object (backendRefs). + properties: + backendRefs: + description: "BackendRefs defines the backend(s) where matching + requests should be sent. \n Failure behavior here depends + on how many BackendRefs are specified and how many are invalid. + \n If *all* entries in BackendRefs are invalid, and there + are also no filters specified in this route rule, *all* traffic + which matches this rule MUST receive a 500 status code. \n + See the HTTPBackendRef definition for the rules about what + makes a single HTTPBackendRef invalid. \n When a HTTPBackendRef + is invalid, 500 status codes MUST be returned for requests + that would have otherwise been routed to an invalid backend. + If multiple backends are specified, and some are invalid, + the proportion of requests that would otherwise have been + routed to an invalid backend MUST receive a 500 status code. + \n For example, if two backends are specified with equal weights, + and one is invalid, 50 percent of traffic must receive a 500. + Implementations may choose how that 50 percent is determined. + \n Support: Core for Kubernetes Service \n Support: Custom + for any other resource \n Support for weight: Core" + items: + description: HTTPBackendRef defines how a HTTPRoute should + forward an HTTP request. + properties: + filters: + description: "Filters defined at this level should be + executed if and only if the request is being forwarded + to the backend defined here. \n Support: Custom (For + broader support of filters, use the Filters field in + HTTPRouteRule.)" + items: + description: HTTPRouteFilter defines processing steps + that must be completed during the request or response + lifecycle. HTTPRouteFilters are meant as an extension + point to express processing that may be done in Gateway + implementations. Some examples include request or + response modification, implementing authentication + strategies, rate-limiting, and traffic shaping. API + guarantee/conformance is defined based on the type + of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific + extension to the \"filter\" behavior. For example, + resource \"myroutefilter\" in group \"networking.example.net\"). + ExtensionRef MUST NOT be used for core and extended + filters. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. + For example, "networking.k8s.io". When unspecified + (empty string), core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For + example "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema + for a filter that modifies request headers. \n + Support: Core" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It + appends to any existing values associated + with the header name. \n Input: GET /foo + HTTP/1.1 my-header: foo \n Config: add: + \ - name: \"my-header\" value: \"bar\" + \n Output: GET /foo HTTP/1.1 my-header: + foo my-header: bar" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from + the HTTP request before the action. The value + of Remove is a list of HTTP header names. + Note that the header names are case-insensitive + (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: + foo my-header2: bar my-header3: baz \n + Config: remove: [\"my-header1\", \"my-header3\"] + \n Output: GET /foo HTTP/1.1 my-header2: + bar" + items: + type: string + maxItems: 16 + type: array + set: + description: "Set overwrites the request with + the given header (name, value) before the + action. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: set: - name: \"my-header\" + \ value: \"bar\" \n Output: GET /foo + HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP + Header name and value as defined by RFC + 7230. + properties: + name: + description: "Name is the name of the + HTTP Header to be matched. Name matching + MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an + equivalent name MUST be considered for + a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for + a filter that mirrors requests. Requests are sent + to the specified destination, but responses from + that destination are ignored. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource + where mirrored requests are sent. \n If the + referent cannot be found, this BackendRef + is invalid and must be dropped from the Gateway. + The controller must ensure the \"ResolvedRefs\" + condition on the Route status is set to `status: + False` and not configure this backend in the + underlying implementation. \n If there is + a cross-namespace reference to an *existing* + object that is not allowed by a ReferenceGrant, + the controller must ensure the \"ResolvedRefs\" + \ condition on the Route is set to `status: + False`, with the \"RefNotPermitted\" reason + and not configure this backend in the underlying + implementation. \n In either error case, the + Message of the `ResolvedRefs` Condition should + be used to provide more detail about the problem. + \n Support: Extended for Kubernetes Service + \n Support: Custom for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "networking.k8s.io". When + unspecified (empty string), core API group + is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: Kind is kind of the referent. + For example "HTTPRoute" or "Service". + Defaults to "Service" when not specified. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace + of the backend. When unspecified, the + local namespace is inferred. \n Note that + when a namespace is specified, a ReferenceGrant + object is required in the referent namespace + to allow that namespace's owner to accept + the reference. See the ReferenceGrant + documentation for details. \n Support: + Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination + port number to use for this resource. + Port is required when the referent is + a Kubernetes Service. In this case, the + port number is the service port number, + not the target port. For other resources, + destination port might be derived from + the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for + a filter that responds to the request with an + HTTP redirection. \n Support: Core" + properties: + hostname: + description: "Hostname is the hostname to be + used in the value of the `Location` header + in the response. When empty, the hostname + of the request is used. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines parameters used to + modify the path of the incoming request. The + modified path is then used to construct the + `Location` header. When empty, the request + path is used as-is. \n Support: Extended \n + " + properties: + replaceFullPath: + description: "ReplaceFullPath specifies + the value with which to replace the full + path of a request during a rewrite or + redirect. \n " + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies + the value with which to replace the prefix + match of a request during a rewrite or + redirect. For example, a request to \"/foo/bar\" + with a prefix match of \"/foo\" would + be modified to \"/bar\". \n Note that + this matches the behavior of the PathPrefix + match type. This matches full path elements. + A path element refers to the list of labels + in the path split by the `/` separator. + When specified, a trailing `/` is ignored. + For example, the paths `/abc`, `/abc/`, + and `/abc/def` would all match the prefix + `/abc`, but the path `/abcd` would not. + \n " + maxLength: 1024 + type: string + type: + description: "Type defines the type of path + modifier. Additional types may be added + in a future release of the API. \n Note + that values may be added to this enum, + implementations must ensure that unknown + values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Attached Condition for the + Route to `status: False`, with a Reason + of `UnsupportedValue`. \n " + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + port: + description: "Port is the port to be used in + the value of the `Location` header in the + response. When empty, port (if specified) + of the request is used. \n Support: Extended" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: "Scheme is the scheme to be used + in the value of the `Location` header in the + response. When empty, the scheme of the request + is used. \n Support: Extended \n Note that + values may be added to this enum, implementations + must ensure that unknown values will not cause + a crash. \n Unknown values here must result + in the implementation setting the Attached + Condition for the Route to `status: False`, + with a Reason of `UnsupportedValue`." + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status + code to be used in response. \n Support: Core + \n Note that values may be added to this enum, + implementations must ensure that unknown values + will not cause a crash. \n Unknown values + here must result in the implementation setting + the Attached Condition for the Route to `status: + False`, with a Reason of `UnsupportedValue`." + enum: + - 301 + - 302 + type: integer + type: object + type: + description: "Type identifies the type of filter + to apply. As with other API fields, types are + classified into three conformance levels: \n - + Core: Filter types and their corresponding configuration + defined by \"Support: Core\" in this package, + e.g. \"RequestHeaderModifier\". All implementations + must support core filters. \n - Extended: Filter + types and their corresponding configuration defined + by \"Support: Extended\" in this package, e.g. + \"RequestMirror\". Implementers are encouraged + to support extended filters. \n - Custom: Filters + that are defined and supported by specific vendors. + \ In the future, filters showing convergence + in behavior across multiple implementations + will be considered for inclusion in extended or + core conformance levels. Filter-specific configuration + for such filters is specified using the ExtensionRef + field. `Type` should be set to \"ExtensionRef\" + for custom filters. \n Implementers are encouraged + to define custom implementation types to extend + the core API with implementation-specific behavior. + \n If a reference to a custom filter type cannot + be resolved, the filter MUST NOT be skipped. Instead, + requests that would have been processed by that + filter MUST receive a HTTP error response. \n + Note that values may be added to this enum, implementations + must ensure that unknown values will not cause + a crash. \n Unknown values here must result in + the implementation setting the Attached Condition + for the Route to `status: False`, with a Reason + of `UnsupportedValue`. \n " + enum: + - RequestHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: "URLRewrite defines a schema for a + filter that modifies a request during forwarding. + \n Support: Extended \n " + properties: + hostname: + description: "Hostname is the value to be used + to replace the Host header value during forwarding. + \n Support: Extended \n " + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines a path rewrite. \n + Support: Extended \n " + properties: + replaceFullPath: + description: "ReplaceFullPath specifies + the value with which to replace the full + path of a request during a rewrite or + redirect. \n " + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies + the value with which to replace the prefix + match of a request during a rewrite or + redirect. For example, a request to \"/foo/bar\" + with a prefix match of \"/foo\" would + be modified to \"/bar\". \n Note that + this matches the behavior of the PathPrefix + match type. This matches full path elements. + A path element refers to the list of labels + in the path split by the `/` separator. + When specified, a trailing `/` is ignored. + For example, the paths `/abc`, `/abc/`, + and `/abc/def` would all match the prefix + `/abc`, but the path `/abcd` would not. + \n " + maxLength: 1024 + type: string + type: + description: "Type defines the type of path + modifier. Additional types may be added + in a future release of the API. \n Note + that values may be added to this enum, + implementations must ensure that unknown + values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Attached Condition for the + Route to `status: False`, with a Reason + of `UnsupportedValue`. \n " + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + type: object + required: + - type + type: object + maxItems: 16 + type: array + group: + default: "" + description: Group is the group of the referent. For example, + "networking.k8s.io". When unspecified (empty string), + core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". Defaults to "Service" when + not specified. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the backend. + When unspecified, the local namespace is inferred. \n + Note that when a namespace is specified, a ReferenceGrant + object is required in the referent namespace to allow + that namespace's owner to accept the reference. See + the ReferenceGrant documentation for details. \n Support: + Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port number + to use for this resource. Port is required when the + referent is a Kubernetes Service. In this case, the + port number is the service port number, not the target + port. For other resources, destination port might be + derived from the referent resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + description: "Weight specifies the proportion of requests + forwarded to the referenced backend. This is computed + as weight/(sum of all weights in this BackendRefs list). + For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision + an implementation supports. Weight is not a percentage + and the sum of weights does not need to equal 100. \n + If only one backend is specified and it has a weight + greater than 0, 100% of the traffic is forwarded to + that backend. If weight is set to 0, no traffic should + be forwarded for this entry. If unspecified, weight + defaults to 1. \n Support for this field varies based + on the context where used." + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + maxItems: 16 + type: array + filters: + description: "Filters define the filters that are applied to + requests that match this rule. \n The effects of ordering + of multiple behaviors are currently unspecified. This can + change in the future based on feedback during the alpha stage. + \n Conformance-levels at this level are defined based on the + type of filter: \n - ALL core filters MUST be supported by + all implementations. - Implementers are encouraged to support + extended filters. - Implementation-specific custom filters + have no API guarantees across implementations. \n Specifying + a core filter multiple times has unspecified or custom conformance. + \n All filters are expected to be compatible with each other + except for the URLRewrite and RequestRedirect filters, which + may not be combined. If an implementation can not support + other combinations of filters, they must clearly document + that limitation. In all cases where incompatible or unsupported + filters are specified, implementations MUST add a warning + condition to status. \n Support: Core" + items: + description: HTTPRouteFilter defines processing steps that + must be completed during the request or response lifecycle. + HTTPRouteFilters are meant as an extension point to express + processing that may be done in Gateway implementations. + Some examples include request or response modification, + implementing authentication strategies, rate-limiting, and + traffic shaping. API guarantee/conformance is defined based + on the type of the filter. + properties: + extensionRef: + description: "ExtensionRef is an optional, implementation-specific + extension to the \"filter\" behavior. For example, + resource \"myroutefilter\" in group \"networking.example.net\"). + ExtensionRef MUST NOT be used for core and extended + filters. \n Support: Implementation-specific" + properties: + group: + description: Group is the group of the referent. For + example, "networking.k8s.io". When unspecified (empty + string), core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example + "HTTPRoute" or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + description: "RequestHeaderModifier defines a schema for + a filter that modifies request headers. \n Support: + Core" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It appends + to any existing values associated with the header + name. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: add: - name: \"my-header\" value: + \"bar\" \n Output: GET /foo HTTP/1.1 my-header: + foo my-header: bar" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the + HTTP request before the action. The value of Remove + is a list of HTTP header names. Note that the header + names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo + \ my-header2: bar my-header3: baz \n Config: + \ remove: [\"my-header1\", \"my-header3\"] \n Output: + \ GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + set: + description: "Set overwrites the request with the + given header (name, value) before the action. \n + Input: GET /foo HTTP/1.1 my-header: foo \n Config: + \ set: - name: \"my-header\" value: \"bar\" + \n Output: GET /foo HTTP/1.1 my-header: bar" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case + insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + description: "RequestMirror defines a schema for a filter + that mirrors requests. Requests are sent to the specified + destination, but responses from that destination are + ignored. \n Support: Extended" + properties: + backendRef: + description: "BackendRef references a resource where + mirrored requests are sent. \n If the referent cannot + be found, this BackendRef is invalid and must be + dropped from the Gateway. The controller must ensure + the \"ResolvedRefs\" condition on the Route status + is set to `status: False` and not configure this + backend in the underlying implementation. \n If + there is a cross-namespace reference to an *existing* + object that is not allowed by a ReferenceGrant, + the controller must ensure the \"ResolvedRefs\" + \ condition on the Route is set to `status: False`, + with the \"RefNotPermitted\" reason and not configure + this backend in the underlying implementation. \n + In either error case, the Message of the `ResolvedRefs` + Condition should be used to provide more detail + about the problem. \n Support: Extended for Kubernetes + Service \n Support: Custom for any other resource" + properties: + group: + default: "" + description: Group is the group of the referent. + For example, "networking.k8s.io". When unspecified + (empty string), core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: Kind is kind of the referent. For + example "HTTPRoute" or "Service". Defaults to + "Service" when not specified. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the + backend. When unspecified, the local namespace + is inferred. \n Note that when a namespace is + specified, a ReferenceGrant object is required + in the referent namespace to allow that namespace's + owner to accept the reference. See the ReferenceGrant + documentation for details. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: Port specifies the destination port + number to use for this resource. Port is required + when the referent is a Kubernetes Service. In + this case, the port number is the service port + number, not the target port. For other resources, + destination port might be derived from the referent + resource or this field. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + required: + - backendRef + type: object + requestRedirect: + description: "RequestRedirect defines a schema for a filter + that responds to the request with an HTTP redirection. + \n Support: Core" + properties: + hostname: + description: "Hostname is the hostname to be used + in the value of the `Location` header in the response. + When empty, the hostname of the request is used. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines parameters used to modify + the path of the incoming request. The modified path + is then used to construct the `Location` header. + When empty, the request path is used as-is. \n Support: + Extended \n " + properties: + replaceFullPath: + description: "ReplaceFullPath specifies the value + with which to replace the full path of a request + during a rewrite or redirect. \n " + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the + value with which to replace the prefix match + of a request during a rewrite or redirect. For + example, a request to \"/foo/bar\" with a prefix + match of \"/foo\" would be modified to \"/bar\". + \n Note that this matches the behavior of the + PathPrefix match type. This matches full path + elements. A path element refers to the list + of labels in the path split by the `/` separator. + When specified, a trailing `/` is ignored. For + example, the paths `/abc`, `/abc/`, and `/abc/def` + would all match the prefix `/abc`, but the path + `/abcd` would not. \n " + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. + Additional types may be added in a future release + of the API. \n Note that values may be added + to this enum, implementations must ensure that + unknown values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Attached Condition for the Route + to `status: False`, with a Reason of `UnsupportedValue`. + \n " + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + port: + description: "Port is the port to be used in the value + of the `Location` header in the response. When empty, + port (if specified) of the request is used. \n Support: + Extended" + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + description: "Scheme is the scheme to be used in the + value of the `Location` header in the response. + When empty, the scheme of the request is used. \n + Support: Extended \n Note that values may be added + to this enum, implementations must ensure that unknown + values will not cause a crash. \n Unknown values + here must result in the implementation setting the + Attached Condition for the Route to `status: False`, + with a Reason of `UnsupportedValue`." + enum: + - http + - https + type: string + statusCode: + default: 302 + description: "StatusCode is the HTTP status code to + be used in response. \n Support: Core \n Note that + values may be added to this enum, implementations + must ensure that unknown values will not cause a + crash. \n Unknown values here must result in the + implementation setting the Attached Condition for + the Route to `status: False`, with a Reason of `UnsupportedValue`." + enum: + - 301 + - 302 + type: integer + type: object + type: + description: "Type identifies the type of filter to apply. + As with other API fields, types are classified into + three conformance levels: \n - Core: Filter types and + their corresponding configuration defined by \"Support: + Core\" in this package, e.g. \"RequestHeaderModifier\". + All implementations must support core filters. \n + - Extended: Filter types and their corresponding configuration + defined by \"Support: Extended\" in this package, + e.g. \"RequestMirror\". Implementers are encouraged + to support extended filters. \n - Custom: Filters that + are defined and supported by specific vendors. In + the future, filters showing convergence in behavior + across multiple implementations will be considered + for inclusion in extended or core conformance levels. + Filter-specific configuration for such filters is + specified using the ExtensionRef field. `Type` should + be set to \"ExtensionRef\" for custom filters. \n + Implementers are encouraged to define custom implementation + types to extend the core API with implementation-specific + behavior. \n If a reference to a custom filter type + cannot be resolved, the filter MUST NOT be skipped. + Instead, requests that would have been processed by + that filter MUST receive a HTTP error response. \n Note + that values may be added to this enum, implementations + must ensure that unknown values will not cause a crash. + \n Unknown values here must result in the implementation + setting the Attached Condition for the Route to `status: + False`, with a Reason of `UnsupportedValue`. \n " + enum: + - RequestHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + description: "URLRewrite defines a schema for a filter + that modifies a request during forwarding. \n Support: + Extended \n " + properties: + hostname: + description: "Hostname is the value to be used to + replace the Host header value during forwarding. + \n Support: Extended \n " + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + description: "Path defines a path rewrite. \n Support: + Extended \n " + properties: + replaceFullPath: + description: "ReplaceFullPath specifies the value + with which to replace the full path of a request + during a rewrite or redirect. \n " + maxLength: 1024 + type: string + replacePrefixMatch: + description: "ReplacePrefixMatch specifies the + value with which to replace the prefix match + of a request during a rewrite or redirect. For + example, a request to \"/foo/bar\" with a prefix + match of \"/foo\" would be modified to \"/bar\". + \n Note that this matches the behavior of the + PathPrefix match type. This matches full path + elements. A path element refers to the list + of labels in the path split by the `/` separator. + When specified, a trailing `/` is ignored. For + example, the paths `/abc`, `/abc/`, and `/abc/def` + would all match the prefix `/abc`, but the path + `/abcd` would not. \n " + maxLength: 1024 + type: string + type: + description: "Type defines the type of path modifier. + Additional types may be added in a future release + of the API. \n Note that values may be added + to this enum, implementations must ensure that + unknown values will not cause a crash. \n Unknown + values here must result in the implementation + setting the Attached Condition for the Route + to `status: False`, with a Reason of `UnsupportedValue`. + \n " + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + type: object + required: + - type + type: object + maxItems: 16 + type: array + matches: + default: + - path: + type: PathPrefix + value: / + description: "Matches define conditions used for matching the + rule against incoming HTTP requests. Each match is independent, + i.e. this rule will be matched if **any** one of the matches + is satisfied. \n For example, take the following matches configuration: + \n ``` matches: - path: value: \"/foo\" headers: - + name: \"version\" value: \"v2\" - path: value: \"/v2/foo\" + ``` \n For a request to match against this rule, a request + must satisfy EITHER of the two conditions: \n - path prefixed + with `/foo` AND contains the header `version: v2` - path prefix + of `/v2/foo` \n See the documentation for HTTPRouteMatch on + how to specify multiple match conditions that should be ANDed + together. \n If no matches are specified, the default is a + prefix path match on \"/\", which has the effect of matching + every HTTP request. \n Proxy or Load Balancer routing configuration + generated from HTTPRoutes MUST prioritize rules based on the + following criteria, continuing on ties. Precedence must be + given to the Rule with the largest number of: \n * Characters + in a matching non-wildcard hostname. * Characters in a matching + hostname. * Characters in a matching path. * Header matches. + * Query param matches. \n If ties still exist across multiple + Routes, matching precedence MUST be determined in order of + the following criteria, continuing on ties: \n * The oldest + Route based on creation timestamp. * The Route appearing first + in alphabetical order by \"{namespace}/{name}\". \n If ties + still exist within the Route that has been given precedence, + matching precedence MUST be granted to the FIRST matching + rule (in list order) meeting the above criteria. \n When no + rules matching a request have been successfully attached to + the parent a request is coming from, a HTTP 404 status code + MUST be returned." + items: + description: "HTTPRouteMatch defines the predicate used to + match requests to a given action. Multiple match types are + ANDed together, i.e. the match will evaluate to true only + if all conditions are satisfied. \n For example, the match + below will match a HTTP request only if its path starts + with `/foo` AND it contains the `version: v1` header: \n + ``` match: path: value: \"/foo\" headers: - name: + \"version\" value \"v1\" ```" + properties: + headers: + description: Headers specifies HTTP request header matchers. + Multiple match values are ANDed together, meaning, a + request must match all the specified headers to select + the route. + items: + description: HTTPHeaderMatch describes how to select + a HTTP route by matching HTTP request headers. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case insensitive. + (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent header + names, only the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST be + ignored. Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered equivalent. + \n When a header is repeated in an HTTP request, + it is implementation-specific behavior as to how + this is represented. Generally, proxies should + follow the guidance from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 + regarding processing a repeated header, with special + handling for \"Set-Cookie\"." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: "Type specifies how to match against + the value of the header. \n Support: Core (Exact) + \n Support: Custom (RegularExpression) \n Since + RegularExpression HeaderMatchType has custom conformance, + implementations can support POSIX, PCRE or any + other dialects of regular expressions. Please + read the implementation's documentation to determine + the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to + be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + description: "Method specifies HTTP method matcher. When + specified, this route will be matched only if the request + has the specified method. \n Support: Extended" + enum: + - GET + - HEAD + - POST + - PUT + - DELETE + - CONNECT + - OPTIONS + - TRACE + - PATCH + type: string + path: + default: + type: PathPrefix + value: / + description: Path specifies a HTTP request path matcher. + If this field is not specified, a default prefix match + on the "/" path is provided. + properties: + type: + default: PathPrefix + description: "Type specifies how to match against + the path Value. \n Support: Core (Exact, PathPrefix) + \n Support: Custom (RegularExpression)" + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + description: Value of the HTTP path to match against. + maxLength: 1024 + type: string + type: object + queryParams: + description: QueryParams specifies HTTP query parameter + matchers. Multiple match values are ANDed together, + meaning, a request must match all the specified query + parameters to select the route. + items: + description: HTTPQueryParamMatch describes how to select + a HTTP route by matching HTTP query parameters. + properties: + name: + description: "Name is the name of the HTTP query + param to be matched. This must be an exact string + match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). + \n If multiple entries specify equivalent query + param names, only the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent query param name MUST + be ignored. \n If a query param is repeated in + an HTTP request, the behavior is purposely left + undefined, since different data planes have different + capabilities. However, it's *recommended* that + implementations should match against the first + value of the param if the data plane supports + it, as this behavior is expected in other load + balancing contexts outside of the Gateway API. + Users should not route traffic based on repeated + query params to guard themselves against potential + differences in the implementations." + maxLength: 256 + minLength: 1 + type: string + type: + default: Exact + description: "Type specifies how to match against + the value of the query parameter. \n Support: + Extended (Exact) \n Support: Custom (RegularExpression) + \n Since RegularExpression QueryParamMatchType + has custom conformance, implementations can support + POSIX, PCRE or any other dialects of regular expressions. + Please read the implementation's documentation + to determine the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP query param + to be matched. + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 8 + type: array + type: object + maxItems: 16 + type: array + type: object + status: + description: Status defines the current state of HTTPRoute. + properties: + parents: + description: "Parents is a list of parent resources (usually Gateways) + that are associated with the route, and the status of the route + with respect to each parent. When this route attaches to a parent, + the controller that manages the parent must add an entry to this + list when the controller first sees the route and should update + the entry as appropriate when the route or gateway is modified. + \n Note that parent references that cannot be resolved by an implementation + of this API will not be added to this list. Implementations of this + API can only populate Route status for the Gateways/parent resources + they are responsible for. \n A maximum of 32 Gateways will be represented + in this list. An empty list means the route has not been attached + to any Gateway." + items: + description: RouteParentStatus describes the status of a route with + respect to an associated Parent. + properties: + conditions: + description: "Conditions describes the status of the route with + respect to the Gateway. Note that the route's availability + is also subject to the Gateway's own status conditions and + listener status. \n If the Route's ParentRef specifies an + existing Gateway that supports Routes of this kind AND that + Gateway's controller has sufficient access, then that Gateway's + controller MUST set the \"Accepted\" condition on the Route, + to indicate whether the route has been accepted or rejected + by the Gateway, and why. \n A Route MUST be considered \"Accepted\" + if at least one of the Route's rules is implemented by the + Gateway. \n There are a number of cases where the \"Accepted\" + condition may not be set due to lack of controller visibility, + that includes when: \n * The Route refers to a non-existent + parent. * The Route is of a type that the controller does + not support. * The Route is in a namespace the controller + does not have access to." + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, type FooStatus struct{ + \ // Represents the observations of a foo's current state. + \ // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // + +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates + the name of the controller that wrote this status. This corresponds + with the controllerName field on GatewayClass. \n Example: + \"example.net/gateway-controller\". \n The format of this + field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + \n Controllers MUST populate this field when writing status. + Controllers should ensure that entries to status populated + with their ControllerName are cleaned up when they are no + longer necessary." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + parentRef: + description: ParentRef corresponds with a ParentRef in the spec + that this RouteParentStatus struct describes the status of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. \n Support: + Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n Support: + Core (Gateway) \n Support: Custom (Other Resources)" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified, this refers to the local namespace of + the Route. \n Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. + It can be interpreted differently based on the type of + parent resource. \n When the parent resource is a Gateway, + this targets all listeners listening on the specified + port that also support this kind of Route(and select this + Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to + a specific port as opposed to a listener(s) whose port(s) + may be changed. When both Port and SectionName are specified, + the name and port of the selected listener must match + both specified values. \n Implementations MAY choose to + support other parent resources. Implementations supporting + other types of parent resources MUST clearly document + how/if Port is interpreted. \n For the purpose of status, + an attachment is considered successful as long as the + parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them + by Route kind, namespace, or hostname. If 1 of 2 Gateway + listeners accept attachment from the referencing Route, + the Route MUST be considered successfully attached. If + no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name. When both Port (experimental) and SectionName are + specified, the name and port of the selected listener + must match both specified values. \n Implementations MAY + choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this + will reference the entire resource. For the purpose of + status, an attachment is considered successful if at least + one section in the parent resource accepts it. For example, + Gateway listeners can restrict which Routes can attach + to them by Route kind, namespace, or hostname. If 1 of + 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + required: + - controllerName + - parentRef + type: object + maxItems: 32 + type: array + required: + - parents + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/assets/gateway-api/gateway.networking.k8s.io_referencegrants.yaml b/assets/gateway-api/gateway.networking.k8s.io_referencegrants.yaml new file mode 100644 index 0000000000..8f71490f7a --- /dev/null +++ b/assets/gateway-api/gateway.networking.k8s.io_referencegrants.yaml @@ -0,0 +1,149 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/1086 + gateway.networking.k8s.io/bundle-version: v0.6.0-dev + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + name: referencegrants.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: ReferenceGrant + listKind: ReferenceGrantList + plural: referencegrants + shortNames: + - refgrant + singular: referencegrant + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: "ReferenceGrant identifies kinds of resources in other namespaces + that are trusted to reference the specified kinds of resources in the same + namespace as the policy. \n Each ReferenceGrant can be used to represent + a unique trust relationship. Additional Reference Grants can be used to + add to the set of trusted sources of inbound references for the namespace + they are defined within. \n All cross-namespace references in Gateway API + (with the exception of cross-namespace Gateway-route attachment) require + a ReferenceGrant. \n Support: Core" + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of ReferenceGrant. + properties: + from: + description: "From describes the trusted namespaces and kinds that + can reference the resources described in \"To\". Each entry in this + list must be considered to be an additional place that references + can be valid from, or to put this another way, entries must be combined + using OR. \n Support: Core" + items: + description: ReferenceGrantFrom describes trusted namespaces and + kinds. + properties: + group: + description: "Group is the group of the referent. When empty, + the Kubernetes core API group is inferred. \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: "Kind is the kind of the referent. Although implementations + may support additional resources, the following types are + part of the \"Core\" support level for this field. \n When + used to permit a SecretObjectReference: \n * Gateway \n When + used to permit a BackendObjectReference: \n * HTTPRoute * + TCPRoute * TLSRoute * UDPRoute" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + namespace: + description: "Namespace is the namespace of the referent. \n + Support: Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - namespace + type: object + maxItems: 16 + minItems: 1 + type: array + to: + description: "To describes the resources that may be referenced by + the resources described in \"From\". Each entry in this list must + be considered to be an additional place that references can be valid + to, or to put this another way, entries must be combined using OR. + \n Support: Core" + items: + description: ReferenceGrantTo describes what Kinds are allowed as + targets of the references. + properties: + group: + description: "Group is the group of the referent. When empty, + the Kubernetes core API group is inferred. \n Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: "Kind is the kind of the referent. Although implementations + may support additional resources, the following types are + part of the \"Core\" support level for this field: \n * Secret + when used to permit a SecretObjectReference * Service when + used to permit a BackendObjectReference" + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. When unspecified, + this policy refers to all resources of the specified Group + and Kind in the local namespace. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + type: object + maxItems: 16 + minItems: 1 + type: array + required: + - from + - to + type: object + type: object + served: true + storage: true + subresources: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/go.mod b/go.mod index 8d26db2da6..cc89b5ec2d 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,10 @@ module github.com/openshift/cluster-ingress-operator go 1.19 require ( - github.com/Azure/azure-sdk-for-go v30.0.0+incompatible + github.com/Azure/azure-sdk-for-go v36.1.0+incompatible github.com/Azure/go-autorest/autorest v0.11.27 github.com/Azure/go-autorest/autorest/adal v0.9.20 - github.com/Azure/go-autorest/autorest/to v0.2.0 + github.com/Azure/go-autorest/autorest/to v0.3.1-0.20191028180845-3492b2aff503 github.com/IBM/go-sdk-core/v5 v5.8.0 github.com/IBM/networking-go-sdk v0.26.0 github.com/aliyun/alibaba-cloud-sdk-go v1.61.1286 @@ -16,14 +16,16 @@ require ( github.com/go-logr/zapr v1.2.3 github.com/google/go-cmp v0.5.9 github.com/kevinburke/go-bindata v3.11.0+incompatible - github.com/openshift/api v0.0.0-20230213202419-42edf4f1d905 + github.com/maistra/istio-operator v0.0.0-20230213165116-3138f8d64e59 + github.com/openshift/api v3.9.1-0.20190924102528-32369d4db2ad+incompatible github.com/openshift/client-go v0.0.0-20230120202327-72f107311084 - github.com/openshift/library-go v0.0.0-20230120214501-9bc305884fcb + github.com/openshift/library-go v0.0.0-20230209193239-2e9167362f31 + github.com/operator-framework/api v0.3.7-0.20200528122852-759ca0d84007 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/common v0.37.0 github.com/spf13/cobra v1.6.0 - github.com/stretchr/testify v1.8.0 + github.com/stretchr/testify v1.8.1 github.com/summerwind/h2spec v0.0.0-20200804131034-70ac22940108 github.com/tcnksm/go-httpstat v0.2.1-0.20191008022543-e866bb274419 go.uber.org/zap v1.24.0 @@ -33,30 +35,33 @@ require ( gopkg.in/fsnotify.v1 v1.4.7 gopkg.in/yaml.v2 v2.4.0 k8s.io/api v0.26.1 + k8s.io/apiextensions-apiserver v0.26.1 k8s.io/apimachinery v0.26.1 k8s.io/apiserver v0.26.1 - k8s.io/client-go v0.26.1 - k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 + k8s.io/client-go v12.0.0+incompatible + k8s.io/utils v0.0.0-20230209194617-a36077c30491 sigs.k8s.io/controller-runtime v0.14.4 + sigs.k8s.io/gateway-api v0.5.1-0.20220921185115-ee7a83814203 ) require ( cloud.google.com/go v0.97.0 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/autorest/validation v0.1.0 // indirect + github.com/Azure/go-autorest/autorest/validation v0.2.1-0.20191028180845-3492b2aff503 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/blang/semver v3.5.1+incompatible // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect - github.com/fatih/color v1.7.0 // indirect + github.com/fatih/color v1.12.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/ghodss/yaml v1.0.0 // indirect + github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 // indirect github.com/go-openapi/errors v0.19.8 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.20.0 // indirect @@ -82,8 +87,8 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/leodido/go-urn v1.2.0 // indirect github.com/mailru/easyjson v0.7.6 // indirect - github.com/mattn/go-colorable v0.1.2 // indirect - github.com/mattn/go-isatty v0.0.8 // indirect + github.com/mattn/go-colorable v0.1.8 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/moby/spdystream v0.2.0 // indirect @@ -91,10 +96,12 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/ulid v1.3.1 // indirect + github.com/operator-framework/operator-sdk v0.18.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect github.com/robfig/cron v1.2.0 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect go.mongodb.org/mongo-driver v1.5.1 // indirect go.opencensus.io v0.23.0 // indirect @@ -114,7 +121,6 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.26.1 // indirect k8s.io/component-base v0.26.1 // indirect k8s.io/klog/v2 v2.80.1 // indirect k8s.io/kube-aggregator v0.26.1 // indirect @@ -124,3 +130,11 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) + +// These replace stanzas are necessary to import maistra/istio-operator and +// github.com/operator-framework/operator-sdk. +replace ( + bitbucket.org/ww/goautoneg => github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d + github.com/openshift/api => github.com/openshift/api v0.0.0-20230213202419-42edf4f1d905 + k8s.io/client-go => k8s.io/client-go v0.26.1 +) diff --git a/go.sum b/go.sum index 063e427e3b..42f18416d6 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,14 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.49.0/go.mod h1:hGvAdzcWNbyuxS3nWhD7H2cIJxjRRTRLQVB0bdputVY= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= @@ -34,40 +38,54 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.3.0/go.mod h1:9IAwXhoyBJ7z9LcAwkj0/7NnPzYaPeZxxVp3zm+5IqA= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +contrib.go.opencensus.io/exporter/ocagent v0.6.0/go.mod h1:zmKjrJcdo0aYcVS7bmEeSEBLPA9YJp5bjrofdU3pIXs= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-sdk-for-go v30.0.0+incompatible h1:6o1Yzl7wTBYg+xw0pY4qnalaPmEQolubEEdepo1/kmI= -github.com/Azure/azure-sdk-for-go v30.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v23.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v36.1.0+incompatible h1:smHlbChr/JDmsyUqELZXLs0YIgpXecIGdUibuc2983s= +github.com/Azure/azure-sdk-for-go v36.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v11.2.8+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.9.3-0.20191028180845-3492b2aff503/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A= github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.1-0.20191028180845-3492b2aff503/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg= github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= -github.com/Azure/go-autorest/autorest/to v0.2.0 h1:nQOZzFCudTh+TvquAtCRjM01VEYx85e9qbwt5ncW4L8= -github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= -github.com/Azure/go-autorest/autorest/validation v0.1.0 h1:ISSNzGUh+ZSzizJWOWzs8bwpXIePbGLW4z/AmUFGH5A= -github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= +github.com/Azure/go-autorest/autorest/to v0.3.1-0.20191028180845-3492b2aff503 h1:2McfZNaDqGPjv2pddK547PENIk4HV+NT7gvqRq4L0us= +github.com/Azure/go-autorest/autorest/to v0.3.1-0.20191028180845-3492b2aff503/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= +github.com/Azure/go-autorest/autorest/validation v0.2.1-0.20191028180845-3492b2aff503 h1:RBrGlrkPWapMcLp1M6ywCqyYKOAT5ERI6lYFvGKOThE= +github.com/Azure/go-autorest/autorest/validation v0.2.1-0.20191028180845-3492b2aff503/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= @@ -76,17 +94,37 @@ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUM github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/IBM/go-sdk-core/v5 v5.8.0 h1:Bn9BxTaKYKWpd+BDpVsL6XOOJl4QDgxux4gSdWi31vE= github.com/IBM/go-sdk-core/v5 v5.8.0/go.mod h1:+YbdhrjCHC84ls4MeBp+Hj4NZCni+tDAc0XQUqRO9Jc= github.com/IBM/networking-go-sdk v0.26.0 h1:K/geWMCgg5P0pbaVQ0eZLhim2G6yOZc8rjszbv2Kmzc= github.com/IBM/networking-go-sdk v0.26.0/go.mod h1:tVxXclpQs8nQJYPTr9ZPNC1voaPNQLy8iy/72oVfFtM= +github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= +github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Masterminds/sprig/v3 v3.1.0/go.mod h1:ONGMf7UfYGAbMXCZmQLy8x3lCDIPrEZE/rU8pmrbihA= +github.com/Masterminds/squirrel v1.2.0/go.mod h1:yaPeOnPG5ZRwL9oKdTsO/prlkPbXWZlRVMQ/gGlzIuA= +github.com/Masterminds/vcs v1.13.1/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OneOfOne/xxhash v1.2.6/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -95,35 +133,74 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/aliyun/alibaba-cloud-sdk-go v1.61.1286 h1:+Ah33S/QRnOFp4dM6VV2gYDbFu3Cj4HrRy1VpOhBzm8= github.com/aliyun/alibaba-cloud-sdk-go v1.61.1286/go.mod h1:9CMdKNL3ynIGPpfTcdwTvIm8SGuAZYYC4jFVSSvE1YQ= +github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= github.com/aws/aws-sdk-go v1.38.49 h1:E31vxjCe6a5I+mJLmUGaZobiWmg9KdWaud9IfceYeYQ= github.com/aws/aws-sdk-go v1.38.49/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= +github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= +github.com/brancz/gojsontoyaml v0.0.0-20191212081931-bf2969bbd742/go.mod h1:IyUJYN1gvWjtLF5ZuygmxbnsAyP3aJS6cHzIuZY50B0= +github.com/brancz/kube-rbac-proxy v0.5.0/go.mod h1:cL2VjiIFGS90Cjh5ZZ8+It6tMcBt8rwvuw2J6Mamnl0= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/bugsnag-go v1.5.3/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/bugsnag/panicwrap v1.2.0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= +github.com/cenkalti/backoff v0.0.0-20181003080854-62661b46c409/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/certifi/gocertifi v0.0.0-20180905225744-ee1a9a0726d2/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= +github.com/cespare/xxhash v0.0.0-20181017004759-096ff4a8a059/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -133,37 +210,117 @@ github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200107194136-26c1120b8d41/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY= +github.com/containerd/continuity v0.0.0-20200228182428-0f16d7a0959c/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY= +github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/containerd/typeurl v0.0.0-20190228175220-2a93cfde8c20/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/prometheus-operator v0.38.1-0.20200424145508-7e176fda06cc/go.mod h1:erio69w1R/aC14D5nfvAXSlE8FT8jt2Hnavc50Dp33A= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= +github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg= +github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= +github.com/cznic/internal v0.0.0-20180608152220-f44710a21d00/go.mod h1:olo7eAdKwJdXxb55TKGLiJ6xt1H0/tiiRCWKVLmtjY4= +github.com/cznic/lldb v1.1.0/go.mod h1:FIZVUmYUVhPwRiPzL8nD/mpFcJ/G7SSXjjXYG4uRI3A= +github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= +github.com/cznic/ql v1.2.0/go.mod h1:FbpzhyZrqr0PVlK6ury+PoW3T0ODUV22OeWIxcaOrSE= +github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ= +github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= +github.com/cznic/zappy v0.0.0-20160723133515-2533cb5b45cc/go.mod h1:Y1SNZ4dRUOKXshKUbwUapqNncRrho4mkjQebgEHZLj8= github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= +github.com/deislabs/oras v0.8.1/go.mod h1:Mx0rMSbBNaNfY9hjpccEnxkOqJL6KGjtxNHPLC4G4As= +github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= +github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dgryski/go-sip13 v0.0.0-20190329191031-25c5027a8c7b/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v0.0.0-20180920194744-16128bbac47f/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= +github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v0.7.3-0.20190103212154-2b7e084dc98b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v0.7.3-0.20190817195342-4760db040282/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= +github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/libnetwork v0.0.0-20190731215715-7f13a5c99f4b/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elastic/go-sysinfo v1.0.1/go.mod h1:O/D5m1VpYLwGjCYzEt63g3Z1uO3jXfwyzzjiW90t8cY= +github.com/elastic/go-sysinfo v1.1.1/go.mod h1:i1ZYdU10oLNfRzq4vq62BEwD2fH8KaWh6eh0ikPT9F0= +github.com/elastic/go-windows v1.0.0/go.mod h1:TsU0Nrp7/y3+VwE82FoZF8gC/XFg/Elz6CcloAxnPgU= +github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/elliotchance/orderedmap v1.4.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.10.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.11.1+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -175,27 +332,46 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= +github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= +github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW64qjjJq8M2u4dxNaBiDfKK+z/3eGDpXEQhc= +github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v0.0.0-20161025120501-bf82308e8c85/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= +github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/structtag v1.1.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk= +github.com/fsouza/go-dockerclient v0.0.0-20171004212419-da3951ba2e9e/go.mod h1:KpcjM623fQYE9MZiTGzKhjfxXAV9wbyX2C1cyRHfhl0= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/getsentry/raven-go v0.0.0-20190513200303-c977f96e1095/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew= +github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -205,24 +381,31 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.2.1/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= +github.com/go-logr/zapr v0.1.1/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.17.2/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.17.2/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= github.com/go-openapi/errors v0.19.8 h1:doM+tQdZbUm9gydV9yR+iQNmztbjj7I3sW4sIcAwIzc= github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.17.2/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= @@ -230,56 +413,74 @@ github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUe github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.17.2/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.17.2/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= +github.com/go-openapi/runtime v0.18.0/go.mod h1:uI6pHuxWYTy94zZxgcwJkUWa9wbIlhteGfloI10GD4U= github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.17.2/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.17.2/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= +github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= github.com/go-openapi/strfmt v0.20.2 h1:6XZL+fF4VZYFxKQGLAUB358hOrRh/wS51uWEtlONADE= github.com/go-openapi/strfmt v0.20.2/go.mod h1:43urheQI9dNtE5lTZQfuFJvjYJKPrxicATpEfZwHUNk= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.17.2/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/validate v0.17.2/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= +github.com/gobuffalo/envy v1.6.5/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ= github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/flect v0.1.5/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= github.com/gobuffalo/flect v0.2.0/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= +github.com/gobuffalo/flect v0.2.1/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= @@ -289,16 +490,28 @@ github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxs github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/logger v1.0.1/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc= github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/goccy/go-yaml v1.8.8/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA= +github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -306,9 +519,13 @@ github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptG github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-migrate/migrate/v4 v4.6.2/go.mod h1:JYi6reN3+Z734VZ0akNuyOJNcrg45ZL7LDBMW3WGJL0= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -341,10 +558,22 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho= +github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8= +github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= +github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= +github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= +github.com/gonum/graph v0.0.0-20170401004347-50b27dea7ebb/go.mod h1:ye018NnX1zrbOLqwBvs2HqyyTouQgnL8C+qzYk1snPY= +github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks= +github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A= +github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -359,9 +588,13 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= @@ -372,6 +605,7 @@ github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIG github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -381,58 +615,134 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0 h1:6DWmvNpomjL1+3liNSZbVns3zsYzzCjm6pRBO1tLeso= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gophercloud/gophercloud v0.2.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gophercloud/gophercloud v0.6.0/go.mod h1:GICNByuaEBibcjmjvI7QvYJSZEbGkcYwAR7EZK2WMqM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de h1:F7WD09S8QB4LrkEpka0dFPLSotH11HRpCsLIbIcJ7sU= +github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/mux v0.0.0-20191024121256-f395758b854c/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.4/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-health-probe v0.2.1-0.20181220223928-2bf0a5b182db/go.mod h1:uBKkC2RbarFsvS5jMJHpVhTLvGlGQj9JJwkaePE3FWI= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.1.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4= github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/memberlist v0.1.5/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/serf v0.8.5/go.mod h1:UpNcs7fFbpKIyZaUuSW6EPiH+eZC7OuyFD+wc1oal+k= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb v1.7.7/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= +github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= +github.com/jessevdk/go-flags v0.0.0-20180331124232-1c38ed7ad0cc/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jinzhu/copier v0.2.3/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= +github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -441,20 +751,26 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jsonnet-bundler/jsonnet-bundler v0.3.1/go.mod h1:/by7P/OoohkI3q4CgSFqcoFsVY+IaNbzOVDknEsKDeU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jteeuwen/go-bindata v3.0.8-0.20151023091102-a0ff2567cfb7+incompatible/go.mod h1:JVvhzYOiGBnFSYRyV00iY8q7/0PThjIYav1p9h5dmKs= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.1.0/go.mod h1:+1DpV8uIwteAhxNO0lgRox8gHkTG6w3OeDfAlg+qqjA= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/kevinburke/go-bindata v3.11.0+incompatible h1:RcC+GJNmrBHbGaOpQ9MBD8z22rdzlIm0esDRDkyxd4s= @@ -475,9 +791,25 @@ github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE= +github.com/kubernetes-sigs/kube-storage-version-migrator v0.0.0-20191127225502-51849bc15f17/go.mod h1:enH0BVV+4+DAgWdwSlMefG8bBzTfVMTr1lApzdLZ/cc= +github.com/kylelemons/godebug v0.0.0-20160406211939-eadb3ce320cb/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= +github.com/leanovate/gopter v0.2.4/go.mod h1:gNcbPWNEWRe4lm+bycKqxUYoH5uoVje5SkOJ3uoLer8= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.0/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= +github.com/lovoo/gcloud-opentracing v0.3.0/go.mod h1:ZFqk2y38kMDDikZPAK7ynTTGuyt17nSPdS3K5e+ZTBY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -486,24 +818,61 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/maistra/istio-operator v0.0.0-20230213165116-3138f8d64e59 h1:JI/0TPDapa9gBljIcFwb66+xNtp+uh0iihROQJ7gQHM= +github.com/maistra/istio-operator v0.0.0-20230213165116-3138f8d64e59/go.mod h1:Ls3+Sa4I7ZFjKm6myTbYYLsodrEKLiB3hi831fTbCk8= +github.com/markbates/inflect v1.0.4/go.mod h1:1fR9+pO2KHEO9ZRtto13gDwwZaAKstQzferVeWqbgNs= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20191113090002-7c0f6868bffe/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= +github.com/mattn/go-isatty v0.0.6/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.12.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM= github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.22/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/mikefarah/yaml/v2 v2.4.0/go.mod h1:ahVqZF4n1W4NqwvVnZzC4es67xsW9uR/RRf2RRxieJU= +github.com/mikefarah/yq/v2 v2.4.1/go.mod h1:i8SYf1XdgUvY2OFwSqGAtWOOgimD2McJ6iutoxRm4k0= +github.com/mikefarah/yq/v4 v4.6.0/go.mod h1:g/GwMlJwAzFgBFjgpN+QllD5aXAMa9yF2qE2jFkge0Q= +github.com/minio/minio-go/v6 v6.0.49/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -515,6 +884,10 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mozillazg/go-cos v0.13.0/go.mod h1:Zp6DvvXn0RUOXGJ2chmWt2bLEqRAnJnS3DnAZsJsoaE= +github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= @@ -522,72 +895,183 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= +github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v0.0.0-20170117200651-66bb6560562f/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M= github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= +github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= +github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= +github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= +github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= +github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.0.0-20191031171055-b133feaeeb2e/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v0.1.2-0.20190618234442-a950415649c7/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/openshift/api v0.0.0-20230213202419-42edf4f1d905 h1:f+W57UXpRIJeZIh9lGLIPix/YxdFDBgHDGo0OkIgQw0= github.com/openshift/api v0.0.0-20230213202419-42edf4f1d905/go.mod h1:ctXNyWanKEjGj8sss1KjjHQ3ENKFm33FFnS5BKaIPh4= +github.com/openshift/build-machinery-go v0.0.0-20200211121458-5e3d6e570160/go.mod h1:1CkcsT3aVebzRBzVTSbiKSkJMsC/CASqxesfqEMfJEc= +github.com/openshift/client-go v0.0.0-20200116152001-92a2713fa240/go.mod h1:4riOwdj99Hd/q+iAcJZfNCsQQQMwURnZV6RL4WHYS5w= github.com/openshift/client-go v0.0.0-20230120202327-72f107311084 h1:66uaqNwA+qYyQDwsMWUfjjau8ezmg1dzCqub13KZOcE= github.com/openshift/client-go v0.0.0-20230120202327-72f107311084/go.mod h1:M3h9m001PWac3eAudGG3isUud6yBjr5XpzLYLLTlHKo= -github.com/openshift/library-go v0.0.0-20230120214501-9bc305884fcb h1:ru6U+KzNbVFZXSfUkuH6WfHGCZ8rpBvKkJo8nXF+n5k= -github.com/openshift/library-go v0.0.0-20230120214501-9bc305884fcb/go.mod h1:wrrjvk/CK+nte9Wxend9/K6apy6Zep28lzM27/aJar8= +github.com/openshift/library-go v0.0.0-20200214084717-e77ad9dd8ebd/go.mod h1:0rRwY0q5NuKHdiP88Pe5+OVNU8mi0mv5XQ7f7nUbYVc= +github.com/openshift/library-go v0.0.0-20230209193239-2e9167362f31 h1:GYaeuwjUyjIOVvIVfYwExbPcQtGDpDZdH2e8jp6kl2Y= +github.com/openshift/library-go v0.0.0-20230209193239-2e9167362f31/go.mod h1:xO4nAf0qa56dgvEJWVD1WuwSJ8JWPU1TYLBQrlutWnE= +github.com/openshift/origin v0.0.0-20160503220234-8f127d736703/go.mod h1:0Rox5r9C8aQn6j1oAOQ0c1uC86mYbUFObzjBRvUKHII= +github.com/openshift/prom-label-proxy v0.1.1-0.20191016113035-b8153a7f39f1/go.mod h1:p5MuxzsYP1JPsNGwtjtcgRHHlGziCJJfztff91nNixw= +github.com/opentracing-contrib/go-stdlib v0.0.0-20190519235532-cf7a6c988dc9/go.mod h1:PLldrQSroqzH70Xl+1DQcGnefIbqsKR7UDaiux3zV+w= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/operator-framework/api v0.1.1/go.mod h1:yzNYR7qyJqRGOOp+bT6Z/iYSbSPNxeh3Si93Gx/3OBY= +github.com/operator-framework/api v0.3.4/go.mod h1:TmRmw+8XOUaDPq6SP9gA8cIexNf/Pq8LMFY7YaKQFTs= +github.com/operator-framework/api v0.3.7-0.20200528122852-759ca0d84007 h1:fbpQelcJmwRofhaRrMOUynmBcT6SBhOZOjSlgaXVyyk= +github.com/operator-framework/api v0.3.7-0.20200528122852-759ca0d84007/go.mod h1:Xbje9x0SHmh0nihE21kpesB38vk3cyxnE6JdDS8Jo1Q= +github.com/operator-framework/operator-registry v1.5.3/go.mod h1:agrQlkWOo1q8U1SAaLSS2WQ+Z9vswNT2M2HFib9iuLY= +github.com/operator-framework/operator-registry v1.12.1/go.mod h1:rf4b/h77GUv1+geiej2KzGRQr8iBLF4dXNwr5AuGkrQ= +github.com/operator-framework/operator-registry v1.12.4/go.mod h1:JChIivJVLE1wRbgIhDFzYQYT9yosa2wd6qiTyMuG5mg= +github.com/operator-framework/operator-sdk v0.18.0 h1:YdtgXvjHu+f0hE/Nzvw9JIU3XvOZyp2Kd2cOLW486rU= +github.com/operator-framework/operator-sdk v0.18.0/go.mod h1:xP/DNvnYnIoGK1bLKiD0s7aYZp2fa4AI6t1v3INaoZg= +github.com/otiai10/copy v1.0.1/go.mod h1:8bMCJrAqOtN/d9oyh5HR7HhLQMvcGMpGdwRDYsfOCHc= +github.com/otiai10/copy v1.0.2/go.mod h1:c7RpqBkwMom4bYTSkLSym4VSJz/XtncWRAj/J4PEIMY= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v0.0.0-20190513014714-f5a3d24e5776/go.mod h1:3HNVkVOU7vZeFXocWuvtcS0XSFLcf2XUSDHkq9t1jU4= +github.com/otiai10/mint v1.2.3/go.mod h1:YnfyPNhBvnY8bW4SGQHCs/aAFhkgySlMZbrF5U0bOVw= +github.com/otiai10/mint v1.2.4/go.mod h1:d+b7n/0R3tdyUYYylALXpWQ/kTN+QobSq/4SRGBkR3M= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.3.0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/alertmanager v0.18.0/go.mod h1:WcxHBl40VSPuOaqWae6l6HpnEOVRIycEJ7i9iYkadEE= +github.com/prometheus/alertmanager v0.20.0/go.mod h1:9g2i48FAyZW6BtbsnvHtMHQXl2aVtrORKwKVCQ+nbrg= +github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.2.0/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= +github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= +github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190425082905-87a4384529e0/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.6/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/prometheus v0.0.0-20180315085919-58e2a31db8de/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s= +github.com/prometheus/prometheus v1.8.2-0.20200110114423-1e64d757f711/go.mod h1:7U90zPoLkWjEIQcy/rweQla82OCTUzxVHE51G3OhJbI= +github.com/prometheus/prometheus v2.3.2+incompatible/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +github.com/robfig/cron v0.0.0-20170526150127-736158dc09e1/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -595,40 +1079,80 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.5.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rubenv/sql-migrate v0.0.0-20200212082348-64f95ea68aa3/go.mod h1:rtQlpHw+eR6UrqaS3kX1VYeaCxzCVdimDS7g5Ln4pPc= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190810000440-0ceca61e4d75/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/santhosh-tekuri/jsonschema v1.2.4/go.mod h1:TEAUOeZSmIxTTuHatJzrvARHiuO9LYd+cIxzgEHCQI4= +github.com/satori/go.uuid v0.0.0-20160603004225-b111a074d5ef/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/vfsgen v0.0.0-20180825020608-02ddb050ef6b/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= +github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= +github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.0-20170118185516-dc208f4211e7/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -637,22 +1161,47 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/summerwind/h2spec v0.0.0-20200804131034-70ac22940108 h1:ecwW3RnjsJlnVZkvXHaxa+Hg0EW+6KF8mFovyFk+WZA= github.com/summerwind/h2spec v0.0.0-20200804131034-70ac22940108/go.mod h1:jn/HqC28P+sr5C23xwQQyRzsvJPpWnPGX20sJKIJIwE= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tcnksm/go-httpstat v0.2.1-0.20191008022543-e866bb274419 h1:elOIj31UL4RZWgLfLV4pWZA0j5QqGO95/Dll2WIwOZU= github.com/tcnksm/go-httpstat v0.2.1-0.20191008022543-e866bb274419/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZwPG41aurT8= +github.com/thanos-io/thanos v0.11.0/go.mod h1:N/Yes7J68KqvmY+xM6J5CJqEvWIvKSR5sqGtmuD6wDc= +github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/timtadh/data-structures v0.5.3/go.mod h1:9R4XODhJ8JdWFEI8P/HJKqxuJctfBQw6fDibMQny2oU= +github.com/timtadh/lexmachine v0.2.2/go.mod h1:GBJvD5OAfRn/gnp92zb9KTgHLB7akKyxmVivoYCcjQI= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/uber/jaeger-client-go v2.20.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= +github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8= +github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -660,13 +1209,32 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/gorelic v0.0.7/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20160601141957-9c099fbc30e9/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= +gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= +go.elastic.co/apm v1.5.0/go.mod h1:OdB9sPtM6Vt7oz3VXt7+KR96i9li74qrxBGHTQygFvk= +go.elastic.co/apm/module/apmhttp v1.5.0/go.mod h1:1FbmNuyD3ddauwzgVwFB0fqY6KbZt3JkV187tGCYYhY= +go.elastic.co/apm/module/apmot v1.5.0/go.mod h1:d2KYwhJParTpyw2WnTNy8geNlHKKFX+4oK3YLlsesWE= +go.elastic.co/fastjson v1.0.0/go.mod h1:PmeUOMMtLHQr9ZS9J9owrAVg0FkaZDRZJEFTTGHtchs= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.5.1 h1:9nOVLGDfOaZ9R0tBumx/BcuqkbFpyTCU2r/Po7A2azI= go.mongodb.org/mongo-driver v1.5.1/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -676,33 +1244,54 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/automaxprocs v1.2.0/go.mod h1:YfO3fm683kQpzETxlTGZhGIVmXAhaw3gxeBADbpZtnU= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/multierr v0.0.0-20180122172545-ddea229ff1df/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v0.0.0-20180814183419-67bc79d13d15/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= @@ -744,29 +1333,45 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/net v0.0.0-20161104230106-55a3084c9119/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -791,15 +1396,23 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -828,39 +1441,63 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190310054646-10058d7d4faa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190425145619-16072639606e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -874,6 +1511,7 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -881,6 +1519,7 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -899,38 +1538,54 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180805044716-cb6730876b98/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190118193359-16909d206f00/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -942,6 +1597,7 @@ golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -949,12 +1605,24 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools v0.0.0-20190813034749-528a2984e271/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190918214516-5a1a30219888/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190930201159-7c411dea38b0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191004055002-72853e10c5a3/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191030203535-5e247c9ad0a0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191111182352-50fa39b762bc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -973,9 +1641,13 @@ golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200403190813-44a64ad78b9b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200616195046-dc31b401abb5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= @@ -985,6 +1657,7 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= @@ -993,15 +1666,24 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= +gomodules.xyz/jsonpatch/v3 v3.0.1/go.mod h1:CBhndykehEwTOlEfnsfJwvkFQbSN8YZFr9M+cIHAJto= +gomodules.xyz/orderedmap v0.1.0/go.mod h1:g9/TPUCm1t2gwD3j3zfV8uylyYhVdCNSi+xCEIu7yTU= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= +google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1032,6 +1714,7 @@ google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqiv google.golang.org/api v0.57.0 h1:4t9zuDlHLcIx0ZEhmXEeFVCRsiOgpgn2QOH9N0MNjPI= google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -1039,14 +1722,19 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= @@ -1097,11 +1785,17 @@ google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEc google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I= google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -1143,8 +1837,11 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= @@ -1153,20 +1850,30 @@ gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M= gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= +gopkg.in/imdario/mergo.v0 v0.3.7/go.mod h1:9qPP6AGrlC1G2PTNXko614FwGZvorN7MiBU0Eppok+U= +gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.1.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1184,6 +1891,9 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +helm.sh/helm/v3 v3.2.0/go.mod h1:ZaXz/vzktgwjyGGFbUWtIQkscfE7WYoRGP2szqAFHR0= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1191,74 +1901,179 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0= +k8s.io/api v0.0.0-20190620084959-7cf5895f2711/go.mod h1:TBhBqb1AWbBQbW3XRusr7n7E4v2+5ZY8r8sAMnyFC5A= +k8s.io/api v0.0.0-20190813020757-36bff7324fb7/go.mod h1:3Iy+myeAORNCLgjd/Xu9ebwN7Vh59Bw0vh9jhoX+V58= +k8s.io/api v0.0.0-20190918155943-95b840bb6a1f/go.mod h1:uWuOHnjmNrtQomJrvEBg0c0HRNyQ+8KTEERVsK0PW48= +k8s.io/api v0.0.0-20191115095533-47f6de673b26/go.mod h1:iA/8arsvelvo4IDqIhX4IbjTEKBGgvsf2OraTuRtLFU= +k8s.io/api v0.0.0-20191122220107-b5267f2975e0/go.mod h1:vYpRfxYkMrmPPSesoHEkGNHxNKTk96REAwqm/inQbs0= +k8s.io/api v0.16.7/go.mod h1:oUAiGRgo4t+5yqcxjOu5LoHT3wJ8JSbgczkaFYS5L7I= k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= +k8s.io/api v0.17.1/go.mod h1:zxiAc5y8Ngn4fmhWUtSxuUlkfz1ixT7j9wESokELzOg= +k8s.io/api v0.17.2/go.mod h1:BS9fjjLc4CMuqfSO8vgbHPKMt5+SF0ET6u/RVDihTo4= k8s.io/api v0.18.0-beta.2/go.mod h1:2oeNnWEqcSmaM/ibSh3t7xcIqbkGXhzZdn4ezV9T4m0= +k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8= +k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= +k8s.io/api v0.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA= +k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI= +k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= +k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783/go.mod h1:xvae1SZB3E17UpV59AWc271W/Ph25N+bjPyR63X6tPY= +k8s.io/apiextensions-apiserver v0.16.7/go.mod h1:6xYRp4trGp6eT5WZ6tPi/TB2nfWQCzwUvBlpg8iswe0= k8s.io/apiextensions-apiserver v0.17.0/go.mod h1:XiIFUakZywkUl54fVXa7QTEHcqQz9HG55nHd1DCoHj8= +k8s.io/apiextensions-apiserver v0.17.1/go.mod h1:DRIFH5x3jalE4rE7JP0MQKby9zdYk9lUJQuMmp+M/L0= k8s.io/apiextensions-apiserver v0.18.0-beta.2/go.mod h1:Hnrg5jx8/PbxRbUoqDGxtQkULjwx8FDW4WYJaKNK+fk= +k8s.io/apiextensions-apiserver v0.18.0/go.mod h1:18Cwn1Xws4xnWQNC00FLq1E350b9lUF+aOdIWDOZxgo= +k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY= +k8s.io/apiextensions-apiserver v0.18.6/go.mod h1:lv89S7fUysXjLZO7ke783xOwVTm6lKizADfvUM/SS/M= k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= +k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA= +k8s.io/apimachinery v0.0.0-20190809020650-423f5d784010/go.mod h1:Waf/xTS2FGRrgXCkO5FP3XxTOWh0qLf2QhL1qFZZ/R8= +k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655/go.mod h1:nL6pwRT8NgfF8TT68DBI8uEePRt89cSvoXUVqbkWHq4= +k8s.io/apimachinery v0.0.0-20191115015347-3c7067801da2/go.mod h1:dXFS2zaQR8fyzuvRdJDHw2Aerij/yVGJSre0bZQSVJA= +k8s.io/apimachinery v0.0.0-20191121175448-79c2a76c473a/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= +k8s.io/apimachinery v0.16.7/go.mod h1:Xk2vD2TRRpuWYLQNM6lT9R7DSFZUYG03SarNkbGrnKE= k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= +k8s.io/apimachinery v0.17.1/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= +k8s.io/apimachinery v0.17.2/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= k8s.io/apimachinery v0.18.0-beta.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= +k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= +k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= +k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= +k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= +k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ= k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= +k8s.io/apiserver v0.0.0-20190918160949-bfa5e2e684ad/go.mod h1:XPCXEwhjaFN29a8NldXA901ElnKeKLrLtREO9ZhFyhg= +k8s.io/apiserver v0.0.0-20191122221311-9d521947b1e1/go.mod h1:RbsZY5zzBIWnz4KbctZsTVjwIuOpTp4Z8oCgFHN4kZQ= +k8s.io/apiserver v0.16.7/go.mod h1:/5zSatF30/L9zYfMTl55jzzOnx7r/gGv5a5wtRp8yAw= k8s.io/apiserver v0.17.0/go.mod h1:ABM+9x/prjINN6iiffRVNCBR2Wk7uY4z+EtEGZD48cg= +k8s.io/apiserver v0.17.1/go.mod h1:BQEUObJv8H6ZYO7DeKI5vb50tjk6paRJ4ZhSyJsiSco= k8s.io/apiserver v0.18.0-beta.2/go.mod h1:bnblMkMoCFnIfVnVftd0SXJPzyvrk3RtaqSbblphF/A= +k8s.io/apiserver v0.18.0/go.mod h1:3S2O6FeBBd6XTo0njUrLxiqk8GNy6wWOftjhJcXYnjw= +k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw= +k8s.io/apiserver v0.18.6/go.mod h1:Zt2XvTHuaZjBz6EFYzpp+X4hTmgWGy8AthNVnTdm3Wg= k8s.io/apiserver v0.26.1 h1:6vmnAqCDO194SVCPU3MU8NcDgSqsUA62tBUSWrFXhsc= k8s.io/apiserver v0.26.1/go.mod h1:wr75z634Cv+sifswE9HlAo5FQ7UoUauIICRlOE+5dCg= -k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k= -k8s.io/client-go v0.18.0-beta.2/go.mod h1:UvuVxHjKWIcgy0iMvF+bwNDW7l0mskTNOaOW1Qv5BMA= +k8s.io/autoscaler v0.0.0-20190607113959-1b4f1855cb8e/go.mod h1:QEXezc9uKPT91dwqhSJq3GNI3B1HxFRQHiku9kmrsSA= +k8s.io/cli-runtime v0.18.0/go.mod h1:1eXfmBsIJosjn9LjEBUd2WVPoPAY9XGTqTFcPMIBsUQ= +k8s.io/cli-runtime v0.18.2/go.mod h1:yfFR2sQQzDsV0VEKGZtrJwEy4hLZ2oj4ZIfodgxAHWQ= +k8s.io/cli-runtime v0.18.3/go.mod h1:pqbbi4nqRIQhUWAVzen8uE8DD/zcZLwf+8sQYO4lwLk= k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= +k8s.io/code-generator v0.0.0-20190912054826-cd179ad6a269/go.mod h1:V5BD6M4CyaN5m+VthcclXWsVcT1Hu+glwa1bi3MIsyE= +k8s.io/code-generator v0.16.7/go.mod h1:wFdrXdVi/UC+xIfLi+4l9elsTT/uEF61IfcN2wOLULQ= k8s.io/code-generator v0.17.0/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= +k8s.io/code-generator v0.17.1/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= k8s.io/code-generator v0.18.0-beta.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= +k8s.io/code-generator v0.18.0/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= +k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= +k8s.io/code-generator v0.18.3/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= +k8s.io/code-generator v0.18.6/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= +k8s.io/code-generator v0.19.3/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= +k8s.io/component-base v0.0.0-20190918160511-547f6c5d7090/go.mod h1:933PBGtQFJky3TEwYx4aEPZ4IxqhWh3R6DCmzqIn1hA= +k8s.io/component-base v0.0.0-20191122220729-2684fb322cb9/go.mod h1:NFuUusy/X4Tk21m21tcNUihnmp4OI7lXU7/xA+rYXkc= +k8s.io/component-base v0.16.7/go.mod h1:ikdyfezOFMu5O0qJjy/Y9eXwj+fV3pVwdmt0ulVcIR0= k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc= +k8s.io/component-base v0.17.1/go.mod h1:LrBPZkXtlvGjBzDJa0+b7E5Ij4VoAAKrOGudRC5z2eY= k8s.io/component-base v0.18.0-beta.2/go.mod h1:HVk5FpRnyzQ/MjBr9//e/yEBjTVa2qjGXCTuUzcD7ks= +k8s.io/component-base v0.18.0/go.mod h1:u3BCg0z1uskkzrnAKFzulmYaEpZF7XC9Pf/uFyb1v2c= +k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM= +k8s.io/component-base v0.18.3/go.mod h1:bp5GzGR0aGkYEfTj+eTY0AN/vXTgkJdQXjNTTVUaa3k= +k8s.io/component-base v0.18.6/go.mod h1:knSVsibPR5K6EW2XOjEHik6sdU5nCvKMrzMt2D4In14= k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/helm v2.16.7+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.3/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-aggregator v0.17.1/go.mod h1:H5LcB3fx+P1gpowuZpzDu5B1XfABdO7JBKyB9J9bt34= k8s.io/kube-aggregator v0.18.0-beta.2/go.mod h1:O3Td9mheraINbLHH4pzoFP2gRzG0Wk1COqzdSL4rBPk= k8s.io/kube-aggregator v0.26.1 h1:TqDWwuaUJpyhWGWw4JrXR8ZAAaHa9qrsXxR41aR3igw= k8s.io/kube-aggregator v0.26.1/go.mod h1:E6dnKoQ6f4eFl8QQXHxTASZKXBX6+XcjROWl7GRltl4= +k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kube-openapi v0.0.0-20190320154901-5e45bb682580/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4= +k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= +k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= +k8s.io/kube-state-metrics v1.7.2/go.mod h1:U2Y6DRi07sS85rmVPmBFlmv+2peBcL8IWGjM+IjYA/E= +k8s.io/kubectl v0.18.0/go.mod h1:LOkWx9Z5DXMEg5KtOjHhRiC1fqJPLyCr3KtQgEolCkU= +k8s.io/kubectl v0.18.2/go.mod h1:OdgFa3AlsPKRpFFYE7ICTwulXOcMGXHTc+UKhHKvrb4= +k8s.io/kubectl v0.18.3/go.mod h1:k/EpvXBDgEsHBzWr0A44l9+ArvYi3txBBnzXBjQasUQ= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +k8s.io/metrics v0.18.0/go.mod h1:8aYTW18koXqjLVKL7Ds05RPMX9ipJZI3mywYvBOxXd4= +k8s.io/metrics v0.18.2/go.mod h1:qga8E7QfYNR9Q89cSCAjinC9pTZ7yv1XSVGUB0vJypg= +k8s.io/metrics v0.18.3/go.mod h1:TkuJE3ezDZ1ym8pYkZoEzJB7HDiFE7qxl+EmExEBoPA= +k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= +k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200229041039-0a110f9eb7ab/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= -k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= +k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +maistra.io/api v0.0.0-20210601141927-1cbee4cb8ce8/go.mod h1:Os/zrIv6nsjgC43UAo17FFv+fvYlzANUWIpNNZEZ/KE= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= +sigs.k8s.io/controller-runtime v0.6.0/go.mod h1:CpYf5pdNY/B352A1TFLAS2JVSlnGQ5O2cftPHndTroo= +sigs.k8s.io/controller-runtime v0.6.3/go.mod h1:WlZNXcM0++oyaQt4B7C2lEE5JYRs8vJUzRP4N4JpdAY= sigs.k8s.io/controller-runtime v0.14.4 h1:Kd/Qgx5pd2XUL08eOV2vwIq3L9GhIbJ5Nxengbd4/0M= sigs.k8s.io/controller-runtime v0.14.4/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= +sigs.k8s.io/controller-tools v0.2.4/go.mod h1:m/ztfQNocGYBgTTCmFdnK94uVvgxeZeE3LtJvd/jIzA= sigs.k8s.io/controller-tools v0.2.8/go.mod h1:9VKHPszmf2DHz/QmHkcfZoewO6BL7pPs9uAiBVsaJSE= +sigs.k8s.io/controller-tools v0.3.0/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI= +sigs.k8s.io/controller-tools v0.4.1/go.mod h1:G9rHdZMVlBDocIxGkK3jHLWqcTMNvveypYJwrvYKjWU= +sigs.k8s.io/gateway-api v0.5.1-0.20220921185115-ee7a83814203 h1:t53lCjyZa7bsj1vZbAboYAH0p0OpqdGpGeM30IZIew8= +sigs.k8s.io/gateway-api v0.5.1-0.20220921185115-ee7a83814203/go.mod h1:x0AP6gugkFV8fC/oTlnOMU0pnmuzIR8LfIPRVUjxSqA= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kube-storage-version-migrator v0.0.4 h1:qsCecgZHgdismlTt8xCmS/3numvpxrj58RWJeIg76wc= sigs.k8s.io/kube-storage-version-migrator v0.0.4/go.mod h1:mXfSLkx9xbJHQsgNDDUZK/iQTs2tMbx/hsJlWe6Fthw= +sigs.k8s.io/kubebuilder v1.0.9-0.20200513134826-f07a0146a40b/go.mod h1:FGPx0hvP73+bapzWoy5ePuhAJYgJjrFbPxgvWyortM0= +sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= +sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= +sigs.k8s.io/structured-merge-diff v1.0.2/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI= +vbom.ml/util v0.0.0-20180919145318-efcd4e0f9787/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI= diff --git a/manifests/00-cluster-role.yaml b/manifests/00-cluster-role.yaml index f514a00ef8..1d813bf19d 100644 --- a/manifests/00-cluster-role.yaml +++ b/manifests/00-cluster-role.yaml @@ -98,6 +98,7 @@ rules: - infrastructures - ingresses - dnses + - featuregates - apiservers - networks verbs: @@ -107,6 +108,7 @@ rules: - config.openshift.io resources: - dnses + - featuregates - infrastructures - ingresses verbs: @@ -144,6 +146,36 @@ rules: verbs: - '*' +- apiGroups: + - gateway.networking.k8s.io + resources: + - gatewayclasses + - gateways + - httproutes + verbs: + - '*' + +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - '*' + +- apiGroups: + - operators.coreos.com + resources: + - subscriptions + verbs: + - '*' + +- apiGroups: + - maistra.io + resources: + - servicemeshcontrolplanes + verbs: + - '*' + # Mirrored from assets/router/metrics/cluster-role.yaml - apiGroups: - route.openshift.io diff --git a/pkg/dns/aws/dns.go b/pkg/dns/aws/dns.go index de1201ed17..5d321e0076 100644 --- a/pkg/dns/aws/dns.go +++ b/pkg/dns/aws/dns.go @@ -1,6 +1,7 @@ package aws import ( + "context" "fmt" "reflect" "regexp" @@ -23,9 +24,12 @@ import ( "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi" "github.com/aws/aws-sdk-go/service/route53" + "k8s.io/apimachinery/pkg/types" kerrors "k8s.io/apimachinery/pkg/util/errors" configv1 "github.com/openshift/api/config/v1" + + "sigs.k8s.io/controller-runtime/pkg/client" ) const ( @@ -42,6 +46,11 @@ const ( govCloudTaggingEndpoint = "https://tagging.us-gov-west-1.amazonaws.com" // chinaRoute53Endpoint is the Route 53 service endpoint used for AWS China regions. chinaRoute53Endpoint = "https://route53.amazonaws.com.cn" + // targetHostedZoneIdAnnotationKey is the key of an annotation that this + // provider adds to DNSRecord CRs to track the target hosted zone id of + // the ELB that is associated with the record, which is needed when + // deleting the record. + targetHostedZoneIdAnnotationKey = "ingress.operator.openshift.io/target-hosted-zone-id" ) var ( @@ -91,6 +100,10 @@ type Config struct { ServiceEndpoints []ServiceEndpoint // CustomCABundle is a custom CA bundle to use when accessing the AWS API CustomCABundle string + + // Client is a Kubernetes client, which the provider uses to annotate + // DNSRecord CRs. + Client client.Client } // ServiceEndpoint stores the configuration of a custom url to @@ -503,7 +516,40 @@ func (m *Provider) change(record *iov1.DNSRecord, zone configv1.DNSZone, action // Find the target hosted zone of the load balancer attached to the service. targetHostedZoneID, err := m.getLBHostedZone(target) if err != nil { - return fmt.Errorf("failed to get hosted zone for load balancer target %q: %v", target, err) + err = fmt.Errorf("failed to get hosted zone for load balancer target %q: %v", target, err) + if v, ok := record.Annotations[targetHostedZoneIdAnnotationKey]; !ok { + return err + } else { + log.Error(err, "falling back to the "+targetHostedZoneIdAnnotationKey+" annotation", "value", v) + targetHostedZoneID = v + } + } + // If this is an upsert, store the target hosted zone id in an + // annotation on the DNSRecord CR in case we later on need the id + // and for whatever reason cannot look it up using the AWS API. + if action == upsertAction { + var current iov1.DNSRecord + name := types.NamespacedName{ + Namespace: record.Namespace, + Name: record.Name, + } + if err := m.config.Client.Get(context.TODO(), name, ¤t); err != nil { + // Log the error and continue. The annotation is only + // needed as a fallback mechanism, and anyway we might + // succeed in adding it on the next upsert. + log.Error(err, "failed to get dnsrecord", "dnsrecord", name) + } else if _, ok := current.Annotations[targetHostedZoneIdAnnotationKey]; !ok { + updated := current.DeepCopy() + if updated.Annotations == nil { + updated.Annotations = map[string]string{} + } + updated.Annotations[targetHostedZoneIdAnnotationKey] = targetHostedZoneID + if err := m.config.Client.Update(context.TODO(), updated); err != nil { + log.Error(err, "failed to annotate dnsrecord", "dnsrecord", name) + } else { + log.Info("annotated dnsrecord", "dnsrecord", name, "key", targetHostedZoneIdAnnotationKey, "value", targetHostedZoneID) + } + } } // Configure records. diff --git a/pkg/manifests/bindata.go b/pkg/manifests/bindata.go index 3d042454af..9ab2febe06 100644 --- a/pkg/manifests/bindata.go +++ b/pkg/manifests/bindata.go @@ -4,6 +4,10 @@ // assets/canary/namespace.yaml (212B) // assets/canary/route.yaml (456B) // assets/canary/service.yaml (331B) +// assets/gateway-api/gateway.networking.k8s.io_gatewayclasses.yaml (21.869kB) +// assets/gateway-api/gateway.networking.k8s.io_gateways.yaml (84.172kB) +// assets/gateway-api/gateway.networking.k8s.io_httproutes.yaml (216.696kB) +// assets/gateway-api/gateway.networking.k8s.io_referencegrants.yaml (6.917kB) // assets/router/cluster-role-binding.yaml (329B) // assets/router/cluster-role.yaml (883B) // assets/router/deployment.yaml (2.215kB) @@ -15,7 +19,7 @@ // assets/router/service-account.yaml (213B) // assets/router/service-cloud.yaml (631B) // assets/router/service-internal.yaml (432B) -// manifests/00-cluster-role.yaml (3.181kB) +// manifests/00-cluster-role.yaml (3.61kB) // manifests/00-custom-resource-definition-internal.yaml (7.756kB) // manifests/00-custom-resource-definition.yaml (105.24kB) // manifests/00-ingress-credentials-request.yaml (4.861kB) @@ -182,6 +186,86 @@ func assetsCanaryServiceYaml() (*asset, error) { return a, nil } +var _assetsGatewayApiGatewayNetworkingK8sIo_gatewayclassesYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5c\x6f\x73\xdb\x36\xd2\x7f\xef\x4f\xb1\x8f\x9e\x3e\x4f\xec\x54\xa4\xac\xe4\x2e\x6d\x75\x93\xc9\x65\xdc\xa6\x93\x49\xd3\xc9\xc4\x6e\x3b\x93\xc8\xd7\xac\xc8\x95\x84\x86\x04\x58\x00\xb4\xad\xf6\x7a\x9f\xfd\x66\x01\xfe\x15\x49\xd9\x49\xa6\x73\xf7\x82\x9c\xbc\x88\x08\x70\xb1\x58\xec\xfe\xf6\x0f\x76\x8c\x99\xf8\x91\xb4\x11\x4a\x2e\x00\x33\x41\x37\x96\x24\xff\x32\xe1\xfb\x2f\x4d\x28\xd4\xec\x6a\x7e\xf4\x5e\xc8\x78\x01\x67\xb9\xb1\x2a\x7d\x4d\x46\xe5\x3a\xa2\xaf\x69\x2d\xa4\xb0\x42\xc9\xa3\x94\x2c\xc6\x68\x71\x71\x04\x80\x52\x2a\x8b\xfc\xda\xf0\x4f\x60\x9a\x01\x66\x99\x56\x57\x14\x87\xef\xf3\x15\x69\x49\x96\x98\xf2\x02\xb6\xd6\x66\x66\x31\x9b\x6d\x84\xdd\xe6\xab\x30\x52\xe9\xac\x9e\x11\x18\xb1\x31\xb3\x0d\x5a\xba\xc6\x5d\x80\x99\x98\x65\x79\x92\xcc\xe6\xa7\x5f\x3e\x72\x84\x8b\x91\x50\x92\xbd\x56\xfa\xbd\x90\x9b\x92\xe3\x55\x2e\xe3\x84\x82\xab\x72\x5b\x57\xa7\xe1\xa3\xf0\x34\x88\xe9\xea\x96\x0f\xa3\x2d\x4a\x49\xc9\x02\xe8\x26\x23\x2d\x52\x92\x16\x93\x23\x80\x48\x93\xdb\xd2\x85\x48\xc9\x58\x4c\xb3\x05\xc8\x3c\xe1\x11\x89\x29\x2d\x4a\x8a\x51\x82\xc6\x90\x09\x07\x17\x38\x32\x19\x45\x2c\x96\x8d\x56\x79\xb6\x18\xe6\xa4\xa0\x5c\x88\x30\x42\x4b\x1b\xa5\x45\xf9\x3b\x80\x86\x54\xdc\x1b\x7f\x40\xdf\xfa\xb7\x67\xcc\x86\x7b\x9d\x08\x63\x5f\x74\x86\xbe\x13\xc6\xba\xe1\x2c\xc9\x35\x26\xfb\xec\xbb\x21\xb3\x55\xda\x7e\x5f\xb3\x10\xc0\x26\xf2\x03\x42\x6e\xf2\x04\x75\xfb\xab\x23\x00\x13\xa9\x8c\x16\x70\x96\xe4\xc6\x92\x3e\x02\x28\xc4\xef\x08\x04\x80\x71\xec\x94\x05\x93\x57\x5a\x48\x4b\xfa\x4c\x25\x79\x2a\x2b\xf2\xbf\x18\x25\x5f\xa1\xdd\x2e\x20\x64\x21\x85\x91\x92\x56\xab\x24\x21\xcd\x5c\xb8\x49\xa5\xb4\xcf\xaa\xa1\xe2\xb5\xdd\xf1\xca\xc6\x6a\x21\x37\x3d\xe4\x2c\xda\xdc\x30\x41\xcf\x81\x79\xfb\xe4\xf8\xef\x21\x7f\xf3\xf8\xf1\xe4\x69\x14\x51\x66\x29\x9e\x9c\x5c\x16\x13\x5b\x4b\x95\xc3\x77\x5a\xa8\x34\x83\xb0\xa3\x2e\x6d\x9a\x1b\x6a\x91\x8b\xd1\xd2\x80\x10\x62\x32\x91\x16\x99\x33\xb2\x26\x89\xaf\x3b\xef\x33\x2d\x94\x16\x76\xb7\x80\xf9\x10\xaf\xfe\xd3\xab\x39\x26\xd9\x16\x1f\xf8\xc3\x8c\xb6\x94\xe2\xa2\xf8\x42\x65\x24\x9f\xbe\x7a\xfe\xe3\xc3\xf3\xd6\x6b\x80\x06\x1b\x0b\x98\x34\x55\xa9\x18\x5a\x91\x01\x04\xa7\x09\xa0\xd6\xa5\xb2\x19\xc0\x2b\x14\x09\xae\x12\x02\xab\xc0\x6e\xa9\xa2\x08\x90\x1b\xd2\xb0\x56\xba\xb0\x2d\xb9\x29\xbf\x02\x5d\x00\x8c\x09\x61\x29\xe1\xb9\x05\x61\x40\x53\xa4\xd2\x94\x64\x4c\x31\xd8\x2d\x5a\xb0\x5b\xf7\xd6\xcf\x6c\x90\x5d\x11\x53\x8e\x01\x99\x21\x4b\x69\x96\xa0\x25\xb7\x4e\xc9\x54\x08\x17\xfc\x6d\x4a\x28\x8d\xa7\x85\xd5\xd2\xc2\xc0\x0a\xf9\xf3\x4a\xae\x4e\x92\x5b\x02\xd6\x0d\xe2\xbd\xf1\x8f\x96\x04\x1c\x33\x04\x56\xa4\x04\xc2\xc2\x35\x1a\xbf\x25\x66\x42\xc6\xc0\x90\xb2\x21\x03\x56\xed\x51\x6c\x11\x51\x1a\xd0\x18\x15\x09\xf7\x5d\x86\x1a\x53\xb2\xa4\x0d\xa0\x26\x90\xca\x42\xa6\x55\x86\x1b\x37\x1a\xab\x6b\xc9\xf2\xa4\x1b\x61\x6c\x79\xb8\xfe\xd9\xdb\x63\x25\x35\xa7\x8d\xbc\x3b\xb6\x3c\x2f\x44\x05\x89\x48\x85\xe7\x7d\x95\xa0\xb1\xa0\x31\x16\xb9\x3b\xbf\x82\xe7\x26\xc3\xea\x6e\xfc\x86\xf0\x7c\x0d\x22\xcd\x12\x72\xd8\xe9\xcc\x0d\xa2\xad\x52\xc6\xa9\x40\xb5\x8b\x2e\xcf\x9e\x6e\x2d\xad\x6a\x7b\xd5\xa6\xa6\xfe\xb4\x5e\xfe\x70\x7e\xc1\xc7\x1c\x25\x84\x3a\xd9\x41\xac\xa2\x9c\x17\xab\x8c\xd4\xa9\xc1\xce\x6d\xac\xcd\x89\xd3\xa7\x9f\xb6\x24\xe9\x8a\x34\x28\x49\xbc\x8d\x54\x69\x6a\x28\xac\x66\xfd\xe1\x55\xb1\xc5\xd8\xb4\x41\x7b\x7f\x7b\x8e\x21\x8c\x63\xb7\xe2\xbb\x12\x99\x1d\xfb\x26\x58\x0b\x89\x89\xf8\x8d\xf4\xb0\x53\x78\xd7\xa0\x5d\x4d\x07\x25\x1d\xbd\x86\x94\x9b\xfc\x14\x07\x4c\xd2\xe4\x9a\xf6\xd5\xb8\xc6\x7f\xff\x34\x68\x5c\x0b\xbb\x6d\xeb\x3b\x2b\x57\x4c\x09\xb9\xd1\xad\x48\x08\x84\x64\x13\x72\xc2\x6a\x9d\x8d\x68\xd1\x2c\x81\x1e\x12\xba\xa2\xa4\x32\xc5\x70\x52\x4d\xe2\xc3\x26\x6d\x2b\xaf\x55\x7c\x58\x87\x1b\x8d\xb7\x7b\x18\x73\x8f\x61\xc8\xcf\x82\x98\xe3\x0c\xb7\x47\x2a\x5d\x0a\xc5\x05\x72\x79\x83\x74\x9a\x9e\x69\x32\xe5\x99\xb4\x08\x03\x4f\x42\x09\x6a\xf5\x0b\x45\x36\x84\x73\xd2\x4c\x86\x3d\x5c\x9e\xc4\x10\x29\x79\x45\xda\x3a\x5b\xd9\x48\xf1\x5b\x45\xdb\x14\x98\x05\x8c\x20\x85\xc3\x6c\x28\x01\xbb\x30\x89\x09\x5c\x61\x92\xd3\xd4\x99\x7a\xea\xc0\x8b\x57\x81\x5c\x36\xe8\xb9\x29\x26\x84\x97\xac\x6a\x42\xae\xdb\x81\x4f\x15\x7b\xa8\x34\xcd\xa5\xb0\xbb\x99\x73\x7d\x62\x95\x5b\xa5\xcd\x2c\x66\xf1\xce\x8c\xd8\x04\xa8\xa3\xad\xb0\x14\xd9\x5c\xd3\x8c\xa3\x2a\xc7\xba\x74\x4a\x18\xa6\xf1\xff\x56\xb8\x79\xaf\xc5\x6b\xc7\x0f\xf8\xc7\x45\x0c\x07\x4e\x80\xc3\x06\xd6\x0f\x2c\x3e\xf5\xbb\xa8\x05\xcd\xaf\x58\x3a\xaf\xbf\x39\xbf\xa8\x4e\xdf\x1d\xc6\xbe\xf4\x9d\xdc\xeb\x0f\x4d\x7d\x04\x2c\x30\x21\xd7\xa4\xfd\x21\xae\xb5\x4a\x1d\x4d\x92\x71\xa6\x84\xf4\xe0\x14\x25\x82\xe4\xbe\xf8\x4d\xbe\x4a\x85\xe5\x73\xff\x35\x27\x63\xf9\xac\x42\x38\x73\xb1\xa7\x73\x01\x19\x3b\xd5\x38\x84\xe7\x12\xce\x30\xa5\xe4\x0c\x59\xa3\xff\xe4\x03\x60\x49\x9b\x80\x05\x7b\xb7\x23\x68\x86\xcd\xfb\x93\xbd\xd4\x1a\x03\x65\xe4\x38\x70\x5e\xe7\x19\x45\x2d\x53\x89\xc9\x08\xcd\xca\x5c\x3a\xae\x16\x7c\xb4\x08\xf5\x1b\x2a\x3f\xed\x20\x6c\x7f\x74\x3f\x30\x38\x6b\xcd\x66\xe5\x61\x46\x38\xec\x28\x1d\x67\x4d\xcf\x43\x56\x47\x59\x9c\x58\x50\xe2\xa6\x09\xfc\x95\x95\x47\x25\xf4\x51\xa1\x8d\xe5\xc0\x5a\x50\x12\x97\x9e\xa1\x87\x24\x42\xac\x52\x14\x12\x32\x4d\x6b\x71\xe3\x5c\x96\xdd\x3a\x88\xfb\xe6\x06\x19\xcf\x17\xb0\x9c\x90\xff\x2f\x23\x74\x95\x76\xd4\x1c\x2f\x27\x61\x0f\xe5\xa5\xf4\x48\xec\x39\x28\xf0\x34\xcd\xad\x0b\x7a\x9c\xff\xaf\x94\x92\xd2\xcc\xee\xdc\x9a\xe7\x79\x96\x29\x6d\x39\x92\xd5\x34\xe9\x50\x4d\xf1\xe6\x3b\x92\x1b\x0e\x03\x1f\xfc\xf5\x61\x77\x58\xc8\x72\x78\xde\x19\xcc\xd0\x32\x30\x2d\xe0\x1f\x6f\x31\xf8\xed\x34\xf8\xea\xf2\xf8\x6d\x50\xfc\xef\x7e\xf9\xea\xe4\xc9\xf1\x32\x3c\x38\x7e\x72\x7f\x39\x7b\xfb\x34\x78\xe3\x5f\x2c\x67\xcb\x20\xfc\xf9\x5f\xff\xf7\x3f\x9f\xfd\xff\xbd\xe3\x93\xfb\x9f\x4f\xff\xf6\x78\x71\xf9\xf9\x67\x9d\xc5\x07\xf4\x7c\x5f\x53\x0e\xab\x51\x23\xb6\x85\x2d\x25\x59\x1d\x63\xee\x79\x38\xef\xcc\x9c\xff\x8e\xc9\xa2\x48\x4c\xf7\x80\x1a\xa2\x7c\xf4\x97\x0f\xe1\xb7\x0e\x69\x5e\xd3\xfa\x36\xc5\x7f\xd5\x9c\xec\x41\x53\xd3\x9a\x34\xc9\xc8\x85\x3d\xd8\x04\x48\xb4\xce\x0c\x50\xc8\x3e\xe5\x2f\xac\x64\x2d\x36\xb9\xf6\x51\x5b\x23\x18\x8c\x94\xd6\x64\x32\x4e\x64\x18\x7d\x55\x27\x8e\xec\xd3\x50\xa7\x9e\xc2\x80\xca\x7c\xfa\x05\xa2\x63\x8b\xb1\x22\xaf\xb8\x0c\xa7\x42\xb3\xe2\xee\x1a\x09\x5b\x0f\xd1\x16\x8b\x4e\xa7\xdb\x32\x88\x50\x36\x44\xc0\x3e\x04\x65\x8c\x3a\x86\x17\x55\x7a\xdf\x43\xb5\x94\xd2\x14\x44\x48\x21\xe7\x79\x6b\xb1\x79\x89\xd9\xd4\xc5\x9b\x72\x2f\xf2\x0a\x18\x12\xc5\x5a\x44\x10\xb9\xc2\x44\x1d\x83\xf4\x4a\x81\xea\x43\x60\xee\x5c\x04\xe9\x22\x98\xc0\x65\xae\x31\xaf\xe1\x72\xee\x0c\x23\x2a\xde\xf9\x0c\x64\xbd\x97\xba\xd4\xec\xba\x0d\xda\x86\x8d\xaf\x55\x2e\xe3\x69\xe7\x5c\xee\x19\x58\x4e\x9e\xcb\x2b\x4c\x44\x5c\x0b\x6a\xd9\x35\x7d\x00\x9f\x84\x42\x95\xad\xc2\xb5\x48\x12\x26\x6d\x75\x4e\x7b\xe8\xe1\xb6\xdd\x25\x32\x8c\xe7\xfc\xf8\xd2\x43\xcf\xc0\x9e\x56\x7f\xcb\xf3\x4a\x10\x77\x1f\x95\x28\x5e\xee\xbb\x4f\xce\xb7\xa2\x17\xb4\x40\xea\xb3\x7f\x7e\x2a\x4e\x75\x51\x08\x0e\x5b\x36\xf4\x06\x3f\xbd\x22\x28\x63\x20\x9e\xfe\xc1\x9b\x7f\xd4\xbf\xf7\x83\xe8\x0d\x1d\x04\x7f\x1a\xbc\x29\x76\xfe\x34\x78\x53\x6d\xbe\xf8\xff\xc9\x93\x8f\xda\xbd\xec\xf5\xe5\x9d\xdd\x0f\x39\xf1\x4f\x3e\xfe\x5b\x45\x70\x07\xfe\x9d\x95\xde\x71\x13\x6e\x6e\x73\x27\xfe\xc5\xfe\x76\x1c\x52\xf6\x52\x84\xda\xbd\x17\x08\xc9\xb9\x12\x15\x10\xa7\x0b\x30\xc6\x7a\xb1\x12\x52\x7a\x0a\x14\xcd\x87\xe3\x83\x32\x9d\xcd\xa5\x21\xdb\x4b\xf5\xac\x0d\x53\x87\x50\xee\x4f\x50\xc0\x41\xd3\xfb\x08\xd5\x2b\x85\xd7\x3d\xb7\xc0\x23\x4c\xcf\x7b\xb6\xbd\x9e\xd7\xb2\x2e\x0a\xee\x2f\xde\x09\x9d\x87\x16\x0e\xa0\xb7\xc8\x78\x90\x96\x87\xe7\xfd\x40\x7c\x8d\x79\x62\x7b\x82\xe7\xa2\xe0\xb8\x3f\x12\x40\x82\xc6\x5e\x68\x94\x46\x94\x75\xc2\x05\x4c\xe6\x5f\x7d\x71\x1a\x9c\xce\x83\xd3\xf9\xc5\xe9\xe9\xc2\xfd\x7b\xd3\x13\x1d\x92\x31\xb8\xa1\x05\xfc\x84\xc2\x65\x61\xae\x88\xb6\x5f\x12\x6d\xee\x1d\x0d\x5b\x42\x31\xbd\x33\x5e\xec\x08\x7e\x90\xef\xa5\xba\xde\xcf\x9d\x4b\x41\xec\x15\x42\xcb\x8d\x37\x33\x10\xef\xb8\x9a\x39\x48\x94\x6b\xe7\x1f\x3f\x35\x07\x19\x10\xe3\xa0\xe4\x3f\x51\xc2\x1f\x2e\xe3\xdb\xa5\x7c\xbb\x9c\x0f\x4a\xba\x23\x6d\x4e\xb6\x0a\xb1\x94\xc8\xd6\x94\x76\xde\xc8\xa6\x0f\xf2\xcd\x1b\x73\x29\x54\xbb\xba\xb4\x94\x8d\x2a\x7b\x55\x2b\xc9\x1c\x32\xb9\x42\x5e\xbe\x4a\x84\xd9\x36\x0e\xa7\x87\xb6\x2f\xa4\xf9\xea\xc7\xfe\xe9\x57\xec\x5f\xec\x32\x2a\xb8\x20\x27\x01\x9e\x49\x18\x6d\xa1\x9a\x12\x76\x8f\x48\x58\x4a\x7b\xa3\x9b\x01\x21\x55\x21\x77\x99\x2a\xb8\x25\x95\x24\x40\x8e\x22\x6d\x95\xa0\x7a\x19\xf6\x42\x5b\xa3\x04\x2c\x0c\x3c\x7d\xf5\x1c\xca\xab\xb0\x10\x82\x20\xf0\x81\xb6\xb1\x3a\x8f\x6c\xab\xd4\xca\x2b\xc5\x42\xef\x63\x52\x2d\x25\x72\xd5\x6a\x09\xa8\x35\xee\xca\x7a\xb2\xf7\x38\x9c\xa6\xf6\xdc\x60\x84\x00\xcf\x94\x86\x22\x61\x9d\x0e\x22\x31\x3c\x53\xaa\xb0\x4b\xcf\xd8\xef\x6e\x68\x36\x83\xd7\x55\x39\xc6\xad\xa6\x56\x86\xf4\x55\x51\xd0\x54\x6b\xc0\x5e\x92\x6b\xa5\xee\x99\xb6\x55\x87\x25\xc1\x17\xac\xd4\x7d\xac\x3a\x3e\x50\x0f\x38\xeb\xe5\xe4\x69\x79\x47\xb0\x9c\x4c\x61\x39\x79\xa5\xd5\x46\x93\x61\xd5\xe1\x17\xec\x22\x97\x93\xaf\x69\xa3\x31\xa6\x78\x39\x29\x97\xfb\x3c\x43\x1b\x6d\x5f\x92\xde\xd0\x0b\xda\x3d\xe6\x45\xfa\xe9\xb7\xe6\x9f\x5b\x8d\x96\x36\xbb\xc7\x29\x7f\x58\xd1\x4a\x84\xb1\xac\x87\x8f\x53\xcc\x5a\x2f\x5f\x62\x76\x3b\xf5\x86\x25\xbe\xbd\x4c\xc9\xe2\xd5\x3c\xac\x15\xef\xdd\x2f\x8c\x0b\xcb\x49\x2d\x91\xa9\x4a\x59\x7d\x33\xbb\xeb\x4d\x00\x9c\x03\xae\x59\x5d\x2c\x27\x8e\xd9\xe5\x04\x5a\x5b\x5e\x2c\x27\xcc\x16\xbf\xd6\xca\xaa\x55\xbe\x5e\x2c\x27\xab\x9d\x25\x33\x9d\x4f\x35\x65\x53\xf6\x90\x8f\xeb\x55\x97\x93\x77\xfd\x5b\x90\xe5\x8e\x95\xdd\x92\xf6\x7a\x67\xe0\x8f\x3e\xd6\x0e\x27\x16\xd0\x87\xb9\x03\x91\x4f\xcb\x4c\xbb\x9f\x95\x90\xe6\xee\x25\xdc\xcd\x4a\x01\x64\x7e\x33\x03\x44\x01\x6c\x45\x85\xed\x8e\x01\x90\x4d\xbc\x00\x44\x0e\xa6\xa4\xdb\x64\x51\x3d\x2f\x50\x6d\x45\x2e\xec\x1a\x26\xba\xe5\xe8\x2c\x26\x9d\xec\x18\xcf\xea\xcc\xcc\x5f\x56\xc4\x21\xf8\x14\xd1\xd5\xb3\x5c\x1a\xed\x00\xde\x65\x81\xc3\x54\x3d\x38\x56\x37\x47\x2e\xf0\xe3\x5f\x8c\x2b\xde\xf6\x0b\xf2\xae\x9e\xe0\x7c\x02\x1b\x49\x7f\xd4\xe7\x70\x3c\x45\xeb\x2f\x13\x03\xa6\x38\x30\xef\x96\xd0\xba\x76\x7d\x77\x39\xb8\x62\xae\xaf\x78\x6c\xf3\xd4\x25\xfd\x18\xbb\xda\x57\x35\x26\x63\x11\xe1\x80\x4f\x2c\x69\x7a\x48\xc6\x95\xca\x8b\xcb\xb4\xea\x1c\xcb\xdb\x3a\xdc\xf1\x39\xa1\xf4\x55\xb4\x62\x03\x43\xc2\x68\x04\xc1\x0f\x1f\x7c\xf1\xe8\xcb\x8f\x95\x85\x47\x45\x8a\xbf\x25\x49\xbe\xd4\x71\x27\xb1\x74\x3f\x6b\x54\xbf\xdd\xfe\xea\xab\xe2\x4d\x35\xe7\x80\xfe\x15\x2e\xa1\x51\x13\x40\x03\x9c\x2e\xf8\xcb\xca\x3c\x63\x39\xb1\x43\x10\xd2\x58\x94\xae\x80\xb2\xfe\xb0\x45\x44\x85\xeb\xc9\x0e\xe6\x0f\xa6\xb0\x2a\x8e\xa2\xe7\xfa\xfc\xe6\x32\xec\x6e\xf1\x10\xe5\xaf\xa6\x7b\xfc\x0b\x03\x7c\xd4\x6a\xed\xf4\xd5\x17\xf2\x34\x79\x4f\x5c\x94\xb5\x0e\x79\x62\x68\x7b\x63\xaa\xf6\x7d\x9b\x75\x08\x69\x7b\xca\x80\xfe\x49\x85\x14\x69\x9e\x2e\xe0\xf4\xa0\xba\xb0\x5b\xdf\xf4\x86\x52\x55\x10\x78\x17\x1d\xf1\x53\xeb\xb0\x04\x19\x5c\x37\x1a\xd3\x14\xad\x88\x40\xc4\x24\xad\x58\x0b\xd2\x77\x31\x20\x9f\xc6\x3a\x82\x65\x24\x55\xc9\xfa\x9e\x29\x50\xb4\x61\x52\xaf\xb4\x8a\xf3\x88\xf4\x50\xb6\xeb\xae\xcc\xea\xea\x5a\x75\x6c\xee\x82\xc3\xd9\xa2\x8f\xf2\x5d\x9b\x4c\x64\xab\x2b\x2e\xf6\xd6\x83\x24\x53\x42\x29\xe4\xc6\xd4\x21\xa7\x83\x39\xef\xe2\xaf\xb7\xe4\xbc\x8f\x2d\x4b\xfb\xfe\x2a\x36\x52\xd2\x88\x98\x74\x4f\x34\x5c\x3e\x08\x9b\x1c\x35\x4a\x4b\x14\x33\x78\x36\xaf\x07\x6a\x80\xc7\xfa\x1a\xe8\x16\xec\x80\x66\x3d\x9f\xb7\xda\xaa\xde\xdf\x0e\x38\xf3\xd3\x07\x07\x34\xec\x70\xe6\xdd\xca\xbd\x7d\xf5\xfd\xf2\xb8\x2e\xc3\xff\x3c\x5d\x5c\xde\x6f\xfc\x1c\x4c\xc2\xef\x00\x6d\x7d\x79\x6c\xfd\xb4\x54\xb5\x70\x9f\xf5\x15\x8e\xd7\x86\xa9\xbf\x41\x5f\xc3\x85\xce\x69\x0a\xcf\x30\x31\x34\x2d\xb3\x9b\x21\x41\x91\xcc\xd3\xa1\x45\x03\x98\x30\xa9\xfe\x98\xc8\x0d\xbb\x35\x86\xc7\x87\x33\x2b\xb8\x8b\x48\xdc\x84\xbb\x08\xa4\xcc\x52\x1a\x78\xd6\xb8\x66\x04\x87\xc3\x1c\x2b\x87\xe5\x85\x52\xa4\xd2\x59\x7d\x0d\x39\xa8\x78\x9c\x44\xbc\x44\xb9\x83\x1a\x6c\x7d\xf4\xbc\x6f\x11\xc6\x72\xfc\x8d\x91\x56\xa6\x6e\x82\x19\x36\xe6\x44\xbc\x27\xa8\xc2\x6c\x0f\xed\x2b\x8a\xd0\x65\x1e\x7a\x25\xac\x46\xbd\x6b\xa4\x72\x65\x7d\x3c\x37\xb4\xce\xfb\xaa\xff\xfe\x39\x36\x44\x10\x4a\x15\x53\xd7\x47\x9c\x78\xc4\xc7\x95\x48\x84\xdd\x31\xa6\xc7\x14\x29\xb9\x4e\x44\x34\x70\xeb\xe7\x1f\x91\x66\x4a\x5b\xf4\xd5\x38\x06\xb5\x0d\xdd\x80\xb0\x90\x72\xe8\x4b\x2e\xd5\x3d\x8e\xa5\x99\xcf\x1f\x3c\x3c\xcf\x57\xfe\x52\xef\x59\x6a\x67\x27\x4f\x8e\x7f\xcd\x31\x61\xc4\x8c\xbf\xc7\x94\x9e\xa5\xf6\xe4\x0e\xc1\xc1\xfc\xd1\xad\x76\x78\xfc\x89\xf5\x69\x66\xad\x61\xc3\x97\x6f\x83\xda\x80\xc3\xcb\xfb\x27\x4f\x1a\x63\x27\x1f\x69\xce\xc3\x75\xb5\xfe\x4a\x48\xef\xb4\x22\x60\xeb\x1d\xf3\xce\xa5\x77\xa8\xd5\x34\xd7\x1e\x1a\x48\x9b\x06\xab\x74\xe0\x4f\xe7\xb9\xcb\xed\xa1\x1b\xb5\xf9\x0f\x5d\x96\xdc\x19\xbb\x09\x1a\x8d\xa3\x9c\xba\x05\x29\x66\xc1\x7b\xda\xf5\x60\xdc\x00\x67\x5d\x12\x7e\xc1\x14\xb3\xdb\x2b\x83\xdd\x23\x08\x9c\x07\x3d\x1a\xfc\xca\x07\x50\x0b\x58\x33\xa8\xf9\x37\x56\x69\x57\x75\x6a\xbc\xca\x57\x95\x7d\x97\xa4\xcb\x42\xd2\xef\x7f\x8c\x8d\x95\x6d\x9a\xff\xe1\xc6\xca\x15\x59\xf4\x93\xc6\xbe\xca\xb1\xaf\x72\xec\xab\x1c\xfb\x2a\xc7\xbe\xca\xb1\xaf\x72\xec\xab\x1c\xfb\x2a\xc7\xbe\xca\xb1\xaf\x72\xec\xab\x84\xb1\xaf\x72\xec\xab\x1c\xfb\x2a\xc7\xbe\xca\xb1\xaf\x72\xec\xab\xf4\xcf\xd8\x57\x39\xf6\x55\xba\x67\xec\xab\x6c\x6d\x7c\xec\xab\xbc\xa3\x94\xc7\xbe\xca\xb1\xaf\x72\xec\xab\xec\x3e\x63\x5f\x65\xf7\x19\xfb\x2a\xc7\xbe\xca\xb1\xaf\x72\xec\xab\x2c\xd9\x1c\xfb\x2a\x7b\x9e\xb1\xaf\xb2\xc1\xd9\xd8\x57\x39\xf6\x55\xb6\x9e\xb1\xaf\xb2\xf3\x8c\x7d\x95\x63\x5f\x25\x8c\x7d\x95\x63\x5f\xe5\x7f\x59\x5f\xa5\xd5\xf9\x5e\x5b\x65\xfd\xe6\x70\x57\x65\x8d\xe1\x58\xd4\x8c\x1a\x7f\x08\xd3\xff\xa5\xcd\x89\x47\xcb\xf2\x0f\x68\xba\x9f\x8d\x82\x1a\xbc\xbd\x3c\xf2\x0b\x53\xfc\x63\xf9\x67\x30\xf9\xe5\xbf\x03\x00\x00\xff\xff\x2e\x91\x67\xfa\x6d\x55\x00\x00") + +func assetsGatewayApiGatewayNetworkingK8sIo_gatewayclassesYamlBytes() ([]byte, error) { + return bindataRead( + _assetsGatewayApiGatewayNetworkingK8sIo_gatewayclassesYaml, + "assets/gateway-api/gateway.networking.k8s.io_gatewayclasses.yaml", + ) +} + +func assetsGatewayApiGatewayNetworkingK8sIo_gatewayclassesYaml() (*asset, error) { + bytes, err := assetsGatewayApiGatewayNetworkingK8sIo_gatewayclassesYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "assets/gateway-api/gateway.networking.k8s.io_gatewayclasses.yaml", size: 21869, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x75, 0xf4, 0xc, 0x82, 0xed, 0x58, 0x4c, 0xa0, 0x99, 0x11, 0x82, 0xed, 0xd9, 0x60, 0x55, 0x67, 0x20, 0xcb, 0x6e, 0x9a, 0xc6, 0xa6, 0x90, 0x45, 0x67, 0xde, 0xfb, 0x9a, 0x79, 0x67, 0xe, 0x90}} + return a, nil +} + +var _assetsGatewayApiGatewayNetworkingK8sIo_gatewaysYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x7b\x73\x1b\x37\x96\x28\xfe\x7f\x3e\x05\x7e\xdc\xfd\x5d\x4b\x1e\x92\x92\xec\x49\x66\xc2\xad\x54\x56\xe5\x38\x89\x2a\xb6\xa3\xb2\x94\x6c\xed\x84\xde\x15\xd8\x0d\x92\x88\xba\x1b\x9c\x06\x5a\x32\x33\x3b\xf7\xb3\xdf\xc2\x39\x78\x35\xd9\x8d\x06\x65\x39\x99\xda\x09\x6a\xaa\x26\x56\x37\x4f\x03\x07\xc0\x79\x3f\xe8\x86\xff\xc8\x6a\xc9\x45\x35\x23\x74\xc3\xd9\x7b\xc5\x2a\xfd\x2f\x39\xbd\xfd\xb3\x9c\x72\x71\x72\x77\xf6\xc9\x2d\xaf\xf2\x19\x79\xd1\x48\x25\xca\xb7\x4c\x8a\xa6\xce\xd8\x57\x6c\xc9\x2b\xae\xb8\xa8\x3e\x29\x99\xa2\x39\x55\x74\xf6\x09\x21\xb4\xaa\x84\xa2\xfa\xcf\x52\xff\x93\x68\x98\x13\xba\xd9\xd4\xe2\x8e\xe5\xd3\xdb\x66\xc1\xea\x8a\x29\xa6\x21\xcf\xc8\x5a\xa9\x8d\x9c\x9d\x9c\xac\xb8\x5a\x37\x8b\x69\x26\xca\x13\xff\xc6\x44\xf2\x95\x3c\x59\x51\xc5\xee\xe9\x76\x42\x37\xfc\x64\xd3\x14\xc5\xc9\xd9\xe9\x9f\x3f\x03\xc0\xe6\xc9\xb4\x62\xea\x5e\xd4\xb7\xbc\x5a\xd9\x19\x2f\x9a\x2a\x2f\xd8\xe4\xce\x2e\xeb\xee\x74\xfa\xd9\xf4\x74\x92\xb3\xbb\x81\x1f\x66\x6b\x5a\x55\xac\x98\x11\xf6\x7e\xc3\x6a\x5e\xb2\x4a\xd1\xe2\x13\x42\xb2\x9a\xc1\x92\xae\x79\xc9\xa4\xa2\xe5\x66\x46\xaa\xa6\xd0\x4f\x2a\x5a\xb2\x99\x85\x28\xa7\xbd\xa0\x3f\x91\x1b\x96\x69\x84\xac\x6a\xd1\x6c\x66\xfd\x73\x30\x30\x0d\xf2\x32\xaa\xd8\x4a\xd4\xdc\xfe\x7b\x42\x02\x7c\xc0\x5f\x70\x6b\xbe\xc1\xbf\xc2\x5f\x0a\x2e\xd5\x77\xe1\x5f\x5f\x71\xa9\xe0\xc9\xa6\x68\x6a\x5a\xf8\xe9\xc2\x1f\xe5\x5a\xd4\xea\x8d\xff\xe4\x84\xac\xd4\x3d\x3e\xe1\xd5\xaa\x29\x68\xed\x7e\xf0\x09\x21\x32\x13\x1b\x36\x23\xf0\xfe\x86\x66\x2c\xff\x84\x10\x83\x67\xf8\xfd\x84\xd0\x3c\x87\x53\x41\x8b\xcb\x9a\x57\x8a\xd5\x2f\x44\xd1\x94\x95\x83\xfe\xb3\x14\xd5\x25\x55\xeb\x19\x99\x6a\x9c\x58\x94\xbd\x28\xa8\x94\x1a\x2c\xbc\x66\x11\x0b\x7f\x35\x7f\x51\x5b\xfd\x65\xa9\x6a\x5e\xad\x3a\x60\x29\xaa\x1a\x39\xa5\x79\x5e\x33\x29\x99\xfc\xe9\xe9\xbb\xe9\x1d\x2d\x9a\x36\xbc\x73\x7c\x7c\x08\xc4\x4c\x54\xb8\x20\xf9\xd3\x97\x47\xff\x3e\xd5\xbf\xf9\xe2\x8b\xd1\x5b\x46\xf3\xed\xe8\xf8\x9d\x79\xab\xf5\x11\x78\x96\xf4\x09\x7b\x71\xa6\x7b\x07\xac\x3d\xeb\x15\x6b\x81\xcb\xa9\xc2\x3f\xe0\xe3\xbb\x33\x5a\x6c\xd6\xf4\x19\x6e\x5a\xb6\x66\x25\x9d\x99\xf7\xc5\x86\x55\xe7\x97\x17\x3f\x3e\xbf\x6a\xfd\x99\x90\x9c\xc9\xac\xe6\x1b\x05\xf7\xc3\x9c\x13\x52\xb3\x4d\xcd\x24\xab\x94\x24\xb4\x22\xbc\x92\x8a\x56\x19\x23\x62\x49\x28\x91\xac\xbe\xe3\x19\x9b\xa8\x9a\x2e\x97\x3c\x23\x6b\x5a\xe5\x85\x5d\x14\x0e\x5e\x2d\x6b\x2a\x55\xdd\x64\xaa\xa9\x19\x59\x6c\xc9\x82\x57\x39\xaf\x56\x44\x9f\x40\x56\xb1\x5a\x12\x25\x00\x96\xd2\x40\x2f\x2e\x89\xdb\xae\xa9\x83\xb3\xa9\xc5\x86\xd5\xca\x1d\x79\x1c\x01\x95\x0a\xfe\xba\xb3\x8e\x27\x7a\xa9\xf8\x16\xc9\x35\x79\x62\x92\xa8\x35\xb3\x07\x94\xe5\x06\x3b\xfa\xe3\x6a\xcd\xa5\x5f\x30\x20\xbf\x05\x98\xc0\xb2\x2b\x22\x16\x3f\xb3\x4c\x4d\xc9\x15\xab\x35\x18\x7d\x5d\x9a\x22\x27\x99\xa8\xee\x58\xad\x48\xcd\x32\xb1\xaa\xf8\x2f\x0e\x36\x2c\x51\x7f\xb4\xa0\x8a\x99\x7b\x17\xa2\x48\xb1\xba\xa2\x05\x81\xa3\x39\x26\xb4\xca\x49\x09\x98\xd7\x5f\x21\x4d\x15\xc0\x83\x57\xe4\x94\xbc\x16\x35\xd3\xb8\x6d\xd3\x4b\x47\xb2\x44\x59\x36\x15\x57\xdb\x93\x4c\x54\xaa\xe6\x8b\x46\x89\x5a\x9e\xe4\xec\x8e\x15\x27\x92\xaf\x26\xb4\xce\xd6\x5c\x31\xd8\x93\x13\x4d\x8c\x61\xea\x15\x9c\xe8\x69\x99\xff\x4b\x6d\xe8\xb9\x7c\xd2\x9a\xeb\xde\xc1\xc5\x01\xe4\x26\xb2\x03\x9a\xf0\x10\x2e\xf5\x26\xc3\x4f\x71\x15\x1e\xd1\xfa\x4f\x1a\x3b\x6f\x5f\x5e\x5d\x13\xfb\x69\xd8\x8c\x5d\xec\x03\xde\x83\x23\xe9\xb7\x40\x23\x8c\x57\x4b\x56\xe3\x26\x2e\x6b\x51\x02\x4c\x56\xe5\x1b\xc1\x2b\x05\xff\xc8\x0a\xce\xaa\x5d\xf4\xcb\x66\x51\x72\xa5\xf7\xfd\xaf\x0d\x93\x4a\xef\xd5\x94\xbc\x00\x96\x45\x16\x8c\x34\x1b\x7d\xb3\xf2\x29\xb9\xa8\xc8\x0b\x5a\xb2\xe2\x05\x95\xec\xa3\x6f\x80\xc6\xb4\x9c\x68\xc4\xa6\x6d\x41\xc8\x6d\x77\x5f\x46\xac\x05\x0f\x2c\xdb\xe9\xd9\xaf\xab\x0d\xcb\x5a\x57\x25\x67\x92\xd7\xfa\x30\x2b\xaa\xe0\xe6\x1b\xda\x30\x6d\xc1\xe8\xbe\xa3\x7a\xb8\x0b\xbd\xfb\x60\xe7\xc3\xa3\x73\xfb\xa2\xdd\x0c\x96\x93\xa5\x30\x5b\x6a\x3f\x4a\xae\xf5\xbf\xb8\x24\x62\x83\x2c\x65\x0f\x28\x81\x2b\xb4\x60\x6b\x7a\xc7\x45\x4d\x32\xaa\x6f\xfe\x86\x55\x39\x11\x15\x2c\x88\x97\x9b\x82\x95\xf6\x8a\x4f\xc9\x85\x26\x66\x78\x28\xb9\xd4\x94\xa8\x03\x24\xc7\x9f\x6a\xdc\x01\x78\xfd\x0f\x3f\x4b\xb3\x44\xfd\x73\x5e\xdd\xd1\x82\xe7\x44\xd4\xa4\xa9\xe8\x1d\xe5\x05\x5d\x14\x6c\xdc\x01\x72\x7f\x2a\xe4\xf5\x0f\x57\xd7\x44\x13\x48\xcd\xe4\x71\xdd\xe6\xc3\x54\x4a\x91\x71\x7d\x14\x09\xab\x54\xad\x4f\x7b\x07\x48\x83\xa4\x2b\x64\x53\x0e\x9f\x53\x32\xaf\xc8\xf5\x9a\x11\x8f\xe1\x25\x67\x45\xde\xa2\xee\x76\x39\x1d\x60\x71\x13\x98\x5d\xe6\x11\x93\xc7\x16\x97\xf3\x91\x68\x94\xe4\x39\x43\x02\xca\xec\x14\xe6\xa3\x31\x51\x6b\xaa\x88\x61\x0e\x1d\x50\x17\xa2\xa9\xf6\x37\x98\xdc\xf3\xa2\x20\x8d\xbe\x64\xb0\xd3\x19\xd0\xd6\x05\x03\xe0\x9e\x3d\x10\x51\x77\x80\x5c\x0b\xa9\x34\x03\x34\x84\x5a\x0b\xae\x40\x5a\x0b\x41\x73\xb2\xa0\x85\xe6\x5d\xb5\xde\x1a\xa1\xd6\xac\x26\x5e\xd2\xda\x61\x54\x5d\xdb\x25\x6a\x22\x85\x06\x0d\x3f\xb5\xd3\x08\xd7\x88\x53\x5f\x30\xa2\x31\x0a\x74\xc4\xa0\x7d\x5a\x18\x66\x37\xb5\x13\xec\x42\x32\xec\x08\x97\x7a\xed\xb9\xe6\x18\xb5\x68\xf4\x21\x30\xb0\xe1\x43\x6b\x2a\x09\x2d\x6a\x2d\x4c\x10\x5a\xd7\xfc\x4e\x9f\x3d\x15\xe2\xbd\xeb\x9c\x21\xf3\xc9\x44\x5d\x6b\xf2\xc9\xab\x49\x56\x34\x52\xb1\x5a\x5f\x3f\xc5\x2b\x73\x0b\xe6\x95\xbe\x08\x95\x08\x0e\x09\xad\xf1\xc4\xf3\x25\x67\x79\xea\x11\x3e\xff\x4f\x60\x7b\x79\x53\xb0\x70\x62\xfa\x20\x6b\x09\xa2\xf5\xf6\xc4\x40\xef\x3a\x1e\xa5\x96\xbb\xeb\xb1\x3e\xf9\x7c\x55\xe9\x3d\xa2\x15\x01\xad\x61\x53\xeb\x8b\x60\x45\x86\xfd\x53\xde\xfe\x46\x07\x68\xb8\x66\x5a\x10\x21\xb4\x28\xda\x92\x08\xbb\x63\xf5\xd6\xce\xf9\x3c\xdc\x64\xae\xcc\x54\x76\xd9\x52\x80\x63\xbb\x56\x4d\x21\x68\x9e\x13\x8a\x58\x97\x1b\x81\x42\x8f\xbd\xba\xbd\x17\xb5\x03\xf4\xbc\x22\x57\xcd\x66\x23\x6a\x35\x23\x2f\xb5\x26\x96\xb3\x7c\xb4\xf7\x1e\x57\xac\xec\x20\xb0\xdd\x52\x9d\x5d\x17\x3e\x5b\x30\x90\xed\x5a\x27\x5a\x13\xcd\x05\xc3\x2b\xda\x01\x94\xa0\xd0\xd6\xc9\x08\x70\xf4\xb3\x03\xf3\x7b\xcd\x9b\x3a\x9f\xe8\x29\x2f\x69\x53\xa8\x19\xb9\xb8\x6c\x0b\xe7\xd1\xb5\x5d\x6f\x37\x8e\x08\x99\xb5\x74\x4d\x8c\xc0\xd1\x7a\xff\x8a\x55\x2b\x2d\x6f\x3f\xfb\xf4\x79\xdf\x4b\xbc\xb2\x2f\x9d\xf5\xbc\xb2\xa1\x4a\x13\x98\x19\xf9\xaf\x6f\xcd\xbd\xfe\x1f\x37\xe5\xff\xd1\x8a\x4b\x6e\xff\xf1\x13\x9d\xfc\x72\x3a\xf9\xfc\xdd\xd1\x4f\x13\xf3\x5f\x4f\xed\x9f\x8e\xbf\x3c\x9a\x4f\xa3\xcf\x8f\x9f\xce\x4f\x7e\x3a\x9f\xfc\x05\xff\x30\x3f\x99\x4f\xa6\xff\xfd\x7f\xff\xff\xff\xef\x5f\xff\xcf\x93\xa3\xe3\xa7\x7f\x18\xff\xdb\x17\xb3\x77\x7f\xf8\xd7\x9e\x29\xf6\x08\x0c\x7e\x00\xdf\xeb\xdf\x89\x90\x3f\xff\x08\x2c\x72\x07\xc5\x70\xe3\x80\xe5\x71\xb5\xb5\x0f\x51\x4e\xed\x01\x4a\x90\x4e\xb6\x79\xb2\x9e\x27\x5c\x1b\x89\x67\x5d\xab\x0a\x48\xb5\x2a\x55\x8b\xa2\x60\xb5\xbe\xde\xbd\x10\x5f\xbe\xa7\xfa\xd2\xcb\x19\xb9\x39\x9b\x3e\x9b\x3e\x9f\xfe\xf1\x66\x4c\x6e\xce\x9e\xfd\x79\x36\x3b\xd3\xff\x55\x6e\x27\x7c\x33\x31\x73\xbe\x99\xee\xdf\x1f\x1c\x8f\x75\x30\x06\xb0\xae\x39\xad\x16\xa9\xba\xd0\x3e\x21\xa1\x8a\xba\x0f\x74\x4f\x9c\x73\x33\xbf\x00\x12\x40\xce\x3e\xdb\x7b\x88\xbf\xa4\x75\xbd\xc7\x1f\x76\x35\xed\x01\x11\xed\x9b\x9d\xd7\x91\x57\xf5\xcb\x68\x7a\x07\x7b\xd8\x1d\x68\x90\x21\x3c\x27\xfa\xef\xdf\xda\x81\x6d\x89\x6e\x48\x64\x2b\x2c\x57\x1e\x14\x4c\x3d\x87\x08\xc4\xb0\x7b\xae\xd6\x3b\xcb\xf6\xef\xa1\xfc\xdc\xb1\xec\x42\xac\x78\x46\x0b\xa7\x98\x18\x7a\xab\x39\x2d\xca\x43\x70\x1f\x3c\xd0\x27\x32\x50\x88\xc9\x79\x97\x74\x56\x30\x2a\x15\x11\x15\x73\xdf\x37\x0c\x2e\x60\xde\xc0\x1b\x5f\xd2\x6c\xed\x16\x0d\xfc\x38\x22\x35\x94\x8d\xd4\xf2\xc6\x1d\x23\x94\x34\x15\xff\x6b\xa3\xef\x62\xb9\x30\xe2\x82\xde\x3e\x4b\xf3\xc6\xe4\x52\xd4\x0a\x15\xd7\xcb\x5a\x28\x91\x89\xa2\x87\x91\x9d\xef\x0a\x00\x20\x2e\x80\xfd\x2b\x40\xde\x62\x0b\x10\xad\x9c\x5d\x91\x4c\x14\x05\xdd\xc8\x2e\x7c\x32\xbd\x26\x04\x20\x96\x01\x0c\x5e\xa1\x59\x81\x57\xab\x22\x40\x0c\x5f\x76\xc8\x2c\x9d\x5c\x53\xb1\xba\x34\x2a\x90\x91\xb0\x42\xe0\xf0\x07\xfc\xac\xde\xba\xf9\x28\x13\xe5\x86\x2a\xbe\x28\xd8\x7c\x34\x25\xe7\x5d\x30\x3b\x56\x4e\x0b\x29\x0c\x18\x25\x56\x0c\x25\xcb\x2a\x77\x0b\x26\x1e\xac\xff\x7c\x97\x28\xcd\x0a\x51\xad\x40\x91\x16\x24\xe7\xcb\x25\xab\xb5\x08\xfa\x8d\xb5\x41\x6a\xdc\x7f\x2d\x6a\xc2\x90\x4c\x8e\xf7\x25\xb1\xae\x13\xc0\x57\x6b\xa5\x09\xb0\x16\xef\xeb\xb6\x98\xb4\x68\x4d\x0d\xae\x02\xec\x04\x0a\xc7\x7c\xa9\x05\xab\xee\x4b\xaf\x11\xb7\x14\x45\x21\xee\xf5\x74\xbd\x25\x0d\xf0\x58\x32\x35\xd3\x73\x3d\x9b\x92\x97\x1c\x40\x01\x54\xfb\xe9\x0e\x88\xfa\xd3\xad\xed\xb0\x47\x5e\x1a\xf5\xe4\xdb\xeb\xeb\xcb\xf9\x48\xbf\x6a\xcf\xa6\x96\xe4\x3f\x00\x2c\xc3\x89\x19\xe9\x17\x3f\x70\x35\x1f\x69\xa8\xf3\xd1\xf5\x2b\xfd\x9f\x03\xb7\xe0\xd9\x14\xaf\xa2\x3b\x95\x91\xaf\x51\x77\xcd\x8c\x14\xda\xb5\xfd\xe6\x7e\x76\xcc\x1b\x76\xfe\xf9\x94\x9c\x83\xf9\x45\x43\xa5\x05\xc9\xa8\x64\xe3\x16\xc1\xe8\xc7\x00\x35\x33\x2a\xe9\x96\x88\x92\xab\xe0\xd6\xa3\x56\x7c\xbf\xe6\xd9\x1a\x40\x22\xdd\x8a\x80\x2c\xa9\xca\xd6\x4c\x92\x7b\x7d\xa7\x2b\x61\x0e\x8b\xc3\x82\x7f\xc3\x2a\x23\x69\x57\x55\x30\x19\xbf\x30\x63\x00\xe4\x74\xc3\x4d\x2d\xee\x78\xce\x72\x73\x8d\x3b\x95\xfd\x4c\x94\x70\x3c\xc1\x62\x64\x35\x63\x47\x56\x71\x9a\x39\x0a\xc1\x6e\xfe\x4a\x90\x25\x47\x92\xd5\x01\xd3\xaa\x5f\x46\x6b\x79\xab\x95\x3b\x23\x3d\xb9\xcf\xb9\x29\xee\x7e\xa8\x91\xdd\x82\x84\x5e\x97\x3b\x1f\xa8\x40\x2e\x77\x4f\xb7\x5e\xa6\xa8\xf5\x0d\x16\x4b\x52\x0a\xa9\x35\x53\xc3\x33\xac\xf6\xd5\x75\x4e\xaf\xf1\xb4\x8d\x35\xcd\xc8\x94\xdb\x3b\x60\x0b\x0b\x40\x62\xa6\x99\x92\x56\xcd\x97\xa2\xd6\x34\xa0\xc8\x33\x5a\xe7\x6e\x0f\xbb\xcf\xfe\x85\x31\xb3\xe2\x64\xfd\x39\x2f\x9b\x42\xf1\x4d\xb8\x6b\x56\xe3\xbd\x43\x35\x52\x76\x8b\x11\xc0\x28\xd0\x76\xb3\x68\x90\x8f\x56\x42\x05\xc7\x60\xdc\xa5\xa4\xc2\x2a\x6a\xca\x3b\x59\x0a\x25\xf3\xd1\x0b\x51\x2d\x0b\x9e\x29\x96\xcf\x47\x9e\x48\x59\xc2\xef\x50\x6b\xfc\x01\x2d\x1d\xed\x85\xa8\xd9\x43\xf5\x33\x07\x98\x95\x0b\x91\x5b\x22\x96\x89\x2a\x63\x1b\x85\x22\xd3\xae\x00\xd1\x29\x81\xde\xaf\x59\xcd\x3c\x7b\x27\x34\xd3\x00\xa4\x35\x78\x68\x88\x15\xcb\xd0\xdc\xf8\x00\xe5\x8d\x6a\xf2\xcd\x72\x3c\xc3\x43\x5a\x5c\xaf\xcc\x5e\x59\x87\x51\x2f\x08\x3d\x96\xb5\x28\x67\xe4\xaa\x7b\xf7\xc9\xbe\x0d\x31\x9c\x5a\xcb\x8c\x09\x36\x55\x8d\xc3\x1a\x9f\xe9\xe3\xd5\xfb\x5d\xcd\x9c\x17\x8c\x50\xa5\x68\xc7\x4d\xb7\x06\x40\x55\x37\x60\xfe\xf3\x2b\x41\xcc\xf7\x82\x55\x6b\x21\x19\xde\x7d\x27\xee\x4a\xfb\x31\x63\x8a\x83\xd3\x74\x5e\xa8\xb5\x68\x56\x6b\x42\xbb\xad\xd6\x7e\x58\xda\xa4\x09\x34\x5c\x3d\x7f\x95\xd0\x80\x54\x37\x05\x93\x9a\xdc\x17\x5b\xa0\xf9\xfa\xdf\xfa\xed\x5e\x88\xfa\xe7\x25\x55\xac\xd8\x92\x9a\x65\x8c\x9b\x0b\x68\x3e\x34\x25\xaf\xf5\x57\x34\xb9\xda\xe8\xc7\x39\xab\x32\x47\xb0\x7a\x61\x3a\x79\x2a\x6f\x91\xa3\x1d\x61\xa0\xe6\x8a\xd5\x9c\x82\x08\xf0\x14\x48\xa3\xa6\x57\xbd\x40\x2d\xf9\x32\xeb\xa6\x76\xbf\x73\xab\x3c\x22\xa2\xf5\xc6\x4f\x0d\x3c\x51\xe4\xdd\x26\x4e\x1c\xf8\x83\x05\xd5\x74\x4d\x54\xce\xc7\x4b\x94\xf5\xc1\x4d\x77\xc4\x28\xf3\x0b\xcd\x2c\x7b\x81\xce\x35\x49\xd9\x07\xa5\xd7\x3f\x1f\x3d\x3b\x7d\x76\x3a\x39\xfd\x7c\x72\xfa\x67\x72\x7a\x36\x3b\x7d\x36\x3b\x7d\x3e\x1f\x69\xd5\x69\xc5\xef\x58\xbf\xbe\x1b\xa0\x5e\xdc\x01\xef\x0c\xa7\x92\xf4\xbd\x5e\xd8\x66\x1e\x7f\xd4\x82\xec\x53\x4d\xb0\xc1\x26\xa6\x60\xcb\x59\x21\xc1\x48\xae\x15\xd8\x3b\x5a\xb0\x4a\x8d\x3d\xa6\x7b\x21\xd2\xcd\x86\x51\x70\xfd\x2c\x79\x2d\x95\x3e\x02\x9a\x88\x6c\xd6\x74\xc1\x14\x50\x33\x3c\x11\x47\xee\x22\x9d\xe8\xff\x3a\x36\x9e\xb5\x5e\xb8\x0b\x86\x68\x0a\xd0\x81\x1b\x44\xfc\x16\x2d\x85\x38\x59\xd0\xda\xa1\x34\x78\xb7\x17\x2e\xa0\x14\x7f\xf8\x8b\xb9\x8e\x05\xda\x38\xf0\x36\x79\xe1\x08\x71\x1e\x90\x89\xc8\xd5\x0f\x84\x23\xeb\x32\x5c\x04\x9c\x09\x9d\x4c\xf8\x95\xb7\xfe\xe6\x92\x8c\xf6\x1f\x03\xfd\xfb\x55\x25\x6a\x96\x93\x23\x29\x4a\x06\x9b\x8d\x8c\x13\x6c\x2c\x25\xa3\xc8\xb1\x96\x4d\x51\x20\xd4\x63\xf4\x77\x0c\x5c\x01\x20\x12\xaa\xa6\x95\x34\xd2\x39\x78\xd4\x70\x72\x4a\x58\x27\xc7\xd8\x59\x6b\x96\x9d\xe6\x78\xbb\x72\xaa\x42\xb0\x7e\xed\x79\x2d\x36\x1b\xa4\xae\xac\x92\x4d\xcd\x50\xdb\xd0\x38\xca\xb6\xb0\x93\xbd\x40\xdd\xfe\x32\xbd\xa7\x5a\xe1\x20\x4b\x5e\x28\x8d\x5a\xab\xf3\x6a\x2a\x40\xc3\x0f\x7b\xef\x4c\x97\x2d\xdb\x4e\x16\x28\xb3\xb2\xd4\xa9\xb5\xdf\xc1\x4a\xcc\x22\xa4\xb2\x26\x7f\x44\x04\xcb\xfb\x6c\x8e\x24\x41\x48\xc0\x31\xc4\x7d\x89\xf1\xb9\x46\xd9\x66\x9b\x2b\x7e\xa7\x5f\xdf\x51\x8d\x40\xae\x97\xc0\xcb\x00\x9a\x97\x4a\x23\x60\x89\x37\x57\x18\x21\x00\xb4\x41\x10\x7b\x45\xdb\x8f\x63\xcf\xfa\x94\xfc\xc7\x3a\x42\xc9\x08\xe8\x2f\x7e\xd3\x34\x79\x2d\x37\x6a\x8b\x74\x65\x67\x66\x44\xb2\x82\x65\xe0\x71\x8b\x70\x59\xd2\x66\x38\x20\x3c\xb7\xe5\xb6\x8d\x55\xd0\xe0\x72\x23\xf0\x6f\x34\x3e\x34\xa2\xa2\x70\x81\xd1\x79\xa3\xbe\x5e\xf5\xee\x1c\x1d\x86\xbc\x10\x1a\x05\x69\x0c\x49\x4c\x93\xc9\x82\x67\x48\xb6\xed\x0c\x83\xe3\xbc\x23\x7c\x3e\x89\xef\x93\xd3\x76\x41\xd2\xc6\x4b\xbf\x67\x7d\x01\xdd\x49\xcb\xcb\xe6\xf8\x46\x21\x8a\xda\x87\x36\xd8\x58\x09\xeb\xac\xdf\x6e\xd8\x98\x70\xa3\x21\x69\x15\x07\x75\xe3\xb7\x4c\x8a\xe2\x8e\xe5\x6f\xd9\x52\xce\xfb\xce\x3b\x0e\x2f\x64\x2b\x41\xbe\xa6\x9a\xcf\x38\xbb\x62\x4b\x51\x36\xa0\x0d\xa9\x04\x9c\xc3\xf1\x1e\x80\x5f\x33\x2a\x8d\x9b\x2b\xe9\x16\x92\x98\xd0\xee\x47\xeb\x9e\xb5\xcf\x91\x73\xe4\xca\xd0\x5a\x64\xae\x5b\x14\xa8\xb1\x8e\xb6\xe5\xc4\x7e\xc2\x42\x12\x89\x06\x0e\x8c\x36\x1b\x78\x29\x70\xc2\xc4\xc2\xd2\x86\x40\x84\xa6\x63\x58\x3e\x0f\x71\x61\x48\x2c\x2c\x33\xbe\x3a\x92\x6a\x9b\xf7\xc3\xfb\x66\xfe\xf5\x7f\xfe\xeb\x03\xdd\x2f\x7d\xce\x15\x3f\x06\xdd\x2c\x7e\xec\x87\xcb\x74\x8d\x16\xee\x6c\x04\x8d\xa5\x88\x0f\xc7\xdc\x67\xc3\x88\x4b\x70\x6f\xf8\xe1\xb1\xac\xf1\x75\x3e\xf9\x8b\x41\xe1\xf9\xe4\x2f\x0e\x8b\xe6\xbf\x8f\xbf\x7c\x44\x34\xc6\x3c\x28\x7e\x4c\x86\xaf\x5a\xd4\xa9\xe2\x87\x77\xaf\xf4\xcb\xcd\x31\x3f\x8b\x1f\x69\x5a\xef\xa0\xf2\x4c\x52\x54\x63\xb2\x27\x08\xbc\xf1\x9a\xaa\xa7\x4e\x81\xfa\x0a\x62\x1e\x98\xf4\xa2\x5f\x36\x9c\x4e\xeb\x9c\x3b\x5a\x72\x8b\x5e\x7b\x47\x90\x16\xa9\x6a\xb0\xa7\xc4\x77\x43\x38\x97\x11\x4c\xc8\x45\xe5\x59\xa1\x62\xb1\xb5\xa8\x69\x51\xf2\x28\xd0\x21\x2a\x9f\x4a\x3a\x01\xdd\x03\x47\xd8\x51\xcd\x81\x5d\x21\x7b\x3b\xf3\xb5\xc6\xbc\xdf\x13\xb4\xe0\x18\x3c\xfb\xb8\x12\x94\x7e\x06\xef\xd1\xbe\x47\xee\x52\x48\x09\x56\x51\x74\xcd\x6a\xf9\x64\x46\x9e\x6a\xc5\x66\x96\x22\xf5\x11\x34\xf6\xd2\xa2\x08\x4f\x8b\xd9\x7f\x70\x02\x82\xca\x1d\x7e\xf1\x29\xb9\x82\xe9\x8a\x7a\x98\xda\x99\x75\xf2\x2a\x84\xee\x64\x3d\xa3\xcd\x4b\x03\x2e\x6a\xbc\xb0\x23\x98\x16\xd9\x9f\x18\xc4\xc8\x7e\x5f\x15\x5b\xff\xe5\x61\xda\x64\x8c\x90\xc1\xe9\x8c\xae\x3f\xe2\xad\xb6\x23\x59\x10\xd1\x83\x55\xcd\xe0\xf1\x9b\xe8\x0d\x1d\x7c\xc7\xee\xcb\xf0\x8b\xc3\x87\x38\x99\x62\xcb\xc4\xc3\xd0\xbe\x15\x57\x6e\xcf\x8d\xdd\xd9\x8b\xc3\xe0\x45\xc0\x5b\x33\x7c\x76\x41\x24\x15\x64\xee\x00\xce\x47\x10\xd2\x69\x82\x5d\xd0\x1f\x72\xd0\x71\x78\x13\x5e\x03\x63\x10\x83\x03\xe0\xa6\x7c\xf0\xad\xdd\x3b\x42\xd7\xde\x52\xae\xc9\xa8\xd1\xf4\x97\x2e\x7e\x6d\x20\xcc\xc2\x0e\x30\xfc\x68\x4c\xe9\x45\x1f\x22\xff\x92\x83\x04\x4b\xe3\xbe\x79\xf9\x7e\x53\x33\x29\x7d\xb6\x47\x7c\xb4\xf6\x7b\x17\x00\x86\x0d\x17\x1c\xf5\xf1\x82\x2e\xd8\xd0\xe9\xc6\xe1\x48\x85\x91\x13\x4a\x8c\x16\xbe\x36\x66\x4c\xfb\x17\xd0\xd2\xce\xdf\x7c\x15\xd3\xda\xfd\x48\xd0\x06\x3a\x17\x75\x8e\x13\xef\x9c\x14\x2c\x30\x09\x64\xb0\x28\x3c\xb4\xa2\x52\x94\x57\xd2\x1c\x82\x31\xa1\xe4\x96\x6d\xd1\x0b\x1f\xb1\x18\xb5\x87\xde\x5a\xea\x40\xd6\xac\x70\xda\xca\x2d\xc3\x28\x36\x13\x71\x9e\x04\xef\x90\xa3\x82\xe3\x96\x6d\x53\x5f\xdd\x41\xaa\x9e\x9f\x91\x88\x11\xbb\xfa\x0f\xd6\x55\x9f\x0c\x32\x40\x2a\x28\xdf\x0c\xc2\xbf\x93\x7f\x7e\x80\xd4\x6f\x87\xc5\xf8\x03\x97\xed\x36\xac\x15\xb9\x7b\xcb\xb6\x4f\x24\x6e\x9f\xbe\x35\x6b\xbe\x39\x00\x03\x61\xfa\x85\xcd\x2f\xf8\x11\x43\x98\xcd\xc7\xe4\xa0\xb5\xa5\x3d\x2e\xaa\x31\x79\x23\x94\xfe\xbf\x97\xef\xb9\x54\x68\x64\xfa\x4a\x30\xf9\x46\x28\xf8\xcb\x47\x45\x31\x2e\xe2\x81\x08\x36\xe2\x11\xc7\x90\x48\x2d\xc9\x6b\xbc\x1c\xf4\x7d\x3f\x87\xa9\x75\x62\xbb\x6d\xe3\x52\x73\x1d\x51\x1b\xfc\x1c\xb2\x4d\xeb\x40\x76\xd3\xd3\xb2\x1c\xb1\x12\xd5\x04\x2c\x66\xf6\x6b\x07\x00\x0d\xe7\x65\xb6\x4a\xd4\xad\x9d\x1a\x1f\x08\xb1\x73\x8a\x66\x7a\xc0\xce\xf0\x49\x02\xcb\xf6\xa3\x66\x9b\x82\x66\x2c\x27\x79\x03\x4e\x04\x48\x24\xa1\x8a\xad\x78\x46\x4a\x56\xaf\x98\x56\x43\xb3\x75\xfa\xa1\x3a\x80\x92\xe3\x78\xc0\x29\x4c\xd3\x06\xc3\x91\xa6\xd3\xda\x31\xd1\xb7\x3e\xf1\x4d\xbb\xcd\x49\xaf\x27\x6a\xc4\xed\xd7\xd3\x56\x09\xec\xfd\x95\x26\xd7\x49\xd8\x0f\xd3\x06\x0f\xe3\x2c\x07\xee\xd7\xbe\x0c\x82\x93\x44\xf1\xa3\xa4\x60\xaa\xfa\x9b\x66\xaf\x70\xbc\xff\x9e\xc6\x0d\x29\xaf\xe5\x94\x9c\xdb\x18\xb4\xe0\xf7\xd6\x94\x1b\x7c\x2a\x09\xa4\x9e\x49\xcb\xf9\x06\xc4\xbb\x22\x0c\x6d\xba\x10\xe0\xb1\x23\x41\xa5\x91\x98\x7b\xf0\x4b\x6b\x16\xea\xa4\xcd\xd1\x2d\xdb\x8e\xc6\x7b\xd4\x6b\x74\x51\x8d\xd2\x60\x5a\x27\x79\x8b\x22\x38\xa9\x05\xa4\xed\x11\x3c\x1b\x81\x60\x76\xc8\x15\x79\x80\xf0\x76\xc0\xa9\x4e\x7c\x35\xe1\xb5\xc1\x57\x6c\xc0\x4f\x5a\xfc\xb5\x8b\xf4\x69\x3b\x72\xee\x78\xad\x1a\x5a\xf8\xe8\x21\x25\xf0\x18\xf4\x4e\x5e\x6b\x10\xce\xc1\x80\x71\x11\x20\x3a\xa1\xfb\x1c\x95\x10\x13\x74\x82\xde\x9b\xd0\x43\xd3\xbf\xfb\xb4\xf0\x93\x30\xf1\x7c\x18\xbf\x14\xd3\x64\xec\x3c\xfa\x6f\x00\x4e\x4d\x54\x4f\x94\xdd\x7f\xbf\x54\x74\xd5\x5b\x05\x0c\xe3\xc6\x5a\x2e\x8e\x7e\xb0\xe0\xaa\xd0\x52\xdf\xd6\x87\x50\x39\x4d\x2e\xc8\x33\x29\xb6\x3e\xa6\x4a\xc4\x19\xac\x0f\x65\x70\xab\xb2\xb1\x0c\xaf\xae\x66\xa0\x7e\x38\x57\xc6\xb7\x61\xac\x57\x2f\x44\x8c\x6c\xd0\xbb\x7c\xf5\xe6\x62\x4a\x9e\x92\x6f\xaf\xaf\x2f\x63\x90\xfc\x2f\x7a\x61\xea\xf7\xc9\x9a\xd1\x20\x06\xc3\xc5\x76\xe0\x07\xfa\xe6\xda\x0b\xf2\xea\xdb\xef\x7f\x78\xf5\x95\x8d\xc3\x50\x64\x21\x8c\x9f\xe6\xfa\xd5\x15\x10\x02\x0d\x15\x35\x04\x3c\x74\x05\xdd\x62\x38\x75\x2f\x48\x9b\x9b\x92\x13\xba\x10\x77\x6c\xc8\x81\x45\xac\x07\x39\x1a\xd6\xe3\xe6\x75\xf5\xe6\x02\xe7\x15\xe0\xc2\xe3\xda\x2d\xdc\x9e\xb3\xfe\x33\x3f\x27\xce\xed\x95\x15\x8c\xd6\xc5\x96\xe4\x22\x6b\x80\x1c\xeb\xa9\xb8\xd0\x5b\x8d\x01\x13\x2d\x50\xe5\x1a\x2f\xf1\x90\x09\x17\x1d\x04\x24\xb8\x66\x46\x22\x85\x64\x61\x0a\x91\x5b\xde\x19\x76\x03\x49\xf3\xee\xe6\xdd\xf4\x5f\x50\x4d\x83\xcd\x8d\x06\x54\x14\x61\x44\x13\x86\x0b\xe1\x3d\xdf\xfa\x8b\x6c\x26\x10\xbf\x47\x0b\xe6\x66\x27\x31\xb0\x8c\x2c\x98\xba\x67\xac\x0a\x79\x80\xbe\x47\xd6\xad\x15\x09\x95\xd0\xc0\x20\x60\x4d\x53\x0e\x8d\xbb\xd2\x66\xdb\xd6\x25\x6c\xfb\x98\xd4\x6c\x89\x11\x97\x3e\xcc\x27\x92\x4a\x86\xe3\x5b\x47\x9a\xec\x0e\xf9\xcc\x37\xff\xcc\x79\x6f\x37\x35\x5b\xf2\xf7\x26\xd0\xbf\x1f\xa5\x3e\xf0\x11\xf5\xd0\xa3\x9b\xa7\xd3\x9b\x63\x80\x00\xe8\xd8\xd4\x0c\xfc\xd5\x10\x80\xdb\x2c\x97\xfc\x3d\x1e\xb4\x7e\xa6\x05\x91\x97\x25\xa3\x95\x9d\x8c\x39\x99\x1a\x7b\x37\x4f\xa7\x26\xf2\x61\x9a\x89\xf2\x86\xdc\x43\x14\x02\x3e\xd7\x3b\xda\x0b\xf4\x46\xe9\xfb\x1d\xfe\x16\x4d\x05\x37\x4b\x21\xa6\x1d\xcf\x16\x8d\x82\x7b\x75\x13\xfe\xf9\xc3\x63\x1b\x1e\x3f\xf3\xea\x68\xfe\x74\x3e\x3d\xfe\xf2\x23\x79\xf8\x06\x05\xc9\x74\xee\x0d\xf9\x32\x41\x4e\x8c\xa5\xbd\x3b\xce\x92\x61\x9e\xb0\x60\x36\xe0\xdb\x85\x21\x05\x46\xe7\xdf\x6a\x1f\x7e\xab\x0d\x88\xf9\x7f\xda\x1b\x00\xa1\xc2\x76\x03\x4c\x20\xac\xfe\xf5\x94\xbc\xb6\x11\x93\x2e\x23\x28\x1e\x20\x29\x7d\x48\x32\x40\x18\x13\xd9\x60\x6d\x02\x43\x91\x1c\x03\xb1\x21\x20\xbc\xe0\x6a\x8b\xc1\x44\x1f\x7e\x89\x90\x0e\xce\x34\x7d\x79\xfe\xac\x7f\x83\x79\xd9\x94\x33\xf2\xd9\xa7\x9f\x3e\xff\xb4\x7f\x83\xf1\xa5\x78\x1e\x9b\xa6\x63\xab\xce\x88\x7e\xcf\xd1\x13\xb7\x60\x37\xaa\x65\x67\x37\x9c\x4c\xaa\x6f\x42\xd1\x9f\x49\x80\x83\xbd\xdf\xb0\x0c\x2a\x36\xd8\x40\xd5\x07\x5e\x80\x08\x7e\x0e\xbb\x00\xc6\xd5\x8d\x67\xfc\xaa\xdb\x09\xfe\x98\xb9\xa0\x1f\x90\xf7\xa9\xfa\x75\xf0\xf6\x9e\x69\x11\xce\xdc\x1a\xfd\x9f\x99\xa8\x96\x7c\xd5\xd4\x28\x7f\xd9\xca\x00\x8e\x88\x45\xb8\x5a\xa8\x01\x58\x5b\x87\x4d\xc8\x6a\x47\x2b\xe9\x37\x5c\x62\x4d\x2f\x44\x9f\x70\x33\x25\x17\x2a\xac\xbd\xa0\x84\x89\x41\xf2\x9f\x6c\x7f\xa6\x5f\x82\x6f\x7f\x7e\x3e\x1a\xeb\x6f\xbc\x80\xff\x80\xef\xfd\xf0\xd5\xa5\xf1\xa2\x5c\x07\x55\x19\xba\x33\x53\xcc\x34\x97\x5a\xda\x84\x53\xfa\x82\xd5\x4a\x8b\x28\x54\x31\x17\xaa\xec\x93\xc1\xaf\x5f\x5d\xbd\x00\xe4\xea\xef\x9b\xc7\xfd\x4c\xc0\xc6\x28\xf7\xa4\x80\xb4\x6e\x90\x9b\x6f\x98\x6f\x19\x17\xe8\x2c\x8d\x2b\x44\xb5\xc2\xf0\x72\xa3\x19\x69\xc9\x59\x34\x98\x8c\x50\x14\xc4\x55\xb8\x20\x99\x5f\x5c\x3f\x6c\x90\x00\xab\x2d\x9c\xa4\x35\xad\x72\xb9\xa6\xb7\x07\xdc\xda\x14\x0f\x43\x30\x8f\xb7\x6c\x79\x40\x90\xe4\x8b\xf6\x0f\xbd\xad\x02\x2a\x1d\x71\x93\x3c\xc0\x20\xb7\x2e\x1b\x8a\x92\x14\xe4\x3b\x57\xb5\xcc\x58\x00\xe4\x8e\xe3\x06\x6e\x53\x80\x34\x2d\x8f\x45\x81\x6e\x6a\x7e\xa7\x8f\xce\x2d\xdb\xa2\x33\x4b\xb2\x1d\x00\x35\x73\xd5\x23\x98\x54\x74\x51\x70\x19\x0f\xe4\xa0\xed\x9d\x80\xfd\xf1\x95\x70\x40\x10\x75\x5a\x51\x50\x5c\x23\xbe\xf6\x76\xb9\x92\xd6\x21\x74\xd6\xb0\x36\xb2\x63\xda\x00\x4e\x33\xc0\xe6\x15\xcb\x6a\x86\xb5\x30\xe6\x23\x7d\x5a\xe6\x23\x1b\xbf\x38\x4d\xd6\xfe\x89\x49\xf2\xc8\xd6\x42\x48\x30\x99\xd8\x50\x66\x8c\x66\xd1\x47\xdd\x25\x52\x24\x1d\x6d\x62\x7d\x29\x96\x16\xa2\x10\x0d\x17\xd1\x15\xa3\xd1\x44\xaa\xbb\x02\x46\xdc\x88\x35\xaf\xc8\x5b\x77\xf2\xf0\x33\x2e\xf8\x92\x57\x41\xca\xa7\x0f\x4e\x18\xf2\xd9\x58\x62\xf9\xc3\x9b\x57\x2f\xaf\xae\x02\x2d\xd3\x7f\xe9\x9b\x9a\x56\xca\x1a\x2b\x15\xad\x57\x9d\xa5\x71\xfc\xf0\x1f\x47\xc5\xa5\x28\xc4\xbd\x49\x61\x0a\x28\x1f\xa6\x8f\xda\xa0\xa1\xf8\xba\xa1\x34\xcf\xce\x7c\x9c\xce\x0f\xf0\x6d\x24\xaa\x79\x65\xd8\x5f\xb1\x1b\x95\x1a\x44\x9e\xba\xb4\x69\x8c\x16\x68\x47\xa1\x46\x81\x16\xfd\x11\xaa\xed\x93\x3e\x1f\x05\x91\xa8\x51\x90\x3d\x0c\x53\x09\x93\x95\xad\x82\xc4\x6f\x6b\x00\xbe\x1f\x8a\xb4\x06\xab\xb3\xc8\x6d\xa1\x23\x8c\x89\xb8\x86\x48\x69\xaa\xf4\x45\x3a\x32\x11\x4c\xc7\xa0\x1d\xc6\xcb\x2c\xf9\x01\xe1\x08\xf7\x5c\x22\x29\xdf\x23\xa4\xb4\xf2\x1b\x04\x57\x4d\xd1\x2a\xa7\x75\x9c\xda\x05\x37\x3e\x30\x86\xf0\x29\x9b\x1a\x0a\x00\x1c\x39\xbd\x9e\x8c\x1f\x19\x14\xad\xf4\x50\xf7\xf9\x0f\x99\x78\x4a\xe5\x66\x3e\x7c\xf3\xf7\x89\x94\xd6\xf1\xb6\x1b\x46\x5a\x45\x2e\x4f\x54\x21\x93\xa3\xd7\x2e\xba\x17\x48\x8e\xa0\x04\x99\x5a\xd3\x0a\xb3\xba\x1c\x7e\x6d\x74\x48\x14\x6a\x2b\x72\x5b\x1e\x3f\x66\x10\xf4\x08\x97\xfe\x3d\xf0\x3c\x77\x75\x09\xcf\x59\xa5\x4c\x4e\x73\x45\xce\x2f\x2f\x06\xac\xf0\xa6\xd8\x1b\xaf\xb2\xa2\x81\xda\x39\x5c\x05\x91\x8a\x63\x1b\x69\x67\x72\xde\xf1\x9b\x43\x8e\x00\x5b\x05\xeb\xf2\xc2\x82\xb7\x1e\x4a\x24\x85\x86\xd2\x99\xf2\x48\xff\x96\xe0\xfa\xfc\xc6\x05\x75\x43\x8c\xae\x05\x57\xb3\x95\x26\x08\x35\xdb\x85\x19\x4d\x94\xc1\xd1\xa6\x67\x86\x5a\xc2\xfc\xa6\xfb\x6c\xc0\x48\x16\x03\x20\x81\x28\x59\x7a\xbf\x33\x65\x9b\x31\x6b\x12\x7a\xa8\x59\xc5\x00\x44\x58\xe3\xcf\xad\xf0\xbc\xf6\x4d\x1c\x9b\x44\x34\x6f\x47\x1f\x80\xf8\xc2\x57\x02\x80\x60\x84\xca\x95\x7f\xa1\x1c\xaa\x3f\x99\xaa\x8b\xf1\x78\xa5\x8f\x17\x06\x3f\x1a\x0a\x94\x4a\x8e\x77\x37\x7b\xab\xe2\x09\x4e\x7e\xb8\x54\xa7\xd1\x5e\x08\xfe\x68\xdf\x3d\x43\x8e\xc0\xdb\x9e\x00\x17\x95\xc3\xe3\x31\xc9\x34\x25\xd1\x97\x62\x65\xe7\x0c\xa5\x14\xeb\x14\xcf\xda\x3f\x5b\x54\xbe\x0d\xef\x05\x7a\x73\xd8\x89\xb0\x51\xfc\x61\x04\x7f\xeb\x2c\xd8\x9d\x4e\xd8\xbb\x91\x73\x27\x40\xe1\x89\xd1\x15\x96\x62\x1d\xfd\x53\x26\x03\xc4\xad\xb0\x7e\xb4\x76\xa3\xcf\x1c\xeb\x76\xe4\xb1\x8f\xfe\x41\xa8\x3c\x70\xed\xc0\x13\x0f\x44\x80\xcf\x05\x08\xd1\x10\x84\xdd\x33\xb2\xa0\xd9\x2d\xab\x92\xfc\xeb\x7b\x5e\x62\x63\x3d\xc8\x68\x10\x31\x7e\x18\x69\x01\x7e\xfd\x46\x28\xa3\x4d\x40\xbc\x2f\x6d\x03\x0b\x3e\xb7\xab\x26\x24\x80\xb7\x22\x46\x68\x8e\xaa\x5a\x87\x20\xd4\x68\x86\xf3\x9d\x88\xd3\x48\x68\xf0\xcb\x27\x92\x88\x7b\x53\x1f\x04\xdd\x5a\xe1\x27\x86\xf2\xba\x70\x5c\x31\xb4\xc6\xec\x69\x42\x81\x1f\x0b\x14\x95\x9c\x29\xca\x8b\xa4\x78\xcd\x43\x03\x81\x7f\x45\xd2\xd1\x4b\xf4\x7f\x83\x0c\xa2\xa8\xdf\x9b\x3c\x24\x83\xe8\xb3\x3f\x46\x5e\x4b\x09\xa7\xd2\x0a\x5c\x4a\xf2\x10\x71\x8a\x5d\xb2\x0d\xec\xb5\xd6\x0d\xc3\xaa\x19\xd7\xaf\xae\xbc\xf5\xc2\x5a\x7b\xaf\x5f\x5d\x45\x51\x22\x31\xf8\x88\x40\x33\x00\x1a\xc8\x88\x58\xcb\x02\x6c\x57\x35\x58\x28\x88\xba\x17\x64\x63\x72\x53\xa2\x30\xf5\xa2\x31\x9a\x62\xe2\xd7\x85\x71\x0a\x7a\x8e\xf6\x93\xa1\xd7\x39\x17\xf7\x95\x54\x35\xa3\x65\x5c\x1d\xc4\x22\x3f\x3e\x62\xc9\x55\x2c\x95\x44\xd9\x2f\xed\xd6\x59\x8d\xdf\x30\xd0\xdd\x41\xcf\x36\xc7\x4c\xee\x1b\x26\x8d\x64\xaf\x85\x5d\x2c\xf9\x05\x92\x6e\xdc\x0c\xd6\xa1\xf3\x4f\xc9\x84\x5c\x52\x29\xd5\xba\x16\xcd\x6a\xbd\x8f\x91\x01\xcb\xc5\x9b\xef\xaf\xc3\x55\x9a\x8d\x6a\xa7\x20\x60\xed\x32\x1e\x14\x43\x8b\x82\xb4\xf8\xcb\x68\xf5\x44\x91\x9c\x65\x7c\xb3\x66\xee\xe4\x10\xdc\x12\xc2\xde\x03\x2d\x5c\x42\xb9\x86\x21\x90\x2f\x60\x8f\xbe\x65\x45\x21\x48\xc9\xa4\xa4\x2b\xc7\xa4\x34\x48\x9f\xcf\x4d\x76\xad\x0f\x51\xb0\x7b\x11\x49\xdc\x54\xdf\xd3\x7b\x77\x58\xae\xc4\x50\x7a\xce\x24\xe9\x36\xb6\xf6\x72\x90\x4c\x0c\x90\x39\x34\xdd\x44\x35\xa1\xc3\x43\x2c\xdb\xa9\x0d\xae\xb3\xc7\x8f\xb6\x7c\xb6\x0b\xf7\x30\x35\x98\x7d\xf3\x8f\x01\xda\xed\x1d\x21\x5a\x17\xf1\xa9\x83\xae\xc4\x24\x68\xa8\xae\xfa\x60\x49\x37\x43\x6a\xaf\x6c\xb0\x2a\x8c\x3e\x21\x06\x17\x06\x2c\xa0\xb7\xd8\xba\xaa\x56\xde\x70\x33\x00\xd2\xaf\x26\x98\xce\x98\x50\x5b\xae\x07\x84\x1e\xe0\x7a\xc1\xf3\xe1\x85\xbb\x34\x24\xbd\xe0\x96\x6b\x87\x55\x8a\xd7\x8c\x48\xfe\x8b\xaf\xbc\xea\xdb\xa9\x0c\x21\x00\xea\x59\xc7\x49\x55\xc0\xd4\xff\x78\xfa\xf9\x7e\xed\xd0\xd6\xbb\x9e\xa5\x9f\x26\xf0\xc4\x41\x2e\xdc\xe6\x3d\xdf\x6f\x7c\x21\x40\x9f\xf4\x73\xcb\xb6\x27\x78\x9e\x20\xa0\x16\x6b\x85\xd0\x21\x6e\xc1\x4c\xa1\xe4\x1e\x97\x25\x04\xf3\xed\x96\x81\x1f\xd2\xc6\x9d\x1e\x6e\xe1\xd9\xb2\x12\xc6\x8d\x0e\xdf\x32\x7d\x25\xa0\x5a\xb8\x2d\x09\x12\xe7\x3e\x48\x1c\x65\xc3\x95\xb1\x44\x9e\xdb\x6c\x8c\x4c\x94\xa5\xa8\xc0\xdd\x63\x6b\x44\x0d\xb9\x05\x89\x4d\x23\x43\x85\x9e\xdb\xea\x2f\xaa\xa9\xd9\x94\x5c\x0b\x42\xef\x04\xcf\xc1\x05\x47\xcb\x05\x5f\x35\x5c\x6d\xc7\x0f\x32\xa2\xe6\xae\xd7\x8f\xf4\x1e\xc3\x5c\x94\x94\x57\x13\x17\x3a\x65\x02\xc8\xec\x45\x0c\x83\x89\x4e\xca\xed\x04\x0d\xb1\x13\xbc\x9b\x91\xe8\x22\x3d\x7e\xd8\x05\x0b\xe7\xa4\x66\x92\xd5\x77\x86\x40\xdc\xb2\xad\x79\xe4\xeb\x40\x25\x31\x2a\xa0\x37\x21\xb1\xef\x31\xba\xc6\xe8\x7f\x49\xdf\x07\x24\xb4\xab\x0a\xaf\x1f\x1f\x1e\x3a\x1c\xaf\x20\xdc\x23\xb3\x4e\x48\x4f\x8d\x8f\x89\x63\xa0\x1d\x0f\x13\xcb\x0e\x77\x48\xb5\x25\xaf\x6c\x4d\xe2\xbd\x67\x31\x39\xf7\xfd\x24\xe8\xf8\xa4\xe9\xc0\xa4\xa4\x9b\x89\xbe\x06\xfb\xcb\xed\x59\xec\x3e\x08\xfc\x60\x49\xdb\xa9\x51\xdd\x78\x9c\xec\xd5\x45\xde\x79\x5c\x74\xd6\x62\xed\xeb\xb7\x01\x45\x02\x77\x3b\x6e\x74\xe6\xf7\xfb\x72\xa8\xbb\x4f\x26\xa4\xa0\x52\x5d\xbb\x8a\x4c\xd7\xbc\x64\x33\x32\x3a\xfb\xfc\x4f\xa7\x93\xd3\xb3\xc9\xe9\xd9\xf5\xe9\xe9\x0c\xfe\xf7\x97\xfd\x53\x6a\x24\xa6\x19\xf9\x0f\xca\xc1\x62\xae\x6f\x8b\xaf\xac\xbd\xf7\x3e\x7a\xa8\x66\x5a\xf9\x7e\xcb\x32\x51\x65\xbc\xe8\xa0\x39\x66\x5d\xe4\x87\xea\xb6\x12\xf7\xfb\x5c\x0e\xd1\x71\x65\x7a\x01\xe4\x3b\xeb\x0f\x3b\x8e\x00\xa0\x96\xda\x91\x35\x35\xe8\xdf\x1f\xbb\xe7\x88\xef\x75\x50\x70\x74\x79\xb3\x56\x0f\xa2\xa0\x08\x25\xcd\x54\x43\x8b\x62\x4b\x16\xac\xd3\xc9\x86\xe5\x9b\xdb\x8d\x00\xac\x97\xde\xc3\x2b\xe9\xd6\x78\x6b\x7d\x93\x1a\xf7\xb4\x03\xaa\xa1\xe0\x57\x1b\x96\x8d\x09\x9b\xae\xa6\x36\x94\xc5\x95\x76\x6c\x94\x28\x29\x54\x51\x2b\xb6\xb6\x43\x41\x50\xcf\xbf\x03\x26\x7c\x98\x7a\xda\xb9\x11\x5d\xa5\x6a\x7f\xef\x28\xf0\x7b\x47\x81\x5e\x3c\xff\xde\x51\xe0\xf7\x8e\x02\xdd\xec\xbb\x9f\x85\x45\xaa\xda\x7c\x10\x77\x3b\x9c\xbf\xa5\x72\xb8\x61\x1e\x17\xe7\x72\x64\x3f\xc6\xcc\x7b\x39\x2d\xa9\x6c\xf1\xbb\xa0\x1e\x7a\xbb\x9f\x52\x5f\x39\xe5\x76\xb8\x93\x2d\x4b\xb8\x71\xf9\x11\x0c\x53\x01\xbd\x4d\xc6\x7f\x20\x56\x54\xfa\xc6\x46\x0a\xda\xd7\x35\x2d\xbc\xc1\x8c\x81\xdd\x47\x6f\x01\x97\x37\x50\xbb\x51\xd1\xaa\xd3\x1b\x2d\x05\x72\x81\x20\xa5\x1c\x98\xa5\x28\x30\x3c\x04\x7b\xe7\xad\x98\xbe\xbc\xd4\x2a\x3e\x77\x22\xa3\x8b\xa6\xa0\x75\x4f\x57\x23\x87\x41\xbb\x38\x90\x16\x40\x92\xff\x4e\xef\x56\x58\x53\x0e\x92\xdc\xa0\xe8\x0d\xe4\x63\xcd\x47\x6e\xc7\x3a\x23\x4c\x9f\x42\x98\x10\xcd\xb7\xf3\x0e\xbf\x6f\x1a\x67\xf4\x7b\xed\x43\xfe\x8c\x79\x1e\x4b\x78\x54\x8c\x50\xad\x59\xb8\x5a\x93\xe6\x10\x74\x52\x00\x27\x08\x81\x79\x4a\xeb\x76\xb6\xe9\xea\x94\x4c\x26\x13\x34\x6b\xa0\xbe\x8f\x5e\x16\xa3\xff\x82\x53\x80\xd7\x7d\x8a\x86\x56\xda\x68\x90\xeb\x6e\x8c\x9c\x68\x17\xdb\x50\xb5\xee\xe8\x79\x39\x25\xad\x22\xb8\xbd\xcc\x98\x7c\x2d\x84\x11\xed\x70\x62\x7f\x83\x47\x27\x27\xe4\xad\x2f\x5e\x00\xf9\xa5\x0b\x2d\x88\x50\x77\xec\xbb\x0b\x62\x2c\x85\x78\x22\xdb\x82\xe1\xd4\x02\xc4\xed\xee\x98\x2a\x32\x81\xba\x87\x1d\xcd\x47\xe7\x36\x7c\x15\x23\x7d\x2f\x6b\xb1\x82\xcc\xd9\x6a\xa5\xff\xa0\xcf\xe8\x7c\xf4\x15\x5b\xd5\x34\x87\x4a\xe0\xe6\x73\x7f\x80\x7c\xf3\xd7\xfa\xc0\x7e\xc7\xb6\x5f\xe8\x8f\x74\xc3\x6f\xbd\x7f\x85\x49\xeb\xdb\x2f\x30\x67\xdd\x3e\xd3\x82\xa7\xbe\x5d\x5f\x94\x74\xd3\xfa\xe3\x6b\xba\x19\x86\x1e\x10\x94\x9f\xde\x95\x4c\xd1\xbb\xb3\xa9\x3f\x78\x37\x3f\x6b\x2a\x37\x1f\x79\x8c\x8c\x45\xa9\x8f\xef\x46\x6d\x7b\x22\xab\x5b\x53\x9d\xcd\x47\x30\xd9\xf9\x88\xb4\x96\x3c\x9b\x8f\xf4\xb4\xf4\x9f\xb5\xe2\xb8\x68\x96\xb3\xf9\x68\xb1\x55\x4c\x8e\xcf\xc6\x35\xdb\x8c\xb5\xe4\xf2\x85\xff\xea\x7c\xd4\x9d\x94\x36\xaf\xec\x8a\xb1\xa0\x0d\x9c\x3b\x49\xfe\xde\x35\xb5\x21\xf9\xaf\x83\x83\xa4\xc8\x20\xfb\x3f\xf3\x75\x45\xa4\x82\xf2\xc9\x56\x6c\xc0\xc5\xf4\x4a\x0c\xbe\x5c\xae\xbe\x77\x5a\xc6\xd6\x57\x1c\xcf\x24\x26\x6a\xc3\x22\x8d\x09\xd2\x57\xc1\x8d\x06\xed\xe9\x4f\x37\x55\xce\xea\x62\xdb\xea\x97\x41\xb2\x35\xad\x56\x2c\x9f\x12\xac\xfa\x00\xc5\xfa\x21\x90\x07\x18\x15\xb8\x5f\xfb\xa1\xfa\x92\xa8\xb0\x3e\x70\xad\x5a\x9b\x11\xde\x7d\x03\x1e\x02\x42\xc1\x69\xa9\x2f\x49\x9f\xf4\x6b\x13\x52\x72\xaa\xd8\x44\x43\x7c\xa8\xe8\x68\x19\x79\xca\xc6\x59\x37\x00\x84\xac\xae\x9b\x12\x82\x0c\x69\x0e\xb1\xe8\xee\x19\xd6\x53\x8b\x59\x21\x2d\x49\xa6\x0b\xd1\x28\x53\xd5\xdd\xee\xa3\xd9\x2a\x5b\xe6\xae\xc2\x42\x16\x66\x01\x09\xaa\xc0\xf3\x67\x7f\xfa\xac\xaf\x5e\xe0\x20\x2e\x90\x2a\xb2\xfc\x1b\x56\x31\x34\x5d\x26\xa1\x65\xff\x67\x61\xad\x18\xbd\x3e\xdf\x62\x78\xe5\xde\x89\x9c\x3f\xc3\x12\xfc\xc9\xbb\xa7\x18\xa2\x85\x76\xea\x66\x63\x6c\xa7\xae\x39\xf0\x58\xab\xa8\x07\x7d\x84\x3b\xba\x5e\x6c\xc9\xd9\x33\x1b\x38\xcd\xba\x1a\x2e\xbf\x7f\x37\xdd\x5f\x62\x0c\xf2\xe7\xe3\x9d\xf9\x73\x69\x13\x18\xf4\x79\xc5\x38\xb5\x9a\x21\x27\xb6\xbd\x12\x23\x9c\x98\xb4\xb9\x31\x73\xeb\x1e\xba\x1d\xbc\x52\xbd\xae\x5f\x97\x89\xd5\x67\x57\x1f\xce\xc4\x32\x22\x6d\xca\x19\xc1\x57\xc3\x04\x87\x8d\x66\x7c\xb4\x04\x43\x82\x0f\xd5\xac\x53\x2e\x10\x06\x33\x00\x40\xeb\x1f\x76\xb8\x7e\x22\x0d\x15\x0d\xae\xd4\x65\x2d\xf2\x26\xeb\xee\x63\x84\x43\x2c\x7d\x69\xff\x5d\x11\x0e\xec\x27\x58\xa6\x00\xd3\xbf\x5c\x57\xe4\x68\xfa\x44\xc9\x68\xc5\xab\x95\xf4\xb9\x31\x40\xe6\x90\xc5\xdf\xaf\xb1\xf3\x52\xab\x5a\x05\x73\x9d\x8f\x22\xe6\x76\x4a\x56\x0d\xad\x69\xa5\x18\xcb\xad\xd7\xca\xba\xbf\x3c\x81\xa7\xbe\x73\xf0\x00\xed\x68\x45\x7d\xeb\xa5\x9a\x2e\xc4\x58\x40\x67\x98\xe0\x9c\x9d\x3e\x8b\x9c\xb0\x03\x72\xd9\xd0\x36\xf0\xee\xc8\x1b\x09\xfe\x7b\x3c\x7b\xf7\x34\xf8\x67\x24\x1a\x63\x90\xb4\x75\x59\x44\xfd\x68\x1d\x55\xc3\x3e\xad\x84\x6c\x4f\x03\xb6\x2f\x12\x4b\x72\x5d\x37\x6c\x8c\x91\xfa\x63\xab\xa5\xf5\x21\x2a\xe6\xa2\x9d\x90\x91\x06\xd5\xa7\xc6\x4f\xc8\x08\xbe\xd1\xff\xbc\x5f\x43\x24\x49\xe9\x78\x51\xeb\x55\x80\x10\x65\x8c\x52\xad\xa6\x34\xfe\x7c\x01\x1d\xd6\xb2\x72\x98\xcf\x7d\xe2\x3b\x57\xf7\x1e\x3c\xad\x44\xbc\xa6\xd5\x96\x78\x62\x8b\xd2\xf3\xee\x8d\x90\x4a\xcb\xdf\x34\xab\x45\xd0\xb3\xaf\xff\x32\x17\xfc\x96\x11\x27\x66\x23\x69\x5f\xb0\x8c\x82\xe6\x51\x2f\xb8\xaa\x69\xdd\x52\x4b\x8d\xa1\xb0\x91\x6c\xd9\xf4\x67\x1d\x1c\x49\xc6\xc8\xb4\x12\x39\xdb\xe7\x11\xc7\x48\xf1\xa9\xc9\xba\x05\x4d\x31\x33\x0d\x7d\x62\xe1\x10\xbc\xdc\x88\x5a\x6b\xb0\xb6\x52\xe0\x8a\xbd\x27\xdc\xf7\x3e\xe2\x92\x1c\xe5\x95\x3c\x3b\x7b\xf6\xfc\xaa\x59\xa0\xaf\xeb\xeb\x52\x9d\x1c\x7f\x79\xf4\xd7\x86\x16\x10\x88\xf6\x86\x96\xec\xeb\x52\x1d\x27\x08\x07\xbd\x2e\xa2\x20\xb9\xfd\x03\xad\x7c\x7a\x6a\xc1\x1d\x7e\xf7\xd3\xc4\x5f\xe0\xe9\xbb\xa7\xc7\x5f\x06\xcf\x8e\x1f\x78\x9d\xe3\xa6\xa7\x7d\xf1\xba\xf3\x35\x23\xb0\x75\x3e\x43\xe6\xd2\xf9\x08\xb7\xbe\xf3\x51\x8f\xda\x94\x68\xf2\xda\x97\xda\x1e\xcf\x61\xd5\x39\xb3\x54\x87\x55\x7a\xd7\x4a\xdf\x48\xcb\x34\x3c\xb3\xb4\xd4\x39\xc0\x4d\x15\x01\x97\xbb\xd4\xe3\x1d\x0c\x32\x55\xad\x2b\xe2\xa1\xde\x02\x3b\x27\x63\x16\x30\x8a\x96\x99\xd7\x6e\x6f\x4d\x1a\xcd\x2a\x1e\xec\x51\x65\xf2\xcb\x86\x9a\x54\x85\xce\xa0\xd6\x4f\x76\xc5\x66\x25\x14\x2d\x48\xd5\x94\x0b\xac\x9b\x33\x50\x35\xd9\x3b\x8e\x16\x8c\x55\x44\x36\x59\xc6\xa4\x5c\x36\xe0\xa5\xe9\x2d\x98\x3d\x2c\x42\xf6\x66\xfc\x0f\x4b\x88\x31\xd3\x6c\x07\x3a\x92\x6d\x95\xd6\x2c\x15\xe1\x01\xf1\xe5\x0d\xa4\x18\x3d\xdc\xac\xd6\x0b\x92\x74\x7b\x19\x87\x8d\x6b\x11\x88\xdd\x66\xb7\x61\x13\x5b\x04\xe4\xa0\xf1\xad\xc7\xd0\x16\x01\x69\x6d\x52\x43\x36\xb8\x4e\x7b\x5b\x02\xdc\x61\x53\xdc\x8e\xd9\x2d\x06\xf3\xb1\x0d\x72\xed\xa9\x1e\x6a\x96\x8b\x80\xdc\x35\xd8\xc1\x1f\x1f\xdd\x36\x87\xe3\x57\xb5\xd0\x19\x8c\x1d\x60\xa7\x33\x93\x4c\x0a\x27\x4c\xb7\xd9\xe1\xf8\x48\x96\x3b\x1c\x0f\xb1\xdf\x0d\x80\x5c\x04\xb6\xb5\x64\x2b\xde\x00\xcc\x1d\x1b\x5f\xba\x2d\x6f\x00\x6e\x92\xa5\x0f\x47\xaa\xbd\x0f\x47\x62\x30\xe0\x80\xed\x0f\xc7\xc7\xb0\x00\x5a\xc8\x8f\x6c\x07\x34\xab\x4a\xb3\x06\x1e\x84\xa9\x74\xcb\x60\x07\xd2\x1e\xd9\x3e\x68\x26\xfe\x00\x2b\xe1\xd0\x71\xec\xb6\x21\x7e\x44\x5b\xa1\xf9\xee\x83\x2c\x86\x03\x40\x3b\x04\x8d\x61\xbb\x21\x8e\x14\xeb\x21\x8e\x41\x1b\x22\x8e\x61\x39\x11\x47\xdc\x9e\x88\xe3\x61\x56\xc5\xa1\x1d\x70\x57\xf6\x50\xdb\xe2\x00\x60\x67\x79\x3c\xd4\xc2\x38\x00\xd7\xdb\x1f\x93\xed\x8c\x89\x10\x5b\x56\xc8\x04\x6b\xe3\x30\x3b\xea\xb0\x45\x3e\xc4\xe6\x88\x23\xcd\xf2\x68\xde\x4d\x4d\x07\x7b\x2c\x2b\x24\x8e\x44\x92\x1a\xb7\x48\xe2\x78\xb0\x5d\x72\x60\x57\x06\xac\x96\x38\x86\xbb\xbf\x0c\x58\x30\xdd\x4b\x51\x3b\xa6\x7d\x2b\x6e\xcd\xc4\x91\x88\xda\x98\x65\x13\xc7\xaf\x62\xdf\x34\x2b\x7b\x88\x95\x73\x00\xa6\x6f\xe4\x7c\xa8\xad\x73\x88\x6b\x84\x96\xd0\x03\x2c\x9e\x43\xcc\x7a\xc7\x1e\x9a\x60\xf7\x1c\x80\xf8\xa1\x56\x51\x1c\x49\xb6\x51\x1c\xff\x60\x16\x52\x83\xd7\x94\xfb\x30\x9c\x76\x9a\x68\x33\xb5\x2f\xf7\x5b\x4e\xed\x1b\xbd\xf6\x53\xfb\x42\xaf\x15\xd5\xbe\x10\xd5\xa7\x13\x92\x19\x86\xbb\xe7\x0d\xa7\xbd\x1e\x62\x63\x4d\x98\x77\xba\xbd\x15\x47\x72\x9d\xd7\xa1\x32\xaf\x56\x56\x06\x8b\x52\x14\xef\xbe\xcb\x6c\xac\x2b\xcd\xff\x9e\x4a\xae\x2e\x5f\xea\xbb\x58\x73\xe3\x9d\x5a\x43\xad\xdf\x38\xfd\x9f\x43\x93\xf1\x96\x18\x09\x2f\xf4\xe2\xda\x7d\xdb\x35\xe1\x2a\xda\x65\x79\x21\xc5\xc9\x29\x4a\x00\xf1\x36\x0a\x71\xbf\x56\xb9\xf9\x86\x95\x0d\xa9\x0a\xcb\xc4\x06\x19\x6a\xd1\x02\xb1\x17\x4b\xd3\x6f\x58\x73\xaa\x56\x6f\xe0\xab\x0d\xcb\x7c\xf5\xea\xa0\xa9\x6f\xac\x64\xbf\x5a\xb3\x2d\xae\xed\xcd\xf7\xd7\xa6\x4f\xbb\x4b\x82\x05\x34\x62\x3f\xa9\xdd\xb5\x44\x0b\x14\xf7\xf5\xff\x6d\xf7\xf8\x9d\xa3\x24\x32\x1f\x3d\xb4\xab\xaf\xad\xa3\x76\xb1\xc4\x62\xe6\x58\xde\x08\xca\x96\xb5\xda\xa8\x77\xe0\x2b\xde\xff\xbb\x63\xad\x61\x41\x26\x1b\x9d\xde\x02\x1f\x2d\x3b\x1f\xb8\x01\xec\x0c\x7a\x03\xc6\x0f\xb1\x85\x1f\xd0\x6f\x38\x6e\x0c\x4f\xef\x35\x9c\x66\xd7\x4b\x28\xae\xf4\x81\xfd\x85\x1f\xaf\xb7\xf0\x01\x65\x5c\x7e\xbd\xea\x45\x89\xb2\xf5\x70\xd5\xa2\xc7\xea\x23\x9c\x5e\xfb\xe3\x21\x8a\xde\x87\x96\x0b\x7a\x34\xd1\x2b\xda\x2f\xf8\x57\x90\x74\xe2\xce\xf4\xb6\x4f\xb3\xf3\x95\xa8\x72\x11\xc9\x0c\x6d\x33\xdf\x8e\x57\x1e\x9e\x06\xfa\x0f\x92\xea\xd9\xb9\x80\x7d\x7c\x4f\x80\x46\x7f\xd2\xfb\x2b\x34\x27\xce\xc8\x52\x33\x2f\xfc\x8b\x12\x35\x64\x9f\x04\x7f\x6a\x16\x4e\x2b\xb4\xa0\x6d\x2a\xc9\xdf\xfe\xfe\x09\xec\x65\x50\x79\x01\x1a\x45\xbc\x10\x45\x53\x5a\xd7\xec\x84\xfc\x2c\x45\x75\x49\xf5\x2d\x9a\x42\x7b\x8f\x9e\x8c\x54\x90\x4b\x49\x58\xd0\x79\xef\x2e\xb4\x61\xa1\xea\xe8\x52\x0e\x7f\x7a\xfa\x6e\x1a\xa6\x07\x21\xbc\x76\x92\x5c\x12\xc4\xc0\xec\xfa\xe5\xd1\xbf\x83\x52\xfd\xc5\x17\x98\x43\x31\x3a\x7e\x37\x6d\xc9\xba\xf8\x11\x78\x96\xf4\x09\x67\x07\xce\x6a\x46\xad\x4e\x24\x15\x2d\x37\xed\x59\x3b\x35\x08\xc1\xe5\xb6\xd6\x06\x3e\xbe\x3b\x5b\x30\x45\x91\x26\xc9\x6c\xcd\x4a\x6a\xb7\x46\x6c\x58\x75\x7e\x79\xf1\xe3\xf3\xab\xd6\x9f\xbb\x53\x1d\x5b\xad\x17\x2b\x67\xc5\x45\xa7\xa9\xc4\x3a\x6c\x13\x55\xd3\xe5\x92\x67\x50\x59\xb9\x68\x13\x25\x5e\x2d\x6b\x8a\x7e\xda\xa6\x66\x5a\xde\x5c\x68\xc6\x5d\xad\x82\x88\x8d\xb0\x27\x63\x98\x8e\xea\x69\x74\x37\x1f\xa6\x1b\xfe\x23\x16\x20\xd8\x4d\x37\x0e\xd6\xf1\x44\x2f\xd5\x94\x29\x08\x73\x6e\x4d\xe9\x02\x96\x1b\xec\x38\x87\xb8\x5b\x70\x97\xfd\x1c\xab\x7c\x98\xe2\x8c\xe4\x4a\xdf\x8e\xda\x45\xb7\x63\x5a\x8f\x22\x35\xcb\xc4\xaa\xe2\xbf\x38\xd8\xd2\x46\xda\x42\xc7\xd1\x5d\x82\x02\xf7\xa1\xa2\x05\x5a\x65\x4c\x51\x4a\xc0\x3c\x14\xec\x6a\xaa\x00\x9e\xed\xb4\xf8\xda\xf6\x88\x99\x91\xb5\x52\x1b\x39\x3b\x39\x59\x71\x65\x44\x89\x93\x4c\x94\x65\x53\x71\xb5\x3d\x81\xb4\x30\xbe\x68\x94\xa8\xe5\x49\xce\xee\x58\x71\x22\xf9\x6a\x42\xeb\x6c\xcd\x15\x83\x3d\x39\xa1\x1b\x3e\x81\xa9\x57\xe8\xba\x2e\xf3\x7f\x71\xd7\xf9\x49\x07\x51\xd9\x63\x3c\xfb\x7c\xb9\xbd\x03\x96\x11\x53\xf3\x53\x63\xc4\x75\x88\xb6\x4a\xcb\xdb\x97\x20\x7a\xda\x5a\xad\xfb\x31\x16\xa6\x84\x99\x3f\x92\x7e\x0b\x34\xc2\xa0\xd8\x9a\xb1\x43\xdb\x6c\x63\x56\xe5\x1b\xc1\x8d\x0e\x83\xb5\x8f\x76\x80\xca\x66\x51\x72\x25\x83\x42\xe0\x62\x4a\x5e\x40\xd9\x11\xb0\x47\x6d\xf4\xc5\xca\xa1\x7f\xb2\x37\xbc\x7d\xec\x0d\x00\xe3\xfc\x04\x84\xed\xa4\x2d\xb0\x34\x63\x36\xcc\x04\x08\x90\xfc\xc8\x7e\x81\x6a\x15\x5e\x95\x9c\x49\x28\x17\xf7\xb1\xd3\xd3\x47\x3e\x3f\xdd\x6c\x06\xcb\x3b\x9a\xbb\xdb\x52\x39\x91\x5a\xcd\xfa\x0a\xb9\x3a\x5e\x19\xad\x76\x92\x65\x77\x6b\xa1\x40\xdd\xed\x3b\x5b\xd3\x47\x76\x96\xba\x34\xf1\x60\x1a\x77\xae\x74\x96\x9f\xa5\x4d\xfe\x0e\xda\x32\x88\x9a\x34\x95\x6b\x18\xd0\xa5\x83\xf5\x69\x5f\x56\xb3\xc1\x75\x9b\x0f\x07\xf1\x62\xac\x52\xf5\xb6\xbb\x6b\xb7\x41\x12\xc6\xc7\x4c\x1d\x3e\x5d\x4b\x04\x8f\x61\xf4\x80\xb4\x1a\xeb\x9a\xe5\x74\x80\xb5\xee\x28\xb3\xcc\x23\x26\x8f\x2d\x2e\xe7\x23\xd1\x28\xc9\x73\xb6\x93\xc2\x39\x87\x76\x8a\x14\x3c\x56\xcb\xee\xf2\x2a\x58\x43\x60\x77\x83\x31\xbb\xb9\xd1\x97\xec\x1a\x5b\xf3\x99\xc0\xf2\x76\xb5\x02\xd2\x59\xbf\x26\xa8\xda\x0f\x9e\xeb\xf7\x86\xb4\x16\x82\xe6\x64\x41\x0b\xcd\xbb\x6a\x57\x34\x9a\x78\x2d\x6c\x87\x51\x75\x6d\x97\xa8\x89\x14\x1a\x34\xfc\xb4\x95\xee\x6f\x19\xa0\x6f\x82\x0e\xdd\x2a\x1d\xda\xa7\xce\xbe\xb2\xee\x6f\x2e\xe7\xca\x73\xd9\xa6\x06\xd8\xa2\xcc\xc2\x36\x21\x76\x92\xd0\xa2\xd6\xb2\x84\x96\x31\xf9\xdd\x5e\xa9\xb6\xae\x73\x66\xd2\x3c\x44\x5d\x63\x91\xe9\x89\xad\xcf\x9c\x33\xa9\x78\xe5\x1b\x83\x5d\x2c\x49\x25\x82\x43\x32\x68\x46\xe8\x3a\xc2\xe7\xff\x09\x6c\x2f\x6f\x0a\xd6\x2e\x30\x57\xed\x9b\x56\x62\xd5\x77\x4a\x5a\x41\x5f\x01\xac\xf2\x00\x7d\x0a\xab\xb0\xc4\xb2\x15\x19\xf6\x4f\x79\xfb\x1b\x1d\xa0\xb1\xf4\x3d\x14\x84\x2e\x8a\xb6\x24\xc2\xee\x58\xbd\xdd\x2d\xf4\x80\xb1\x2a\xca\x16\x9c\xe8\xc7\xb1\xab\x53\x51\x01\x4d\x80\xec\x5e\x6b\xd7\xd4\x2b\xb0\x57\xb7\xf7\xa2\x76\x80\x0e\x4b\xf5\xbc\x34\x95\x9e\x1e\x9a\xa6\xfb\x7b\x01\x0b\x18\xbf\x17\xb0\xf0\xe3\xf7\x02\x16\xc1\xf8\xa7\x2b\x60\xb1\xab\x68\x0f\x88\x68\xdf\xec\xbc\xee\xeb\x15\x76\xcb\x68\xd6\x2f\xd4\xc5\x4e\x97\x9e\x80\x00\xbc\x88\x3d\x76\x60\x5b\xa2\x1b\x12\xd9\x8a\xd4\xe4\x82\x91\xe7\x10\xbb\x61\xfb\xed\x65\xfb\xf7\x50\x7e\xee\x58\x76\x21\x56\x3c\xa3\x85\x53\x4c\x82\x1e\x9c\x28\x0f\x89\xaa\x05\xf4\x89\x0c\x14\x62\x72\xde\x25\x9d\xf9\x2a\xa9\xce\xc5\xe2\x7a\xbb\x38\x0b\xbc\x66\x23\x2f\x69\x16\x74\x41\x0d\x7b\x29\x76\xb1\xdf\x46\xda\x5a\x50\x36\x77\x22\x13\xe5\xc2\x88\x0b\x7a\xfb\x2c\xcd\x1b\x93\x4b\x68\x0b\xa8\x6f\xaf\xed\x39\xd6\xc3\xc8\xce\xf7\x7d\x2b\xe7\xff\x69\x8c\xd8\x1e\x79\x8b\x2d\x40\xb4\x72\x76\x45\x32\x51\x14\x74\x23\xbb\xf0\x09\xb9\x1d\xce\x0a\xee\x61\xf0\x0a\xcd\x0a\xd8\xd6\xc4\x21\xc6\xd4\x93\x1a\x94\x10\x72\x86\x65\x62\x83\x2a\xb0\x2d\xe0\xa1\xd3\xa1\xd6\x52\xb0\xed\x7d\x58\xb0\xf9\x68\x4a\xce\xbb\x60\x76\xac\x9c\x16\x52\x18\x30\x4a\xac\x30\x60\x0a\xeb\xe3\xe2\x82\x89\x07\xeb\x3f\xdf\x25\x4a\xb3\x42\x54\x2b\xd3\x1e\xc4\xf7\x47\x32\xbb\x2b\x5d\x5f\x5e\x17\x49\xbf\x27\x89\x75\x9d\x00\xbe\x5a\x2b\x17\x92\xd5\x16\x93\x16\xad\xa9\xc1\x55\xc0\x9e\xd1\xb0\x04\x0e\xed\xd2\xba\x2f\x3d\xa4\x03\xb8\xd6\xd1\x41\x2a\x1c\xb4\xd0\x66\x0a\x6a\x96\x9c\x4d\xc9\x4b\x0e\xa0\x00\xea\xab\xfe\xe6\x88\xa6\x2b\xa8\xdf\x8e\x76\xb3\x45\xdb\xd9\x8e\x60\x44\x1c\xb6\xdd\x13\x1f\x04\x96\xe1\xc4\x8c\xf4\xeb\x3a\xf7\x05\x1d\xfa\x86\x6e\xc1\xb3\x29\x5e\xc5\x57\x61\x1f\xa5\x9e\xaf\x51\xdf\xef\xae\x3f\x62\xda\xdc\xcf\x8e\x79\xc3\xce\x3f\x9f\x92\x73\x30\xbf\x68\xa8\xb4\x80\xda\xab\xe3\x16\xc1\xe8\xc7\x00\x35\x33\x2a\xe9\x96\x88\x92\xab\xe0\xd6\xa3\x56\x7c\xbf\xe6\xd9\x1a\xcb\xb9\xb6\xb2\x7b\x3a\x25\x7a\x0c\xb1\x81\xa8\xed\x4a\x98\xc3\xe2\xb0\xe0\xdf\xb0\xca\x48\xda\x55\x15\x4c\xc6\x2f\x0c\xc6\x0b\x39\xdd\xd0\x64\x88\xd9\x1c\xaf\x4e\x65\x3f\x13\x25\x1c\x4f\xac\x96\x6d\x34\x63\x47\x56\x4d\xa7\xf7\x76\x07\x34\xfd\xaf\x25\x47\x92\xd5\x01\xd3\xaa\x5f\x46\x6b\x41\xaf\x06\x4a\x4f\xee\x73\xeb\x56\x73\xf3\xe0\x43\xb1\xea\x45\x1d\xfd\x10\x5b\xa7\x5b\x2f\x53\xd4\xa6\xff\x79\x29\x24\x44\xf1\x22\xcf\x88\xb5\x63\xbb\xc6\xd3\x36\xd6\x34\x23\xf3\xe1\x51\xb6\xe9\xcf\xa6\x16\x99\x66\x4a\x5a\x35\x5f\x8a\x9a\xf9\xce\xd0\x76\x0f\xbb\xcf\xfe\xc5\x32\xec\x54\xe9\xcf\xb9\x6b\x3f\x17\x90\x19\x97\x54\xa6\x4c\xff\xd9\x0e\x90\xc0\x28\xd0\x76\xb3\x68\x7c\x34\x80\x3f\x06\xe3\x2e\x25\x15\x56\x51\x53\xde\xc9\x52\x28\x74\xda\xc3\x88\x31\xc8\xbb\x69\x45\xe7\xb5\xc2\x5b\x8c\x3b\x20\xa1\x76\xf6\x61\x29\x83\x84\x95\x0b\x91\x5b\x22\x96\x89\x0a\xaa\x87\x83\xc8\xb4\x2b\x40\x74\x4a\xa0\xf7\x58\x72\xde\xeb\xa3\x90\xeb\x20\x5d\xef\xd9\x4c\x54\x15\x76\x2e\xef\xdc\xa7\xc1\x74\x43\x4d\xbe\x87\xb3\x0d\x7b\xea\x9f\xd9\xe1\x9a\x46\x44\xbd\xeb\xcb\x5a\x94\x33\x72\xd5\xdf\x98\x60\xc7\x86\x18\x4e\xad\x65\xc6\xc4\x80\x67\xb1\x44\xbb\xca\x40\x10\x83\xa9\x40\x1c\xe6\x2e\x06\x37\xdd\x1a\x00\x55\xdd\x80\xf9\xcf\xaf\x04\x31\xdf\x0b\x56\xad\x85\x64\x3b\xe1\x07\xae\xdc\xb1\x31\xc5\x61\x59\x64\x5b\x63\x9b\x76\x5b\xad\xfd\xb0\xb4\x49\x13\x68\x6c\x5f\xe9\xae\x12\x1a\x90\xa0\x0f\xb3\x26\xf7\xc5\x16\x9b\xa7\x35\x05\x8b\x77\x7c\x2e\x14\x2f\xa9\x62\xc5\xd6\x76\x1a\x0e\xad\x9d\x53\xf2\xda\x76\x47\xdd\xe8\xc7\x39\xc4\x89\x18\x82\xd5\x0b\xd3\xc9\x53\x79\x8b\x1c\xed\x08\x03\x35\x57\xac\xe6\xd4\x94\x2d\xbb\x86\xf6\x7d\x91\xee\x5c\x2e\xaa\x1d\xd7\x4d\xc3\x52\xc8\xde\xd5\x0f\x1b\x3f\x35\xf0\x44\x91\x77\x9b\x38\x71\xe0\x0f\x5c\x4d\x72\xeb\x81\x83\x64\x23\x70\xc1\x4d\x77\xc4\x28\xf3\x8b\x68\xd7\xfc\xb9\x26\x29\xfb\xa0\xf4\xfa\xe7\xa3\x67\xa7\xcf\x4e\x27\xa7\x9f\x4f\x4e\xff\x4c\x4e\xcf\x66\xa7\xcf\x66\xa7\xcf\xe7\x23\xad\x3a\xad\xf8\x5d\xa4\xa6\x51\x80\x7a\x71\x07\xbc\x33\x9c\x4a\xd2\xf7\x7a\x61\x9b\x79\xfc\x51\x0b\xb2\x4f\x35\xc1\x06\x9b\x98\x82\x2d\x67\x05\x96\x6d\xd7\x0a\xec\x1d\x2d\x58\xa5\xc6\x1e\xd3\xbd\x10\x31\xd4\x0a\x6a\x15\xf2\x1a\xa2\xd5\x80\x88\x6c\xd6\x74\xc1\xa0\x98\xab\x39\x11\x47\xee\x22\x9d\xe8\xff\x3a\x1e\x0a\xf4\x5f\x30\x44\x53\x80\x0e\xdc\xa0\xa0\x7e\xf9\x52\x88\x93\x05\xad\x1d\x4a\x83\x77\x7b\xe1\x02\x4a\xf1\x87\xbf\x98\xeb\x58\x98\x30\x28\xb8\x4d\x5e\x38\x42\x9c\x07\x64\x22\x72\xf5\x03\xe1\x28\xa8\x97\xe2\x38\x13\x3a\x99\xc2\x60\x2b\xfc\x56\x46\xfb\x8f\x81\xfe\xbd\x69\xe6\x70\x24\x45\xc9\x60\xb3\x4d\x07\x21\x5e\x14\x90\xa1\x61\x8a\xa2\x17\x05\x42\x3d\x46\x7f\xc7\xc0\x15\x00\x22\xe1\x93\x4d\x8c\x47\xcd\x35\x9c\x36\x4e\x8e\xb1\xb3\xd6\xc4\x3a\xfd\xc1\x74\x02\xb0\x7e\xed\x79\x2d\x36\x1b\xd3\xc1\xb7\x92\x4d\x18\x8e\x9e\x6d\xe3\x35\xea\xdd\xfe\x32\xbd\xa7\x1c\x72\x78\x79\xa1\x34\x6a\x5d\x9c\xe0\x62\xeb\x63\xbd\xf4\x87\xbd\x77\x26\x1e\x12\x57\x33\xe9\xca\x14\xb6\xf6\x3b\x58\x89\x59\x84\x54\xd6\xe4\x6f\x43\x4a\x3e\xbc\xe3\x7d\x4a\xd4\xd9\x6d\x2c\x6a\x94\xec\x71\x45\x0c\x18\x6d\xab\x46\x20\xd7\x4b\x17\x33\x27\x13\xd2\xfc\x89\xdd\x4d\xe8\x5a\x80\x9c\x16\xb4\x41\x5e\xf9\xf4\x7e\x2b\x73\xb8\x34\x7f\x68\x97\x15\x85\x19\x76\xf4\xd3\xe4\xb5\xdc\xa8\xed\xd8\x87\x9d\xfa\x99\x11\xc9\x0a\x2c\x83\x34\xd4\xf0\x37\x60\x38\x3e\x67\xd4\x5d\x3f\xdf\x42\x05\x5a\x10\xb4\x43\x0b\xa3\x70\x81\xd1\x79\xa3\xbe\x5e\xf5\xee\x1c\x1d\x86\xbc\x10\x1a\x05\xe9\x22\x42\xe9\x66\x53\x40\x14\xaf\xa8\xdc\x0c\xdb\x61\xaf\xe1\x22\x9e\xc4\xf7\xa9\xdd\x64\x1e\x2f\xfd\x9e\xf5\xc5\x75\x17\x36\xc7\x37\x0a\x11\xba\x65\x9b\x50\x04\x1b\x2b\x11\x34\x56\x1d\x13\x6e\x34\xa4\xbe\x90\xd8\x28\xf4\x56\xb8\x6c\xbb\x19\x71\x5b\x51\x7e\x40\xf0\x2c\x09\x02\x68\x0f\x69\x73\x73\x68\x37\xd8\x03\x42\x54\xa3\x40\x8d\x75\x34\x35\x4c\x95\x7c\xd4\x5e\xa0\x0f\x0b\x59\x25\x8f\x1a\xb6\x4a\xfe\x09\x9b\x6f\x3e\x4e\x28\x2b\xf9\xdf\xd9\x05\x33\xb5\xa1\xdd\xe0\x55\x3b\xb8\xa1\x5d\x2c\xa9\x3d\xa5\x9f\x5d\x9a\xd6\x3b\xa8\x3c\x93\x14\xd5\x98\xf4\xb7\xc1\x94\x01\x75\x0a\xd4\x57\x10\xf3\xc0\xa4\x17\xfd\xb2\xe1\x74\xb6\x46\x40\x6f\x85\x1f\xe7\x08\xd2\x22\x55\xcd\x07\xd3\x8b\x8d\x1b\x7d\xa7\x37\x67\x20\x54\x2c\xb6\x16\x35\xd3\xe4\xa6\xe2\x43\x54\x3e\x95\x74\x02\xba\x07\x8e\xb0\xef\x99\x3b\xd4\x49\x71\x77\x67\xbe\xd6\x98\xf7\x7b\x82\x16\x1c\x83\x67\x1f\x57\x52\xa4\xa4\x68\x93\x0e\x8f\xdc\xa5\x69\x3b\x18\xe4\x7e\xce\xc8\x53\xad\xd8\xcc\x52\xa4\x3e\x82\xc6\x5e\x5a\x14\xe1\x69\x31\xfb\x0f\x4e\x40\x9b\x4a\xe4\xbe\xf8\x94\x5c\xc1\x74\x45\x3d\x4c\xed\xcc\x3a\x79\x15\x42\x77\xb2\x9e\xd1\xe6\xa5\x01\x17\x35\x5e\xd8\x11\x4c\x8b\xec\x4f\x0c\x42\x64\xbf\xaf\x8a\xad\xff\xf2\x30\x6d\x32\x46\xc8\xe0\x74\x46\xd7\x1f\xf1\x56\xdb\x71\x50\x4b\xd2\xe1\xa4\x68\x4d\xf0\xce\x3b\xfd\x2e\xed\x77\xec\xbe\x0c\xbf\x38\x7c\x88\x93\x29\xb6\x4c\x3c\x0c\xbb\xed\xf5\xed\x9e\x1b\xbb\xb3\x17\x87\xc1\x8b\x80\xb7\x66\xf8\xec\x82\x48\x2a\xc8\xdc\x01\x9c\x8f\x20\xa4\xd3\xf5\xa2\x33\x06\xb2\xf4\xe3\xf0\x26\xbc\x06\xc6\x20\x06\x07\xc0\x4d\xf9\xe0\x5b\xbb\x77\x84\x82\x5a\x05\x41\xdb\xc6\xa5\x8b\x5f\x1b\x08\xb3\xb0\x03\x0c\x3f\x1a\x53\x7a\xd1\x87\x76\xc2\x4d\x17\x2c\x8d\xfb\xe6\x25\x36\x61\x18\x6a\xc6\x68\x47\xbb\xc8\xcd\x0e\x00\x0c\x1b\xb6\xdd\xf1\x0a\xba\x60\x43\xa7\x1b\x87\x23\x15\x46\x4e\x28\x31\x5a\xf8\x7a\xcd\x5a\x7f\x01\x2d\xed\xfc\xcd\x57\x69\x0d\x9a\x13\xb4\x81\xce\x45\x9d\xe3\xc4\x3b\x27\x05\x0b\x4c\x02\x19\x2c\x0a\x0f\xad\xad\x3c\x82\x87\x60\x4c\x28\xb9\x65\xdb\xb1\x49\x61\x4c\x04\x69\x3b\x54\x20\xc8\x9a\x15\x4e\x5b\xb9\x65\x18\xc5\x66\x22\xce\x93\xe0\x1d\x72\x54\x70\xdc\xb2\x6d\xea\xab\x3b\x48\xd5\xf3\x73\x05\xb0\x34\x76\xf5\x1f\x92\x1a\xb6\xb6\x87\x43\x2a\x28\xdf\x2c\x96\x7c\xbc\x3f\x0e\x90\xfa\xed\xb0\x18\x7f\xe0\xb2\xdd\x86\xb5\x22\x77\x6f\xd9\xf6\x89\xc4\xed\xd3\xb7\x66\xcd\xbb\xd3\xba\x7b\x16\x11\xa4\x5f\xd8\xfc\x82\x1f\x31\x84\xd9\xf7\x2f\x19\xb0\xb6\xb4\xc7\x45\x35\x26\x6f\x84\xd2\xff\xf7\xf2\x3d\x74\x1a\xd3\x27\xe9\x2b\xc1\xe4\x1b\xa1\xe0\x2f\x1f\x15\xc5\xb8\x88\x07\x22\xd8\x88\x47\x3c\xa8\x61\x28\x96\x87\x7d\xdf\xcf\x61\x6a\x9d\xd8\x6e\xdb\xb8\xd4\x5c\x47\xd4\x06\x3f\x87\x6c\x53\x58\xaf\x5b\x4f\xcb\x72\xc4\x4a\x54\x13\x2c\x5f\x63\xbe\x76\x00\xd0\x70\x5e\x66\xab\x44\xdd\xda\xa9\xf1\x81\x10\x3b\xa7\x68\xa6\x07\xec\x0c\x9f\x24\xb0\x6c\x3f\x6a\xb6\x29\x68\xc6\x72\x92\x63\x1b\x52\x48\x24\xa1\x8a\xad\x78\x46\xb0\x8e\x21\x54\x03\x4c\x3f\x54\x07\x50\x72\x1c\x0f\x38\x85\x69\xda\x60\x38\xd2\x74\x5a\x3b\x26\xfa\xd6\x27\xbe\x69\xb7\x39\xe9\xf5\x44\x8d\xb8\xfd\x7a\xda\x2a\x81\xbd\xbf\xd2\xe4\x3a\x09\xfb\x87\xf7\x6b\x6e\x4f\x2a\x79\xbf\xf6\x65\x10\x9c\x24\x8a\x1f\x25\x05\x53\xd5\xdf\x34\x7b\x85\xe3\xfd\xf7\x34\x6e\x48\x79\x2d\xa7\xe4\xdc\xc6\xa0\x05\xbf\xb7\xa6\xdc\xe0\x53\x49\x20\xf5\x4c\x5a\xce\x37\xac\xd4\x68\xbb\xa3\x63\xa7\xe8\xb6\x04\x95\x46\x62\xee\xc1\x2f\xad\x59\xa8\x93\x36\x47\xb7\x6c\x3b\x1a\xef\x51\xaf\xd1\x45\x15\xad\x62\xea\x87\x75\x92\xb7\x28\x82\x93\x5a\x40\xda\x1e\xc1\xb3\x11\x08\x66\x87\x5c\x91\x07\x08\x6f\x07\x9c\xea\xc4\x57\x3f\xbc\xaf\xad\xcf\x57\x49\x8b\xbf\x76\x91\x3e\x6d\x47\xce\x1d\xaf\x55\x43\x0b\x1f\x3d\xa4\x04\x1e\x83\xde\xc9\x6b\x0d\xc2\x39\x18\x30\x2e\x02\x44\x27\x53\x09\x4e\x61\xde\x0d\x04\x9d\xa0\xf7\x26\xf4\xd0\xf4\xef\x3e\x2d\xfc\x24\x4c\x3c\x1f\xc6\x2f\xc5\x34\x19\x3b\x8f\x81\xe2\xd2\xb9\xa8\x9e\x28\xbb\xff\x7e\xa9\xe8\xaa\xb7\x0a\xd8\xb4\xa3\x4b\x5c\x2f\x58\x70\x55\x68\xa9\x6f\xeb\x43\xa8\x9c\x26\x17\xe4\x99\x14\x5b\x1f\x53\x25\xe2\x0c\xd6\x87\x32\xb8\x55\xd9\x58\x86\x57\x57\x33\x50\x3f\x9c\x2b\xe3\xdb\x30\xd6\xab\x17\x22\x46\x36\x40\x25\xf2\x37\x17\x53\xf2\x94\x7c\x7b\x7d\x7d\x19\x83\xe4\x7f\xd1\x0b\x53\xbf\x4f\xd6\x8c\x06\x31\x18\x2e\xb6\x03\x3f\xd0\x37\xd7\x5e\x90\x57\xdf\x7e\xff\xc3\xab\xaf\x6c\x1c\x86\xc2\x12\x25\x1a\xf0\xf5\xab\x2b\x20\x04\x1a\x2a\x6a\x08\x78\xe8\x0a\xba\xc5\x70\xea\x5e\x90\x36\x37\x25\x27\x74\x21\xee\xd8\x90\x03\x8b\x58\x0f\x72\x34\xac\xc7\xcd\xeb\xea\xcd\x05\xce\x2b\xc0\x85\xc7\xb5\x5b\xb8\x3d\x67\xfd\x67\x7e\x4e\x9c\xdb\x2b\x2b\x18\xad\x8b\x2d\xc9\x45\xd6\x94\x58\x37\x87\x2a\x17\x7a\xab\x31\x60\xa2\x05\x2a\xe8\xd4\x1e\x0f\x99\x70\xd1\x41\x40\x82\x6b\x66\x24\x52\x48\x16\xa6\x19\x16\x1d\xb5\xce\xb0\x1b\xc8\x99\x77\x37\xaf\xbf\xb6\x31\xd0\x60\x73\xa3\x01\x15\x45\x18\xd1\x84\xe1\x42\x78\xcf\xb7\xfe\x22\x9b\x09\xc4\xef\x11\x56\x8a\x85\xd9\x49\x0c\x2c\x23\x0b\xa6\xee\x99\x29\xcf\x6b\x78\x80\xbe\x47\xd6\xad\x15\x09\x95\xd0\xc0\x20\x60\x4d\x53\x0e\x8d\xbb\xd2\x66\xdb\xd6\x25\xc5\xc2\x83\xae\xe5\xa3\x0f\xf3\x19\x6c\xe4\xfe\xad\x23\x4d\x76\x87\x7c\xe6\x9b\x7f\xe6\xbc\xb7\xae\x01\x7b\x34\xb8\x87\xfa\xc0\x47\xd4\x43\x8f\x6e\x9e\x4e\x6f\x8e\x01\x02\xa0\x63\x53\x33\xf0\x57\x43\x00\x6e\xb3\x5c\xf2\xf7\x78\xd0\x62\x5d\x71\xa8\x82\xc8\x0d\x3b\x19\x73\x32\x35\xf6\x6e\x9e\x86\xa5\x00\x6f\xc8\x3d\x44\x21\xe0\x73\xbd\xa3\xbd\x40\x6f\x94\xbe\xdf\xe1\x6f\xd1\x54\x70\xb3\x14\x62\xda\xf1\x6c\xd1\x28\xb8\x57\x61\x17\xfb\x48\xd3\xfa\x54\xab\xd2\xe3\x67\x5e\x1d\xcd\x9f\xce\xa7\xc7\x5f\xfe\x56\x75\xbc\xd2\xb9\xf7\x50\xad\x34\xc3\x24\x87\x79\xc2\x82\xd9\x80\x6f\x17\x86\x14\x18\x9d\x7f\xab\x7d\xf8\xad\x36\x20\xe6\xff\x69\x6f\x00\x84\x0a\xdb\x0d\x30\x81\xb0\xfa\xd7\x53\xf2\xda\x46\x4c\xba\x8c\xa0\x78\x80\xa4\xf4\x21\xc9\x00\x61\x4c\x64\x83\xb5\x09\x0c\x45\x0a\x6a\x9d\x61\x08\x08\x36\xe7\x81\x60\xa2\x0f\xbf\x44\x29\x0d\x32\x4a\xfa\x1e\xeb\x23\x7f\xf6\xe9\xa7\xcf\x3f\xed\xdf\x60\x7c\x29\x9e\xc7\x16\x2b\x9f\x6c\x39\x7a\xe2\x16\xec\x46\xb5\xec\xec\x86\x93\x49\xc3\xa2\x74\xbd\xf8\xc2\x8a\xc5\x90\x8f\x62\x02\x55\x1f\x78\x01\x22\xf8\x39\xec\x02\x18\x57\x37\x9e\xf1\xab\x6e\x27\xf8\x63\xe6\x82\x7e\x40\xde\xa7\xea\xd7\xc1\xdb\x7b\xa6\x45\x38\x73\x6b\xf4\x7f\xb6\xaa\xf7\xb9\xca\x00\x43\x3d\x5d\xc8\x8e\x06\x60\x6d\x1d\x36\x21\xab\x1d\xad\xa4\xdf\x70\x89\x35\xbd\x10\x7d\xc2\xcd\x94\x5c\xa8\xb0\xf6\x82\x12\x26\x06\xc9\x7f\xb2\xfd\x99\x7e\x09\xbe\xfd\x79\x6c\x94\x7b\xfd\x02\xfe\x03\xbe\xf7\xc3\x57\x97\xc6\x8b\x72\x1d\x54\x65\x88\x55\x5a\x17\x4b\x2d\x6d\xc2\x29\x7d\xc1\x6a\xa5\x45\x14\xaa\x58\xd8\x68\xc8\x50\xef\xeb\x57\x57\x2f\x00\xb9\xfa\xfb\xe6\x71\x3f\x13\xb0\x31\xca\x3d\x29\x20\x3b\x65\x1d\xcd\x7c\xc3\x7c\xcb\xb8\x40\x67\x69\x5c\x21\xaa\x15\x86\x97\x1b\xcd\x48\x4b\xce\xa6\x3e\xbc\xd6\xf7\x5c\x85\x0b\x92\xf9\xc5\xf5\xc3\x06\x09\xb0\xda\xc2\x49\x5a\xd3\x2a\x97\x6b\x7a\x7b\xc0\xad\x4d\xf1\x30\x04\xf3\x78\xcb\x96\x07\x04\x49\xbe\x68\xff\x30\xac\xed\x2e\x59\xcd\x4d\xf2\x80\x2d\x8d\x38\x10\x25\x29\xc8\x77\xae\x50\x97\xb1\x00\xc8\x1d\xc7\x0d\xdc\xa6\x00\x69\xd1\x9e\x8e\xb8\x7a\x7e\xa7\x8f\xce\x2d\xdb\xa2\x33\x4b\xb2\x1d\x00\x35\x73\xd5\x23\x98\x54\x74\x51\x70\x19\x0f\xe4\xa0\xed\x9d\x80\xfd\xf1\x95\x70\x40\x10\x75\x5a\x51\x50\x5c\x23\xbe\xf6\x76\xb9\x92\xd6\x21\x74\xd6\xb0\x36\xb2\x63\xda\x00\x4e\x33\xc0\xe6\x15\xcb\x6a\x86\xb5\x30\xe6\x23\x7d\x5a\xe6\x23\x1b\xbf\x38\x4d\xd6\xfe\x89\x49\xf2\xc8\xd6\x42\x48\x30\x99\xd8\x50\x66\x8c\x66\xd1\x47\xdd\x25\x52\x24\x1d\x6d\x62\x7d\x29\x96\x16\xda\x6e\x0d\x5c\xfa\x62\x34\x58\x80\xba\xab\x02\x46\xdc\x88\x35\xaf\xc8\x5b\x77\xf2\xf0\x33\x2e\xf8\x92\x57\x41\xca\xa7\x0f\x4e\x18\xf2\xd9\x58\x62\xf9\xc3\x9b\x57\x2f\xaf\xae\x02\x2d\xd3\x7f\xe9\x9b\x9a\x56\xca\x1a\x2b\x15\xad\x57\x9d\xa5\x71\xfc\xf0\x1f\x47\xc5\xa5\x28\xc4\xbd\x49\x61\x0a\x28\x1f\xa6\x8f\xda\xa0\xa1\xf8\xba\xa1\x34\xcf\xce\x7c\x9c\xce\x0f\xf0\x6d\x24\xaa\x79\x65\xd8\x5f\x11\x29\xd4\xea\xd2\xa6\x31\x5a\xa0\x1d\x85\x1a\x05\x5a\xf4\x47\xa8\xb6\x4f\xfa\x7c\x14\x44\xa2\x46\x41\xf6\x30\x4c\x25\x4c\x56\xb6\x0a\x12\xbf\xad\x01\x38\xda\x5d\x9b\x98\xbb\x59\x8a\xdc\x16\x3a\xc2\x98\x88\x6b\x88\x94\xa6\x4a\x5f\xa4\x23\x13\xc1\x74\x8c\xb5\x65\xa3\x65\x96\xfc\x80\x70\x84\x7b\x2e\x91\x94\xef\x11\x52\xe8\x55\xe3\x4a\xca\x0a\x22\x15\xad\x72\x5a\xc7\xa9\x5d\x70\xe3\x03\x63\x08\x9f\xb2\xa9\xa1\x00\xc0\x91\xd3\xeb\xc9\xf8\x91\x35\x52\x89\xd2\x43\xdd\xe7\x3f\x64\xe2\x29\x95\x9b\xf9\xf0\xcd\xdf\x27\x52\x5a\xc7\xdb\x6e\x18\xf1\x55\x1b\xa7\x5c\x9c\xa8\x42\x26\x47\xaf\x5d\x74\x2f\x90\x1c\x41\x09\x32\xb5\xa6\x15\x66\x75\x39\xfc\xda\xe8\x90\x28\xd4\x56\xe4\xb6\x3c\x7e\xcc\x20\xe8\x11\x2e\xfd\x7b\xe0\x79\xee\xea\xfa\x8e\x28\x60\xc7\x3a\xbf\xbc\x18\xb0\xc2\x9b\x62\x6f\xbc\xca\x8a\x06\x6a\xe7\x70\x15\x44\x2a\x8e\x6d\xa4\x9d\xc9\x79\xc7\x6f\x0e\x39\x02\x6c\x15\xac\xcb\x0b\x0b\xde\x7a\x28\x91\x14\x1a\x4a\x67\xca\x23\xfd\x5b\x82\xeb\xf3\x1b\x17\xd4\x0d\x31\xba\x16\x5c\xcd\x56\x9a\x20\xd4\x6c\x17\x66\x34\x51\x06\x47\x9b\x9e\x19\x6a\x09\xf3\x9b\xee\xb3\x01\x23\x59\x0c\x80\x04\xa2\x64\xe9\xfd\xce\x94\x6d\xc6\xac\x49\xe8\xa1\x66\x15\x03\x10\x61\x8d\x3f\xb7\xc2\xf3\xda\x37\x71\x6c\x12\xd1\xbc\x1d\x7d\x00\x62\xd0\x3f\x0e\x82\x11\x2a\x57\xfe\x85\x72\xa8\xfe\x64\xaa\x2e\xc6\xe3\x95\x3e\x5e\x18\xfc\x68\x28\x50\x2a\x39\xde\xdd\xec\xad\x8a\x27\x38\xf9\xe1\x52\x9d\x46\x7b\x21\xf8\xa3\x7d\xf7\x0c\x39\x02\x6f\x7b\x02\x5c\x54\x0e\x8f\xc7\x24\xd3\x94\x44\x5f\x8a\x95\x9d\x33\x94\x52\xac\x53\x3c\x6b\xff\x6c\x51\xf9\x36\xbc\x17\xe8\xcd\x61\x27\xc2\x46\xf1\x87\x11\xfc\xad\xb3\x60\x77\x3a\x61\xef\x46\xce\x9d\x00\x85\x27\x46\x57\x58\x8a\x75\xf4\x4f\x99\x0c\x10\xb7\xc2\xfa\x91\xd4\xba\xc2\xed\xc8\x63\x1f\xfd\x83\x50\x79\xe0\xda\x81\x27\x1e\x88\x00\x9f\x0b\x10\xa2\x21\x08\xbb\x67\x64\x41\xb3\x5b\x56\x25\xf9\xd7\xf7\xbc\xc4\xc6\x7a\x90\xd1\x20\x62\xfc\x30\xd2\x02\xfc\xfa\x8d\x50\x46\x9b\x80\x78\x5f\xda\x06\x16\x7c\x6e\x57\x4d\x48\x00\x6f\x45\x8c\xd0\x1c\x55\xb5\x0e\x41\xa8\xd1\x0c\xe7\x3b\x11\xa7\x91\xd0\xe0\x97\x4f\x24\x11\xf7\xa6\x3e\x08\xba\xb5\xc2\x4f\x0c\xe5\x75\xe1\xb8\x62\x68\x8d\xd9\xd3\x84\x02\x3f\x16\xb6\xe1\xc5\xc6\x8e\x89\xc8\x3d\x28\x10\xf8\x57\x24\x1d\xbd\x44\xff\x37\xc8\x20\x8a\xfa\xbd\xc9\x43\x32\x88\xa2\x9d\x0d\x53\xc2\xa9\xb4\x02\x97\x92\x3c\x44\x9c\x62\x97\x6c\x03\x7b\xad\x75\xc3\xb0\x6a\xc6\xf5\xab\x2b\x6f\xbd\xb0\xd6\xde\xeb\x57\x57\x51\x94\x48\x0c\x3e\x22\xbc\xe2\x0a\x8d\x40\xb6\x9a\x1f\xd4\xb2\x00\xdb\x55\x0d\x16\x0a\xa2\xee\x05\xd9\x98\xdc\x94\x28\x4c\xbd\x68\x8c\xa6\x98\xf8\x75\x61\x9c\x82\x9e\xa3\xfd\x64\xe8\x75\xce\xc5\x7d\x25\x55\xcd\x68\x19\x57\x07\xb1\xc8\x8f\x8f\x58\x72\x15\x4b\x25\x51\xf6\x4b\xbb\x75\x56\xe3\x37\x0c\x3b\xa8\x6a\x5c\x9a\x63\x26\xf7\x0d\x93\x46\xb2\xd7\xc2\x2e\x96\xfc\x02\x49\x37\x6e\x06\xeb\xd0\xf9\xa7\x64\x42\x2e\xa9\x94\x6a\x5d\x8b\x66\xb5\xde\xc7\xc8\x80\xe5\xe2\xcd\xf7\xd7\xe1\x2a\xcd\x46\xb5\x53\x10\xb0\x76\x19\x0f\x8a\xa1\x45\x41\x5a\xfc\x65\xb4\x7a\xa2\x48\xce\x32\xbe\x31\x9d\x20\x71\x62\xb0\x25\x84\xbd\x07\x5a\xb8\x84\x72\x0d\x43\x20\x5f\xc0\x1e\x7d\xcb\x8a\x42\xb8\x6e\xb7\x86\x49\x69\x90\x3e\x9f\x9b\xec\x5a\x1f\xa2\x60\xf7\x22\x92\x6c\x37\x20\xbd\x77\x87\xe5\x4a\x0c\xa5\xe7\x4c\x92\x6e\x63\x6b\x2f\x07\xc9\xc4\x00\x99\x43\xd3\x4d\x54\x13\x3a\x3c\xc4\xb2\x9d\xda\x50\x55\x02\xb9\xcf\x8f\xb6\x7c\xb6\x0b\xf7\x30\x35\x98\xa9\x7b\x65\x80\x76\x7b\x47\x88\x6d\xf7\x89\xa9\x83\xae\xc4\x24\x68\xa8\xae\xfa\x60\x49\x37\x43\x6a\xaf\x6c\xb0\x2a\x8c\x3e\x21\x06\x17\x06\x2c\xa0\xb7\xd8\xba\xaa\x56\xde\x70\x33\x00\xd2\xaf\x26\x98\xce\x98\x50\x5b\xae\x07\x84\x1e\xe0\x7a\xc1\xf3\xe1\x85\xbb\x34\x24\xbd\xe0\x96\x6b\x87\x55\x8a\xd7\x8c\x48\xfe\x8b\xaf\xbc\xea\xe6\x30\x88\x00\xa8\x67\x9d\xdc\xeb\xe6\x8f\xa7\x9f\xc7\x3b\x11\x06\x2c\x3d\xa5\xed\xee\x20\x17\x6e\xf3\x9e\xef\x37\xbe\x10\xa0\x4f\xfa\xb9\x65\xdb\x13\x3c\x4f\x10\x50\x8b\xb5\x42\xe8\x10\xb7\x60\xa6\x50\x72\x8f\xcb\x12\x82\xf9\x76\xcb\xc0\x0f\x69\xe3\x4e\x0f\xb7\xf0\x6c\x59\x09\xe3\x46\x87\x6f\x99\xbe\x12\x50\x2d\xdc\x96\x04\x89\x73\x1f\x24\x8e\xb2\xe1\xca\x58\x22\xcf\x6d\x36\x46\x26\xca\x52\x54\xe0\xee\xb1\x35\xa2\x86\xdc\x82\xc4\xa6\x91\xa1\x42\xcf\x6d\xf5\x17\xd5\xd4\x6c\x4a\xae\x05\xa1\x77\x02\xfa\x86\x6d\x09\x2d\x17\x7c\xd5\x70\xb5\x1d\x3f\xc8\x88\x0a\x33\x31\x06\x1b\xe7\x31\xc4\x86\x98\x13\x17\x3a\x65\x02\xc8\xec\x45\x0c\x83\x89\x4e\xca\xed\x04\x0d\xb1\x13\xbc\x9b\x91\xe8\x22\x02\x8d\x63\x77\xc0\xc2\x39\xa9\x19\xb6\xa8\x81\x5d\xbd\x65\x5b\xf3\xc8\xd7\x81\x4a\x62\x54\x40\x6f\x42\x62\xdf\x63\x74\x8d\xd1\xff\x92\xbe\x0f\x48\x68\x57\x15\x5e\x3f\x3e\x3c\x74\x38\x5e\x41\xb8\xb7\xf1\x51\x4f\x8d\x8f\x89\x63\xa0\x1d\x0f\x1f\xde\x0b\xa9\xe4\x95\xad\x49\xbc\xf7\xec\x1f\xa4\x4f\x52\x37\x1e\x27\x7b\x75\x91\x77\x1e\x17\x9d\xb5\x58\xfb\xfa\x6d\x74\xb4\x5b\xee\xc9\xef\xf7\xe5\x50\x77\x9f\x74\x35\x4a\x9d\x91\xd1\xd9\xe7\x7f\x3a\x9d\x9c\x9e\x4d\x4e\xcf\xae\x4f\x4f\x67\xf0\xbf\xbf\xec\x9f\x52\x23\x31\xcd\xc8\x7f\x50\x0e\x16\x73\x7d\x5b\x7c\x65\xed\xbd\xf7\x4d\x37\x74\xad\x7c\xbf\x65\x99\xa8\x32\x5e\x74\xd0\x1c\xdb\xe3\xa9\xaf\x7d\x32\xa2\xe3\xca\xf4\x02\xc8\x77\xd6\x1f\x76\x1c\xc1\xf6\xd2\xa1\xda\xb1\xd7\x43\xfe\x23\xf5\x1c\xf1\xbd\x0e\x0a\x8e\x2e\x6f\xd6\xea\x41\x14\x14\xa1\xa4\x99\x6a\x68\x51\x6c\xa1\xb7\x61\xc7\x3d\xc1\xf2\xcd\xed\x46\x00\xd6\x4b\xef\xe1\x41\xc3\x75\xf0\xd6\xfa\x26\x35\xee\x69\x07\x54\x43\xc1\xaf\x36\x2c\x1b\x13\x36\x5d\x4d\x6d\x28\x8b\x2b\xed\xd8\x28\x01\x3d\xe7\x61\x6e\xa6\x43\x41\x50\xcf\xbf\x03\x26\x7c\x98\x7a\xda\xb9\x11\x5d\xa5\x6a\x7f\xef\x28\xf0\x7b\x47\x81\x5e\x3c\xff\xde\x51\xe0\xf7\x8e\x02\xdd\xec\xbb\x9f\x85\x45\xaa\xda\x7c\x10\x77\x3b\x9c\xbf\xa5\x72\xb8\x61\x1e\x17\xe7\x72\x64\x3f\xc6\xcc\x7b\x39\x2d\xa9\x6c\xf1\xbb\xa0\x1e\x7a\xbb\x9f\x52\x5f\x39\xe5\x76\xb8\x93\x2d\x4b\xb8\x71\xf9\x11\x0c\x53\x01\xbd\x4d\xc6\x7f\x20\x56\x54\xfa\xc6\x46\x0a\xda\xd7\x35\x2d\xbc\xc1\x8c\x81\xdd\x47\x6f\x01\x97\x37\x50\xbb\x51\xd1\xaa\xd3\x1b\x2d\x05\x72\x81\x20\xa5\x1c\x98\xa5\x28\x30\x3c\x04\x7b\xe7\xad\x98\xbe\xbc\xd4\x2a\x3e\x77\x22\xa3\x8b\xa6\xa0\x75\x4f\x57\x23\x87\x41\xbb\x38\x90\x16\x40\x92\xff\x4e\xef\x56\x58\x53\x0e\x92\xdc\xa0\xe8\x0d\xe4\x63\xcd\x47\x6e\xc7\x3a\x23\x4c\x9f\x42\x98\x10\xcd\xb7\xf3\x0e\xbf\x6f\x1a\x67\xf4\x7b\xed\x43\xfe\x8c\x79\x1e\x4b\x78\x54\x8c\x50\xad\x59\xb8\x5a\x93\xe6\x10\x74\x52\x00\x27\x08\x81\x79\x4a\xeb\x76\x6f\x6d\x5d\x38\x32\x99\x4c\xd0\xac\x81\xfa\x3e\x7a\x59\x8c\xfe\x0b\x4e\x01\x5e\xf7\x29\x1a\x5a\x69\xa3\x41\xae\xbb\x31\x72\xa2\x5d\x6c\x43\xd5\xba\xa3\xe5\xe5\x94\xb4\x8a\xe0\xf6\x32\x63\xf2\xb5\x10\x46\xb4\xc3\x89\xfd\x0d\x1e\x9d\x9c\x90\xb7\xbe\x78\x01\xe4\x97\x2e\xb4\x20\x42\xdd\xb1\xef\x2e\x88\xb1\x14\xe2\x89\x6c\x0b\x86\x53\x0b\x10\xb7\xbb\x63\xaa\xc8\x04\xea\x1e\x76\x34\x1f\x9d\xdb\xf0\x55\x8c\xf4\xbd\xac\xc5\x0a\x32\x67\xab\x95\xfe\x83\x3e\xa3\xf3\xd1\x57\x6c\x55\xd3\x1c\x2a\x81\x9b\xcf\xfd\x01\xf2\xcd\x5f\xeb\x03\xfb\x1d\xdb\x7e\xd1\xdb\x79\x7f\xde\x7a\xff\x0a\x93\xd6\xb7\x5f\x60\xce\xba\x7d\xa6\x05\x4f\x7d\xbb\xbe\x28\xe9\xa6\xf5\xc7\xd7\x74\x33\x0c\x3d\x20\x28\x3f\xbd\x2b\x99\xa2\x77\x67\x53\x7f\xf0\x6e\x7e\xd6\x54\x6e\x3e\xf2\x18\x19\x8b\x52\x1f\xdf\x8d\xda\xf6\x44\x56\xb7\xa6\x3a\x9b\x8f\x60\xb2\xf3\x11\x69\x2d\x79\x36\x1f\xe9\x69\xe9\x3f\x6b\xc5\x71\xd1\x2c\x67\xf3\xd1\x62\xab\x98\x1c\x9f\x8d\x6b\xb6\x19\x6b\xc9\xe5\x0b\xff\xd5\xf9\xa8\x3b\x29\x6d\x5e\xd9\x15\x63\x41\x1b\x38\x77\x92\xfc\xbd\x6b\x6a\x43\xf2\x5f\x07\x07\x49\x91\x41\xf6\x7f\xe6\xeb\x8a\x48\x05\xe5\x93\xad\xd8\x80\x8b\xe9\x95\x18\x7c\xb9\x5c\x7d\xef\xb4\x8c\xad\xaf\x38\x9e\x49\x4c\xd4\x86\x45\x1a\x13\xa4\xaf\x82\x1b\x0d\xda\xd3\x9f\x6e\xaa\x9c\xd5\xc5\xb6\xd5\x2f\x83\x64\x6b\x5a\xad\x58\x3e\x25\x58\xf5\x01\x8a\xf5\x43\x20\x0f\x30\x2a\x70\xbf\xf6\x43\xf5\x25\x51\x61\x7d\xe0\x5a\xb5\x36\x23\xbc\xfb\x06\x3c\x04\x84\x82\xd3\x52\x5f\x92\x3e\xe9\xd7\x26\xa4\xe4\x54\xb1\x89\x86\xf8\x50\xd1\xd1\x32\xf2\x94\x8d\xb3\x6e\x00\x08\x59\x5d\x37\x25\x04\x19\xd2\x1c\x62\xd1\xdd\x33\xac\xa7\x16\xb3\x42\x5a\x92\x4c\x17\xa2\x51\xa6\xaa\xbb\xdd\x47\xb3\x55\xb6\xcc\x5d\x85\x85\x2c\xcc\x02\x12\x54\x81\xe7\xcf\xfe\xf4\x59\xbc\x35\x76\x04\x17\x48\x15\x59\xfe\x0d\xab\x18\x9a\x2e\x93\xd0\xb2\xff\xb3\xb0\x56\x8c\x5e\x9f\xef\x30\xbc\x72\xef\x44\xce\x9f\x61\x09\xfe\xe4\xdd\x53\x0c\xd1\x42\x3b\x75\xb3\x31\xb6\x53\xd7\x1c\x78\xac\x55\xd4\x83\x3e\xc2\x1d\x5d\x2f\xb6\xe4\xec\x99\x0d\x9c\x66\x5d\xfd\x96\xdf\xbf\x9b\xee\x2f\x31\x06\xf9\xf3\xf1\xce\xfc\xb9\xb4\x09\x0c\xfa\xbc\x62\x9c\x5a\xcd\x90\x13\xdb\x5e\x89\x11\x4e\x4c\xda\xdc\x98\xb9\x75\x0f\xdd\x0e\x5e\xa9\x5e\xd7\xaf\xcb\xc4\xea\xb3\xab\x0f\x67\x62\x19\x91\x36\xe5\x8c\xe0\xab\x61\x82\xc3\x46\x33\x3e\x5a\x82\x21\xc1\x87\x6a\xd6\x29\x17\x08\x83\x19\x00\xa0\xf5\x0f\x3b\x5c\x3f\x91\x86\x8a\x06\x57\xea\xb2\x16\x79\x93\x75\xf7\x31\xc2\x21\x96\xbe\xb4\xff\xae\x08\x07\xf6\x13\x2c\x53\x80\xe9\x5f\xae\x2b\x72\x34\x7d\xa2\x64\xb4\xe2\xd5\x4a\xfa\xdc\x18\x20\x73\xc8\xe2\xef\xd7\xd8\x79\xa9\x55\xad\x82\xb9\xce\x47\x11\x73\x3b\x25\xab\x86\xd6\xb4\x52\x8c\xe5\xd6\x6b\x65\xdd\x5f\x9e\xc0\x53\xdf\x39\x78\x80\x76\xb4\xa2\xbe\xf5\x52\x4d\x17\x62\x2c\xa0\x33\x4c\x70\xce\x4e\x9f\x45\x4e\xd8\x01\xb9\x6c\x68\x1b\x78\x77\xe4\x8d\x04\xff\x3d\x9e\xbd\x7b\x1a\xfc\x33\x12\x8d\x31\x48\xda\xba\x2c\xa2\x7e\xb4\x8e\xaa\x61\x9f\x56\x42\xb6\xa7\x01\xdb\x17\x89\x25\xb9\xae\x1b\x36\xc6\x48\xfd\xb1\xd5\xd2\xfa\x10\x15\x73\xd1\x4e\xc8\x48\x83\xea\x53\xe3\x27\x64\x04\xdf\xe8\x7f\xde\xaf\x21\x92\xa4\x74\xbc\xa8\xf5\x2a\x40\x88\x32\x46\xa9\x56\x53\x1a\x7f\xbe\x80\x0e\x6b\x59\x39\xcc\xe7\x3e\xf1\x9d\xab\x7b\x0f\x9e\x56\x22\x5e\xd3\x6a\x4b\x3c\xb1\x45\xe9\x79\xf7\x46\x48\xa5\xe5\x6f\x9a\xd5\x22\xe8\xd9\xd7\x7f\x99\x0b\x7e\xcb\x88\x13\xb3\x91\xb4\x2f\x58\x46\x41\xf3\xa8\x17\x5c\xd5\xb4\x6e\xa9\xa5\xc6\x50\xd8\x48\xb6\x6c\xfa\xb3\x0e\x8e\x24\x63\x64\x5a\x89\x9c\xed\xf3\x88\x63\xa4\xf8\xd4\x64\xdd\x82\xa6\x98\x99\x86\x3e\xb1\x70\x08\x5e\x6e\x44\xad\x35\x58\x5b\x29\x70\xc5\xde\x13\xee\x7b\x1f\x71\x49\x8e\xf2\x4a\x9e\x9d\x3d\x7b\x7e\xd5\x2c\xd0\xd7\xf5\x75\xa9\x4e\x8e\xbf\x3c\xfa\x6b\x43\x0b\x08\x44\x7b\x43\x4b\xf6\x75\xa9\x8e\x13\x84\x83\x5e\x17\x51\x90\xdc\xfe\x81\x56\x3e\x3d\xb5\xe0\x0e\xbf\xfb\x69\xe2\x2f\xf0\xf4\xdd\xd3\xe3\x2f\x83\x67\xc7\x0f\xbc\xce\x71\xd3\xd3\xbe\x78\xdd\xf9\x9a\x11\xd8\x3a\x9f\x21\x73\xe9\x7c\x84\x5b\xdf\xf9\xa8\x47\x6d\x4a\x34\x79\xed\x4b\x6d\x8f\xe7\xb0\xea\x9c\x59\xaa\xc3\x2a\xbd\x6b\xa5\x6f\xa4\x65\x1a\x9e\x59\x5a\xea\x1c\xe0\xa6\x8a\x80\xcb\x5d\xea\xf1\x0e\x06\x99\xaa\xd6\x15\xf1\x50\x6f\x81\x9d\x93\x31\x0b\x18\x45\xcb\xcc\x6b\xb7\xb7\x26\x8d\x66\x15\x0f\xf6\xa8\x32\xf9\x65\x43\x4d\xaa\x42\x67\x50\xeb\x27\xbb\x62\xb3\x12\x8a\x16\xa4\x6a\xca\x05\xd6\xcd\x19\xa8\x9a\xec\x1d\x47\x0b\xc6\x2a\x22\x9b\x2c\x63\x52\x2e\x1b\xf0\xd2\xf4\x16\xcc\x1e\x16\x21\x7b\x33\xfe\x87\x25\xc4\x98\x69\xb6\x03\x1d\xc9\xb6\x4a\x6b\x96\x8a\xf0\x80\xf8\xf2\x06\x52\x8c\x1e\x6e\x56\xeb\x05\x49\xba\xbd\x8c\xc3\xc6\xb5\x08\xc4\x6e\xb3\xdb\xb0\x89\x2d\x02\x72\xd0\xf8\xd6\x63\x68\x8b\x80\xb4\x36\xa9\x21\x1b\x5c\xa7\xbd\x2d\x01\xee\xb0\x29\x6e\xc7\xec\x16\x83\xf9\xd8\x06\xb9\xf6\x54\x0f\x35\xcb\x45\x40\xee\x1a\xec\xe0\x8f\x8f\x6e\x9b\xc3\xf1\xab\x5a\xe8\x0c\xc6\x0e\xb0\xd3\x99\x49\x26\x85\x13\xa6\xdb\xec\x70\x7c\x24\xcb\x1d\x8e\x87\xd8\xef\x06\x40\x2e\x02\xdb\x5a\xb2\x15\x6f\x00\xe6\x8e\x8d\x2f\xdd\x96\x37\x00\x37\xc9\xd2\x87\x23\xd5\xde\x87\x23\x31\x18\x70\xc0\xf6\x87\xe3\x63\x58\x00\x2d\xe4\x47\xb6\x03\x9a\x55\xa5\x59\x03\x0f\xc2\x54\xba\x65\xb0\x03\x69\x8f\x6c\x1f\x34\x13\x7f\x80\x95\x70\xe8\x38\x76\xdb\x10\x3f\xa2\xad\xd0\x7c\xf7\x41\x16\xc3\x01\xa0\x1d\x82\xc6\xb0\xdd\x10\x47\x8a\xf5\x10\xc7\xa0\x0d\x11\xc7\xb0\x9c\x88\x23\x6e\x4f\xc4\xf1\x30\xab\xe2\xd0\x0e\xb8\x2b\x7b\xa8\x6d\x71\x00\xb0\xb3\x3c\x1e\x6a\x61\x1c\x80\xeb\xed\x8f\xc9\x76\xc6\x44\x88\x2d\x2b\x64\x82\xb5\x71\x98\x1d\x75\xd8\x22\x1f\x62\x73\xc4\x91\x66\x79\x34\xef\xa6\xa6\x83\x3d\x96\x15\x12\x47\x22\x49\x8d\x5b\x24\x71\x3c\xd8\x2e\x39\xb0\x2b\x03\x56\x4b\x1c\xc3\xdd\x5f\x06\x2c\x98\xee\xa5\xa8\x1d\xd3\xbe\x15\xb7\x66\xe2\x48\x44\x6d\xcc\xb2\x89\xe3\x57\xb1\x6f\x9a\x95\x3d\xc4\xca\x39\x00\xd3\x37\x72\x3e\xd4\xd6\x39\xc4\x35\x42\x4b\xe8\x01\x16\xcf\x21\x66\xbd\x63\x0f\x4d\xb0\x7b\x0e\x40\xfc\x50\xab\x28\x8e\x24\xdb\x28\x8e\x7f\x30\x0b\xa9\xc1\x6b\xca\x7d\x18\x4e\x3b\x4d\xb4\x99\xda\x97\xfb\x2d\xa7\xf6\x8d\x5e\xfb\xa9\x7d\xa1\xd7\x8a\x6a\x5f\x88\xea\xd3\x09\xc9\x0c\xc3\xdd\xf3\x86\xd3\x5e\x0f\xb1\xb1\x26\xcc\x3b\xdd\xde\x8a\x23\xb9\xce\xeb\x50\x99\x57\x2b\x2b\x83\x45\x29\x8a\x77\xdf\x65\x36\xd6\x95\xe6\x7f\x4f\x25\x57\x97\x2f\xf5\x5d\xac\xb9\xf1\x4e\xad\xa1\xd6\x6f\x9c\xfe\xcf\xa1\xc9\x78\x4b\x8c\x84\x17\x7a\x71\xed\xbe\xed\x9a\x70\x15\xed\xb2\xbc\x90\xe2\xe4\x14\x25\x80\x78\x1b\x85\xb8\x5f\xab\xdc\x7c\xc3\xca\x86\x54\x85\x65\x62\x83\x0c\xb5\x68\x81\xd8\x8b\xa5\xe9\x37\xac\x39\x55\xab\x37\xf0\xd5\x86\x65\xbe\x7a\x75\xd0\xd4\x37\x56\xb2\x5f\xad\xd9\x16\xd7\xf6\xe6\xfb\x6b\xd3\xa7\xdd\x25\xc1\x02\x1a\xb1\x9f\xd4\xee\x5a\xa2\x05\x8a\xfb\xfa\xff\xb6\x7b\xfc\xce\x51\x12\x99\x8f\x1e\xda\xd5\xd7\xd6\x51\xbb\x58\x62\x31\x73\x2c\x6f\x04\x65\xcb\x5a\x6d\xd4\x3b\xf0\x15\xef\xff\xdd\xb1\xd6\xb0\x20\x93\x8d\x4e\x6f\x81\x8f\x96\x9d\x0f\xdc\x00\x76\x06\xbd\x01\xe3\x87\xd8\xc2\x0f\xe8\x37\x1c\x37\x86\xa7\xf7\x1a\x4e\xb3\xeb\x25\x14\x57\xfa\xc0\xfe\xc2\x8f\xd7\x5b\xf8\x80\x32\x2e\xbf\x5e\xf5\xa2\x44\xd9\x7a\xb8\x6a\xd1\x63\xf5\x11\x4e\xaf\xfd\xf1\x10\x45\xef\x43\xcb\x05\x3d\x9a\xe8\x15\xed\x17\xfc\x2b\x48\x3a\x71\x67\x7a\xdb\xa7\xd9\xf9\x4a\x54\xb9\x88\x64\x86\xb6\x99\x6f\xc7\x2b\x0f\x4f\x03\xfd\x07\x49\xf5\xec\x5c\xc0\x3e\xbe\x27\x40\xa3\x3f\xe9\xfd\x15\x9a\x13\x67\x44\xd5\x26\xa5\x46\x2a\x51\x43\xf2\x89\xff\x4b\xb3\x70\x3a\xa1\x05\x6c\x13\x49\xfe\xf6\xf7\x4f\xbc\xad\xc1\x76\xb9\x80\x4a\x4c\xf8\x26\xdc\x68\x5b\x6c\x6e\x53\x34\x35\x2d\xcc\x3f\x03\xef\x2d\xf9\xe9\xdd\x27\xf8\x61\x96\xff\x88\x09\xe7\xf8\xc7\xff\x17\x00\x00\xff\xff\x44\xce\xc1\x66\xcc\x48\x01\x00") + +func assetsGatewayApiGatewayNetworkingK8sIo_gatewaysYamlBytes() ([]byte, error) { + return bindataRead( + _assetsGatewayApiGatewayNetworkingK8sIo_gatewaysYaml, + "assets/gateway-api/gateway.networking.k8s.io_gateways.yaml", + ) +} + +func assetsGatewayApiGatewayNetworkingK8sIo_gatewaysYaml() (*asset, error) { + bytes, err := assetsGatewayApiGatewayNetworkingK8sIo_gatewaysYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "assets/gateway-api/gateway.networking.k8s.io_gateways.yaml", size: 84172, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x27, 0x98, 0x81, 0x90, 0xec, 0xf0, 0x4d, 0x7d, 0x94, 0x3e, 0xa7, 0x1f, 0xbd, 0x4f, 0x83, 0xff, 0xa1, 0x50, 0xc7, 0x35, 0xfd, 0x19, 0x10, 0x8a, 0x34, 0x56, 0x97, 0xa4, 0x1d, 0xe3, 0xf1, 0xba}} + return a, nil +} + +var _assetsGatewayApiGatewayNetworkingK8sIo_httproutesYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xfd\xfb\x9b\x1b\xb9\x71\x2f\x8c\xff\xee\xbf\x02\x87\x4e\x8e\x46\x0a\xc9\xd1\x48\xeb\x4d\x32\xe7\x9b\xaf\x9f\x89\x76\xe5\xd5\x93\xbd\xe8\x8c\xe4\xf8\x3d\x31\x37\x19\xb0\x1b\x24\x11\x35\x1b\x34\xd0\x9c\x11\x9d\xf8\xfc\xed\xef\x83\x2a\x00\x8d\x6e\xf6\xa5\xc0\x99\x91\xe3\x37\x83\x1f\x6c\x2d\x87\xac\x46\xe3\x52\xf7\xfa\x14\xdf\xc9\x7f\x16\xda\x48\x55\x5e\x32\xbe\x93\xe2\x73\x25\x4a\xfb\x5f\x66\xfe\xe9\xef\xcc\x5c\xaa\xf3\xdb\x8b\x5f\x7c\x92\x65\x7e\xc9\xde\xec\x4d\xa5\xb6\xd7\xc2\xa8\xbd\xce\xc4\x37\x62\x25\x4b\x59\x49\x55\xfe\x62\x2b\x2a\x9e\xf3\x8a\x5f\xfe\x82\x31\x5e\x96\xaa\xe2\xf6\x63\x63\xff\x93\x59\x9a\x33\xbe\xdb\x69\x75\x2b\xf2\xf9\xa7\xfd\x52\xe8\x52\x54\xc2\x52\xbe\x64\x9b\xaa\xda\x99\xcb\xf3\xf3\xb5\xac\x36\xfb\xe5\x3c\x53\xdb\xf3\xfa\x1b\x33\x23\xd7\xe6\x7c\xcd\x2b\x71\xc7\x0f\x33\xbe\x93\xe7\xbb\x7d\x51\x9c\x5f\xbc\xfc\xbb\xaf\x81\xb0\xfb\xcb\xbc\x14\xd5\x9d\xd2\x9f\x64\xb9\xf6\x33\x5e\xee\xcb\xbc\x10\xb3\x5b\xff\x5a\xb7\x2f\xe7\x5f\xcf\x5f\xce\x72\x71\x3b\xf2\xc3\x6c\xc3\xcb\x52\x14\x97\x4c\x7c\xde\x09\x2d\xb7\xa2\xac\x78\xf1\x0b\xc6\x32\x2d\xe0\x95\x3e\xca\xad\x30\x15\xdf\xee\x2e\x59\xb9\x2f\xec\x5f\x4a\xbe\x15\xf8\x1e\x5a\xed\xed\x6b\xf5\x12\xff\x85\xd9\x89\xcc\x2e\xc9\x5a\xab\xfd\xee\xb2\x7f\x16\x8e\xaa\x5b\xbe\x8c\x57\x62\xad\xb4\xf4\xff\x3d\x63\xd1\x8a\xc0\x27\xb8\x39\xdf\x7d\xfc\xf8\xfe\xda\x4e\x01\x3e\x2b\xa4\xa9\xfe\xa9\xf9\xf9\xf7\xd2\x54\xf0\xb7\x5d\xb1\xd7\xbc\x88\x27\x0d\x1f\x1b\x59\xae\xf7\x05\xd7\xd1\x1f\x7e\xc1\x98\xc9\xd4\x4e\x5c\xb2\x1f\xed\x84\x76\x3c\x13\xf9\x2f\x18\x73\xeb\x0a\x13\x9a\x31\x9e\xe7\x70\x0a\x78\xf1\x5e\xcb\xb2\x12\xfa\x8d\x2a\xf6\xdb\x32\x4c\xf7\xdf\x8d\x2a\xdf\xf3\x6a\x73\xc9\xe6\x76\x05\xe6\x1b\x65\x2a\x78\x3f\xf8\xbb\x5f\xc1\xef\x5a\x9f\x56\x07\xfb\x58\x53\x69\x59\xae\x8f\x09\xf9\x03\x37\x3f\xda\x98\x06\xd1\xab\xb5\x68\x90\xcb\xb9\x5b\x1e\xfc\xf3\xed\x05\x2f\x76\x1b\xfe\x0a\x5f\x3f\xdb\x88\x2d\xbf\x74\xdf\x57\x3b\x51\x5e\xbd\x7f\xf7\xcf\xaf\x3f\x34\x3e\x66\x2c\x17\x26\xd3\x72\x57\xc1\xb9\x0a\x6b\xcb\xec\xf1\x96\xb9\x30\x8c\xb3\x3b\x7e\x60\x95\x62\xb0\x80\xf0\x0d\xa6\xc5\x1f\xf6\xc2\x54\x66\xce\x3e\x6e\xa4\x61\xb2\xcc\x8a\x7d\x1e\xde\x14\xa6\xb7\x11\x2c\xe3\x3b\xbe\x94\x85\xac\xe0\xe7\x5b\x5e\x65\x9b\xf0\x4b\xb6\x3c\x30\xbf\x6e\x53\xb6\xe3\xd5\x66\xca\x36\x82\xe7\x42\x4f\x99\xd2\xec\x0f\x7b\xa1\x0f\x6c\xc7\x35\xdf\xce\x23\xaa\x6f\x65\x51\x09\x6d\x58\xc6\x4b\xb6\x14\x6c\x6f\x44\x6e\x49\xdb\x5d\x90\xab\x43\xb4\x71\x76\xfa\x99\x30\xf6\x04\x30\x53\x89\x9d\x99\xb3\x7f\xe4\xd9\x27\x51\xe6\xc6\x7f\x3b\x22\x7b\xb7\x11\x5a\xe0\x04\xed\x0f\xc2\x1c\xcd\x46\xed\x8b\xdc\x3e\x09\xde\x3d\xaf\xa7\xb2\xd3\x6a\x27\x74\x15\xce\x30\x8e\x88\xf1\x44\x9f\xb6\x96\xf8\x99\xdd\x05\xfc\x16\xcb\x2d\xc7\x11\x06\x56\xcb\x9d\x41\x91\xbb\x8d\x63\x6a\xc5\x2a\xbb\xba\x5a\xec\xb4\x30\xf6\xe2\x02\x6b\x62\x8d\xa1\x56\x8c\x97\x4c\x2d\xff\x5d\x64\xd5\x9c\x7d\x10\xda\x92\xf1\x13\xcf\x54\x79\x2b\x74\xc5\xb4\xc8\xd4\xba\x94\x7f\x0c\xb4\x8d\x5d\x35\xfb\xd0\x82\x57\xc2\x5d\xa2\x7a\xc0\x99\xb7\x8b\x78\xcb\x8b\xbd\x98\x32\x5e\xe6\x6c\xcb\x0f\x4c\x0b\xfb\x14\xb6\x2f\x23\x7a\xf0\x15\x33\x67\x3f\x28\x2d\x98\x2c\x57\x4d\x16\x18\xb8\x90\xda\x6e\xf7\xa5\xac\x0e\xe7\x99\x2a\x2b\x2d\x97\xfb\x4a\x69\x73\x9e\x8b\x5b\x51\x9c\x1b\xb9\x9e\x71\x9d\x6d\x64\x25\xb2\x6a\xaf\xc5\xb9\xe5\xaf\x30\xf5\x12\x98\xee\x7c\x9b\xff\x52\x3b\x16\x6d\x9e\x35\xe6\x7a\x74\xa7\x70\x00\xff\x18\xd8\x01\xcb\x47\x98\xb4\x47\x1b\x7f\x8a\x6f\x51\x2f\xb4\xfd\xc8\xae\xce\xf5\xb7\x1f\x3e\x32\xff\x68\xd8\x8c\xf6\xea\xc3\xba\xd7\x3f\x34\xf5\x16\xd8\x05\x93\xe5\x4a\x68\xdc\xc4\x95\x56\x5b\xa0\x29\xca\x7c\xa7\x64\x59\xe1\x0d\x29\xa4\x28\xdb\xcb\x6f\xf6\xcb\xad\xac\x4c\x7d\x0c\x2b\x35\x67\x6f\x40\x0a\xc1\xa1\xdf\xd9\x4b\x9f\xcf\xd9\xbb\x92\xbd\xe1\x5b\x51\xbc\xe1\x46\x3c\xfa\x06\xd8\x95\x36\x33\xbb\xb0\xb4\x2d\x88\x05\x68\xfb\xcb\xb8\x6a\xd1\x1f\xbc\x1c\xe9\xd9\xaf\x0f\x3b\x91\x35\xae\x4a\x2e\x8c\xd4\xf6\x30\x57\xbc\x12\xf6\x0a\x04\xb6\x35\x6f\x50\xe9\xbe\xa5\x76\x04\x96\xdd\xfe\x43\xeb\xd1\x93\xc0\xc5\xc3\x04\x38\x33\xa2\xb2\x0f\xf5\x34\x58\xb5\xe1\x95\xbf\x72\xc0\x44\x8e\x68\x32\xc6\xd7\x5c\x96\x06\x77\x1d\x58\xa8\x25\xec\x38\x1e\xb0\x30\x51\xd8\x93\xc4\x23\x0e\x5c\x29\xcf\xc5\xec\xaf\x3a\x68\xba\x03\xe2\x98\x30\x3c\xd9\x2d\xd0\xf5\xdb\x37\xec\xe2\xe2\xd5\x6b\x9c\x34\xf0\x44\xe0\x14\xf5\x9c\xef\x64\xd5\x35\xcd\x57\xcc\xea\x3a\xcb\x42\x30\xf1\x39\x13\x3b\x54\x7a\xd8\xa2\x64\x17\x73\xf6\xee\xbd\x61\x5c\x0b\xfb\x0d\xc6\x8b\x42\xdd\xd9\x43\xf8\x6a\xce\xae\x6a\xaa\x5b\x7e\xe8\x20\xba\xb4\xd2\x44\xac\xe4\x67\x91\xc3\x73\xad\x48\x91\x45\x9e\x71\x9d\xb3\x82\x2f\x45\xc1\xce\x6e\x5e\xcc\x6f\x9e\xdb\x17\x11\xf5\x9f\xac\xd0\xb7\x7f\xed\xa0\xb8\xdd\x9b\x8a\xf1\xdd\x4e\x70\x6d\x05\x89\xac\x8c\x28\x56\x8c\xe3\xcb\xaf\xa4\x36\x15\xfe\x74\x6e\xa7\xfe\xae\xf1\xe2\xd2\x0b\x00\x09\x92\xff\x68\xae\x07\xb6\x54\xd5\x06\x08\x59\xfd\x42\x94\x42\x03\x03\x0c\xfb\x32\xb5\x7f\xb3\xe2\xc2\xce\x61\x29\x18\xaf\x58\x21\xb8\xa9\x98\x2a\x05\xb2\x4e\x23\xb2\xaa\x79\x1b\xda\xc7\x8e\xad\x94\x0e\x47\x21\xec\x36\x10\xab\x78\xb6\x41\xa9\x16\x4f\x61\xce\xde\x2a\xcd\xc4\x67\xbe\xdd\x15\xe2\xf8\xcc\x32\xfb\x9e\x2f\xd8\x55\x3d\x65\x58\xe7\x1b\xcb\xdc\xe7\xee\x57\x56\x17\xbd\xf1\x6b\x14\xed\x18\x9c\x9a\x0e\x8a\x61\x6a\x06\xc4\x39\xaf\xd8\x86\xdf\x0a\x26\xa4\x7d\x7d\x38\x04\x61\x1d\x19\x2f\x6b\x69\x6e\x40\x80\xdb\xef\x76\x10\x8d\x7e\x52\xd9\xfd\x0d\x0b\xa7\x56\x5d\xb3\x55\x9a\xdd\xbc\x68\x7c\x34\xef\x20\xda\xf1\xe2\x2f\x48\x6f\x1d\xbd\x63\xd7\x92\xa6\xbd\xb6\x7f\xeb\xc1\xe3\x15\x0e\x0b\x83\xb7\x6e\xb2\x90\xf8\x06\x87\xf7\xf1\x5f\x81\x13\xd0\x41\xd1\xbd\xe7\x94\xb1\xf6\x5b\x4f\x3b\x56\x14\x85\xf9\xcd\x4a\xa9\xf9\xd1\xdf\x3a\x88\xdf\x01\x4f\x63\xf6\xba\xe3\xec\xe6\xec\xa7\x12\xe6\xa7\x60\x39\x36\xbc\xcc\xa7\xec\xa6\xb9\xd6\xf6\x01\x0d\xe2\xa5\xa8\x86\x88\xdb\x35\x75\xc4\x17\x65\xad\x36\xe3\x9a\x58\x86\xd3\xc7\x3c\x3a\x68\xc6\xec\x04\x7e\x0b\x17\x72\xa7\x45\x65\xb7\x0b\x98\xf7\x7e\xb5\x92\x9f\xfd\x03\x3f\xc2\xba\x0b\x5e\xe2\xe3\xba\x76\xcc\x29\xae\xab\xe3\xb3\xe8\xde\x00\xff\x0e\x5c\xa3\x63\xc1\xbb\x48\xf6\x6e\xc1\x94\x2d\xf7\x15\x2c\x48\x63\x4d\x3d\x1b\xf3\x9c\xa9\x83\x66\x37\xaf\x6a\x1d\xc8\xf8\x8e\xda\xb3\x1b\x7d\xaf\x65\xac\xc4\x03\xf6\x21\x57\xf5\x3e\x75\x1f\x50\xf6\xc3\x6f\x3f\x7c\xb4\x3c\x4c\xae\x4b\xa5\xad\x6c\x88\x58\x56\xd7\x32\x48\xcb\x97\x03\x99\x7a\x92\x47\xc7\xd8\xbe\x52\x93\x59\x0e\x5d\xb1\x2e\xa6\xd7\x79\x24\xdb\xf7\xc3\x7e\x06\x5c\xbd\x83\xa8\xd3\xbd\x32\x55\x1a\x99\x0b\xab\x7b\xd8\xf3\xc0\xa3\x73\x1b\x6d\x4f\xcf\x66\x74\xc9\x83\x81\xed\xc9\x59\x69\x59\x04\xae\x38\x9c\x7c\xd0\x18\xb5\xac\x84\x96\x9c\xf1\xa5\xba\xed\x5c\xd6\x6a\x23\xca\xd6\x72\x49\x83\x42\x3b\xb3\x22\xdd\xee\x8c\x95\xb3\xd2\xbe\xf4\xd6\x9b\x15\x28\xce\x34\x97\xa6\x6b\x9e\xbc\x64\xcf\xae\xdc\xaf\x9f\xb1\x37\xaa\x44\x3b\xcb\x5f\x48\xab\x87\xed\x0d\xf0\xf0\xb7\xbc\x30\xe2\x86\x49\x9c\x42\xa6\xb4\x16\x66\x67\xbf\xdf\x29\x0f\x61\x7a\xef\xb9\x16\x65\xf5\x01\x68\xc0\x52\x7e\xd8\xef\x76\x4a\x57\x97\xec\x8d\xd2\x62\x72\xf4\x33\x59\x89\x6d\x87\xde\xd6\xa7\xb9\xd9\xb7\x07\xb5\x60\x5f\x14\x07\xf6\x87\x3d\x2f\x70\xb1\x73\xb5\xe5\xb2\x04\xc3\x19\x75\x23\xe7\xb6\xe8\x20\x8c\x82\xfb\x21\xf5\xac\xfb\x6a\x5a\x9d\x24\xad\xc9\xf1\xf0\xba\x56\xa2\xb6\x15\x96\xdd\xd9\xe8\x8b\xc9\x4e\x8b\x4c\x1a\xb1\x38\xde\x49\x06\xb6\xb7\xcc\x36\x68\x8c\xc5\x3b\x62\xe7\xae\xf6\xa8\x2f\x57\x42\x6f\x65\xc9\xc1\x2c\xcb\x55\x45\xdb\x2d\x76\x26\xe6\xeb\x39\x5b\x4c\x2c\xa3\x8d\xb8\xc1\x62\xf2\xdc\x4a\xea\xc5\xc4\xbf\xfb\x62\x32\x3d\x9e\x44\x27\x59\x98\x58\x7b\x75\x8d\x2c\xd7\x85\x38\x5a\x64\x78\x78\x8b\x93\x3d\xef\x52\x5e\x40\x75\xfb\x51\x55\x4e\x07\xe0\x86\xed\x84\xb6\x07\xeb\xe2\xe5\xeb\x5f\x01\x1b\xb0\xff\xbe\x78\xf5\x7a\xca\x38\x7b\x01\xd4\x5f\xe0\x8e\x00\x33\xea\xe4\x56\xe0\x16\xb0\xc7\x46\xb3\x8c\x1b\xc1\xc0\x29\x54\xee\xb7\x42\xcb\x8c\x65\x1b\xae\x79\x06\x6e\x14\xa5\xd9\xb3\xd9\x33\x67\xe0\x5b\x92\xa6\xe2\xba\xb2\xff\xd9\x49\x54\x94\xfe\xad\xcb\x1e\x92\x73\xf6\xa3\x72\xaa\xc1\x6e\x5f\x66\xd5\x1e\x79\x8b\x5d\x58\x77\x8c\xbb\x0e\xc1\x96\x7f\xfe\x5e\x94\xeb\x6a\x73\xc9\x5e\xfd\xea\x75\xd7\x17\x64\xe9\xbf\x70\xd1\xf1\xe7\x1d\xaf\x2a\xa1\xcb\x4b\xf6\xaf\x67\x8b\x17\x8b\xf9\xf3\x5f\xff\x9e\xcf\xfe\xf8\x72\xf6\xf7\x3f\x9f\xfd\x7e\xe6\xfe\xf5\xc2\x7f\xf4\xfc\xd7\x67\x8b\xf9\xe0\xdf\x9f\xbf\xf8\xab\x2e\xae\xda\x6d\xe6\x86\x17\x78\x07\x4c\x89\x5d\x7c\x7d\xf4\x47\xfc\x25\xd7\xfa\xc8\x36\xda\x01\xe3\xbb\x16\xab\x51\x2b\xf4\x7d\xf8\x26\xd3\x62\x25\xb4\x28\x33\xc7\x81\x82\x63\x84\x9d\xed\xcd\x9e\x5b\x16\xf7\x1b\xf4\xa6\x9a\xe7\x7d\xb2\x9c\x23\xdf\x65\x77\xbc\x04\xef\x42\xcb\xf0\x98\x47\xc7\x11\x1f\xe1\x9e\x98\xbb\x19\x77\x9a\xa2\xce\x49\x52\x0a\x91\x03\x4d\xd8\x70\xe7\xfb\x70\xc6\x0e\x3e\xc3\x8a\x1c\xf7\xd0\x4c\xd9\xbb\xd1\xb6\xda\x71\x58\xe5\xc1\xbf\xc9\xd4\xe9\xc7\x4e\x4f\x13\xfe\x0f\xed\xa7\x45\x0f\x58\x69\xb5\xed\x13\x38\x26\xb8\xd6\x3e\xc9\x32\x47\x51\xeb\xbd\xc1\xc0\xc3\x2c\x6b\x54\x65\x71\xc0\xbf\xab\x95\x7b\xef\xf0\x96\x5d\xca\xac\xbd\x17\x8b\x89\x95\x58\x8b\x09\x33\x28\xc1\xec\xc1\x77\x53\x75\xc2\xe3\xea\xfd\x3b\xcf\xa6\x21\x2c\x91\x8b\xdc\xc9\xca\x0e\x9a\xab\x7d\xb5\xd7\x60\x19\x7a\x7a\x91\x83\x13\x5c\x31\x1d\x73\x33\xcc\xec\xb3\x8d\xe5\x23\xaa\xec\x22\x0a\xaf\xee\x1c\x9a\x48\x04\xd5\x17\x98\xac\x2c\x6f\x79\x21\xc1\xfa\x0c\xbb\x6e\x6f\xbb\xcc\x45\x59\xc9\x8c\x17\xfd\x27\x60\xab\x34\x9c\x99\x92\xa9\xd2\x2e\x23\x12\xec\x20\xb7\xdd\x17\x95\xdc\x15\x82\xe5\xd2\x54\xb2\xcc\x2a\x06\xf6\xb2\x2a\xbb\x74\x4f\xbb\xac\x4e\x97\x30\xc0\x7d\x9b\x2f\x3b\x0d\x2f\xfb\x2a\x28\x5d\xc6\xff\x88\x87\xb5\xef\xb6\x97\x71\x86\x3b\x65\x8c\xb4\x62\x18\x9c\x30\x3b\xae\x79\x25\x8a\xc3\xe0\x7c\xd1\x7f\xd5\xab\x2a\xbb\xfd\xcd\x54\x51\xf0\x9d\x11\xb9\x95\x99\x76\x0d\x1b\xfa\x56\x53\x3b\x66\x46\x6d\xdb\x1a\x59\x17\x7d\x4b\x3a\xdb\x28\x65\x60\xba\x5b\xa1\xd7\x78\x89\x78\x05\xaf\xe0\xaf\x45\xbd\x14\x95\x5a\x0b\xcb\x8e\xe7\x56\x3f\xed\xb1\x70\x9c\x7e\x64\x25\xc5\x14\x9d\xc2\xd2\x80\x90\xc5\x50\x4a\xcb\x27\x61\x9f\x1d\x9d\x35\xf0\x7a\x75\x69\x8c\x85\x81\x2b\x0e\x73\xec\x62\xfb\x44\x2d\x2e\x70\x3e\xb7\x1b\x78\x12\x57\xd2\xce\xab\x84\xeb\xe4\x7c\xb0\x9e\xfd\x75\x4a\xae\x70\x14\x9e\xe3\x16\x39\xdd\x24\x52\xe7\xb9\x3f\x5a\xb5\xd7\xdd\x71\xb4\x11\xc2\xb0\x48\x4e\x9d\x1a\xe2\x19\xdd\x1c\xa2\x93\x68\x02\xd7\x38\xe6\x11\xdd\xd3\x24\xf0\x8d\xfa\x2e\xd5\xde\x54\xc7\x0c\x3b\x69\x46\x6b\xef\x5d\x61\x78\xdb\xbd\xee\x5f\xec\x4d\x25\xf4\xff\x42\x86\xad\xd5\x7e\x07\x9c\x16\x7c\xef\x3d\x56\x16\xb8\x0a\xb5\x58\xdb\xe3\xab\x45\x9b\x92\x93\x23\x32\x92\x81\x4e\x8e\xc0\x73\x3b\x55\x8b\x7e\x0f\x30\x0e\x8c\x5c\x76\xfe\xc9\x9e\xc4\x15\xdf\x17\xd5\x70\x60\xb3\xfb\x87\xf1\x11\xc6\x77\x77\xb7\x0c\x1e\x18\x98\x30\xbe\x47\xd5\xb0\x7a\x7a\x68\xb2\x1e\x6b\x08\xc7\xa8\x0a\xc5\x1a\x7a\xd2\x5f\xfd\xe7\xbf\x3e\x82\x8e\xc4\xc6\xf4\x24\xd6\x19\x9b\x89\xd7\xcd\x2d\xb8\x3b\xfe\xa4\xe5\xf5\xc1\x1c\x7f\xef\x7a\x17\x16\x16\xb0\x77\x75\xcf\x02\x87\x68\xfc\x04\x12\x04\xd8\xd9\x4f\xa0\xd3\xfa\x44\x01\xf3\x9c\xb0\x0f\x5f\xf7\x6d\xc3\x88\x36\xcb\x1a\x3b\x65\xd7\xfc\x6a\xf6\x2f\x6e\x1b\xae\x66\xff\x12\x76\xc2\xfd\xfb\xf9\xaf\x4f\xde\x0a\x88\x19\x93\xd6\xf8\xc7\xc8\x8e\xf6\x06\xf3\x9f\xe1\x00\x13\x56\x8e\xf4\xd2\xa0\xe9\xd1\xdf\x1c\xbe\x1e\xbf\x3e\x7e\x70\xb4\x06\xbf\xdb\x88\x6e\xc3\xd1\x8e\x7d\x19\xfc\x3c\xd3\x88\x8b\xd5\x91\x58\x65\xd5\xab\x23\xea\x1d\x51\xad\x78\x8c\x7b\x4b\xdc\xca\x3d\xc6\xb9\xec\x65\x0f\x27\x9f\xc8\xa1\xf3\xd3\xd2\x0b\x9c\x7a\x0d\x5b\x82\x6c\x19\x7e\x8d\x4b\xeb\x42\x2a\x5c\xaf\x45\x65\xac\x2e\xda\xbb\x80\x4e\x13\x88\xdd\xc4\xb9\x5c\xe1\x8e\x16\x07\xb6\xe4\x56\x81\x53\x28\x87\xec\xf4\x6b\xc9\xd9\x4b\xd2\x4b\x54\xb8\x14\xbf\xf3\xde\xb8\xb6\x3a\x00\xce\x06\xc7\x73\xdc\x81\x70\xf3\xed\x25\xcc\x8b\x02\x74\x33\x54\xed\xf0\x5f\xb2\x5c\xfb\xe9\xd5\x7e\x44\xb7\x10\xd6\xd4\xb3\x6a\xd8\x90\x66\x00\xdb\xb2\x89\xd8\x27\x2c\xdd\x99\x95\xd4\x2e\x24\x59\x2f\xe8\x73\xbb\x92\xcf\xd0\x97\xa8\x45\xa6\xb6\x5b\x50\x45\xfa\xe9\x2a\x08\x95\xde\xd8\xbd\xba\x61\xfb\xb2\x70\xa1\x4c\x56\xcb\x51\xb6\x14\x1b\x7e\x2b\x95\x8e\xa2\x72\xac\xc7\xfd\x02\x4b\xe0\xb6\xd6\xbb\xa4\x0a\x48\x2d\xe1\xfe\xc7\x19\xbe\xba\x35\x7e\x76\x3b\xe5\xb2\x43\x78\x58\xb4\xb3\x4e\x9b\x18\xc7\x1d\x68\xb6\xf6\xe7\x67\xe6\x79\xd0\xe1\x37\xbc\xb4\xea\x2b\x6e\x23\xf8\x77\xe1\xe0\xd9\xe5\xf9\x80\x56\xcb\x8f\x7d\xde\x38\x98\xae\x8e\xb6\x65\x5a\xb3\x4f\xfb\x7b\x98\xa9\xbb\xe5\xb8\xd4\x22\x0f\x33\xed\xa5\x08\x2f\x1e\x45\x1c\xea\x55\xf3\x99\x18\xd6\xb2\x69\x1a\x12\xec\x87\xab\xff\xe3\xcc\x86\xc1\xbd\x72\x46\xa6\xf3\xdf\xb4\xd4\xc3\xf9\x11\x55\xf7\xfd\xbe\xbb\x6c\x07\x92\x82\xdc\x81\x4e\x53\x15\x42\x06\x59\x21\xb8\x2e\x0e\x2c\x57\xd9\x1e\x6c\xf7\x8d\xba\x3b\x97\xab\x5e\xa2\xfe\xea\x47\x77\x16\xde\xfa\xad\x73\x33\xec\xf6\xda\xee\xbd\x7d\x20\x3a\xa6\xa7\xe0\xb0\x0a\xbe\x81\x5e\xc2\xd2\xc4\x16\x81\xd9\x67\x99\x30\x66\xb5\x2f\xec\x79\x2a\x54\xb9\xf6\x2e\xcf\xf6\x55\x46\xbf\x7a\xff\xbd\x95\x95\xfd\x49\x25\xad\x15\xd1\xb2\xfb\xbc\xc5\x56\x5f\x6b\xcb\x90\xb4\xb0\x3c\x32\xeb\x9f\x29\xfa\x2b\x9d\x33\x23\x0b\x6f\xe7\x64\xc9\xd6\x5a\x9c\xd7\xc1\xc0\x9f\xd6\x52\xa5\x2b\x5e\xe0\x76\x2a\x8e\x34\xbe\x5b\xb1\x0b\xbb\x7c\xaf\x3a\xe6\x87\x2f\x4b\x59\xce\x90\xf2\xe2\xd5\x75\x7b\xdf\xeb\x10\xba\x9b\xa1\x8f\x1a\x75\xae\x7c\x8f\xd5\xc5\x20\x92\x8a\x56\x29\xcc\xb6\x54\x94\x99\xfa\x19\x1d\xa5\xf1\xd4\x83\x32\xbd\x5c\x38\x7b\x38\xbc\xe0\x80\x9f\x01\x47\x2c\xa6\xbf\xf5\x16\xdc\xa2\x64\xff\x3f\x67\x59\x5c\xc6\xd9\x99\xff\xff\x3e\x21\xbe\x52\x7a\xcb\xab\x4b\x7b\xf0\x5f\xbf\xea\x17\xf4\x72\xbb\xdf\x5e\xb2\xaf\x7f\xf5\xab\xd7\xbf\xea\x97\xf4\xf8\xa5\x61\x2d\xca\x5e\xb0\x75\x0f\x2f\x32\x35\xf7\xa3\x09\xec\x88\x5d\xb6\x35\x49\xee\xa9\x45\xee\x9e\x7e\x46\x05\x42\x32\x12\xb2\xef\x9c\x21\xac\x8a\x42\xdd\x61\xfa\x5e\xb0\x68\x9b\x0f\xed\xbf\xa0\xcd\x20\x71\x83\xdc\x25\xa6\x56\xb8\x2d\xbe\xac\x63\x7b\x96\x68\xff\x8e\xb7\x04\xc6\x59\xbc\xc1\xcf\xdb\xf2\xa3\x25\x27\x06\x04\x35\x55\x7e\xb4\xe5\x44\x2f\xc9\x44\xf9\x31\xe6\x68\x60\xe1\x66\x86\xcb\x0e\x1a\x2e\x0a\x82\x58\x98\xa0\x3b\xaa\xe1\x7c\x1a\x7a\xef\x43\xbf\xac\x68\xed\x72\x43\x2e\x0c\xdd\x48\xd8\xa2\x48\x2d\x67\x67\x62\xbb\xab\x0e\x4e\x3f\x7d\xee\x94\xb2\x3b\x59\x14\xb1\xc3\x61\xe0\x68\x8a\xb2\x92\x5a\x44\x47\xf3\xf1\x24\x92\x5c\x35\xf3\x8e\xfc\x05\x92\xb1\xb2\x39\xaa\xa1\x7a\xc9\xc5\x64\xf5\x24\x97\xfe\xbb\xcb\xa5\x2f\x61\x9d\x13\xed\xc7\x47\x73\x3f\x69\xf1\x87\xbd\xd4\xa2\xd3\x01\x35\x63\x3d\x81\xf5\x9e\xa4\xd5\xb0\x32\x2e\xf4\xd7\x21\x92\xfb\x43\x7f\x7a\x5f\x74\xe7\x9e\xa2\x03\xec\xe8\x0f\x33\x9f\x76\xd0\x3d\xf3\x1d\xaf\x36\x7d\x62\x18\x27\xf1\x9e\x57\x9b\xf7\x10\xba\xee\xf9\x1a\xb0\xff\x4b\x76\x3e\x1c\x89\xbc\xb6\xf3\x06\x71\xc5\x43\x98\x00\xd2\x59\x71\x7a\xda\x4c\xd9\xca\xe5\xe8\x5b\x19\xc5\x31\xb0\x73\x7c\x00\x69\xde\xff\xe0\x88\xb6\x8f\x0d\x09\xb8\x46\x6c\x79\x59\xc9\x0c\x03\x8b\x21\x6b\x9f\x97\xf0\xfd\xce\xd7\x73\x99\xb2\xb5\x39\x9f\xf9\x14\x16\xc3\xce\xdc\xca\x3e\x9f\xc6\x45\x03\xb2\x62\x67\xee\x4d\x9e\x77\x73\x27\xfb\x7e\x2b\xa5\xef\xb8\xce\x7d\xbe\xb8\x7f\x8c\x35\x3a\x9b\xc1\x89\x25\x16\x1f\x5c\x8b\x95\xe9\xcc\x02\x18\xf3\x53\x47\xbf\xa7\xa9\x5b\xff\x58\xff\xa0\x91\x3a\xed\x08\x59\x1b\xb7\x59\xf5\x30\x20\x2c\x8e\xaa\x21\x8c\x77\xf9\xbd\xe5\xb2\xd8\x6b\x11\xac\x78\x06\x24\x73\xb1\x13\x65\xde\xcf\xcc\x54\x09\x62\x7b\xcb\xcb\x03\x8b\xe7\xd9\xd0\x82\x60\x7d\xc3\xd7\x30\x95\x0f\xfd\xfc\x43\xdc\xec\xdd\x8a\xbd\xe0\x45\xf1\xc2\xca\x62\x2d\x85\x55\x06\x8e\x1e\xe1\xe8\x84\xbc\xb2\x01\xa7\x30\x1c\xf4\xc2\x28\xcb\xc8\xfd\xb9\x8e\xfd\x14\xce\x91\x07\x1c\xd9\x5e\xe9\xa9\x7b\x7a\xa5\xf9\x6a\x25\xb3\x11\x39\x59\x67\x12\x59\x22\xf6\x88\x03\x57\xd7\x22\x13\xf2\xd6\xde\xb0\x5f\xbd\x7c\xe9\x73\xab\x32\x95\x83\x43\xa9\x97\xe4\x07\x21\x42\xd6\x57\xfd\xc6\x71\x62\x92\x0f\xc3\x6b\xbc\xc3\x4b\xb5\xaf\xd8\x5d\x77\x48\x10\xc7\x96\x7f\xc2\x7c\x77\x4c\x71\x69\x51\xf6\xdb\x11\x54\x29\xde\xfa\xc6\x90\x56\x13\xf6\xa0\xf5\x8a\x26\x08\x36\x2d\xaa\xbd\x2e\x5d\xa2\x9d\x3f\x83\x03\x1a\x22\xaf\x5c\x3a\x26\xe4\xd4\x81\xbe\x79\x27\x8d\x3d\x9a\xa2\x74\xe5\x3b\xee\x5e\xfa\x20\xb7\xbb\x0a\xfd\xe7\xe9\xdd\xaa\x0e\xfe\x2e\x7d\xf5\x50\xcb\xa5\x03\x8e\x32\xe5\x54\x78\xff\x56\x83\x0a\xbc\xbd\xea\x4a\xfb\x54\xb1\xba\xc8\xa3\x7e\x83\x7a\xf2\xf0\x2e\xf6\x0d\xfa\x6f\xe7\xc0\x9b\x8d\x1d\xa7\xa1\x8b\xd4\xd0\x06\xe5\x8a\x55\x77\xaa\x67\x0d\x30\xb0\x29\xfe\xb0\xe7\x05\xbb\x13\x72\xbd\xa9\x4c\xff\x02\xd8\xe5\x82\x3c\xf9\xc6\x11\x60\x3b\xa1\x33\x1f\x7c\xc5\xab\xe3\xf2\x11\xe3\xb9\x0f\x6c\x54\xcb\x5e\x89\xc2\xe4\x1b\x48\x42\xe1\x55\xfc\x14\x69\x59\x22\x26\x95\x8d\x98\x08\x0d\xe5\x08\x4e\xe2\x3f\x85\x62\x4e\xa8\xf4\x91\x99\xe8\x88\x17\xf5\xab\x9e\x4a\x43\xe2\x6d\xd3\x1c\x8a\x28\xc0\x37\x70\x15\x87\x35\xb2\x5e\x01\x8a\xe3\x48\x8c\xb6\x59\x82\x30\xb0\x34\x71\xbd\x49\x6f\x2c\x3f\x9a\xbd\x95\x76\x5e\xd2\x86\xfa\x93\xde\x9f\x8c\x49\x35\x47\x16\x19\xeb\xd0\x57\xda\xd2\xcd\xd7\x01\xe2\xab\x40\x31\x01\x30\xd1\x42\xdc\x8a\xa2\x16\x54\x83\x14\x19\x13\x9f\x45\x06\xb7\xc7\x5a\x53\x70\x30\x8b\x03\x9c\xf5\x48\x94\x4b\xc3\x96\xc2\xca\x77\xf7\xf2\x03\xee\x6e\x1c\x2e\x9c\xe3\xaf\xa0\x9f\xa1\x15\x33\xf3\xce\xd0\x62\x77\x5a\x7f\x3c\x96\x5a\x41\x99\x50\x70\xd0\xae\xfc\x9a\x4d\xd9\xde\x20\xdb\xf7\x2b\xb2\x92\xa2\x18\xf4\xa0\xe3\x68\x68\x56\xf3\xde\x70\x26\x8e\x91\xb3\x86\xa3\x5b\x71\xc3\x69\x85\x23\xd7\xae\xca\x1c\xa1\xe9\x13\x6a\x5c\x7a\x81\x4f\x17\xcb\x59\xbe\xd7\x6d\x9d\x0b\xa4\x84\xd9\xa9\x72\xc0\xc9\xed\x47\x21\x57\x22\x3b\x64\x85\x98\xb7\x67\x8a\xbc\x6d\x2b\x78\x09\x51\x04\x5e\xb2\x50\x3d\x3e\x4a\xd5\x95\xf5\x29\x26\x3e\xef\xb4\x30\x8d\xb7\x8d\x13\x83\x72\x2c\x14\x1a\x09\x72\xd7\xa3\x95\x16\x34\x67\x1f\xac\xbc\x71\xcc\x39\x14\xdf\x46\x0b\x31\x4a\xd1\x2f\x14\xdb\xaa\x5c\xae\x64\x06\x84\xa7\xf5\x83\x40\x9d\xde\x57\x1b\x4c\xfa\xea\xa8\x3a\x3d\x1e\xa6\xd2\xbc\x12\x6b\x29\xcc\x94\xd9\x7f\xcd\x0a\xb9\x95\x96\x90\x53\xb3\x1c\x57\x37\x1b\xbe\x93\xe5\x7a\x6e\x95\xe3\x51\x9a\xeb\x3d\xd7\xbc\xac\x84\x38\xcf\x54\x09\xce\xcf\x12\x03\x67\xfe\x52\x1d\x45\xe7\x46\x49\x3a\x7f\x19\x5e\x9f\x7e\xc6\x85\x83\xc6\xbe\x70\x84\x63\x72\x2d\x56\xe3\xdf\x6e\xf3\xb3\x6f\xa3\x5f\x43\x64\xb0\x64\x6a\x87\x09\x3b\xd3\xd6\xfe\xcf\x7c\xa8\x8b\xf0\x90\x68\x5a\x9e\x2f\x2d\x26\xf8\xee\x8b\x49\x50\xda\xe7\x6c\xac\x52\xe3\x78\xd4\xa2\x6b\xb2\x3d\x80\x0e\x12\xc8\xca\xd2\x25\xb9\x2c\x26\x51\xbe\x4c\x54\x64\xb1\x98\xf4\x24\x42\xb7\x47\x63\x55\x40\x97\xf9\xf1\xa7\x8f\xa1\xee\xdb\x4a\xca\xcc\x8a\x65\x7b\xbe\x7c\x5a\x14\x89\xae\x63\x9e\x4d\x76\xfc\xae\x7b\x95\x87\x39\x23\x8e\x94\x73\xc2\xc6\x92\x8e\xda\xa3\x71\x50\x08\xa9\x44\x44\xb2\xcd\x3d\x67\x93\xa3\xd4\xa6\xc9\xfc\xc8\x41\x4a\x26\xdd\x76\xa4\xc2\x36\x59\x73\x78\xed\xe7\x0f\x95\xd1\x7a\x48\xfb\x6a\x0e\x92\x03\xaa\x3d\xbe\x44\xbe\x53\x7b\x8c\xa6\x38\xb4\xc7\x50\x3e\x54\x7b\x34\xce\xc2\x70\xde\xd3\xb8\x56\x51\x0f\x77\x0a\xd8\x24\x08\xc3\x89\x15\xa7\x13\xa7\xe0\x4e\x4e\xd8\xa4\xde\x24\x93\xa3\xdf\x8c\x3b\x0d\xdb\xe3\x41\x92\xa3\xda\x23\x79\xdf\x86\x92\xa7\xda\xa3\xb1\x6f\xa3\xb9\x54\x8f\x79\x25\x4e\x58\xee\xc4\x95\x19\x72\xb1\xb6\xc7\x0c\x19\x02\xe9\x9b\xf6\x98\x93\xbe\xd8\x5b\x1e\xd5\x1c\x83\x5e\xdd\xf6\x70\xba\xd5\x77\x50\xae\xff\x03\x28\x4d\x42\xa7\x8b\xf9\xeb\x2e\x32\x31\xb0\x00\x80\x73\xd0\x64\x18\x94\x1f\xa2\x24\x73\xda\x25\xd2\x0b\xb8\x11\x0e\x5c\xc0\x0c\x7a\x8d\xe2\x41\x8a\x04\xc4\x23\x55\xee\xf1\xfc\x34\x4e\x37\xb9\xca\x73\xfb\x63\x27\xf6\xe4\xad\x28\xdd\xcb\x9d\x99\xe7\xec\x0c\x20\x64\xc8\xcc\x0e\xfc\xdc\xcf\xbd\x3a\x14\x1c\xc3\x62\x85\xf5\x0b\xc2\xf9\xac\x07\x93\xc6\x8e\x5e\x6c\x07\x0e\x4f\xf4\xc2\x1c\x98\xf8\x0c\x95\x02\x0e\x56\xc4\x30\x6e\x8c\xca\x24\xaf\x12\x24\x68\xa8\xf7\x74\x08\x11\x18\xff\x5a\x94\xec\x5d\xb9\xdb\x57\x97\x8c\xb1\xdf\x7c\xfb\x91\x9d\xaf\x54\x5f\x0a\xf2\xf1\xb0\xcc\xfd\xfc\x62\x7e\x61\xb9\xc0\x61\x86\x74\x2f\xd9\x4a\x29\x4b\xf6\x8d\x2a\x57\x72\x7d\x99\xb6\x49\x50\x22\x3f\x73\xd0\x43\x56\x11\x74\x54\x17\x13\xf8\xa3\x8b\x28\x2c\x26\x4b\xae\x7b\x8a\xff\x3a\x69\x96\xec\xa7\x7d\xd5\x7a\xcb\xee\xd9\x93\x69\x5a\x0a\x8d\xd7\x5e\x72\x4d\x9d\x11\xc9\xfa\xad\xc7\x91\x1d\x8c\xb7\x3d\xc2\x88\x19\x8c\x54\x74\x8f\xef\xea\x53\x00\xea\x2e\xe2\xd5\xf0\xc8\x12\x3a\xb0\xeb\xb7\x6f\x12\x28\xfe\xed\xab\xd7\x03\x0e\xb5\xf6\x48\xbd\xe9\x38\x52\x44\x24\x0e\x52\xd6\x71\x12\x45\xe6\xd0\x56\x02\xd0\xca\xd2\xa3\x3f\xe4\x73\x14\xc5\xa3\x01\x90\xee\x11\x02\xb0\xdc\x58\x6b\xde\x58\x4b\xa5\x92\xb7\x62\xce\xce\x3e\x08\x11\x30\x78\x2a\xa5\x0a\x33\x97\xa2\x5a\xcd\x95\x5e\x9f\x6f\xaa\x6d\x71\xae\x57\x99\x5d\xfe\x5f\xba\xa0\xfd\xec\xf5\xfc\x15\xd1\x22\xaa\x07\xc6\x3a\x82\x7b\xda\x87\x3b\x3c\x12\x96\x15\xc2\xb7\xbc\x18\x0a\x83\x77\x8f\x88\xdf\x98\x69\x54\xe0\x6b\x1f\x70\xf0\xd5\x9f\x89\x34\xeb\xc9\xb0\x06\x50\x40\xb3\x9a\x3e\x91\x68\xa8\xbd\xff\xb0\x5f\x1a\xcb\xc5\xcb\x2a\xac\xc2\xbd\xa7\x19\xad\xc2\x11\xac\x41\x22\xd5\x6f\xf6\xc2\x0b\x1b\x7b\x54\x66\xf5\x51\x91\xd5\x01\x60\x84\xe0\x59\x89\x54\xdd\xfe\x40\x75\xf3\x62\x02\x3c\x61\x31\x79\x8b\xff\xd6\xf1\xca\x9e\xbc\x06\x9d\xe5\x34\xfd\xa3\xa1\x8d\x1e\x17\xc1\x0e\xfe\x34\x5d\x27\xc5\x11\x19\x02\x57\xb3\x7f\x41\x63\xed\x7f\xfc\xf2\xaf\xfe\xfa\x7f\x3e\x7b\xf1\x37\x8b\xd9\xfc\x5f\xff\x6d\xf1\xf9\xeb\x97\xff\xf9\x7f\x7f\xfe\x1b\xaa\x11\x80\x23\xd9\x14\xc0\x81\xe2\xee\x74\x76\xf7\xcf\xc0\xd3\x1d\xbb\x43\x06\xef\x82\xeb\xa9\x0c\xaf\x8b\xd7\x9d\xba\x99\x5f\xbd\xfc\xfb\x2f\xb4\x9b\x27\x2d\x7b\x8a\xb5\x81\x83\x6c\x20\xf8\xaf\xc3\x56\x90\xbf\x9f\x64\x56\xe0\x18\xac\x1e\x1f\x7a\x4a\x57\x62\x49\xdf\xf8\x3c\x8b\x60\x48\x0b\x69\xaa\xd9\x96\xef\x66\x9f\xc4\x81\x2c\xd1\x93\x16\xee\xf8\x71\x38\xe5\x2d\xa7\x58\x7b\x76\x5f\xb7\xea\xf6\x34\xfb\x7a\x72\x0d\xbf\xed\xb4\x15\x7a\xaa\xc2\xbb\x47\x80\x6a\x1b\x30\x12\x3e\xfa\xbb\x4a\xa6\xaa\x56\xcc\x4d\x10\x2a\x40\x1a\x49\x34\xb1\xf0\xa5\xdf\xd8\x66\xb5\x7e\x4c\x03\x65\x41\x53\xea\xd0\x67\x7a\x66\x22\x3d\x26\xe7\x15\xaf\x34\xcf\x3e\x09\x5d\x6b\x33\xb9\xca\x82\x46\xf3\xea\xeb\x8b\xaf\x83\x46\xf3\x55\x92\x46\xd3\x65\xd6\x74\x2a\xfc\x17\x27\x6b\xfc\xaf\x40\xe5\x8f\x3f\x79\x6d\x3f\xf9\x23\xd5\x36\x66\x50\xbe\xe6\x6d\x24\x77\x3a\xd9\xef\x23\xa3\xe7\x62\x31\x99\xc6\x46\xd0\xeb\xc5\xe4\xe7\x47\xb0\x79\x5e\xd1\x97\xe0\xf1\x6c\x9c\x13\x58\xf5\x17\x60\x72\x46\x0c\xd4\x1e\x36\x47\x3b\x35\xbd\x62\xea\x56\xe8\x3b\x2d\xab\x00\xab\x81\x57\xbe\x17\xbe\xa7\x73\xc2\x2d\x8e\xe3\x5c\x13\xde\xe5\x50\xb3\x0f\xba\x63\xc1\xb1\x19\xf2\x0d\x49\xbb\x20\x0d\xc3\xdf\x2e\x1f\xeb\xb1\xe7\x53\x1c\x02\x6d\xc3\xbf\xfb\x70\xdf\xd3\x6d\xf1\x64\xbf\x3f\xd9\xef\x4f\xf6\x7b\xc7\x78\xb2\xdf\x9f\xec\xf7\x27\xfb\xfd\xc9\x7e\x7f\xb2\xdf\xfd\xd7\x9f\xec\x77\x1c\x5f\xd0\x7e\x3f\x25\xb6\xfa\x83\xd4\x5a\x9d\x1e\x53\xc5\x9f\x1f\xc5\x52\xc9\x82\xa9\x15\x4b\x05\x6a\x26\xea\x73\x71\xed\xf3\xb4\x21\xf7\x99\x2a\x97\x9d\xe0\xa8\x73\xa5\x73\x61\x2a\x80\xb2\x54\x25\x62\xfd\xfa\x54\x3c\x43\xf7\x4d\x20\x1e\x6f\x4d\x08\x53\xcf\x3d\xe8\x6e\x57\xa9\xf1\x63\x04\x73\xeb\x8a\x94\xd3\x8c\xae\x28\x21\x39\x82\x34\xe4\x43\x18\x7b\xdd\xc3\x95\xb1\xc0\x8e\x89\xbc\x4e\xa8\xf7\x1b\xe5\xd1\x79\x53\x34\x4f\x9f\x8b\xc1\xb2\xd0\x76\x61\xa5\xf6\xa5\x47\x6e\x21\xd4\x38\xb4\x47\x04\xae\x17\xd0\x36\x97\x82\xe5\x5a\xed\x76\x49\x25\x7b\xed\xf1\x11\x60\x76\xcb\x4a\xab\xa2\xf0\x75\xbf\xa2\x34\x7b\xe7\xa8\x5a\x4c\xae\x85\x51\xc5\xad\x80\xfa\x97\x04\x4b\x2e\x54\x48\xf9\xfc\x4a\x97\x24\x8e\xf5\x03\xd2\x00\xb4\x47\xa5\xd8\x0d\x7e\x42\x67\xe0\x0e\x21\x18\x01\x8e\x01\xc5\x74\x25\xd7\x38\x5d\x69\x42\xde\xf4\x48\x15\x78\x7b\xec\xcb\x5c\xe8\xe2\x00\x95\x5b\x2d\x9c\xbd\xb0\xfb\x7a\xb0\x06\xbc\x3d\x38\xcb\xb4\x32\x66\x56\x23\xf2\x34\x50\xc7\x78\xc9\x5e\xf8\x38\xff\x0b\xba\xf3\x0f\xcb\xc1\x7c\xe5\x73\x84\xef\x0b\x20\x81\x2c\xe0\xdc\xfd\x46\xf3\xb2\xa2\x27\x35\x54\x8f\x74\x08\x16\x7d\xc7\xe0\xde\xfb\x3f\xad\x53\x1c\xec\xec\x56\x3f\xaa\xea\xbd\xd0\x5b\x59\x55\x22\x5f\x4c\x98\x16\xdc\x10\xb2\x8e\xfd\x20\x1d\xa6\xe8\x90\xd0\xaf\x6d\xc7\x61\x2a\x7d\x33\x00\x01\x22\x27\xe0\x26\x92\x89\xfe\x20\x8c\xe1\xeb\x90\xf8\x75\x13\x6f\xce\x4d\x84\xae\x3d\x5a\x90\xd1\x1c\x51\x43\x24\xd7\xbc\x09\x41\x39\x73\x51\x71\x59\xb8\x82\x2f\x57\x81\xb4\x2c\xc4\x36\xc9\x41\x7b\x0c\x5f\xd1\x5d\x0d\x73\x12\x4d\x57\x0a\xd1\x5d\x1d\x43\x3d\xad\xa7\xf8\x38\x92\x32\x71\x59\x8c\x50\x37\x49\x31\xaf\x1e\x2d\x87\x97\x91\xf3\x78\x93\x48\x0e\x81\x22\x34\x73\x79\x93\xc8\x9e\x90\xf7\xcb\x4e\x4d\x74\x64\x7f\xa6\xfc\x5f\x76\xaa\x25\x94\x92\x07\xcc\xe2\x93\x98\x7a\xf1\x52\xd2\x88\x4f\x3d\x88\xf7\x4e\x25\xc6\xf1\x0d\xbe\x23\x24\xd6\x05\x12\x56\xe1\x2b\x9b\x8d\x58\x4e\x3c\x4d\xe4\x24\x65\x76\xba\x5d\xfc\x28\xc9\xca\xec\xd4\x43\x96\xea\xd1\x7d\x94\xc4\x65\x76\x9f\x3b\x7d\xe2\x36\x9c\xbc\x5a\x83\x50\x91\x5d\x83\x0a\x1f\x99\x74\x11\xdc\x4a\xfb\x8a\xe5\xa3\xca\x8c\x34\xfd\xc3\x8e\x36\xdc\x64\xcc\x9b\x1b\x1d\x09\x92\xa8\xde\x61\x1d\x78\x83\x6c\x5c\x2c\xdd\x52\x70\xd3\xd6\x00\x75\x67\x69\x82\xd3\xc8\xeb\x75\xc1\x5a\x3b\x6d\x71\x23\xb0\x7a\x1e\xd1\x78\x66\x98\xba\x2b\xd1\x11\x87\x90\x2d\x69\x54\x63\xe4\xfc\x79\x28\xcf\xbf\xc7\x02\x78\xcc\x23\x1e\xaa\xf9\x51\xb3\x33\x34\xf4\xd5\xae\x41\xcd\xf4\xf6\xe3\xcf\xca\x3c\x93\xe1\x46\xbb\xc6\x49\x8c\x20\x75\x61\x1b\x3c\x00\xf0\xbf\xfc\x25\x08\xfd\x0b\xbd\xf3\x26\xcd\x61\x6e\x49\x95\xfb\xed\x12\x4f\xe5\xde\x88\x18\x13\xdb\xa1\x4e\x25\x51\xf4\x58\x8a\xe1\x4a\xdd\x79\xbc\xd2\x70\xa9\x12\x6c\x66\x06\x76\xf3\xb1\x51\xe0\x40\xda\xa4\x39\xc1\x58\x6a\xbf\xb7\xe3\xa3\xc6\x15\xdf\x47\x7f\xa2\x9b\xcb\xcc\x75\x74\x82\xb2\x51\xc4\x93\xb3\x74\x10\x03\xab\x05\x55\x96\x46\x35\x76\xcb\xc1\xd4\xb6\x72\xbd\x41\x4f\x8f\xd0\xf2\xd6\x79\x7a\x4e\x65\x24\x11\xe6\xa4\xdf\x76\xa8\xf7\x4e\xd9\x73\x0a\x88\x60\xd7\x20\x01\x0b\x76\xfe\x70\x0c\x6c\xb0\x6b\x8c\x03\x10\x1e\x8f\xd4\x58\x42\x92\x43\x3c\x31\x2e\x90\x56\x05\xb5\x4c\xf1\x27\x9e\xe2\x5c\xbf\x16\xb9\xd4\x22\x23\x31\xb1\x4e\xf7\xba\x27\xf0\x50\x0e\x76\xd7\x15\xcc\xb4\xeb\x70\x52\x22\xbf\x2e\x37\x0f\x27\xe6\xbd\x33\x8f\x5e\xc4\xe4\xd1\xe8\x4e\xf3\x7a\xb7\x9b\x92\xd5\x0d\x20\xd5\x38\x5e\x45\x3d\xc0\xcf\xe3\xb4\x9f\x10\x6a\x04\x5f\xd2\xf7\x0a\x0b\xf6\x6f\x52\xe3\xd2\x41\x97\xc2\x78\x84\xd3\x31\xc1\xf8\x9f\x36\xa6\x4a\x77\x76\x1e\x21\x69\xd8\x69\x9f\xb6\x4b\xec\x0b\x16\x3c\x3e\x3a\x48\x5d\x7b\x24\xeb\x24\x43\x70\x6f\xed\xd1\x6e\xa7\x52\x6d\x6a\x34\x0e\xae\xf9\x56\x00\xea\x85\x73\x1c\x92\xf7\x16\x8a\x0d\x0f\x0e\x6b\xb2\xda\xf8\xbd\x96\x65\xa6\xb6\x51\x0b\xf5\x79\x6f\xf7\x90\x5e\xa2\x80\x5f\x6e\x49\xe2\x0d\x29\x83\x4f\x33\x53\xa5\xa9\xf4\x1e\xdc\xe7\x74\x9a\x47\x17\xe2\xf8\x60\xbb\xb9\xd2\xb5\x41\x37\x3b\x98\x18\x37\x33\x69\xba\xa3\x6e\x29\xb9\xa5\x69\x40\xc0\x47\x33\x3a\xc1\xf5\xa9\xc5\xae\xe0\x99\x78\xbb\x2f\x8a\xf7\x09\xc7\x89\x75\x48\x88\x06\xa1\x5a\xd5\x4d\xd6\x72\x90\x93\x81\x08\x40\x80\x34\xe8\x1b\x05\xd4\x99\xef\xe0\x98\x9a\x60\xb2\x41\x80\x61\xcf\x84\x1c\x70\x8c\xfd\x00\xb2\x3d\x29\x68\x29\xf1\xf0\xe2\x66\x9e\x8e\xde\xdc\x35\x22\x96\x76\xf1\xf2\xd5\x57\x8f\x6d\xc7\xb8\xc5\x44\x1c\xc8\x1f\x78\x95\xdd\x7f\xdb\x23\x5a\x8f\xb8\xf3\xbb\x21\xe4\xca\xee\x81\xd8\xc7\x8f\xb4\xf9\x0d\x9f\x3b\x8f\x71\x1f\x17\x93\xf3\x95\x52\xe7\x69\x25\xaf\xcc\x57\xfc\x72\xf7\xa6\xf5\xec\x91\xde\x62\x82\xd0\x70\x49\x14\x97\xa2\xe6\xa8\x38\x33\x98\xd5\x3d\xdc\x3b\x55\xbb\xff\x69\xc0\x7d\x74\xfc\x7f\x14\x65\xb4\x7b\xb8\xae\xc2\x87\x9d\x68\xf5\x58\xb5\x37\x1e\x6f\xb1\xc0\x30\x5c\x42\x59\x84\x1d\x57\x8d\x1f\xb7\x3b\xae\xb8\xd2\x0b\xe8\xa9\x99\x76\x66\x03\xcc\x32\xf0\xbb\x42\x56\x6c\x89\xc2\xf0\xe6\xfc\xc6\x77\x91\x53\xa3\xf8\x42\xcd\x01\x62\xa9\xe1\x2c\xab\x34\x97\x85\x3d\xb1\x96\xaa\x34\xa7\x65\x30\x36\x8e\xaa\x9f\xb4\x61\x37\xe7\x7c\x99\xdd\x4c\xf1\xff\xcf\x3b\xdb\x54\xf7\x0f\xe8\xa7\x0c\x3f\xcc\xc5\xca\xb7\xc1\x0e\x3d\xc2\x4f\xbd\xb1\x7e\x4a\x4b\x1f\xa6\xb4\xab\x0b\x1f\xe6\xfe\x19\xa5\x4a\x8c\x49\xfc\x25\x72\x69\xf8\xd1\xc9\x7c\xf9\xe3\x61\x27\x1a\x88\xaf\x75\xd7\x9a\x84\x52\x06\x56\xab\x63\x7a\xce\xae\xea\xf6\x71\xd8\xcb\xc3\x21\x99\xf1\x9c\x0a\xb9\xe4\x07\xb4\x65\x74\x3d\xeb\xb4\x28\x04\x37\xc1\x74\xb9\x7a\xff\x2e\xb0\xa6\x44\xae\xc4\x2b\x0f\xb5\x10\x4f\x0c\xef\xb9\x34\x4c\x94\xfb\x6d\xda\x01\x97\x6d\x40\xc9\x46\x42\x05\xaf\xd8\xbe\xfc\x54\xaa\xbb\x34\xef\x9d\x9b\x22\x00\xca\x43\xb2\x02\xdf\x1b\x01\x79\x26\xdc\x60\x0f\xf1\xdf\x9e\x4e\x15\x93\xa0\x10\x33\xd3\xec\x8b\xca\xb3\xa8\xe6\x9b\x24\x51\x36\xa2\xaa\x3c\xca\xde\x95\xef\x01\x59\x67\x27\x38\x38\xd9\x24\x92\xae\x2f\x53\x9d\x35\xd2\xcc\x06\xe1\xec\x3a\x2d\xef\x83\xa1\x99\x79\xf3\xdb\xd2\x61\x23\x8a\x1c\xd2\x70\x6f\x1e\x48\x3f\xb3\x27\x27\xe5\x2a\xce\x58\x4b\x1b\x3e\xe5\xb7\x91\x4a\xf5\xb8\xac\x26\xdd\x61\x46\xc2\xd8\x8b\xe7\x93\x90\x48\x9b\xe2\x64\xef\xef\x05\x86\xad\xaf\x54\x48\x86\x19\x45\xc2\x8c\x66\x3c\xea\x4c\x49\xcd\x4a\xeb\x76\xa6\xc0\x14\xcf\xe4\xaa\x16\xf6\xfd\x5d\xa9\xda\x83\xe2\x53\x49\xc9\xfa\x64\x27\x7a\x84\x4f\xf2\x06\x27\x7b\x82\xd3\xbd\xc0\xe0\x94\x3c\xd1\x37\xf7\x01\x7e\x1b\x02\x0c\xf8\x5f\xf5\x51\x4a\xf5\xa4\x7d\x89\xa3\x14\x4d\xb4\x79\x32\xe8\x93\x1d\x3a\x41\xa7\x59\x0a\xa3\xa2\x98\xd0\xe8\xb8\x7b\xf4\x89\xe1\x6e\xd1\x4a\x26\xdb\x21\x82\xfb\xc4\x6a\xea\x21\x68\xbe\x69\xa7\x48\x25\x93\x3c\x12\xbd\xfd\xe2\x94\x4c\xb3\x21\x76\x7b\x44\x29\x95\x8f\xa4\x08\xcb\x19\x14\xd8\x25\x7d\x99\x7a\x4c\x92\x05\x21\xae\xdd\x1b\x95\x27\xf0\x0d\x97\x7b\xf5\xfa\x25\x95\x61\xb6\x58\x4d\x78\xa4\x67\x37\x10\xcc\xc0\x99\x90\x37\x2f\xb3\xbf\x6f\xc8\xba\x88\x4d\x90\x1b\xdf\xb6\x47\x7c\xe7\x1f\x50\xad\xa6\xaa\xd4\xee\x91\x09\x27\x78\x4c\x9d\x4e\xa5\x48\x53\xa5\xfd\x5d\x4e\x52\x2f\xfa\xd5\xe8\xe3\xbb\x4c\x26\xdc\xa9\x42\x7f\xd1\xbb\xfc\xfa\x25\x55\xa2\xcf\x12\xae\x4c\xaa\xf4\x4f\xd2\x38\xa9\x46\x76\x87\x71\x1d\xb5\xa0\x8f\xed\x6b\x0c\x6f\x92\xde\xad\x52\xd8\xbb\x74\xce\xae\x5c\xb1\x2b\x26\x1d\x5c\xbd\x7f\x87\x01\x7d\x33\x75\x86\x36\x27\x5e\xdc\xac\xe0\xc6\xf8\xae\x24\x70\x41\xb5\x80\x92\x80\x00\x9b\x0d\xd0\xf8\x06\xba\xd9\xcd\x48\x24\x2d\xd3\xb8\x74\xb8\xf2\x7e\x36\xd8\x30\x45\x02\xf0\xb2\x0b\xe1\x5a\x71\xe6\xd3\xee\xe9\x36\x66\x54\xf7\xce\xd8\x62\xd2\xe0\x54\x88\x21\x0d\x2c\x66\xc7\xb3\x4f\x7c\x4d\x44\x77\x14\xf3\xf5\x1c\x8a\x09\x3a\x40\x36\x17\x93\x39\xbb\x2a\x8a\x63\x3e\x44\xa2\x0c\xcc\xc0\xa3\xef\x43\x02\x74\x0c\x21\x3d\x0b\xfa\x92\x5f\x2e\xda\x21\xa0\x2f\xa9\x5f\x2e\x12\xdd\xf6\x92\xfa\xc9\x75\x2c\x2b\x2c\x19\x89\xe8\xa2\x59\x67\x67\x97\x33\x00\x66\x0b\x6d\x5c\xab\x1c\x51\x66\x6a\xaf\xf9\x9a\x38\xd3\xa8\xe7\xac\x08\x55\x05\x8d\x85\xc5\xc2\x00\xbf\xac\xb4\xcd\xc2\xbe\xc7\x5a\xd4\xcd\x21\xca\x9c\x05\x3e\x68\x97\x27\x34\x0b\xbe\x15\x65\xae\x34\xd1\xa7\xbc\x60\xa1\xd5\x24\xf8\xaf\xea\x4e\x57\x66\x83\x8d\x27\x33\x55\xde\x0a\xbd\x16\x25\x31\x01\x51\x96\xb5\x03\x9d\x43\xb5\x51\x0d\x08\x70\xda\x41\x05\x61\x78\x54\x99\x8f\x2d\x02\x8c\xeb\x0f\x18\x96\x9a\x18\xfd\x80\xf3\xce\x3a\x78\xc9\xdc\x6d\x4b\xc0\x4a\x3f\x81\x0f\xd8\xd9\x99\x7d\xb6\x09\x6b\xc9\x1a\x29\xa3\x6c\x6f\xbc\xba\x1c\x83\xc1\xd3\x48\x43\x66\x14\xbb\xb1\x3c\xfb\xa6\xd1\xbc\x0a\x1c\x04\xf6\x4c\xc7\x34\x89\xe1\x1a\x40\x9d\x77\xe5\x2a\xd1\x51\x6d\x5c\x86\xd3\xae\x02\x1e\x57\x4f\xbc\xa5\x6c\x20\xb3\x80\xde\x12\x76\xf7\x88\x17\x41\xd4\xd5\x1a\x20\x65\x7a\x3a\x09\xd4\x9d\x00\x68\x17\x01\x0a\xea\x78\xab\x1e\xae\xb9\x2a\x28\x15\xb1\x7a\x92\xc6\xb5\xb0\x6f\x66\x71\xeb\xfb\x64\x3b\x3a\x31\xec\xbf\xf9\x24\x77\x3b\xe8\xac\x58\x9a\x4a\xf0\x81\x3e\x4b\xf1\xe8\xea\xb0\x14\xfa\x2a\xf9\x1e\x1d\xc8\x18\xc8\x66\x6e\x3c\xb9\xba\x47\x11\xe8\xf0\x58\x14\x16\xeb\xe1\x24\x8a\x09\x2a\xf7\xe9\x22\xec\x61\x4d\xe7\x04\xb3\x99\xea\x86\x23\x9a\xcc\xb5\xfa\x4c\xbe\xb3\x83\xe6\xf2\x09\xde\xe7\x7e\xaf\x33\x85\x8f\x50\xd5\xeb\x19\xeb\xd4\x66\x52\x7e\x89\x02\x3b\xe5\x17\x3e\xd7\x8f\xf4\x9b\xdf\x5e\x7f\x7f\x8d\xd1\x74\xd2\xd7\x13\xb9\x78\x92\x2d\xbf\xd7\x85\x9b\x4a\xba\x62\x5f\xbf\x46\x67\x86\x23\x23\x82\xb2\x77\xc1\xb1\x1f\xe5\x1f\xd4\x4d\x23\xc9\xfc\xf6\x01\x9a\x87\xc7\xe3\xcf\x9b\xf3\x88\x8e\xd1\x13\x1c\xab\xad\xa4\x10\x4b\xd7\x7b\x53\x91\xe6\x89\x0b\xcc\x1e\x65\x91\xd9\x53\xca\x62\x73\x86\x0f\x91\xb2\xc8\x31\x2b\xc0\x25\xf0\x90\xa5\x2b\x8b\xdb\x1b\x3c\xdc\xf6\x3e\xe5\xdd\x75\x8f\xa7\xbc\xbb\xf6\xec\x9f\xf2\xee\x9e\xf2\xee\x9e\xf2\xee\x9e\xf2\xee\x9e\xf2\xee\xfe\xeb\x72\xe9\xa7\xbc\xbb\xa7\xbc\xbb\x64\xaa\x4f\x79\x77\x4f\x79\x77\x7f\xc9\x79\x77\x09\x5f\xa7\x4e\x9b\x34\x5d\xf2\x73\xc9\xe8\x9a\x34\x4c\x4d\x02\xe2\x13\x15\xe3\x29\x15\xd5\x29\xa5\xcb\x2e\xa9\x1f\x6b\x1b\x9b\x69\x84\xe6\xa9\x5d\x58\x13\x9c\x18\x5f\x0e\x71\x89\x78\xed\xc6\x51\x95\x92\x70\x94\xd2\x1a\xb0\xfa\xcd\x1e\xdb\xeb\x3e\xac\xa4\x01\xfc\xa3\x11\x92\x09\xe8\x48\x74\x48\x0f\xb2\x5f\xea\x01\x31\x8f\x88\xdb\x3c\xee\x9c\x7c\x40\x24\xa3\x84\xfb\x40\x5e\xb2\x84\xf7\x24\x20\x12\x51\x31\x88\xda\xb8\x42\x23\xa7\xaa\x13\x75\x68\x0c\x49\x68\x84\x66\x1d\xf7\x7a\x58\xec\xa0\x14\xb4\xa0\x80\x00\x34\x26\xb3\x46\xf0\x81\x3a\x30\x7f\x46\x29\xb6\x11\x81\x1e\x06\xe5\x67\xbc\xac\xfe\xd1\xaf\xfd\x89\x68\x3d\xc4\x8b\x30\xbe\x08\x09\x18\x3c\x31\x88\xcc\xd8\x86\xf5\xa1\xee\xf4\x23\xe9\x8c\x6a\x55\x01\x67\xe7\x81\xb0\x73\x88\x68\x39\x2d\x04\x1c\x02\xd1\x6e\x7c\x9c\x7e\xcc\x9b\x11\x92\x31\x22\xce\xfd\x51\x6e\xe8\x55\x0c\x09\xb5\x0b\xc4\x8a\x05\x6a\xa6\xe2\x9d\xb0\x2b\x43\xd4\x47\x86\x1f\xd9\x64\xf1\xbf\x03\xc2\xad\x13\xbe\xd3\xca\x6e\x87\xc4\x64\x50\x9f\x06\x31\xb2\x29\x2e\x76\xe6\xad\xf8\x88\x9f\xe5\x35\xfc\x1c\xf8\x0a\xed\x89\x54\xdb\xdd\x7e\xbc\xad\x31\x37\xee\xcd\xcf\xcf\xcc\x7e\x0b\xbe\xe1\xa2\x70\x1f\x99\x90\x94\x56\x83\x6a\x1b\x70\x11\x8e\xb6\x54\xb1\x87\xb1\x54\xe5\xec\x8f\x42\x2b\x67\x8e\x4f\x1d\xce\xb3\x73\x47\x18\xb5\x15\x4c\xec\x8c\x2c\x2c\x2b\x1d\x07\x5e\xb2\xef\x2b\x3e\xf3\xac\x8a\xd7\xce\xa7\x91\x01\xe1\x5c\xec\x04\x26\xe8\x39\x38\xe4\x9d\x16\x99\x34\xe3\x26\x3e\x2f\x8f\x12\x1b\x90\x95\x9b\x39\x73\xbb\xe7\x01\xa1\xd9\x4e\xe8\xcc\x7e\x6d\x3d\x76\x83\x5c\xf2\x20\x73\xab\xea\x57\x34\x57\x02\x49\x95\x02\xf7\x51\xfc\x61\xcf\x0b\x76\xf1\xf2\x25\x41\x20\xbf\x5b\x31\x55\x16\x07\xa6\x4a\x51\xe3\x27\xc7\x29\x59\xf6\xa1\xb2\x62\x1b\x6e\xf9\x15\x3e\x72\x84\xe4\x5a\x0b\xee\xe2\xe2\x25\x7b\x39\xb5\x13\xf9\x6b\xaf\x7a\x54\x9a\xaf\x56\x32\xb3\x8f\x88\x8f\x1e\x45\x12\x87\xe3\xf8\xce\xbf\x7a\x04\x4b\xfd\xd2\xf2\xb7\x40\x9d\x84\xa4\x0c\x20\xef\x7e\x0a\x81\xc3\x43\xe3\x1c\x78\x46\x43\xf3\x21\xbd\x78\x1e\xe9\xef\x17\xb1\xfc\xae\xc9\x03\x67\x63\xb7\x1c\xfa\xde\x2c\xf9\x78\x38\xdc\x9d\xbb\x4c\x95\x95\xf8\x5c\x39\xf4\x7b\x28\xe1\x19\x16\xf8\x27\xf0\xc7\x8b\x97\x30\x68\x1c\x72\xf8\x6b\x34\x0e\x39\xee\x61\x18\xc1\xec\x22\x78\x15\x08\xfe\x84\x31\x4f\x82\x4b\xfc\xeb\x9b\x65\x93\x35\xbb\xd4\x55\x9f\xde\x57\xa7\xb6\x99\x3a\x53\x95\xef\x76\x85\x1c\x3e\xf7\xcd\x2c\x36\xef\xef\xb7\xfa\xc6\xbe\xc0\x6a\x8f\x8f\x96\x79\xad\x56\x22\xab\x8c\xbd\x5c\x4a\x5b\xf9\x3a\xa0\x44\xa9\xa8\xfd\x94\x8f\x27\xb9\x8e\x91\x7b\x6d\xc5\x70\x71\x88\x8f\xbc\xe3\xfa\xd9\x00\x38\x57\xb6\xe1\xe5\x5a\x78\x3d\xdb\x79\x9b\xe1\x4c\xdb\x53\xbb\x12\x22\xb7\x57\xd6\x87\x03\xa1\x8d\x66\xb1\xdb\x70\x66\x2c\xab\xeb\xe7\xf6\xae\x4b\x9d\x4b\x3e\x9d\x61\xf2\x29\x83\x76\x97\xd2\x60\x2e\x6a\x23\xdf\x37\x3c\x71\x48\x55\x6a\x66\xed\x63\x5a\x3c\xbb\xfa\xfe\xfb\x46\x7a\x77\xe8\x1d\x15\xa7\x0f\xf7\x92\xb4\x42\xad\xe5\xc0\x9e\xb3\xd9\x50\x6a\x68\x94\x01\xdd\x4b\xf5\x38\x33\x3a\x22\xd9\xca\xe3\x6c\x26\xa6\xf6\x92\x84\xec\xc7\x52\xa1\x2f\x68\xcf\xad\xd9\x21\x84\xf1\x29\xc8\x47\x5e\x78\x64\x5c\xd8\x98\x6c\xe8\x40\xf1\x78\xed\xea\xb3\x55\xc9\xad\x30\x20\x2e\x62\xd7\x55\x9d\x46\x1b\x25\x16\x0f\x9e\x81\xab\xa2\x08\xfb\x02\xcb\xf8\x79\x27\xb2\x0a\x17\x11\x52\x9e\xb7\x3b\x5e\xc9\x65\xe1\xe2\xd9\x82\x67\xae\xac\x62\x60\x69\xc1\x6a\xf3\xe9\x81\x51\x0e\x98\x95\x71\x6d\xe4\x3b\xf7\xec\x29\x46\xca\x7b\x89\x5a\xd5\xc3\xb5\x0c\xc9\xd4\x76\x69\x4f\x24\x48\x8f\x63\x05\x20\xe3\x0e\xc6\x7a\xe4\x04\xa0\xc2\x8d\xc4\x5c\x5c\x24\x1c\x5c\xd4\x78\x0e\x18\x81\xc8\x0a\xc1\x75\x71\x08\x26\x64\xff\xe1\xb7\x3c\xa4\x90\x5b\xe9\xdb\x1a\xbc\x2b\xe1\xf4\x5a\x0b\xc3\x38\x91\x02\x50\x5e\x7e\x45\x95\xb6\x9b\xe7\x2f\x41\x2f\xdd\x78\x7b\x22\x59\xd9\x8e\xea\xc0\xad\xe2\x79\x6e\xf5\x07\xae\xcb\xa1\x33\x55\xb7\x9f\xb0\x57\x05\x62\x17\x74\x00\xb9\x91\xce\x8f\x47\x9d\x1e\xc1\x07\xe7\x0a\x5e\x02\x46\x1a\xe6\x07\x5b\x86\x65\x2a\xb1\x33\x63\xc1\x7b\xdf\xd8\xc5\x2e\x5e\x21\xec\xf1\x8c\xd8\x9d\xcf\x57\x88\x12\x84\x59\x21\x57\x22\x3b\x64\xc5\x20\x70\x6b\x6b\x76\xb8\xc2\x5b\xc1\xcb\xca\x2a\xd7\xdc\x25\xf5\x1b\xb4\xc0\x64\x59\x61\xa6\xf8\x4e\x0b\x33\xa4\xef\x47\xef\xe6\xa4\x0a\x68\xcd\xb9\x55\xfd\x64\xe9\x5b\xd1\x1c\xb1\x83\x01\x8a\x1f\x40\xe1\x46\xaf\xa7\xc1\xb2\x83\xbc\xfb\xb5\x31\xc8\x89\x35\xd1\x43\x8e\xeb\xf0\x70\xc8\x20\xd9\x57\x1b\xfb\xcf\xcc\x69\xd0\x95\xe6\x95\x58\x4b\xab\xf7\xdb\x7f\xcd\xe0\x48\xcb\x72\x3d\xb5\x17\x78\x80\x68\xad\x16\xf2\x9d\x2c\xd7\xf3\x26\x27\x3c\x8f\x4b\x1d\xa4\x69\xca\x95\x01\xaa\x4e\x33\xf3\x92\xa5\x96\xf4\xfd\x2b\x46\x4b\x20\x13\x51\xd2\x6c\x8a\xe3\x2f\x4e\xb6\x05\xf7\x42\xc9\xd4\x0e\xe3\xc9\xed\x4b\x19\x64\xc8\x88\xf6\x59\x9f\x33\x67\x1e\x2e\x26\xf8\x8e\x8b\x49\x5d\x45\xc0\x52\x22\x1d\xc1\xd6\x5f\x4c\xb6\x07\x6d\xcf\x78\x20\x28\x4b\x17\xaa\x58\xc4\xe1\x10\x47\x77\x5e\x8a\x6a\x31\x19\x35\x12\x1b\x6b\x10\x17\x13\x40\xc5\x2c\x54\x73\x58\xa1\x65\x19\xbe\x97\xb4\x63\x16\x72\x54\xf6\x11\xd8\x50\x8f\x44\x1e\x56\xc9\xe9\xe9\x83\xc4\x3e\x25\xa7\x44\xa4\x08\x31\xc2\xf1\xee\x22\x1d\x51\x29\x02\xdd\x9e\x9e\x22\x69\x7d\x42\x12\x53\x6c\xbf\x6c\x4f\x90\x84\xe0\x30\xad\xff\xc7\xa3\x04\xa0\xd8\x50\x10\x2a\x65\x03\x08\x98\xf0\x49\xc9\xcd\x0f\xdc\x3c\x23\x61\x37\x68\xd9\xee\x0f\xdc\x1e\x23\xf1\x28\x27\x2d\x25\xf9\xdd\x69\x51\xfe\x19\xa1\xfd\xcf\x0c\x0e\xe6\xc8\x57\x46\x11\x85\x89\x89\x02\xba\xab\x4e\x26\x45\x58\x76\x16\xda\x9c\x02\x77\xcd\xbb\xcb\x40\xbc\x12\x84\x05\x0b\x0f\x1c\xcd\xa1\x4b\x12\x9e\xa7\x72\x99\xc9\x95\xd5\xd4\xf3\xdc\x09\x92\xa8\xbf\xfd\x99\x79\xee\x5a\xdc\x13\x18\x8c\x6b\x82\xdf\xc2\xfb\xae\x7b\xe2\x87\x5e\xf7\xef\x2a\xc6\x77\x3b\x51\xe6\x94\xd4\x50\xe8\xc4\x77\x60\xbe\x13\x9f\xcf\xca\xe2\xc6\xa8\x4c\x72\xab\x7e\x87\x36\x73\x64\x3c\x6c\xfb\x46\x0f\xdc\x72\xff\xa8\xd9\xbe\xdd\x86\xbe\x66\xfb\xf5\x72\x51\x48\x0f\x76\xd9\xbf\xd7\x84\xd3\x1b\xee\x93\x5b\xed\xd3\x9b\xec\xbb\x6e\xc8\x04\x9a\x6c\xb4\xbd\x3e\xb9\x69\x7e\x6a\x5d\xc7\xe9\xb5\x51\x7d\x42\x23\xf5\xd5\x19\xde\x85\xde\xe6\xf8\x8d\x76\xf7\x64\x8a\x5f\xb2\x2d\xfe\xc3\x37\xc4\x27\xb5\xc2\x3f\x85\xf0\x40\x13\xfc\xae\xb6\xf6\x64\xba\xad\xf6\xf7\x43\x0d\xed\xc9\x34\xa3\xc6\xf7\xc3\xad\xec\xc9\x14\x43\xcb\xfb\x47\x68\x62\x7f\x42\xfb\xfa\x93\x1a\xd7\xdf\xaf\xc4\xee\x61\x9a\xd5\x27\x27\x8e\x26\x35\xa8\x27\xb6\xa6\xbf\x1f\x8f\x49\xdf\xa2\x84\x76\xf4\x27\xec\x51\xe2\x92\xa6\x35\x69\x21\xf6\xbe\xa0\x37\x9c\x4f\xca\xd4\x4d\x6a\x32\x9f\xd2\x5e\xfe\x3e\x8d\xe5\x89\x8b\x72\x7a\x33\x79\x2d\xb6\xea\x36\xd5\x10\x9b\x5c\xc3\xaf\x3a\xd5\x55\x9f\x6b\x42\xd8\x1e\xd7\x5e\xa6\x57\x4f\xfd\x18\xdf\x25\x7c\x24\x81\x2a\x64\xf9\xf8\x0a\x28\x78\x44\xcc\x4c\xe7\x51\x3e\x5c\xb2\xce\xea\x82\x77\x4d\xce\x2e\xd8\x99\x89\xe4\x76\xce\x2b\x5e\x69\x9e\x7d\x12\xba\x96\xde\xb9\xca\x82\x04\x7f\xf5\xf5\xc5\xd7\x41\x82\x7f\x45\x94\xe0\x64\x5d\xf9\xe2\xd2\x6a\x96\x14\x8a\xd1\x8f\x5e\x81\xf6\x19\x93\x79\x6d\x3f\xf9\x63\xa4\x51\xd3\x28\xba\xd3\xc4\x7e\x1f\xa9\xdb\x17\x8b\xc9\x34\x56\xbf\x5f\x2f\x26\x3f\x47\xba\x34\x8d\xf0\xe0\x3b\xbf\x7a\x68\xe5\x39\x89\xcb\x3d\x12\xdf\x30\x82\xb0\x36\x2d\xcc\x43\x51\x31\x75\x2b\x34\x44\xd8\x0c\x3b\xea\xfa\x44\xbb\x95\xf1\x85\x76\xc6\xa7\x37\x2d\x3b\xee\x28\xa9\x3c\x9c\x68\xe6\xb5\x8c\x38\xda\xc9\xb0\xeb\x44\xb0\xf3\xbc\x15\x47\xbb\x6b\x54\x3b\xef\xc9\x68\x1b\x7b\xf0\x93\xd1\xf6\x64\xb4\x3d\x19\x6d\x4f\x46\xdb\x93\xd1\x76\x34\x9e\x8c\xb6\x81\xd9\x3e\x19\x6d\x23\xaf\x41\x8d\xd7\x20\x3a\xd9\x09\x71\x1a\xfc\x61\x0f\x58\x17\x0d\x8b\x17\xe3\x33\x40\x27\x84\x67\xcc\xdc\xe7\x7d\xb9\x2c\x26\x81\xc9\x34\x90\x65\xed\x23\xdc\x23\x74\xa3\x7a\x08\x04\x55\xf0\x49\x2f\xc6\x9b\x9f\xbc\x6a\x14\x4d\x8c\x83\xfc\x06\x69\x90\xde\xe7\x81\xae\x16\xd5\x5d\x68\x53\x55\xfb\x3a\x75\xbf\x2e\x17\x40\xe0\x33\x97\xdb\x01\x29\x65\x84\xdb\x85\xbb\x21\xf2\x3a\xdd\xd5\x6f\xc2\xdc\xe9\x1a\x8d\x3a\x11\x32\xbe\x24\xa4\x76\xef\x4b\xa8\x58\x6b\x94\x1a\x60\xae\xc1\x2d\x2f\x24\x26\xb6\xbb\xf4\x2d\x8a\x36\xac\xd5\x6e\x17\x57\xaf\xb8\x74\x29\x74\x0c\x64\xaa\xac\xb4\x2a\x0a\x48\x84\x0c\x18\x06\x14\xfe\x02\x39\x35\xd7\x0e\x0a\xf3\x5a\xac\xcc\x62\x12\x65\xc1\xb9\x1c\x23\xac\xe7\x27\xc3\xc5\xd7\x69\xf1\xad\xfa\x7f\x78\x67\xc0\x44\x70\xc8\xad\x02\x16\x88\xb2\xa2\xbe\x34\x00\x27\xb4\x2f\x73\xa1\x8b\x83\x55\x5a\x9b\x89\x45\x6e\xdf\x68\x6f\xae\x05\xfa\x47\x20\x11\x75\x56\xd7\xe7\x35\x91\x46\x4b\xf6\xc2\xc7\xfb\x5e\x10\xe8\xba\x4a\x40\xb8\x75\xbe\xc4\xa2\x28\xd4\x1d\x5a\x18\xed\xb2\x42\x4a\x28\xb3\xea\xdd\xe0\xce\xed\x23\x59\x8a\x3d\x5b\xdc\xbb\x73\x94\x79\x86\xd0\xa7\x9d\xd1\xea\x47\x55\xbd\x17\x7a\x2b\xab\x0a\xb0\xa0\x35\xc2\xc4\x1f\x1d\x00\xd2\xfb\x4b\x93\x74\x00\x48\x46\x38\x13\x12\x12\x5d\x11\x40\x35\x14\xbb\xb1\x1f\x84\x31\x7c\x5d\x77\x52\x89\x17\xf7\x86\x40\xb9\x46\xce\xa8\x31\x80\x7d\x4f\xd9\x9d\x56\xb7\x32\x17\x6c\xab\x20\x7f\xbc\xe2\x92\x02\x74\xc6\x97\xca\x43\xe5\x68\xb5\x2c\xc4\xb6\xa7\x7b\x8a\x95\x45\x75\x41\x1f\x81\xb0\x4b\xba\x69\x26\xb8\xba\x9c\x6e\x2b\xd7\xca\x43\xab\xfa\x6e\xfc\x6c\xa5\x59\xc5\xc4\x3c\x33\x96\x80\x92\x50\x7f\x3f\x2d\x37\x8d\xa8\x3d\x36\x60\x96\x48\xf9\x69\x44\xc2\x2d\x6c\x85\x7b\xe5\xa8\xb1\xd3\xa0\x20\xbf\x6c\xae\x1a\x4b\xd7\xc5\x69\x39\x6b\x2c\x15\x65\xa1\xfe\x51\x4a\xb2\x1b\x71\x5f\xdd\x61\xa1\xa1\x2e\x10\x69\x36\xb1\x19\x52\xd0\x17\xfc\x48\x4b\xa2\x63\xa7\x58\x5a\x0f\x9c\x4c\xc7\xd2\x8f\x0b\xdd\xe3\xf6\xc0\x89\x75\xec\xb4\xfb\x97\xbc\xc4\x27\xac\x07\x01\xcd\xc1\x8f\x44\x54\x07\xe2\xd9\x0d\x55\x94\x24\x74\x07\x22\xd1\x16\x06\xc4\x30\xca\x03\x91\xe6\x00\x16\x44\x07\xda\x03\x75\xa2\xa3\x98\x10\x47\xa8\x0f\x44\xca\xe3\xd8\x10\x1d\xe8\x0f\x54\x3f\x11\x09\x23\x82\x90\x37\xe8\xc7\x17\x67\x3f\x27\xa2\x43\xf8\x91\x78\xd1\xe8\xad\x25\x53\x51\x23\x88\x1b\xe6\xd0\x18\xe8\xe8\x11\x44\xba\x1e\x63\x82\x84\x22\x41\xf5\xc7\x35\xb0\x26\xc6\xd0\x24\x92\x16\xa0\x8d\x39\x31\x80\x2a\x41\xf7\x98\x76\x63\x4f\xf4\xa3\x4b\x10\x29\x9f\x82\x41\xe1\x47\x7a\x47\xcd\x13\xfa\x69\x26\x76\xd3\x4c\xeb\xa6\x45\xf7\xb2\x12\xdd\x89\x64\xbf\x29\x35\xff\xbc\xf6\x56\x3d\xa0\x3b\xd2\x17\x7b\x9e\xe0\x90\x0c\x75\xa2\xf7\x76\x49\xba\x2e\x50\xa6\x9d\x2b\xed\x23\x4c\x2e\x31\x05\x1f\x67\x2d\xec\x11\xa2\x69\x22\x81\x6e\x30\xd2\xbb\x02\x0c\xf7\x03\xf0\x74\xd2\x5a\x02\xa4\x74\x59\xad\xdb\xb1\x10\x08\xb7\xfb\xab\x86\xe9\xf5\xf4\xde\xa5\xc5\xec\x13\x85\xf2\x63\x96\x82\x7c\xc1\x66\x01\x09\x72\x9a\xd6\x20\x60\xa0\x35\xc0\x8e\x6b\xbe\x15\x50\x1d\xeb\xdd\x3b\x50\x7c\x41\x09\x92\x06\xd8\x63\xb7\xc7\x50\xfc\x2c\xcb\xb5\xdf\x6c\x74\xea\x06\x54\x6f\x22\xa4\x2f\x9e\xef\x32\x4c\x27\x53\xa5\xa9\xf4\x3e\xab\xba\x0f\xeb\x29\x87\xd3\x1f\x46\x98\xbc\x3b\x91\x8c\x9b\x99\x4c\x2a\x30\x61\xbe\x50\xf2\x9e\x5d\x11\xd2\x9c\x4d\x27\x75\x42\x20\xf6\x40\xa8\x79\x03\x55\x93\x1a\xec\x7e\x70\xdc\xd1\x80\xaa\x9f\x1c\x43\xdf\x3f\x5c\x2f\x83\x53\xf0\xb1\x93\xa3\xad\xa7\x75\x2e\xa0\xf7\x2c\x48\x30\x55\x69\xdd\x0a\x30\xd0\x4d\xb5\xd2\x46\xfa\x14\x34\x7b\x0f\xa4\xb9\x98\x06\x3a\x14\x34\xbb\x0e\x90\x23\xf2\x9d\xbd\x09\x7a\xfb\x0d\x10\xc9\x36\xcc\xf3\xb1\x4e\x03\x44\x9a\x75\x3f\x02\x42\x8f\x01\xea\xaa\xfa\x4e\x04\xe3\xdd\x05\xe8\x9b\x8f\x3d\x08\x1e\xb8\xaf\x00\xbd\xa3\xc0\x29\x87\xaa\xbf\x97\x40\xab\x3f\x00\x95\xf3\xf5\x76\x11\xe8\xec\x0c\x40\xa4\x7a\xdc\x3f\xe0\x2f\x80\xdb\xd1\x3b\x00\x24\x60\xff\xd7\x78\xfe\xc4\xa5\x1b\x44\xfd\xef\x42\xf2\xa7\x1f\xf7\x36\xde\x7f\x2f\x86\x3f\xd5\x57\x30\xd4\x97\xf0\x08\xbd\x9f\x48\x74\xb0\x33\xe1\x3d\x70\xfb\x1f\x03\xb1\x9f\x86\xd5\x8f\xc1\x5c\xfa\x9a\x0e\xa3\xf4\xf7\x20\xef\xd3\xd9\xfd\x7d\x6e\x21\x1d\x99\xff\x34\x4c\xfe\x93\xd1\xf8\x93\xae\x7a\x8a\x7b\x83\x84\xbd\x9f\x90\x16\x46\x53\xc8\x5b\x86\x8e\x73\x0f\x06\x87\x5c\xb3\xeb\x7f\x8a\xb2\x4b\x36\x95\x63\x5b\x83\xe8\x63\x65\x67\x72\x55\x0b\xbe\xe7\x7d\x16\xf3\x89\x96\xc9\xf8\x01\x4d\xf3\xbb\x25\xfa\xdc\x12\xfc\x6d\x29\xbe\x36\x70\x12\x25\xfb\x50\x3e\xc0\xaf\x82\x43\x16\xff\xeb\xe8\x50\x10\x16\xf7\xf1\xfd\x27\x6e\x72\xfd\x67\x81\x92\x18\xd1\xd5\xbb\xef\xbe\x02\x2c\x4d\x78\x25\xb4\x9e\x21\x0b\x2e\xf7\x4d\x02\x49\x9a\xd0\x8a\xc5\x11\x81\xe8\x98\xc0\xba\x4f\xda\xd1\x88\xb0\x1a\xbf\xcb\x34\x41\x33\x83\xe2\x06\xe2\xd7\xc6\x17\x3a\x41\x88\xe0\xba\xbc\x51\x39\xe9\xee\xba\xec\x87\xd7\x2f\xc7\xd9\x52\xeb\xa2\x87\xc7\xf8\xcb\x0e\xee\x5f\x7c\x3a\xcb\xec\xe7\xa4\x34\x85\x88\x31\xc4\xbd\xa9\x9b\x7e\xc9\xd4\x0e\x75\x8f\xd1\xaa\x3a\xad\x51\x35\xa9\x31\x6f\x4a\x9b\x6a\xe2\xd5\x49\x6a\x52\x4d\x00\x8d\x61\xbe\x19\x00\xad\x51\xd3\xa3\xdf\xaa\xd7\x2f\xc7\xa5\xdc\x8c\x74\x9c\xe9\xb2\x90\xa8\x43\x8d\x1b\x69\x1d\xc6\x99\xcc\x45\x59\xd5\x9e\xc1\x26\xfa\x2b\x44\xe9\x77\xbb\xe2\x30\x26\xde\xae\x5c\x99\x0f\x06\x2b\xaf\xde\xbf\xc3\xa0\xa0\x99\x3a\x43\x0d\x0a\x68\x0a\x6e\x0c\x3a\x63\x64\x49\x00\xb2\xd6\x42\xc4\x10\xa8\x88\x67\x6b\x1c\x20\xad\xbd\x94\x97\xec\x6d\xdd\x52\xdf\x8c\x20\x1b\x22\x4d\x21\x01\xd6\xce\x05\x92\xec\xc1\xf4\xe9\x9d\xbc\x01\x69\xbe\x3c\x00\x80\x4c\x02\x0c\x11\xa2\xf2\xc1\x05\xdf\xf1\xec\x13\x5f\x8b\x29\x13\xf3\xf5\x1c\x52\x4c\x3b\x00\x94\xc6\xdd\x50\x57\x45\xd1\xd7\xf8\xcd\x1d\xef\x06\x24\x2f\x41\x61\x98\x05\x2d\xe1\x78\xe9\xc6\x17\x67\x84\x78\xcf\xd2\x85\x47\x76\x2c\xd0\x08\xc5\xe6\xf2\x61\x5d\xc3\x62\x32\x6f\xe2\x06\xb3\x16\x72\xf0\xd8\x11\x08\xb8\xc2\x1d\xf8\xc1\x78\xb2\x20\xad\xd4\x2f\xd0\x28\xac\x29\x73\x33\xf0\xaf\x6f\x97\x32\x06\x45\x66\x01\x83\xf8\x56\x94\xb9\xb2\x8f\x61\xe3\x29\x07\x35\x4c\xf4\x34\x60\xc7\x9a\x8d\xba\x73\x9b\x72\x2b\xf4\x1a\xb2\xbe\x65\x19\xfc\x90\x63\x73\x44\x0c\xe3\x50\x91\x78\x7c\xb2\x40\x7e\x2c\x13\x0a\xdd\xac\x4a\x04\x48\xa6\x00\x7b\x29\xcb\x7a\x45\x3d\x78\x24\xeb\xb8\xc0\xa3\xcd\x0b\xe0\x75\x23\xe8\xe6\xc6\x05\xb5\xcf\x34\xfb\x6c\x13\x56\x85\x8d\xe7\x49\xd5\x00\x8c\x7b\xe3\x65\x51\x03\xfd\x12\x13\x18\xd8\x8d\x65\x88\x37\x64\x48\x7c\x97\x7e\x6e\x0f\x7b\x4c\x6d\x31\x41\xf0\xcc\x06\xe2\x34\xa5\xbd\xc0\x30\x1a\xb6\x43\x49\x77\x64\x93\x5c\x32\x78\xc7\x01\xf8\xd6\xee\x8f\xcb\xd2\x77\x49\xbb\xc0\xb6\x4f\x83\x3c\xad\x61\x4d\xb1\x02\x85\xb7\xca\x11\x9a\x6b\x40\x71\x17\x60\xd9\x8a\x5d\x5c\xed\x72\xd9\xa7\x11\x5a\x6c\x03\xa5\xd4\x7c\x92\xbb\xdd\x78\x90\xf9\x5d\x69\x2a\xc1\xf3\x69\x0b\x26\x1e\x9d\xaf\x00\xf7\xbd\x14\xa2\xf4\x80\xbf\xc3\x30\xe6\x6e\x35\xed\xef\xe3\x09\x69\x91\x09\x79\x6b\xcd\x18\x50\x40\x31\x4b\xbf\xa1\x4a\x12\x1a\x88\xd2\x5a\x86\x26\x6a\x8d\xa9\x1a\xa3\xd3\x07\xc7\xb3\x26\x68\xda\x62\xda\x29\x4d\x71\x18\xc6\x7a\xe0\x18\x3b\x49\xd0\x12\xed\xab\x0d\x6b\x8a\xe3\x5a\xe2\x8c\x75\x8a\x7b\xda\x6f\x50\xc6\xd1\xbe\xeb\xd3\x6a\x46\xbe\x5d\x63\xb7\x8f\x7c\x31\xe6\x61\x04\x6d\x74\xd4\x14\xdc\xeb\xc2\x3d\x38\x45\x27\x8d\xa0\xe6\xef\x5f\xc1\xe8\x11\x26\x8f\x02\x99\xae\x9b\x09\x20\x5c\xd3\x5d\x6e\xf7\x4d\x04\xf8\xf2\x09\x44\xe8\xc3\x8a\xbc\x5f\x24\x8b\x38\x8e\x1c\x5b\x8a\xde\xe5\x85\xd4\x8e\x97\x90\x40\xb2\xb3\x0a\xe8\x1e\x0e\xf7\xa7\x2c\xa0\xee\x31\x90\x05\xc4\x31\xe6\xe6\x22\xf8\x4f\x49\x30\x4f\x49\x30\x1d\xe3\x29\x09\xa6\x31\x9e\x92\x60\x9e\x92\x60\x9e\x92\x60\x9e\x92\x60\xa2\xaf\x9f\xc0\xdf\x9e\x92\x60\x9e\x92\x60\x9e\x92\x60\x5a\xe3\x29\x09\xe6\xe4\x2f\x52\x9a\x41\x0e\x4e\xeb\xcb\x34\x83\x74\x92\xbc\xbf\x19\x24\x86\x7e\x7b\xfe\x3c\x1b\xb5\x78\xf0\xf9\xb5\x2e\x31\xf0\x55\x87\x25\x79\xde\x3b\x95\x98\x5d\xff\xe0\x34\x10\xef\x71\xf5\xd7\xd5\xd4\x9d\x91\x02\x0e\xe1\x90\xce\xa3\xf7\x85\x60\x7c\xcd\x65\x69\xaa\xba\x6e\x22\x06\xcf\x35\x73\xf6\x2d\xcf\x36\x4e\xb2\x42\x69\x30\xb6\xd1\x15\x43\x70\x2b\x72\x2e\xe6\x75\x87\xcb\xe0\xb6\x77\x28\x66\x4c\xae\xd8\x8b\x17\xbc\x3c\xbc\x78\x01\x9d\x6a\x1d\x5b\x77\x9b\xd1\x4f\xd4\x30\xc3\x2b\x69\xb0\xa1\xe5\xa2\x6c\xc2\x47\x54\xfc\x93\xb3\x76\x54\x51\x60\x14\xc2\xeb\x69\x0d\xf7\x7c\xff\x76\x2d\x4a\x76\x73\x73\x13\xce\x84\xdf\xde\x78\x77\x82\xde\xea\xb1\x0e\x0d\x00\x84\xf6\x92\xf4\xc0\xa1\xb7\x42\x1b\xa9\xca\x36\x6c\xe8\xed\xab\xc5\xa4\xe7\x31\xb7\xaf\xf0\x49\xbd\xa4\xed\x54\xdd\x1a\x34\x94\x74\xdc\x28\xbf\xa7\x61\x0f\xa6\x04\xc3\x0f\xe3\x76\xb0\xc4\x07\xf6\xed\xbb\x8f\xdf\x7d\x7b\x1d\x3a\xfd\xde\xa9\xe8\x94\xb9\x00\x27\xe8\x06\xa8\x68\x0d\xc8\x5b\xe0\xfc\x37\xf6\x6d\x6e\xd8\xd5\x8f\xdf\x00\xf8\x8e\x9d\x5c\x84\x91\xcc\x6e\xdc\x02\x5d\xb2\xdb\x57\x37\x4d\xca\xbd\x74\xad\x0c\x71\xcb\x04\x2b\xe1\x8b\xb2\x8f\xeb\xab\x03\x58\x04\x1a\x6e\x03\xa2\x71\xa3\xee\x20\xfc\xe6\x20\x30\x43\x24\x0a\x17\x35\xba\x66\xa0\x75\xd4\x90\x34\x57\x3f\x7e\x33\xb0\x02\x95\x5a\x8b\x6a\x23\x42\x10\xa2\x54\xe1\x68\xb6\x9a\x2d\x62\x95\x32\x30\x1d\x28\x06\xee\x25\xe9\xd4\x5b\xd4\xce\xdc\x5b\xd9\x63\xb3\x98\xb8\x16\x97\xd0\xb3\xb3\x0a\x5d\x65\xa1\x61\xac\xe3\x08\xbd\x44\xc5\xad\xd0\x87\xc6\xed\x87\x19\xbf\xd7\xea\xf3\xc1\x5a\x92\xdf\x2b\x9e\xb3\x7f\xe4\x05\x2f\x33\xa1\x99\x56\xfb\x8a\x1e\x80\x5d\x8b\x52\x68\xe8\xe9\x02\x35\xbd\x61\x4b\x5c\x43\xc9\x9d\x96\x4a\xcb\x4a\xfe\x51\xc0\x69\x35\xb4\x3e\xb0\xf5\x55\xcf\xac\xb5\xab\x25\x9f\xc2\xf1\x92\xe5\xde\x77\xf9\x96\xc2\xcc\xd9\x7b\x2d\x32\x91\x43\xd0\x67\x0c\x23\x0c\x21\x8a\x9d\x25\x76\xbd\xf7\x0d\x49\xc1\x2e\xe3\x7a\x6d\x2f\x99\xab\xa7\x56\x2b\xb8\x06\x2f\xd8\x9b\x0d\xd7\x3c\x1b\x6c\xda\x0a\x2a\x6f\xe0\xc8\xa5\x2a\x67\x77\xb2\xc8\x33\xae\xf3\xe0\x47\x9d\x37\x28\x35\x7f\x31\x70\x5e\xc7\x7f\x0c\x87\xc4\x7e\xc1\x21\xfe\xba\xa3\xd7\xaf\x6d\xbd\x60\xff\x7b\x6f\x0f\x02\xd4\xe4\x85\xaf\x7b\x08\x37\x80\x88\xad\x2c\x43\x07\x1c\xaf\x76\xd0\xb6\x97\x2a\xee\xf6\x34\x9a\x56\xbd\x29\x1e\xd9\x35\x17\x95\xd0\x5b\x88\x51\xcb\x12\x9b\x20\x33\xd5\xef\xe9\x6f\x72\xfb\xa1\x23\xe0\x76\xea\xe3\x46\x30\x55\xe4\x43\x3c\x10\x63\x37\xe1\xf4\x65\x5a\x20\x1f\x81\x46\xb8\x15\xdf\xee\xe6\x8e\x0e\x7e\x91\xef\x76\x82\xa3\xb3\x59\xea\x01\xb2\x76\x47\x8a\xdd\x86\x2f\x45\x25\x33\x5e\xb8\x77\x73\x79\x08\xff\x11\x00\x2a\xfe\x74\x0e\xff\xfe\xd3\x62\x12\xaf\x77\x2f\xd5\x78\x1f\xec\x31\x95\x31\xfa\x18\xb0\x28\xcb\x05\x20\x7a\x88\xe7\xba\x5e\xf3\x7e\xd9\x3d\xb4\x41\x6b\x68\xb2\x99\xfb\xfb\xf1\xf6\xdd\xf5\x87\x8f\xe3\xa7\x14\x74\x80\x33\x59\x3a\xe8\x7c\xfb\xea\xcf\xd9\x56\x88\x60\x77\xf0\xa5\xba\x15\x61\x03\xe1\xd5\x7f\x87\x58\x3c\x83\x34\x4d\x3d\xd7\x5a\x04\xd6\x01\x53\xb3\xcf\x32\x61\xcc\x6a\x5f\x14\x07\xc6\xbd\x69\x33\x10\x5e\x40\x07\x01\x20\x31\xf0\x38\xd7\xd5\xa9\x45\x96\x71\x4d\x7d\x08\xf5\xab\x97\x5f\xc5\x79\x7c\xbd\x34\xfd\xca\x69\x51\xed\x75\x39\xd0\xe8\x3d\xa5\xdf\xed\xa4\x25\xd1\x62\xc3\x7d\xa7\x45\x2e\x33\x5e\x51\xa2\x29\x28\x39\xea\xb0\xb3\x62\xdc\x1d\x14\x8f\xc1\xfe\x43\x53\x02\x86\x4c\xa9\x01\xa2\x20\x0b\x83\xcc\x9b\x7a\x5d\xd0\x93\x00\x5d\x50\x58\x45\x87\x63\x90\xb4\xd2\x7b\xc1\x54\x59\x0c\x05\xb5\xe5\x0a\x5b\x1c\xd7\x02\x18\x04\xe7\x80\x36\xe8\x9f\x37\x40\x74\x29\x0a\x75\x87\xf3\x71\x4a\x53\xb3\x6d\x84\x9d\x93\x7d\xb2\xac\x8c\xf3\xab\x55\x5c\x57\x43\x01\xed\xb6\xaa\x23\xab\xa6\xb6\x13\xa9\x39\x17\x3e\x4b\xfb\x72\x38\xed\x22\x68\xa4\x97\x3e\xc0\x02\x1f\x0f\xeb\xa3\xa3\x60\x4d\x9d\x1a\xa9\xfd\xf4\x62\x31\xb1\x8f\xec\x57\x3b\x69\x01\x12\x3f\x19\x7a\x54\x15\x85\x93\x89\xbc\xea\x8d\xbd\xd8\xc4\xb2\x4b\x8f\x26\xe8\xb4\x8e\xad\x6f\x2c\xa7\xc5\xd1\xe9\xdc\x0a\x5e\x62\xd3\xe1\x11\x92\x7e\x26\xa0\x40\xb8\xf3\x52\x14\x4d\x6c\x59\xff\xde\xa0\x43\x8a\x62\xbc\x9c\x04\x92\xea\xed\x3d\x1e\x7e\x21\x12\xca\x7f\x0f\xc2\xbf\xe7\x10\xf6\x8f\x4b\x61\x82\x8a\x4b\x99\x1e\x0b\x57\x02\xa5\xe2\xa1\x66\xb8\x1d\xbb\x33\xba\x2b\x29\xc1\x35\x2a\xdc\xd8\xe3\x80\xfb\x93\x81\xfd\x1b\x80\xfd\x24\xd2\x8f\x08\xea\x4f\x06\xf4\xa7\xb7\xa6\x61\x1e\x72\x1e\x98\xe1\x03\x21\xfa\x3f\x06\x9a\x7f\x02\x92\x3f\x0d\x22\x98\x11\x51\xfc\x6b\x74\xfe\x94\xe5\x1c\x47\xf0\x8f\x91\xf9\xa9\xbb\xff\x3b\xc4\x67\xf3\xe5\x3f\x86\x69\xb1\x13\x60\x74\x59\xfd\xb3\x6c\x5c\x5a\x1a\x48\x93\x04\x05\xa8\x27\xf7\xae\x0e\xad\x71\x60\x79\x1b\x75\x47\xbb\x5d\x1b\x4b\xd3\xd4\xbd\x47\xec\x22\xff\x06\x0c\xc4\xa2\x38\x4c\x2d\x9f\xf8\x0c\x07\x97\x92\xe5\x88\x03\xcd\x00\x44\x24\xdd\xcb\x1c\x72\x39\x03\x78\xd4\xf5\xdb\x37\x97\xe1\xca\xdd\xdd\xdd\xcd\xf5\x2a\x9b\x89\x5c\x56\x4a\xc3\xb5\xd3\xab\xcc\xdf\xba\xb9\xbd\x82\xf1\xd5\x9b\xd3\x20\xa0\xb4\x58\x63\xa6\x49\xdc\x97\x9f\xd7\xeb\x8f\x5b\xe2\xdc\xe0\xb0\x7e\x9c\x02\x56\xcb\xd8\x86\x97\x79\xe1\x92\x59\xd8\x62\xf2\x41\x54\xb3\x37\x4a\x7d\x92\x62\x31\x21\x35\x6c\x48\x6e\xd6\x90\x88\x0d\xf7\xa0\x4d\x1a\x92\x3c\xe0\xd4\x50\x57\xa8\xdf\xf9\xf6\x33\x27\x48\xbc\xce\xc8\x58\xad\x95\x38\xf1\xd9\xf0\xb2\x11\x0f\x7d\x0b\xef\xc8\xe1\xc6\x1c\xd7\xf1\x9c\xc1\x44\x9f\x53\x2f\x7d\x1b\x6c\xf8\xec\x5a\xac\xf7\x05\xd7\xdf\x7e\xb6\xb7\xcb\x2a\x79\xcf\xe1\x6b\xb2\x24\x22\x40\x1e\xfd\x9e\x45\x9a\x04\x2c\x87\xb5\x2a\x5d\xe2\x6c\x94\x3c\x4d\xe4\x28\xad\x10\x5b\xc6\xcb\x90\xee\xfe\xfe\xa7\x0f\xef\xfe\x9f\x29\x7b\xff\xe6\xfa\x5b\x86\x90\xc9\x24\x92\x58\xd1\x91\x4b\x6e\x55\x1a\x63\xd7\x57\xe3\x2b\x30\x11\xde\xc1\xcc\xd9\x7b\x7a\xa8\x51\x0b\x9e\x77\x84\xd4\x9e\x99\x96\x77\x11\x92\x9e\x9d\xcf\x82\x7c\x0a\xea\xd4\x7b\x37\x65\xd2\x45\xa6\x86\xad\x66\xe4\x73\x3e\x3b\xde\xe9\x87\xbe\xa3\xe4\x06\x2a\x69\xcd\x53\xa8\xe0\xbe\x69\x8d\x53\xd2\x9b\xa6\x24\xf2\xca\x84\xa5\xa3\x86\xf7\x48\x00\x7e\xb4\x06\x29\xe4\x00\x20\xb9\x31\x0a\xb5\x29\xca\xa9\x0d\x51\x08\x2f\x7f\x5a\x23\x94\xad\xa8\x36\x6a\x64\xed\x5b\x01\x39\xf8\x45\xdb\x7a\x45\x3a\xde\x6a\xc5\xa2\xfc\x91\x5d\x68\x04\x03\xac\x8e\x04\x96\x57\x3b\x80\xe6\x5d\x13\x51\x51\xf6\x08\x5d\x1f\x0e\xa8\x6d\x55\x9c\xdc\x29\x5d\x49\x28\x19\xe6\xbf\xf9\x76\xb8\x63\xd6\x8c\x7d\xf7\xed\xd5\x37\x23\x5f\x79\xff\xd3\x48\xdf\xad\x19\x7b\xff\xdb\xb1\x6f\x7c\xf3\xed\xf7\xdf\x7e\xfc\x76\xe4\x4b\x6f\x7e\xfa\xf1\xc7\x6f\xdf\x8c\x91\xfa\xe9\xfd\xc7\x77\x3f\xfd\xf8\x61\xe4\x5b\x1f\xaf\xaf\xde\x8c\x3d\xef\xfd\xd5\xc7\x37\xdf\x11\x2e\xcf\x28\xb3\x18\xcf\xb9\x1d\x09\x62\x37\x9f\x47\x0a\x55\xb3\xf1\x70\xb5\x7f\x74\x0c\xc8\xdb\x4c\x6f\x6d\x39\xdb\xea\x48\xd6\x78\x9a\x11\x74\x92\xf1\xa0\xae\xbe\x2d\x48\x23\x5b\xcd\xc7\xd0\x12\xf2\x29\x5d\xe7\x8e\xc9\xf9\x24\xe0\xf1\xb9\x06\x13\x23\xc2\x83\xee\xd5\xa0\x69\xac\x41\x5f\x25\xef\xc5\xe3\xa8\xac\x21\x9d\x10\xc4\x71\xaf\x9e\x3a\x8d\xe6\x49\xd1\x59\x69\x1a\xeb\xc3\x15\x43\xd3\xb4\xa1\x59\xca\x6a\x9f\xa2\x38\x25\xc8\x7e\xa2\xd2\x14\xce\xc9\xf0\x1d\x64\xdd\xda\x55\xec\x18\x83\x5d\x6e\x9f\x90\x71\x8d\x29\x35\x9d\x91\xbc\x04\x44\x4d\xe4\x0f\x7b\xa1\x0f\xef\xb9\xe6\x63\xbe\xd1\xc6\xeb\xff\xef\xfa\x57\x6d\x71\xfd\x87\x3a\xec\x29\xc6\xeb\x77\x82\x2f\x9a\xee\x6d\x1e\xa3\x18\x7c\xd1\x34\x6f\x33\xcc\x77\xcc\xe7\x5a\x03\xab\x06\xaf\xef\xe3\xba\x9d\xeb\x05\x7e\x4c\xd7\x73\x6b\xaf\xfe\xab\xfb\x9e\x29\x5b\xe5\x26\x0a\x51\xf7\x96\x03\x1a\xd3\xce\x31\x75\x01\xbc\x9b\x96\xa9\xa5\x74\xb2\x74\x4e\xd5\x64\xe7\xf3\xab\xf9\xdf\xce\x5f\x3f\xb8\xfb\x39\x75\x35\xfe\xf2\x7d\xd0\xd1\x71\x4d\x6c\x29\x1b\xb7\x93\xf5\x35\xcc\x31\xb5\xa6\x97\x97\x44\xb2\xed\x09\x6e\x96\x49\x58\xc5\x67\xaf\x77\xca\x88\xe2\xc0\x0a\xb1\xa2\xbd\xfb\xbe\x74\xe8\x02\x53\x66\x64\x99\x09\x96\xcb\x95\xeb\x6a\x90\xf3\x8a\xb3\x5d\xc1\x4b\xcb\x02\xf8\x6d\xf4\x27\x12\xe5\x8c\xef\xf8\x52\x16\x12\x53\x79\xbe\x53\x77\xe2\x16\xc2\xca\xd5\x33\xc3\x5e\x68\x91\xa9\xed\x16\x6c\x96\x17\xf4\x0c\xed\xb6\x0f\xca\x25\x72\xb5\x53\xe7\xc4\x48\x52\x47\x3c\x1a\xae\x3d\xb7\x33\xf8\x1f\xf5\xeb\x7b\xcf\x0f\xad\x0b\x89\xac\xa6\xe0\x57\x87\x7e\x6d\xd1\xe6\x88\xcf\x3b\x91\x39\x9f\x3e\x7a\xbe\x0a\xc5\x69\x5e\xf2\x25\xe4\x6e\xb9\xa4\xad\x4a\x7c\xae\x0c\x53\xfb\xca\x1e\x7d\x3f\x73\xd7\x07\x11\x52\xec\x49\x24\x7f\x6b\x1c\xee\x83\x2b\x92\x70\xfc\xba\xd2\x7c\x05\x11\x02\x9f\x48\xe3\xcf\x28\x89\x68\x74\xbe\x41\x6c\xad\xf7\x5c\x83\x3f\x6e\x6b\x44\x71\x6b\x65\xab\xdb\xa3\x9d\xaa\x44\x59\x51\x7d\xe9\xfe\xdc\x65\xc2\x74\xa7\xcc\x9b\xff\x12\x2e\xf5\xff\x56\x5e\xf0\x96\x1c\x4f\xad\xf9\x8c\xaa\x3e\x9d\xdb\x9c\x68\x60\x90\xbd\xeb\xc0\xcc\x8e\x5d\xe2\x2d\x2d\xe7\x23\x25\xc5\x9e\x39\x3f\x4c\x87\xeb\x7c\xc8\x2d\x4e\xa2\x7b\xec\x3a\x27\xba\xc5\x69\xd4\xc1\x75\x4e\x75\x8b\x53\x43\xec\xc1\x75\xfe\xe4\x16\xef\x19\x54\xb7\x78\x74\x8b\xa8\x8b\x7f\xb2\x6f\x9c\x58\xba\xf6\xe4\x1b\xff\xff\xa2\x6f\x3c\xa9\x2c\xe7\xef\x7a\xbe\x31\xfc\xee\x83\x8f\x18\x5c\xdf\x3e\xba\x3d\x14\xbb\xc0\x59\x1a\x17\x0e\xe1\x1b\x1b\xd9\x95\xd9\x5e\x83\x4e\x6b\x7f\x1b\xae\xdf\xf5\xb1\x29\xdd\x6f\x6e\x62\x82\x69\xc7\xee\xb5\x71\x11\xe0\x6b\xd8\x12\x0c\xf3\x66\x57\x3e\x39\x35\x34\xda\x62\x67\x7b\xb3\xe7\x45\x71\xf0\x7a\x9b\xe9\x92\x6b\x90\x08\xcc\xb5\x60\xdc\x18\x95\x49\xb0\x14\x42\x52\x3b\xa8\x6b\x53\x8f\xae\xe6\x53\x5a\x3d\xde\x6b\x4f\xd1\x1f\xfc\x5a\x0b\xab\x0f\x40\xcd\x89\xe0\xd9\xc6\x4d\xce\x21\x0f\x47\xb1\x0b\x97\x79\xeb\xd2\x4b\xf1\x5b\x5d\x9e\x90\xaa\xd9\x98\x19\xe1\x51\x78\xc9\xd7\x3e\xb1\x15\x5f\x1e\xac\x60\x9e\xe7\x60\x60\x81\x05\xe8\x4a\x38\x3b\x48\xc2\xba\x85\x36\x6b\x11\x71\x34\x20\x8d\x70\xa4\xdd\x44\xcb\xdc\x2b\xb2\xfb\x5d\xce\x3b\xdf\x1c\x2a\x2a\xe0\xa9\xdc\x30\xbe\xb3\xdb\xac\xed\x8a\x46\xcd\xdc\x80\x96\xd2\xcc\x95\x28\xda\x1d\xf4\xc5\xed\x5d\x9c\xb6\x51\xc7\x1a\x36\x38\xe8\xa9\xf0\xf1\x31\xe6\x14\x74\xbf\x2e\xc7\x2b\x3e\x95\x73\x95\x23\x8c\x96\x2b\x43\x3d\x02\x6e\xb2\xeb\x14\x61\xd6\x39\x15\xc4\xfd\xb6\x83\xaa\xa5\x66\x15\x14\x30\xc8\x77\x6a\xb7\x2f\xec\x12\xc4\x7d\xcd\x43\xdd\xa8\x3f\x98\xe7\xed\xb3\xdb\xbd\xb8\x07\x38\xa8\x0e\x99\x4a\x2e\x0b\xe8\xb7\x07\x4a\xe1\x95\x87\x7c\xb6\xf3\x7a\xfd\x2a\x10\x0e\xb1\xb1\x28\x9b\xa8\x83\xb6\xc7\xf5\xc3\x57\xbd\x72\x20\xc7\x78\x42\xb6\x82\x97\xf1\x41\xb0\x3a\x1a\xae\x93\x28\x43\xe2\x78\xd7\x7c\x15\xe8\x59\xbe\x77\xfc\xb1\xba\xd2\xeb\x40\x6b\xdc\x75\x58\x37\xbc\xef\x81\xe3\x78\x97\x59\xf3\x4e\xf2\x10\x0e\xec\xa9\x45\x8d\xee\x24\x2f\xe3\xfb\x8e\xe4\xbb\xce\xdf\x98\x63\x2c\xaa\xfa\xea\x61\xe7\x4d\xc6\xf5\xa6\xce\xd1\xee\x7b\x8d\x7a\xa5\x7b\x5f\xa4\xf5\x32\x55\xdc\xa2\x3f\xc6\x7a\x70\x84\x9e\x19\xc6\x6f\xb9\x2c\xd0\x51\xd0\x2f\x51\x2d\x37\x2d\x8c\x62\x66\xef\xfa\xca\x37\x48\x3f\x33\x4c\xdd\x95\x75\x5a\x7f\x9d\x6c\x3e\x00\xdb\x69\x4f\x90\x28\x85\x76\x3f\x0b\x75\x1b\xbe\x0e\xe3\x99\x71\x8b\x7f\x2d\x56\x71\xf8\xab\x5f\xa9\xf4\xfd\xf1\x83\x31\x8e\xc5\x66\xce\x77\xe0\x0a\x69\xc2\xcd\x86\x96\xca\x57\x3f\x7e\x33\xec\xfd\xa8\xdf\x30\xe2\x82\xf6\x9c\x9b\xbd\xb5\xd3\x25\xd4\x3c\x40\xb9\x04\x78\x83\x4a\x7c\x66\xf8\x55\x2f\xdd\x88\x1a\x38\xd3\x00\x70\x10\x9a\xd6\x5f\x41\xe7\x54\xc0\xd4\xec\x6e\x8f\xdf\xef\x0d\xaf\x14\x93\xa5\x2b\x62\xb8\xdb\x80\xeb\xbc\x75\x3b\xf1\x66\xba\x27\x20\xc8\xc9\xbf\x83\x53\xa4\x97\xa6\x43\xc3\x70\x6f\x84\x02\xef\x6e\x73\x70\xac\x05\x59\x57\x87\x3b\x30\x7e\x8f\xfe\x53\xb5\x62\xbc\x62\xd6\x44\xaa\xe2\x7a\x56\xbf\xfd\x58\xaa\x12\xa7\x51\x22\xff\x1e\xaa\x6c\x0b\x87\x7d\x51\xb2\x8f\x50\xef\x0f\x02\xbc\xae\x3d\x83\x4c\x54\x63\x97\x47\x8b\xa3\x15\x1f\xda\x2e\xb7\x13\x5b\x7e\xf0\xb2\xc0\xee\x59\x8e\x29\xae\x05\xcf\x3e\x01\xf1\x7a\x5b\x6f\xa5\x91\x78\xab\x06\x36\xcc\x1e\x16\x80\xd9\xcc\x71\x4e\x65\x54\x70\x85\x6b\x5b\x43\x9c\x70\xa8\x7f\x83\x43\x3e\xe4\x02\xf4\xea\x44\x4c\x44\x3a\x2e\x08\xe0\x14\x81\x03\x44\x93\xcd\xd5\x40\xb5\x14\x44\x89\xf1\x16\x1d\x91\x95\xcd\xbe\xc6\x4d\xb2\xbd\x14\xed\xe3\x80\x2c\xb8\x35\xf1\xfe\xb0\x4a\x3d\x4c\x8d\x4f\x8d\xc1\x10\x6a\x48\x5c\xa3\x60\x10\xae\xf6\xa0\x71\x64\x90\x03\x25\x72\xac\x5b\x6b\x0d\x3a\xc1\x75\x68\x62\x3b\x9b\xcd\x30\xcc\x80\x5d\xee\x06\x28\xc2\x72\x79\x5c\x5a\xa5\x99\x6b\x9d\x09\xd0\x16\x06\xe4\x8e\xd5\xc0\x19\xf7\x2e\x54\x51\x8c\x36\xdd\x9b\x3b\xe6\x59\xf3\xdc\x39\x6b\x15\xf4\xd8\x2d\x7f\xab\x94\x93\x90\x38\xc9\xff\x18\x20\xb9\xb0\xff\x73\x7e\xce\xae\xbd\x5a\x80\x52\x48\x2d\x8d\xd0\xb7\xb5\x86\xc3\xd9\x4a\x29\xcb\x16\xe3\x25\x1a\xb2\x88\x3d\xdd\x7f\x02\x84\x8f\x8e\x89\xc3\x4c\xb9\x86\xea\x9c\x2b\x14\x4a\x85\x58\x4c\x86\x82\x7f\x8b\xc9\x7b\xad\xd6\x1a\xd3\x86\x17\x93\xa9\x4b\x0b\xff\x46\xac\x35\x47\x58\x62\xf7\xd0\xbf\xd9\x59\x93\xfd\x07\xa1\xd7\xe2\x9f\xc4\xe1\x1f\x46\x80\x1d\x16\x8d\x5f\x7d\xa8\x34\xaf\xc4\xfa\xf0\x0f\x5b\xfb\xf3\x40\xd1\xca\xaf\x8f\x87\x9d\xf8\x87\x2d\xdf\xb9\x0f\x07\x48\xc2\xd7\x7f\xe0\x3b\xff\x74\xf8\x30\x12\xf9\xbf\xff\x79\x2b\x2a\x7e\x7b\x31\xaf\x4f\xef\xcd\xbf\x1b\x55\x5e\x2e\x26\xf5\x12\x4d\xd5\xd6\xde\x84\x5d\x75\x18\x60\x55\x90\xda\x52\xcf\xfa\x72\x31\x81\x79\x2f\x26\xac\xb1\x06\x97\x8b\x89\x9d\x87\xfd\x58\xab\x4a\x2d\xf7\xab\xcb\xc5\x64\x79\xa8\x84\x99\x5e\x4c\xb5\xd8\x4d\xed\xa5\xfe\x87\xfa\xd9\x8b\xc9\x10\xaa\xd0\xa2\xf4\xeb\x82\xce\x33\x44\x08\x67\x7f\xba\x6f\x3d\x54\xc1\x4d\xf5\x51\x73\x28\x1a\x50\xe5\x47\x39\x16\x5f\x6c\x70\x82\xe3\x1f\x7b\x27\x90\xfd\x0b\x54\xa6\x7a\x86\x85\x2f\x39\xe6\xcc\x08\xb4\x7c\x35\xb6\xe5\x25\x4e\xeb\x01\xcd\x51\x61\xb5\x3a\xb2\x03\x22\xd4\x70\x30\x80\xf6\x65\x2e\x74\x71\x70\x51\x06\xcf\xc2\x36\xbc\x5c\x8b\x7c\xee\x92\x77\xac\xb8\x18\x8b\x82\x58\xbe\x0a\xe0\x38\x4e\x23\xa9\x81\x91\xe1\x8d\xc3\xf3\x02\x92\xbb\x7f\xc8\x08\x5d\xab\x03\x82\xa4\xb4\xf7\x72\xd8\xf7\xe5\x5b\xd2\x58\x63\x70\x66\x9f\x4a\x70\xe9\x8c\xba\xb0\xb6\xc2\x18\xbe\x4e\x39\x00\xee\x17\xe8\x0b\xd8\xec\xb7\xbc\x04\x4f\xac\x9d\x7f\xfd\x37\x54\x98\xc6\xbd\x67\x5e\x86\xf0\xa5\x72\x98\x58\xf5\x79\x08\xf8\x66\x07\x1f\x67\x06\x23\x09\x5f\x69\x78\xa9\x22\x07\xe1\xeb\x57\x7f\xfb\x75\x9f\xeb\x27\x69\xa5\x90\x57\x8b\x1c\x4b\x43\x86\xc1\x3b\x8e\x16\xed\xf8\xc7\xb5\x85\x88\xb7\x67\x6e\x59\x55\xce\x2b\x3e\x5f\x87\xef\x8c\x5d\x9d\x48\xe7\x70\x27\xfb\xce\x2a\xd1\xa2\x72\x91\xae\xfd\xce\xae\xe2\x5b\x40\x1d\x37\x15\x25\x2b\x5e\xae\x3a\x27\x02\x75\xc7\x28\x93\x8a\x03\xbb\x78\x55\x43\x98\x1d\x8b\x9c\xdf\x7f\xfe\x79\x7e\xfc\xba\xe3\xd7\xe0\xef\xa7\xad\x77\x91\x10\x0f\xb4\x62\x31\xe7\xce\x3a\x6b\x59\x61\x23\x44\x3b\x14\x0d\x11\x56\x82\x76\xd7\x64\x59\x7d\x3d\xec\x5f\x0e\xbd\x9c\x5e\x12\x0e\xd9\x78\xef\x0a\x0d\x90\x54\x09\x27\x0b\x7f\x50\x6b\x65\xdc\x0a\x81\xb5\xe6\xdb\x2d\xaf\x64\x56\x77\xab\x18\x4b\x20\xaa\xaf\xac\xcb\xe3\x05\xb2\xde\x71\x12\x76\xe5\x99\x71\x7c\xbe\xbe\xa6\x23\x84\xdf\x6b\x95\xef\x33\xab\x6e\xab\x15\x8b\x41\xea\xdd\x36\xd7\x98\x6c\x0e\x3f\xc8\x87\x94\x47\xe8\xfa\xc4\xa6\x32\xf7\xa9\x4a\xde\xcf\xe3\x93\x31\xbd\x5d\x15\x6c\x36\x22\xc5\x66\xe5\x1b\x87\x80\x2f\x2f\x2b\x21\x72\x04\x7b\xfb\x18\x22\x1e\x54\x71\xc4\xd9\x1b\xbe\x15\xc5\x1b\x6e\x84\xe7\x5f\xc8\xdc\x50\x54\x44\xe6\x0f\xf0\x38\x32\x73\x1b\x8d\x7e\x90\xe3\x1e\x47\x95\x53\x3f\x9f\xd5\x25\x54\xff\x36\xbd\xfc\xf9\x45\xf4\x9f\x3f\x3f\xff\xf5\x70\x01\x15\x91\xa5\x52\x00\xc9\x1b\x87\xbd\xe9\xb5\x09\x67\x68\xea\x0d\xdd\x8f\x7a\x2f\xa6\x88\xf2\x36\xc6\xe9\x1c\xd6\xdd\xf0\x52\x53\x72\xcb\x27\xf6\xa1\xc3\xc1\xc1\x19\x9b\xc0\x9c\xc6\xbe\x45\xc1\xdf\x23\x2e\x6d\x62\x6b\x1b\x0f\xb0\x18\x71\xdf\x32\x3a\xb3\x20\x41\xac\x6d\x32\x77\x26\xd0\x3c\x53\xdb\xf3\xf0\xf7\x31\x16\x60\xad\xb9\x1f\x78\x79\x60\xb5\x98\x40\xc3\xa4\x7d\xe3\xc0\x08\x77\x20\x2e\xa3\x71\x37\x1f\x76\x28\xe4\x27\xc1\x82\x6d\x83\xa2\x69\x29\x1c\xba\xa1\x5e\xca\x4a\x73\x7d\x88\x1c\x68\x63\x52\x83\x97\x0e\xfd\x7b\xb5\x2f\xd8\x99\x11\x82\xcd\x4b\x95\x8b\x63\x49\xf7\x7c\xea\xf0\x42\x86\xdd\x7c\x38\x20\xc2\x9c\xa9\x72\x55\xc8\xcc\x97\xb1\x2a\x5d\xf1\xd2\x75\x84\xd7\x62\x2d\x3e\x33\x59\x05\x30\xa6\x51\x95\xf4\x2c\x2f\xcd\xc5\xc5\xab\xd7\x1f\xf6\xcb\x5c\x6d\xb9\x2c\xdf\x6e\xab\xf3\xe7\xbf\x3e\xfb\xc3\x9e\x17\xe0\xe0\xff\x91\x6f\xc5\xdb\xed\x48\xed\x5e\xac\x2a\x8d\x44\x09\x6b\x1e\x71\x76\x4f\xa0\x6f\x3b\xcd\x88\xbf\xfc\xfc\xfb\x59\xcd\x5c\xe6\x3f\xbf\x78\xfe\xeb\xe8\x6f\xcf\x1f\x80\xd5\x50\x00\x00\x8f\x0d\x9b\x81\x2f\x3b\x45\x77\xe0\x1b\x28\x40\x07\xbe\x80\xc7\x69\xe0\x0b\x0f\x87\x48\xd8\xa7\xff\x6e\x65\xe9\xe3\x97\x27\x05\x47\xd9\x49\x21\xe1\xc1\x37\x4b\x0d\x03\xd7\x7e\xb1\x1f\x07\xf2\x64\x8f\x7c\x59\xd1\x6f\xd0\x90\xc1\x1b\x74\xee\x90\x55\x34\xaa\x41\xe0\x47\x44\xd7\x6f\xff\x46\xb5\x33\x6c\xdb\x51\xc3\x3b\x8d\x11\x02\x70\x66\xa1\x53\x1e\x44\x7f\xdd\x38\xaa\x9f\x76\x08\x8c\x36\x5f\xd3\xa9\x0d\xaa\xf4\x9e\xd9\x37\x05\x37\xe8\xec\xff\x16\xf9\xf3\x00\xae\xe0\xc4\xb3\xf0\x52\x54\xe7\x2e\x2c\x38\xab\xe9\x3b\xb0\xa7\x8f\x80\x66\x65\x95\xe0\x81\xc8\x1b\x8e\x50\xf8\xf2\xcd\x4f\x3f\x5c\xbd\xfb\x11\x81\xdf\xd8\xfb\xab\x8f\xdf\x4d\x9d\x47\xd8\xfd\xc1\x6a\x63\xf6\x63\xe0\xf7\xb7\xbc\x90\xfd\x9a\xd3\x3f\x85\x43\x80\x7e\x50\x76\xe6\xf3\x84\xeb\xe3\x31\x97\xea\x3c\x57\x99\x39\xcf\x54\x69\x2d\x68\x73\xae\x6e\x85\xbe\x95\xe2\xee\xfc\x4e\xe9\x4f\xb2\x5c\xcf\xec\xfa\xcd\xf0\x92\x98\x73\x20\x74\xfe\x4b\xf8\xbf\x81\x24\xe2\x45\xc9\xea\x03\xe2\x01\xe1\x7c\x54\x31\xaa\xf4\x01\x93\xff\x4e\x4b\x50\x99\xdd\xce\xf6\x12\x8d\x29\xba\xa8\x6e\xdc\x66\xc6\xe7\xea\x56\xca\xab\x38\xfe\x89\x23\x48\x86\xd8\x83\xac\x75\xa0\xb1\x77\x9c\xe0\x25\x98\x80\xc1\x37\x81\xd1\xcc\x01\x14\xab\x42\x95\x6b\xa1\x59\x29\x32\xcb\xdd\x74\x57\x0c\x11\x07\xa9\x99\x04\x41\xf5\x7c\xb0\xc6\x11\x8b\xf3\x5a\x60\x2c\xce\x17\xb3\xf9\xbf\xfd\xdf\xbf\xfe\x1f\x7f\xf5\x3f\x9f\x9d\x3d\x7f\xf1\x37\xd3\xff\xf5\x0f\x97\xfd\x05\xff\xa3\xe2\x63\xe7\xc3\x65\x24\xde\x52\x07\xd7\xa2\xeb\xed\xe1\x86\xeb\x3f\xba\x7c\x4f\x6b\x0d\x0d\x87\x31\xe0\xbc\x1d\x87\x64\xd1\xe1\xdc\x17\xd2\xec\x3b\x86\x14\xef\xe0\x5a\xab\xfd\x6e\x48\x71\x0c\xa9\x9b\x8e\x75\x58\x36\xe2\xae\xdb\xfc\xd3\xdf\xd9\x4b\x39\xf8\xe3\x98\x0f\xff\xc6\x3e\xcb\x7b\x0f\xe1\xc1\x75\x6b\x5f\x4c\xc9\xa6\x27\x60\xbe\x51\x7a\x50\xbd\x26\xf7\x3f\xa9\xcf\xe4\x5f\xfd\xe7\x63\xf6\x33\x21\xe9\x2d\x9f\x64\x39\x98\x58\x16\x36\xc3\xc9\x01\xf2\xd2\xff\x93\x2c\x81\x65\x43\xbc\xf6\x5e\x8b\xce\xce\xdc\xb3\xbb\x73\x5d\x7f\x02\xdb\xdb\x07\x76\xcc\x60\x29\x5d\xb4\x47\x5f\x0f\x6d\x11\xd1\xa8\x6d\x72\x97\xab\xd9\xbf\xb8\x6d\xba\x9a\xfd\x4b\xd8\x29\xf7\xef\x61\x7b\x96\xb4\x55\x63\x65\x3a\xb4\xf2\x9c\x3f\xe3\xc1\x27\xae\x2a\x79\x31\x20\x76\x99\xb6\x22\x18\xee\x8c\x96\x05\x3f\x68\xaf\xcd\xe0\x7a\x40\xc2\xd7\xbe\x3c\xaa\x5c\x6f\x36\xb5\x50\x19\x2f\x1a\x4f\x18\xb6\x31\x7c\x70\xf6\xb8\xee\xf4\xcf\x76\x9e\x7b\xd9\xce\xbd\x4f\xf2\xd8\x99\x6b\xa5\x06\x2a\x5d\x85\x2d\x43\x51\x80\x0d\xfc\x6b\xd1\xc5\x2a\xae\xd7\xa2\x1a\xc9\xee\x7e\x57\x79\xd3\x5b\x96\x95\xd0\x3b\x2d\x30\xfb\xda\x55\xe7\x14\x87\x06\x0a\xaf\xf7\x58\x8c\x18\xac\x8d\x2c\xaf\x1a\xca\x33\xca\xe0\xf3\x7f\x44\x33\xc0\x67\x64\x8c\x1c\x07\xfb\xbe\xf8\x4e\x50\x08\xe9\xb3\x6e\x8c\xfb\x97\xc7\x7a\x8d\xeb\x23\x87\x27\x8a\x0b\xc6\x2b\x9f\x10\xb4\xab\x97\xd0\xb3\x68\x58\xca\x33\x48\x0b\xf4\x75\x93\x23\x2e\x02\xf8\xc5\xf3\x39\x7b\x57\x3d\xc3\xc4\x80\xa8\x3e\x09\x4b\x1f\x2b\x76\x63\xf7\xef\x86\xed\xcb\x02\xb2\x05\x46\x7c\xa4\xb5\xac\x0f\x45\x40\x26\x2a\x01\x85\xbc\x05\xdc\x72\x4c\x8c\xdc\xed\x8a\xc3\x18\x3c\x0a\xaf\x9d\xc2\xf0\xd2\xdc\x30\xb5\xdb\x29\x84\x0b\x75\xe9\xa6\x76\x71\xcf\xcc\x73\x76\xb7\x51\x46\xc0\xd7\xce\x3a\x93\x4b\xeb\xe1\xa2\x46\x21\xd2\x07\xdb\xbe\x54\xd5\x86\xc1\x81\xb5\xcb\xf8\x01\xab\x0a\x83\xca\x5c\xb3\x8c\x51\x66\x00\x2c\xdb\xd2\x80\x19\x3b\xfe\x84\xdb\x22\xf2\x3a\x09\xab\xae\x97\x1d\xa4\x08\xd3\xaa\x57\x11\x9d\x62\x98\xba\xd5\x4a\x82\xfc\xe1\xea\xff\xb0\x6c\xa3\xec\x22\x8c\xac\xaa\x3f\x42\x18\x39\x6e\xa7\x3b\x1e\xa7\x57\xba\xef\x8f\x45\xec\x90\x1c\xba\xec\xbb\x52\x80\xc1\x5a\xb2\xb6\x87\x2e\x0e\xa1\x0c\x63\x90\xe2\x46\xdd\x9d\xcb\x15\xf3\x6c\x24\xba\xfb\x01\x47\x15\x6e\x2b\x16\x01\x42\x0c\x01\xf4\xdc\xe1\x4d\xe2\x3e\x55\x12\x3a\x1a\x81\xb5\x1d\x1c\xfa\x35\x12\xaf\x3d\x6b\xd6\xe8\xc1\xca\xb6\xe1\xa3\xdf\x66\x17\x18\xb5\x35\x4c\x42\x9e\x6c\x25\x79\x51\x1c\xe6\xcd\x2c\x91\x71\xa5\x8c\x45\xac\x23\x83\x40\xaa\xe5\xcd\x59\xe5\x50\xd3\x5d\x72\x5d\x16\xde\xc6\xc9\xaf\xe1\xb2\x8a\xe5\xc1\xdd\x41\xcb\x39\xa6\xb5\x94\x9b\x32\xa5\x23\x8c\xee\x77\x2b\x76\x61\x97\xf3\x55\xe2\x3c\xf1\xc5\xe3\xe5\x0d\xd0\x76\x3e\x53\xd8\xf2\x87\x91\xac\x3a\xd6\xe8\x52\xdf\x91\xeb\xd6\x89\x97\x6c\x67\x3d\xcc\xa0\x54\xc8\x53\x24\xcc\xd8\x0b\xa8\x7b\x4c\x33\x17\x0e\xc9\x39\x2c\x82\x4f\x96\x1b\xa4\xf9\x70\xed\x1d\xa3\x48\xe5\xeb\x21\x74\x40\x97\xaf\x7c\xc9\xbe\xfe\xd5\xaf\x5e\xff\x6a\x58\x1b\xc1\x2f\x8e\x6b\x81\x63\xe1\x4c\x53\x73\x58\xba\x42\x11\xb3\xe5\x96\x86\xcc\x3d\x45\x87\x2f\x3e\xba\x6d\x28\xa4\x23\x05\xe0\x5d\xd9\xc2\x69\x0f\xac\x6b\x1a\xcb\x83\x41\xc2\x4d\x2e\xe5\x78\x47\x4d\xd2\x25\x1b\xba\x63\x70\xc9\xbe\x77\xe7\x70\x90\xe6\x8f\x70\x25\x5b\x42\xea\x2c\x3e\x04\xcf\xbb\x64\xd6\xb0\x08\x68\x76\x72\xa0\xc9\xac\x61\xa1\x5a\xe3\x3f\x24\xc9\xac\x41\xa2\x41\x9e\x05\x99\x85\x17\x35\x30\x11\xd0\xda\x51\xf0\xd4\x02\x6c\x58\x95\x0c\x59\x3d\x01\x26\x75\x8a\x1e\xb0\x4e\xf9\x04\x05\xa4\xa7\xed\x7e\xad\x52\x46\x26\x07\x3b\x8b\x33\x55\x9e\x4f\xc7\x35\x35\xa8\x1a\x88\x7a\x81\x63\x5d\x87\xc4\xe2\x03\x77\x74\x8f\x25\xe1\xf0\xee\xa3\x94\xa4\x4a\xc2\x28\x6b\x78\x58\x01\x28\x45\xb8\x84\xb2\x5b\x91\xae\x25\x63\x53\x1e\x0e\xd2\x3d\xe6\xda\x14\x79\x38\xcc\x00\x50\x56\x26\xca\xc3\x41\x92\xaf\x52\xa4\x4b\x43\x1e\x8e\x2b\xea\xd3\x53\xe4\xe1\xd8\x35\xf8\x4b\x94\x87\x5f\xda\xa3\xf1\x45\xda\x17\x13\x2c\xef\xb1\x20\xe5\x60\x11\xe5\x48\x3c\x70\x88\xf6\xac\x15\x5d\xea\xfc\x4a\x70\x83\x77\xfc\x95\x58\x23\xd9\xa1\x9e\xf4\x85\x17\xbb\xa7\xeb\x67\xd1\xe4\xa5\x9d\x4f\x3f\x26\x30\x6b\x7a\xdb\x8f\x7e\x85\x09\x6b\x97\x6c\xc5\x0b\x07\xcb\x6a\x2a\xa5\xf9\x5a\x34\x3e\xda\x2f\x83\x08\xf2\xa4\x7d\x6f\xc1\xff\xf8\xd3\x2f\xec\x53\x78\xe8\x36\xf9\x5e\x83\xa0\x78\xa3\x8a\xfd\xd6\xd7\x2b\xcd\xd8\xbf\x1b\x55\x42\x7b\x66\x36\xb7\x13\x9a\x7b\x06\xe4\x5f\x0a\x9b\x74\x7d\xd7\xfa\xf4\xe8\xf8\x34\x08\x85\x8c\x3d\xdf\x20\xe6\xa3\xef\x0f\xd3\x20\x7a\x15\x02\xd6\x48\x2e\x54\x15\xe2\x9f\x6f\x2f\x96\xa2\xe2\x78\x53\xb0\x81\xbc\x7f\x45\xb5\x13\xe5\xd5\xfb\x77\xff\xfc\xfa\x43\xe3\xe3\x0e\xb8\x25\xe4\x0b\x0e\xaa\xce\x30\xce\xa0\x62\x48\xb9\x62\x99\x56\x2b\x37\x08\x83\xfa\x42\x8d\x68\x4f\x51\x66\x3b\x9c\x95\x43\x0d\xed\x10\x5a\x83\x2c\x0f\x81\x6f\x4f\x21\x99\x7f\x1a\x20\xad\x95\x8e\xcb\xcf\x63\xa6\xf3\x16\xda\xe0\x9b\x28\xbf\x23\x8f\xbb\x6b\xd5\xfb\x16\x83\x66\x9b\x4a\xec\xcc\x9c\xfd\x23\xcf\x3e\x89\x32\x0f\xf0\x41\x11\x59\x8c\x70\x06\x38\xa8\x30\xc7\xba\x1d\x17\xbc\x7b\xc4\xaa\xbb\xc3\x30\x7c\x27\xff\xd9\xf5\xe3\x68\x1c\xef\xc6\x12\x3f\xb3\xbb\x80\xdf\x6a\x14\x02\xbb\xfe\x19\x56\x4c\x60\xe7\x7f\x5f\x55\x11\x92\x4c\xbb\x92\x30\xad\x46\x5d\xba\x3b\x30\x67\x1f\xec\x05\xa8\xc3\x93\x99\x2a\x6f\x85\x46\x9f\xd1\xba\x94\x7f\x0c\xb4\x6b\x27\x2a\xaf\x8e\x91\x3e\xe1\xc8\xdb\x45\x04\x8d\x10\x33\xf0\xb6\xfc\xe0\x4a\xa2\xd8\xbe\x8c\xe8\x79\xa5\xf1\x07\xa5\x05\x93\xe5\x4a\xd5\xb8\xe8\x6b\x59\xb9\x68\xd2\x79\xa6\xb6\xdb\x7d\x29\xab\xc3\x39\xb0\x29\xb9\xdc\x57\x4a\x9b\xf3\x5c\xdc\x8a\xe2\xdc\xc8\xf5\x8c\xeb\x6c\x23\x2b\x91\x55\x7b\x2d\xce\xf9\x4e\xce\x60\xea\x25\xd6\x3f\x6c\xf3\x5f\x86\x1b\xfb\xac\x83\x6f\x1c\x71\xe4\xe3\x90\x4b\x73\x07\x7c\xe4\x84\xfb\x34\x01\xcc\x04\x0c\x0b\xed\x13\x28\xaf\xbf\xfd\xf0\xb1\xd6\x89\x3a\x34\x40\x5c\xf7\x28\x0d\xb8\xde\x02\xbb\x60\xb2\x5c\x09\x9f\xcc\xe8\x45\xa9\x28\xf3\x9d\x92\xa5\x4b\xfa\x2d\xe4\xb1\x6f\xc5\xec\x97\x5b\x59\x99\xb8\x8b\xce\x9c\xbd\x09\x05\xbb\x58\x49\x9c\x83\x1d\x54\x67\x6f\x3d\xf6\x06\x80\xbb\x68\x66\x17\x96\xb6\x05\x9e\x9d\x5d\x8e\xf3\x79\xb4\x72\x86\xaa\xe6\x77\x22\x6b\x5c\x95\x5c\x18\x09\xfa\xd4\xc9\x35\xf3\x81\x63\x8f\x55\xcd\x07\x26\x1e\x26\xc0\xc1\xe7\xaa\x56\x81\x46\xa3\x75\x5f\x9f\xa7\x30\xc6\x80\x42\xdc\x69\x55\x37\xa1\xa9\x71\xf4\x78\xc4\x81\x2b\xe5\xb9\x58\x8f\x63\x2b\xb4\xd4\xfb\xd8\xee\x50\x7e\xfd\xf6\x0d\xbb\xb8\x78\xf5\x1a\x27\xed\x2a\x25\xad\xed\x1d\xe6\xdc\x53\x27\xfb\x8a\x95\x0a\xca\x18\x98\xf8\x6c\x15\xcc\xd0\x9b\xf1\x62\xce\xde\xbd\x37\x2e\xfb\xa0\x62\xdc\x1a\xca\xf6\x10\xbe\x9a\xb3\xab\x9a\xea\xb6\xd3\x03\xb5\x14\xa1\xa7\xa3\x0f\xa3\x87\x66\x75\xd0\x6c\x9c\x9d\xdd\xbc\x98\xdf\x3c\xc7\x24\xba\xf0\x27\xa8\x72\x59\x8a\x2e\x24\x26\xef\x99\x16\x1c\x5a\x9e\xc9\xca\x88\x62\x15\xac\x78\x28\xc5\x87\x9f\xd6\x00\x67\x61\x8a\xd2\x0c\xfa\xf3\x97\x07\x34\x8b\x2d\x21\x6f\xf5\x03\x03\x0c\xfb\x02\x3a\xbe\x16\x35\x78\x5e\x5c\xa8\x09\xac\x13\x6c\xab\x4e\x15\x31\xcc\xc2\xe7\x64\x37\x76\x7b\x29\xe2\xa6\x62\x8d\x29\x34\xac\xb0\x2e\x05\x10\xfc\x15\x57\xf5\x94\xb1\x71\x94\x65\xee\x71\xba\xe7\x8d\x5f\xa3\x68\xc7\xfa\x5a\xa4\x46\x0d\x15\x99\x6f\xfd\x76\x2b\x98\x90\x60\xc5\x37\x00\x72\xa1\x68\x3d\x5c\x29\xb4\xc9\xf8\x6d\xd7\x91\x8d\x7e\x52\xd9\xfd\x8d\x2b\x5c\x3b\x66\xab\x34\xbb\x79\xd1\xf8\xa8\xcb\x04\xe9\x78\xf1\x17\xa4\xb7\x8e\xde\xb1\x6b\x49\xd3\x5e\xdb\xbf\xf5\xe0\xf1\x0a\x87\x05\xad\xf0\x26\x0b\x89\x6f\x70\x78\x9f\xda\xb8\xed\xee\x8b\x1f\x3c\xd5\xac\xfd\xd6\xd3\x8e\x15\x75\xfd\xf0\x57\x4a\xcd\x8f\xfe\xd6\x41\x1c\x3b\xd5\xb3\xba\x13\xfe\x9c\xfd\x84\x0e\x03\xf4\xe5\x6c\xb8\xb5\xc6\x6f\x9a\x6b\x6d\x1f\xd0\x20\x5e\x8a\x6a\x88\xb8\x5d\x53\x47\x7c\x51\xd6\x5a\x73\x8d\x32\xd2\xc7\x3c\x3a\x68\xc6\xec\x04\x7e\xdb\xf2\xf2\x71\x2c\x4f\xff\xec\x1f\xf8\x11\xd6\xdd\xa1\x35\x74\x56\xbb\x3b\xe8\x46\xb8\xb1\xed\x63\x75\x17\x81\xfc\x01\xd7\xe8\x58\xf0\x2e\x92\xbd\x5b\x80\x89\xcf\x76\x41\x1a\x6b\xea\xd9\x98\xe7\x4c\x1d\x34\xbb\x79\x55\xeb\x40\xc6\x77\xd4\x9e\xdd\xe8\x7b\x2d\x5b\x25\x1e\xb0\x0f\xb9\xaa\xf7\xa9\xfb\x80\x06\x4f\x42\x00\x97\x1c\x71\x1c\x49\xcb\x97\x03\x99\x7a\x92\x47\xc7\xd8\x43\xc9\xd4\xd3\x1d\xba\x62\x5d\x4c\xaf\xf3\x48\xb6\xef\x87\xfd\x0c\xb8\x7a\x07\x51\xa7\x7b\xf5\xc1\x7a\x36\xb7\xa7\x67\x33\xba\xe4\xc1\xc0\xf6\xe4\xac\xb4\x2c\xc2\xf7\x38\xf4\x49\xa4\xae\xa5\x25\x76\xb8\xec\x41\xbd\x29\x5b\xcb\xe5\x00\xcd\x3d\xbc\x01\xca\xd9\x26\xd2\x8b\xeb\xfe\xcf\x65\x67\x3f\x13\x5e\xb2\x67\x1e\x0c\xe0\x59\xd4\xcb\xdf\x5d\xc8\xba\xa4\xe3\x06\xbb\xf3\x7b\xb7\x62\x9d\x40\xd7\x2d\x0f\x8f\xb2\xe2\x28\xc9\x19\x34\x0c\x94\xa0\xb9\x79\x0f\x32\x7a\xdd\x42\x62\xbd\xcb\x16\x8e\xe2\x12\x2e\x30\xde\xe9\x9c\xb1\x3b\xf3\x90\x7a\xd6\x7d\x35\xad\x4e\x92\x2e\x5e\xfe\xc0\xba\x56\xa2\xb6\x15\x96\xdd\xd9\xe8\x8b\xc9\x4e\x8b\x4c\x1a\xd1\x53\x99\x8d\x5e\xe1\x28\x7f\x9b\x85\x75\x0b\xe5\xa4\x80\xe9\x87\x75\x6d\xb9\xaa\x68\xbb\xc5\xce\xc4\x7c\x3d\xc7\xb6\x68\x31\x37\x58\x4c\x9e\x33\x68\x7c\xe5\xdf\xbd\x6e\x70\x1d\x4d\xa2\x93\x2c\x4c\xac\xbd\xba\x46\x96\xeb\x42\x1c\x2d\x32\x3c\xbc\xc5\xc9\x7a\x12\x96\x1b\x78\x4d\xdc\xb0\x9d\xd0\xf6\x60\x5d\xbc\x7c\xfd\x2b\x60\x03\xf6\xdf\x17\xaf\x5e\x4f\x19\x67\x2f\x80\xfa\x0b\xdc\x11\x57\x6d\xd3\x49\x53\xad\x98\x3d\x36\x1a\x5b\x0a\x42\xa3\xe0\x72\xbf\x15\x5a\x66\x2c\xab\xbb\x3a\x2b\xcd\x9e\xcd\x9e\x39\x03\x1f\x5a\xb5\x57\x1c\x13\x2b\x3a\x89\x8a\x32\x0f\x48\xc4\xdd\x24\xe7\xec\x47\x1f\xe6\xd9\xed\xcb\xac\xda\x87\xca\x53\x7f\x8c\xbb\x0e\xc1\xa8\x33\x78\xc4\x09\x1c\xd5\xb4\x2c\x5e\x2c\xe6\xcf\x7f\xfd\x08\x3e\xe0\x41\xdf\xef\x49\x18\x72\x51\x5a\x32\x11\xbb\xcd\x7e\xb3\x89\xe4\x25\x4e\x43\x6e\x73\xae\xff\x3b\x5e\x62\x8f\xde\xa6\xe1\x71\x84\x87\xe4\x9f\x98\xbb\x19\x77\x9a\xa2\xce\x49\x52\x0a\x91\x63\xcd\xbf\x6b\x9f\x27\x6b\xe4\xae\x28\x58\x81\x0f\xcd\x94\xbd\x1b\xdd\xe8\x18\x56\x79\xf0\x6f\x32\x75\xfa\x71\x40\xd5\xf2\xf1\x90\xd6\xd3\x5a\xd1\x90\x3e\x81\xd3\x82\x3a\x02\x51\xeb\x03\x4a\xa1\x70\x02\x90\xc8\x7c\xde\x56\x2b\x3c\xd6\xa5\xcc\xda\x7b\xb1\x98\x58\x89\xb5\x98\x84\x28\xa8\x34\x35\xee\xce\x47\x8f\x90\xe2\xd8\xb4\xf0\x29\x03\xb2\xaf\x25\xfd\x6a\x5f\x41\x75\x41\x14\x55\xad\x1d\x9c\xe0\x8a\xe9\xcc\xdf\x31\xfb\x6c\x03\x19\x58\x9d\x1d\xc4\x1a\x68\x59\x40\x04\xd5\x17\x97\xb9\x03\x25\x1d\xe0\xed\x0d\x91\x4c\x5e\xba\x0a\xe4\x8c\x17\xfd\x27\x60\xab\xb0\x10\xa2\x64\xaa\x84\x28\x3d\x10\xec\x20\x17\xe0\xdc\x73\x00\xa5\xca\x2a\x1f\x8b\xec\xd2\x3d\xa3\x1e\xe4\x06\xb8\x6f\xf3\x65\xa7\xe1\x65\x5f\x05\xa5\xcb\xf8\x1f\xf1\xa1\xb0\x55\x78\xe5\x9d\x32\x08\x0b\x07\x4e\x98\x1d\xd7\xbc\x12\xc5\x61\x70\xbe\xae\x18\xa5\xef\x7a\xf9\xb4\x35\x55\x14\x7c\x67\x7a\x90\xf5\x5a\x69\x46\x46\x6d\x8f\xa0\xa3\x3b\x39\xe5\x21\x8a\xb5\x23\xec\x8a\xbd\x44\xbc\x82\x57\xf0\xd7\xa2\x5e\x0a\xdf\x28\x62\xee\xe3\xe9\x5d\x7a\x78\x2b\xc2\x1e\xc0\x21\x35\x5e\x96\xa6\x4f\x42\x99\x98\xe9\xf4\x16\x4f\x43\x0e\xe4\x52\xe0\x1c\xbb\xd8\x3e\x51\x8b\x0b\x9c\xcf\xed\x46\xa8\x85\x07\x5c\x20\x7b\x9d\x9c\x0f\xd6\xb3\xbf\x4e\xc9\x15\x8e\xc2\xf3\x00\x7f\xd8\x52\xe7\x3d\x8e\x64\xe4\x75\x77\x1c\x6d\x84\xb0\x76\x09\x9a\x63\x3c\xa3\x9b\x43\x74\x12\x4d\xe0\x1a\xc7\x3c\xa2\x7b\x9a\x04\xbe\x51\xdf\xa5\xda\x9b\xea\x98\x61\x27\xcd\x68\xed\xbd\x2b\x0c\x6f\xbb\xd7\xfd\x8b\xbd\xa9\x84\xfe\x5f\xc8\xb0\xa1\x32\xc4\x72\x5a\xf0\xbd\xf7\x58\x59\x0c\x51\x17\xd7\xf6\xf8\x6a\xd1\xa6\x54\x23\x03\x44\x59\x16\x2a\x3c\xb7\x53\xb5\x18\x2b\x97\x19\x2c\x95\x39\xb9\x4c\xe6\x71\x4a\x64\x86\x62\xea\xa4\x78\xfa\x97\x28\x8b\x19\x8d\x91\x0f\x95\xc3\x10\x4b\x61\x4e\x2c\x83\x81\x05\xec\x5d\xdd\x87\x29\x81\xa1\x94\x0b\x24\x17\xd5\x9d\x58\xf6\x32\xba\x15\x43\xe5\x2e\x8f\x51\xea\x72\xef\x03\x4c\x58\x39\xd2\x4b\x0f\x96\xb5\x9c\x5c\xd2\x32\xdc\x8c\x31\xbd\x9c\x25\x2a\x59\xe9\xa5\x4a\xcd\xb9\x79\x94\x73\x99\x5c\xbe\x32\x5e\xa8\x39\x70\x7e\x4e\x2f\x59\x61\xef\xfa\xf3\xe1\x4e\x28\x57\xe9\xd7\x81\x71\x9c\x50\xaa\xd2\x28\x47\xe9\x25\x4c\x2d\x53\xe9\x29\x45\xe9\xa5\x3b\x5e\xa2\x32\x58\x86\xd2\x4f\xb7\xa7\x3c\x65\xbc\x04\xa5\x7f\x09\xba\x4a\x53\x52\xca\x4f\x7a\x29\x37\xca\x52\x12\x4b\x4f\xfa\xa7\xdb\x28\x49\x79\x88\x14\xde\x53\xd3\x77\x9d\xd9\x30\xb8\x57\x0f\x5f\x6e\x72\x52\xa9\x89\x2b\x27\xe9\x25\x9a\x5e\x66\xd2\x4c\xa0\xed\x25\x4c\x2c\x31\xe9\x4b\x96\xed\xa7\x3b\x5a\x5e\xd2\x93\x32\x3b\x70\x58\x07\x4b\x4b\xfa\xd3\x65\xfb\x77\x6a\xb0\xac\x64\x28\xf1\xb4\x97\xe4\x40\x49\x09\x3d\x4d\xb6\xff\x6a\x45\xe5\x24\xc9\x29\xb2\xbd\x54\x29\xd3\x3b\x21\x3d\xf6\x61\x4a\x45\x28\x65\x22\xa4\x12\x91\xd1\xf2\x90\xf1\xd2\x10\x42\x59\xc8\xc9\x25\x21\x83\x75\x5c\xa7\x96\x83\x0c\x61\x31\x9d\x52\x0a\x82\xe5\x1e\xbd\x24\x93\xcb\x40\x28\xa5\x8b\x27\x95\x2d\xc2\x2c\x7a\x49\xa6\x97\x2c\x8e\xaa\x13\x94\xd2\x8f\xce\xf2\x8e\xa1\xf7\x26\x96\x7d\xb4\xe5\xc2\xd0\x8d\x24\x95\x7c\x74\x94\x75\xf4\xd2\x24\x94\x7b\x3c\x94\x44\x6a\x03\xc4\x77\x96\x73\x8c\x6a\xa8\xbd\x65\x1e\x4f\x72\xe9\xbf\x9f\x5c\xfa\x12\xd6\xf9\xa3\x97\x69\x8c\x58\x98\xc3\x25\x14\x3d\x81\xf5\x87\x2f\x8d\x60\xd8\xc1\xa1\x2b\xea\xd7\xd3\x59\x7f\xe6\xd3\x0e\xba\x67\x3e\xd4\xb3\x9f\xd8\x86\xbf\xb7\xfd\x7e\xb3\xb3\x0c\x74\x9e\xc0\xce\x11\x3e\x4c\x00\xe9\xac\xbe\x77\xf5\x94\xad\x5c\x8e\xbe\x95\x51\x1c\x03\x3b\xc7\x07\x90\xe6\xfd\x0f\x8e\x68\xfb\xd8\x90\x80\x6b\xc4\x96\x97\x95\xcc\x30\xb0\x18\xb2\xf6\x5d\x0f\xda\xce\xd7\xf3\xcd\xaf\x83\x39\x1f\xb5\x62\x39\x73\x2b\xfb\x7c\x1a\x17\x0d\xc8\x8a\x9d\xb9\x37\x79\xde\xcd\x9d\xec\xfb\xad\x94\xbe\xe3\x3a\xaf\x01\x77\xf1\x31\xd8\x2c\x27\x0e\x4e\x2c\xb1\xf8\xe0\x5a\xac\xba\x61\xcb\xc6\xfc\xd4\xd1\xef\x69\xea\xd6\x3f\xd6\x3f\x68\xa4\x4e\x3b\x42\x08\xc4\x10\x57\x3d\x0c\x08\x8b\xa3\x6a\x08\xe3\x5d\x7e\x6f\xb9\x2c\xf6\x3a\x6a\xf5\x0b\x24\x73\xb1\x13\x43\x88\x78\xaa\x04\xb1\xbd\xe5\xe5\x81\xc5\xf3\x6c\x68\x41\xb0\xbe\xe1\x6b\x98\xca\x87\x7e\xfe\x21\x6e\xf6\x6e\xc5\x5e\xf0\xa2\x78\x11\xd0\xd8\x64\x79\xf4\x08\x47\x27\xe4\x95\x0d\x38\x85\xe1\xa0\x17\x46\x59\x46\xee\xcf\x75\x03\x2a\x23\xea\x4a\x66\xaf\xf4\xd4\x3d\xdd\x35\xab\x1d\x91\x93\x75\x26\x91\xc4\x9e\x2e\xc8\xd5\xb5\xc8\x84\xbc\xb5\x37\xec\x57\x2f\x5f\xd6\xbd\x83\x72\x70\x28\xf5\x92\xfc\x20\x44\xc8\xfa\xaa\xdf\x38\x4e\x4c\xf2\x61\x78\xec\x1e\x83\x68\xed\x77\x43\x2d\x7e\xb6\xfc\x13\xe6\xbb\x63\x8a\x4b\x8b\xb2\xdf\x8e\xa0\x4a\xf1\xd6\x37\x86\xb4\x9a\xb0\x07\xad\x57\x34\x41\xb0\x69\x51\xed\x75\xe9\x12\xed\xfc\x19\x1c\xd0\x10\x79\xe5\xd2\x31\x21\xa7\x0e\xf4\xcd\x3b\x69\x04\x36\xf6\xc1\xf2\x1d\x77\x2f\x7d\x90\xdb\x5d\x85\xfe\xf3\x14\xf7\x1e\x5f\xfa\xea\xa1\x96\x4b\x07\x1c\x65\xca\xa9\xf0\xfe\xad\x06\x15\x78\x7b\xd5\x95\xf6\xa9\x62\x75\x91\x47\xfd\x06\xf5\xe4\xe1\x5d\xec\x1b\xf4\xdf\xce\x81\x37\x1b\x3b\x4e\x43\x17\xa9\xa1\x0d\xca\x15\xab\xee\x54\xcf\x1a\x60\x60\x53\xfc\x61\xcf\x0b\x76\x27\xe4\x7a\x53\x0d\xe0\x7a\xd8\xe5\x82\x3c\xf9\xc6\x11\x60\x3b\xa1\x33\x1f\x7c\x75\x7d\x9e\x31\x1f\x31\x9e\xfb\xc0\x46\xb5\xec\x95\x28\x4c\x0e\x7d\x85\xed\xd2\x46\x4f\x91\xa6\x6e\x14\x3b\xcc\x4e\x1a\xca\x11\x9c\xc4\x08\xd4\xf2\x83\xd0\xb7\x32\x13\x1d\xf1\xa2\x7e\xd5\xb3\xd1\x48\x37\xa8\xe1\x35\x05\xf8\x06\xae\xe2\xb0\x46\x96\xd2\xf8\xa7\x8b\x25\xb8\x96\xcb\x71\xbd\xc9\x28\x10\xba\x93\x76\xed\x6e\xef\xfd\x2b\x48\x6b\x65\xe2\x18\x6b\x02\xd2\xf5\xc4\xd7\x01\xba\x0e\xf1\xcc\xa3\x2c\x16\xe2\x56\x14\xb5\xa0\x1a\xa4\xc8\x98\xf8\x2c\x32\xb8\x3d\xd6\x9a\x82\x83\x59\x1c\x7c\x8f\x75\x2f\xca\xa1\x55\xba\x95\xef\xee\xe5\x47\x21\xed\x5d\x38\xc7\x5f\x41\x3f\x43\x2b\x66\xe6\x9d\xa1\xc5\xee\xb4\xfe\x78\x2c\xb5\x82\x32\xa1\xe0\xa0\x5d\xf9\x35\x9b\x42\x8f\x24\xfb\x3c\xbf\x22\x0e\xc8\x75\xac\x57\x43\x43\xb3\x9a\x0f\x22\xfa\x8d\x9e\x35\x1c\xdd\x8a\x1b\x4e\x2b\x1c\xb9\x76\x55\xe6\x08\x4d\x9f\x50\xe3\xd2\x0b\x7c\xba\x58\xce\xf2\xbd\x6e\xeb\x5c\x20\x25\xa0\xc9\xe3\x78\xdb\xec\x42\xae\x44\x76\xc8\x0a\x31\x6f\xcf\x14\x79\xdb\x56\xf0\xb2\x72\xad\xa7\x20\xe1\x82\xd4\xb2\xd9\x95\xf5\x29\xdf\x0c\x3b\x7e\xdb\x38\x31\x28\xc7\x42\x21\x12\x64\x8f\x1d\xed\x8e\xf2\xec\x83\x95\x37\x8e\x39\x87\xe2\xdb\x68\x21\x46\x29\xfa\x85\x72\x6d\x44\x33\x8e\x00\xfc\xe1\x41\xa0\x4e\xef\xab\x0d\x26\x7d\x91\x1a\x70\x1b\xec\xaa\x24\x85\x99\x32\xfb\xaf\x59\x21\xb7\x00\xab\xeb\xd4\x2c\xc7\xd5\xcd\x86\xef\xa0\x73\xc2\xd5\xfb\x77\xa3\x34\x43\xcf\x86\xf3\xa8\xb1\x39\x72\x6f\xbc\x54\x47\xd1\xb9\x51\x92\xce\x5f\x86\xd7\x67\x0c\xf2\x9e\xc6\xbe\x70\x84\x63\x32\x80\x32\x1b\x8f\x26\x3f\xfb\x36\xfa\x35\x44\x06\x4b\xa6\x76\x98\xb0\xd3\x6e\xe4\x3e\xf3\xa1\x2e\xc2\x43\xa2\x69\x79\xbe\xb4\x98\xe0\xbb\x2f\x26\x41\x69\x6f\x35\x46\x23\xd1\xad\x45\xd7\x64\x7b\x00\x1d\x24\x90\x95\xa5\x4b\x72\x59\x4c\xa2\x7c\x99\xa8\xc8\x62\x31\x19\x40\x6e\x8e\x47\x63\x55\x40\x97\xf9\xf1\xa7\x8f\xa1\xee\xdb\x4a\xca\xcc\x8a\x65\x7b\xbe\x7c\x5a\x14\x89\xae\x63\x9e\x4d\x76\xfc\xae\x7b\x95\x29\x1d\xe3\x53\xce\x09\xa3\xe0\xf3\xc6\xa3\x71\x50\x08\xa9\x44\x44\xb2\xad\x66\x78\x93\xa3\xd4\xa6\xc9\xfc\xc8\x41\x4a\x26\xdd\x76\xa4\xc2\x36\x59\x73\x78\xed\xe7\x0f\x95\xd1\x9a\xd6\x29\x9e\xa5\xe0\x85\xc4\xe3\x4b\xc1\x00\xc7\x23\xa9\x6b\x3f\x23\xc0\x03\xc7\xa3\x71\x16\x86\xf3\x9e\xc6\xb5\x8a\x7a\xb8\x53\xc0\x26\x41\x18\x4e\xac\x38\x9d\x38\x05\x77\x72\xc2\x26\x0d\x62\xa5\x36\x7e\x93\xd6\xd4\x9f\x3d\x24\x26\x70\x3c\x92\xf7\x6d\x0c\x2b\x38\x1e\x8d\x7d\x1b\xcd\xa5\x7a\xcc\x2b\x71\xc2\x72\x27\xae\xcc\x78\x9b\x8e\x7a\xcc\x90\x21\x90\xbe\x69\x8f\x39\xe9\x8b\x03\x00\x3b\xf1\x20\x34\xdf\xa8\x87\xd3\xad\xbe\x83\x72\xfd\x1f\xb0\xf7\xba\x4e\x17\xf3\xd7\x5d\x64\x62\x60\x01\x00\xe7\xa0\xc9\x30\x28\x3f\x44\x49\xe6\xb4\x4b\xa4\x17\x70\x23\x1c\xb8\x80\x19\xf4\x1a\xc5\x83\x0c\xde\xe4\x47\xaa\xdc\xe3\xf9\x69\x9c\x6e\x72\x95\xe7\xf6\xc7\x4e\xec\xc9\x5b\x51\xba\x97\x3b\x33\xcf\xd9\x19\x40\xc8\x90\x99\x1d\xf8\xb9\x9f\x7b\x75\x28\x38\x86\xc5\x4a\xb9\xb6\xc7\xe8\xb3\x1e\x4c\x1a\x3b\x7a\xb1\x1d\x38\x3c\x7d\xfb\xf6\xd0\x6e\xdb\xb7\x46\x0a\x5d\xd3\xc9\x14\x43\xbd\xa7\x43\x88\xc0\xf8\xd7\xa2\x64\xef\xca\xdd\xbe\xba\x64\x8c\xfd\xe6\xdb\x8f\xec\x7c\xa5\x86\x11\x64\xe3\x61\x99\xfb\xf9\xc5\xfc\xc2\x72\x81\xc3\x0c\xe9\x5e\xb2\x95\x52\xae\x5b\xc6\x4a\xae\x2f\xd3\x36\x09\x4a\xe4\x67\x0e\x79\xc8\x2a\x82\x8e\xaa\xeb\x2e\xeb\x22\x0a\x8b\xc9\x92\xeb\xc1\xb6\xac\x2d\x9a\x25\xfb\x69\x5f\xb5\xde\xb2\x7b\xf6\x64\x9a\x96\x42\xe3\xb5\x97\x5c\x53\x67\x44\xb2\x7e\xeb\x71\x64\x07\xe3\x6d\x8f\x5b\x45\x0e\x45\x2a\xba\xc7\x77\xf5\x29\x00\x75\x17\xf1\x6a\x78\x64\x09\x1d\xd8\xf5\xdb\x37\x09\x14\xff\xf6\xd5\xeb\x01\x87\x5a\x7b\xa4\xde\x74\x1c\x29\x22\x12\x07\x29\xeb\x38\x89\x22\x73\x68\x2b\x01\x68\x65\xe9\xd1\x1f\xf2\x39\x8a\xe2\xd1\x00\x48\xf7\x08\x01\x58\x6e\xa0\x21\xa5\x80\xa6\x53\xb7\x62\xce\xce\x3e\x08\x11\x30\x78\x2a\xa5\x0a\x33\x97\xa2\x5a\xcd\x95\x5e\x9f\x6f\xaa\x6d\x71\xae\x57\x99\x5d\xfe\x5f\xba\xa0\xfd\xec\xf5\xfc\x15\xd1\x22\xaa\x07\xc6\x3a\x82\x7b\xda\x87\x3b\x3c\x12\x96\x15\xc2\xb7\xbc\x18\x03\x6e\x3e\x1e\x11\xbf\xc1\xc6\xfd\xae\xc0\xd7\x3e\xe0\xe0\xab\x3f\x13\x69\xd6\x93\x61\x0d\xa0\x80\x66\x35\x7d\x22\xd1\x50\x7b\xff\x61\xbf\x34\x96\x8b\x97\x75\x0b\x9e\x7b\x4f\x33\x5a\x85\x23\x58\x83\x44\xaa\xdf\x60\x1f\x7c\x9f\xe4\x32\xab\x8f\x8a\xac\x0e\x00\x23\x04\xcf\x4a\xa4\xea\xf6\x07\xaa\x9b\x17\x13\xd7\xdd\xfb\x2d\xfe\xbb\xd1\xfa\xf2\xe4\x35\xe8\x6d\x1c\xd4\x3d\x1a\xda\xe8\x70\x0b\xba\xa3\x9f\xa6\xeb\xa4\x38\x8e\xfa\x5d\xbe\x9c\xfd\xfd\xff\xf8\xe5\x5f\xfd\xf5\xff\x7c\xf6\xe2\x6f\x16\xb3\xf9\xbf\xfe\xdb\xe2\xf3\xd7\x2f\xff\xf3\xff\xf6\x37\x0e\xea\x1e\xc9\xa6\x00\x0e\x14\x77\xa7\xb3\xbb\x7f\x06\x9e\xee\xd8\x1d\x32\x78\x17\x5c\x4f\x65\x78\x5d\xbc\xee\xd4\xcd\xfc\xea\xe5\xdf\x7f\xa1\xdd\x3c\x69\xd9\x53\xac\x0d\x1c\x64\x03\xc1\x7f\x1d\xb6\x82\xfc\xfd\x24\xb3\x02\xc7\x60\xf5\xf8\xd0\x53\x86\x5a\xfa\xb5\x47\x7a\x8b\xbf\xf6\x48\x5a\xb8\xd4\x16\x80\xed\xa1\xc5\x56\xdd\x9e\x66\x5f\x4f\xae\xe1\xb7\x9d\xb6\x42\x4f\x55\x78\xf7\x08\x50\x6d\x03\x46\x42\x68\x23\x4c\xa6\xaa\x56\xcc\x4d\x10\x2a\x40\x1a\x49\x34\xb1\xf0\xa5\xdf\xd8\x66\xb5\x7e\x4c\x03\x65\x41\x53\xea\xd0\x67\x0a\x6d\x53\xbd\x1e\x93\xf3\x8a\x57\x9a\x67\x9f\x84\xae\xb5\x99\x5c\x65\x41\xa3\x79\xf5\xf5\xc5\xd7\x41\xa3\xf9\x2a\x49\xa3\xe9\x32\x6b\x3a\x15\xfe\x8b\x93\x35\xfe\x57\xa0\xf2\xc7\x9f\xbc\xb6\x9f\xfc\x91\x6a\x1b\x33\xec\xff\xe7\x6c\x24\x77\x3a\xd9\xef\x23\xa3\xe7\x62\x31\x99\xc6\x46\xd0\xeb\xc5\xe4\xe7\x47\xb0\x79\x5e\xd1\x97\xe0\xf1\x6c\x9c\x13\x58\xf5\x17\x60\x72\x46\x8c\xb4\xd9\xaa\x47\x3b\x35\xbd\x62\xea\x56\xe8\x3b\x2d\xab\x00\xab\x81\x57\xbe\x17\xbe\xa7\x73\xc2\x2d\x8e\xe3\x5c\x13\xde\xe5\x50\xb3\x0f\xba\x63\xc1\xb1\x19\xf2\x0d\x49\xbb\x20\x0d\xc3\xdf\x2e\x1f\xeb\xb1\xe7\x53\x1c\x02\x6d\xc3\xbf\xfb\x70\xdf\xd3\x6d\xf1\x64\xbf\x3f\xd9\xef\x4f\xf6\x7b\xc7\x78\xb2\xdf\x9f\xec\xf7\x27\xfb\xfd\xc9\x7e\x7f\xb2\xdf\xfd\xd7\x9f\xec\x77\x1c\x5f\xd0\x7e\x3f\x25\xb6\xfa\x83\xd4\x5a\x9d\x1e\x53\xc5\x9f\x1f\xc5\x52\xc9\x82\xa9\x15\x4b\x05\x6a\x26\xea\x73\x71\xed\xf3\xb4\x21\xf7\x99\x2a\x97\x9d\xe0\xa8\x73\xa5\x73\x61\x2a\x80\xb2\x54\x25\x62\xfd\xfa\x54\x3c\x43\xf7\x4d\x20\x1e\x6f\x4d\x08\x53\xcf\x3d\xe8\x6e\x57\xa9\xf1\x63\x04\x73\xeb\x8a\x94\xd3\x8c\xae\x28\x21\x39\x82\x34\xe4\x43\x18\x7b\xdd\xc3\x95\xb1\xc0\x8e\x89\xbc\x4e\xa8\xf7\x1b\xe5\xd1\x79\x53\x34\x4f\x9f\x8b\xc1\xb2\xd0\x76\x61\xa5\xf6\xa5\x47\x6e\x21\xd4\x38\xb4\x47\x04\xae\x17\xd0\x36\x97\x82\xe5\x5a\xed\x76\xc9\x9d\x96\xe2\xf1\x11\x60\x76\x7d\xef\x1f\x24\x2c\x4a\xb3\x77\x8e\xaa\xc5\xe4\x5a\x18\x55\xdc\x0a\xa8\x7f\x49\xb0\xe4\x42\x85\x94\xcf\xaf\x74\x49\xe2\x58\x3f\x20\x0d\x40\x7b\x54\x8a\xdd\xb8\xde\x39\x64\xc2\x0e\x21\x18\x01\x8e\x01\xc5\x74\x25\xd7\x38\x5d\x69\x42\xde\xf4\x48\x15\x78\x7b\xec\xcb\x5c\xe8\xe2\x00\x95\x5b\x2d\x9c\xbd\xb0\xfb\x7a\xb0\x06\xbc\x3d\x38\xcb\xb4\x32\x66\x56\x23\xf2\x34\x50\xc7\x78\xc9\x5e\xf8\x38\xff\x0b\xba\xf3\x0f\xcb\xc1\x7c\xe5\x73\x84\xef\x0b\x20\x81\x2c\xe0\xdc\xfd\x46\xf3\xb2\xa2\x27\x35\x54\x8f\x74\x08\x16\x7d\xc7\xe0\xde\xfb\x3f\xad\x53\x1c\xec\xec\x56\x3f\xaa\xea\xbd\xd0\x5b\x59\x55\x22\x5f\x4c\x98\x16\xdc\x10\xb2\x8e\xfd\x20\x1d\xa6\xe8\x90\xd0\xaf\x6d\xc7\x61\x2a\x7d\x33\x00\x01\x22\x27\xe0\x26\x92\x89\xfe\x20\x8c\xe1\xeb\x90\xf8\x75\x13\x6f\xce\x4d\x84\xae\x3d\x5a\x90\xd1\x1c\x51\x43\x24\xd7\xbc\x09\x41\x39\x73\x51\x71\x59\xb8\x82\x2f\x57\x81\xb4\x2c\xc4\x36\xc9\x41\x7b\x0c\x5f\xd1\x5d\x0d\x73\x12\x4d\x57\x0a\xd1\x5d\x1d\x43\x3d\xad\xa7\xf8\x38\x92\x32\x71\x59\x8c\x50\x37\x49\x31\xaf\x1e\x2d\x87\x97\x91\xf3\x78\x93\x48\x0e\x81\x22\x34\x73\x79\x93\xc8\x9e\x90\xf7\xcb\x4e\x4d\x74\x64\x7f\xa6\xfc\x5f\x76\xaa\x25\x94\x92\x07\xcc\xe2\x93\x98\x7a\xf1\x52\xd2\x88\x4f\x3d\x88\xf7\x4e\x25\xc6\xf1\x0d\xbe\x23\x24\xd6\x05\x12\x56\xe1\x2b\x9b\x8d\x58\x4e\x3c\x4d\xe4\x24\x65\x76\xba\x5d\xfc\x28\xc9\xca\xec\xd4\x43\x96\xea\xd1\x7d\x94\xc4\x65\x76\x9f\x3b\x7d\xe2\x36\x9c\xbc\x5a\x83\x50\x91\x5d\x83\x0a\x1f\x99\x74\x11\xdc\x4a\xfb\x8a\xe5\xa3\xca\x8c\x34\xfd\xc3\x8e\x36\xdc\x64\xcc\x9b\x1b\x1d\x09\x92\xa8\xde\x61\x1d\x78\x83\x6c\x5c\x2c\xdd\x52\x70\xd3\xd6\x00\x75\x67\x69\x82\xd3\xc8\xeb\x75\xc1\x5a\x3b\x6d\x71\x23\xb0\x7a\x1e\xd1\x78\x66\x98\xba\x2b\xd1\x11\x87\x90\x2d\x69\x54\x63\xe4\xfc\x79\x28\xcf\xbf\xc7\x02\x78\xcc\x23\x1e\xaa\xf9\x51\xb3\x33\x34\xf4\xd5\xae\x41\xcd\xf4\xf6\xe3\xcf\xca\x3c\x93\xe1\x46\xbb\xc6\x49\x8c\x20\x75\x61\x1b\x3c\x00\xf0\xbf\xfc\x25\x08\xfd\x0b\xbd\xf3\x26\xcd\x61\x6e\x49\x95\xfb\xed\x12\x4f\xe5\xde\x88\x18\x13\xdb\xa1\x4e\x25\x51\xf4\x58\x8a\xe1\x4a\xdd\x79\xbc\xd2\x70\xa9\x12\x6c\x66\x06\x76\xf3\xb1\x51\xe0\x40\xda\xa4\x39\xc1\x58\x6a\xbf\xb7\xe3\xa3\xc6\x15\xdf\x47\x7f\xa2\x9b\xcb\xcc\x75\x74\x82\xb2\x51\xc4\x93\xb3\x74\x10\x03\xab\x05\x55\x96\x46\x35\x76\xcb\xc1\xd4\xb6\x72\xbd\x41\x4f\x8f\xd0\xf2\xd6\x79\x7a\x4e\x65\x24\x11\xe6\xa4\xdf\x76\xa8\xf7\x4e\xd9\x73\x0a\x88\x60\xd7\x20\x01\x0b\x76\xfe\x70\x0c\x6c\xb0\x6b\x8c\x03\x10\x1e\x8f\xd4\x58\x42\x92\x43\x3c\x31\x2e\x90\x56\x05\xb5\x4c\xf1\x27\x9e\xe2\x5c\xbf\x16\xb9\xd4\x22\x23\x31\xb1\x4e\xf7\xba\x27\xf0\x50\x0e\x76\xd7\x15\xcc\xb4\xeb\x70\x52\x22\xbf\x2e\x37\x0f\x27\xe6\xbd\x33\x8f\x5e\xc4\xe4\xd1\xe8\x4e\xf3\x7a\xb7\x9b\x92\xd5\x0d\x20\xd5\x38\x5e\x45\x3d\xc0\xcf\xe3\xb4\x9f\x10\x6a\x04\x5f\xd2\xf7\x0a\x0b\xf6\x6f\x52\xe3\xd2\x41\x97\xc2\x78\x84\xd3\x31\xc1\xf8\x9f\x36\xa6\x4a\x77\x76\x1e\x21\x69\xd8\x69\x9f\xb6\x4b\xec\x0b\x16\x3c\x3e\x3a\x48\x5d\x7b\x24\xeb\x24\x43\x70\x6f\xed\xd1\x6e\xa7\x52\x6d\x6a\x34\x0e\xae\xf9\x56\x00\xea\x85\x73\x1c\x92\xf7\x16\x8a\x0d\x0f\x0e\x6b\xb2\xda\xf8\xbd\x96\x65\xa6\xb6\x51\x0b\xf5\x79\x6f\xf7\x90\x5e\xa2\x80\x5f\x6e\x49\xe2\x0d\x29\x83\x4f\x33\x53\xa5\xa9\xf4\x1e\xdc\xe7\x74\x9a\x47\x17\xe2\xf8\x60\xbb\xb9\xd2\xb5\x41\x37\x3b\x98\x18\x37\x33\x69\xba\xa3\x6e\x29\xb9\xa5\x69\x40\xc0\x47\x33\x3a\xc1\xf5\xa9\xc5\xae\xe0\x99\x78\xbb\x2f\x8a\xf7\x09\xc7\x89\x75\x48\x88\x06\xa1\x5a\xd5\x4d\xd6\x72\x90\x93\x81\x08\x40\x80\x34\xe8\x1b\x05\xd4\x99\xef\xe0\x98\x9a\x60\xb2\x41\x80\x61\xcf\x84\x1c\x70\x8c\xfd\x00\xb2\x3d\x29\x68\x29\xf1\xf0\xe2\x66\x9e\x8e\xde\xdc\x35\x22\x96\x76\xf1\xf2\xd5\x57\x8f\x6d\xc7\xb8\xc5\x44\x1c\xc8\x1f\x78\x95\xdd\x7f\xdb\x23\x5a\x8f\xb8\xf3\xbb\x21\xe4\xca\xee\x81\xd8\xc7\x8f\xb4\xf9\x0d\x9f\x3b\x8f\x71\x1f\x17\x93\xf3\x95\x52\xe7\x69\x25\xaf\xcc\x57\xfc\x72\xf7\xa6\xf5\xec\x91\xde\x62\x82\xd0\x70\x49\x14\x97\xa2\xe6\xa8\x38\x33\x98\xd5\x3d\xdc\x3b\x55\xbb\xff\x69\xc0\x7d\x74\xfc\x7f\x14\x65\xb4\x7b\xb8\xae\xc2\x87\x9d\x68\xf5\x58\xb5\x37\x1e\x6f\xb1\xc0\x30\x5c\x42\x59\x84\x1d\x57\x8d\x1f\xb7\x3b\xae\xb8\xd2\x0b\xe8\xa9\x99\x76\x66\x03\xcc\x32\xf0\xbb\x42\x56\x6c\x89\xc2\xf0\xe6\xfc\xc6\x77\x91\x53\xa3\xf8\x42\xcd\x01\x62\xa9\xe1\x2c\xab\x34\x97\x85\x3d\xb1\x96\xaa\x34\xa7\x65\x30\x36\x8e\xaa\x9f\xb4\x61\x37\xe7\x7c\x99\xdd\x4c\xf1\xff\xcf\x3b\xdb\x54\xf7\x0f\xe8\xa7\x0c\x3f\xcc\xc5\xca\xb7\xc1\x0e\x3d\xc2\x4f\xbd\xb1\x7e\x4a\x4b\x1f\xa6\xb4\xab\x0b\x1f\xe6\xfe\x19\xa5\x4a\x8c\x49\xfc\x25\x72\x69\xf8\xd1\xc9\x7c\xf9\xe3\x61\x27\x1a\x88\xaf\x75\xd7\x9a\x84\x52\x06\x56\xab\x63\x7a\xce\xae\xea\xf6\x71\xd8\xcb\xc3\x21\x99\xf1\x9c\x0a\xb9\xe4\x07\xb4\x65\x74\x3d\xeb\xb4\x28\x04\x37\xc1\x74\xb9\x7a\xff\x2e\xb0\xa6\x44\xae\xc4\x2b\x0f\xb5\x10\x4f\x0c\xef\xb9\x34\x4c\x94\xfb\x6d\xda\x01\x97\x6d\x40\xc9\x46\x42\x05\xaf\xd8\xbe\xfc\x54\xaa\xbb\x34\xef\x9d\x9b\x22\x00\xca\x43\xb2\x02\xdf\x1b\x01\x79\x26\xdc\x60\x0f\xf1\xdf\x9e\x4e\x15\x93\xa0\x10\x33\xd3\xec\x8b\xca\xb3\xa8\xe6\x9b\x24\x51\x36\xa2\xaa\x3c\xca\xde\x95\xef\x01\x59\x67\x27\x38\x38\xd9\x24\x92\xae\x2f\x53\x9d\x35\xd2\xcc\x06\xe1\xec\x3a\x2d\xef\x83\xa1\x99\x79\xf3\xdb\xd2\x61\x23\x8a\x1c\xd2\x70\x6f\x1e\x48\x3f\xb3\x27\x27\xe5\x2a\xce\x58\x4b\x1b\x3e\xe5\xb7\x91\x4a\xf5\xb8\xac\x26\xdd\x61\x46\xc2\xd8\x8b\xe7\x93\x90\x48\x9b\xe2\x64\xef\xef\x05\x86\xad\xaf\x54\x48\x86\x19\x45\xc2\x8c\x66\x3c\xea\x4c\x49\xcd\x4a\xeb\x76\xa6\xc0\x14\xcf\xe4\xaa\x16\xf6\xfd\x5d\xa9\xda\x83\xe2\x53\x49\xc9\xfa\x64\x27\x7a\x84\x4f\xf2\x06\x27\x7b\x82\xd3\xbd\xc0\xe0\x94\x3c\xd1\x37\xf7\x01\x7e\x1b\x02\x0c\xf8\x5f\xf5\x51\x4a\xf5\xa4\x7d\x89\xa3\x14\x4d\xb4\x79\x32\xe8\x93\x1d\x3a\x41\xa7\x59\x0a\xa3\xa2\x98\xd0\xe8\xb8\x7b\xf4\x89\xe1\x6e\xd1\x4a\x26\xdb\x21\x82\xfb\xc4\x6a\xea\x21\x68\xbe\x69\xa7\x48\x25\x93\x3c\x12\xbd\xfd\xe2\x94\x4c\xb3\x21\x76\x7b\x44\x29\x95\x8f\xa4\x08\xcb\x19\x14\xd8\x25\x7d\x99\x7a\x4c\x92\x05\x21\xae\xdd\x1b\x95\x27\xf0\x0d\x97\x7b\xf5\xfa\x25\x95\x61\xb6\x58\x4d\x78\xa4\x67\x37\x10\xcc\xc0\x99\x90\x37\x2f\xb3\xbf\x6f\xc8\xba\x88\x4d\x90\x1b\xdf\xb6\x47\x7c\xe7\x1f\x50\xad\xa6\xaa\xd4\xee\x91\x09\x27\x78\x4c\x9d\x4e\xa5\x48\x53\xa5\xfd\x5d\x4e\x52\x2f\xfa\xd5\xe8\xe3\xbb\x4c\x26\xdc\xa9\x42\x7f\xd1\xbb\xfc\xfa\x25\x55\xa2\xcf\x12\xae\x4c\xaa\xf4\x4f\xd2\x38\xa9\x46\x76\x87\x71\x1d\xb5\xa0\x8f\xed\x6b\x0c\x6f\x92\xde\xad\x52\xd8\xbb\x74\xce\xae\x5c\xb1\x2b\x26\x1d\x5c\xbd\x7f\x87\x01\x7d\x33\x75\x86\x36\x27\x5e\xdc\xac\xe0\xc6\xf8\xae\x24\x70\x41\xb5\x80\x92\x80\x00\x9b\x0d\xd0\xf8\x06\xba\xd9\xcd\x48\x24\x2d\xd3\xb8\x74\xb8\xf2\x7e\x36\xd8\x30\x45\x02\xf0\xb2\x0b\xe1\x5a\x71\xe6\xd3\xee\xe9\x36\x66\x54\xf7\xce\xd8\x62\xd2\xe0\x54\x88\x21\x0d\x2c\x66\xc7\xb3\x4f\x7c\x4d\x44\x77\x14\xf3\xf5\x1c\x8a\x09\x3a\x40\x36\x17\x93\x39\xbb\x2a\x8a\x63\x3e\x44\xa2\x0c\xcc\xc0\xa3\xef\x43\x02\x74\x0c\x21\x3d\x0b\xfa\x92\x5f\x2e\xda\x21\xa0\x2f\xa9\x5f\x2e\x12\xdd\xf6\x92\xfa\xc9\x75\x2c\x2b\x2c\x19\x89\xe8\xa2\x59\x67\x67\x97\x33\x00\x66\x0b\x6d\x5c\xab\x1c\x51\x66\x6a\xaf\xf9\x9a\x38\xd3\xa8\xe7\xac\x08\x55\x05\x8d\x85\xc5\xc2\x00\xbf\xac\xb4\xcd\xc2\xbe\xc7\x5a\xd4\xcd\x21\xca\x9c\x05\x3e\x68\x97\x27\x34\x0b\xbe\x15\x65\xae\x34\xd1\xa7\xbc\x60\xa1\xd5\x24\xf8\xaf\xea\x4e\x57\x66\x83\x8d\x27\x33\x55\xde\x0a\xbd\x16\x25\x31\x01\x51\x96\xb5\x03\x9d\x43\xb5\x51\x0d\x08\x70\xda\x41\x05\x61\x78\x54\x99\x8f\x2d\x02\x8c\xeb\x0f\x18\x96\x9a\x18\xfd\x80\xf3\xce\x3a\x78\xc9\xdc\x6d\x4b\xc0\x4a\x3f\x81\x0f\xd8\xd9\x99\x7d\xb6\x09\x6b\xc9\x1a\x29\xa3\x6c\x6f\xbc\xba\x1c\x83\xc1\xd3\x48\x43\x66\x14\xbb\xb1\x3c\xfb\xa6\xd1\xbc\x0a\x1c\x04\xf6\x4c\xc7\x34\x89\xe1\x1a\x40\x9d\x77\xe5\x2a\xd1\x51\x6d\x5c\x86\xd3\xae\x02\x1e\x57\x4f\xbc\xa5\x6c\x20\xb3\x80\xde\x12\x76\xf7\x88\x17\x41\xd4\xd5\x1a\x20\x65\x7a\x3a\x09\xd4\x9d\x00\x68\x17\x01\x0a\xea\x78\xab\x1e\xae\xb9\x2a\x28\x15\xb1\x7a\x92\xc6\xb5\xb0\x6f\x66\x71\xeb\xfb\x64\x3b\x3a\x31\xec\xbf\xf9\x24\x77\x3b\xe8\xac\x58\x9a\x4a\xf0\x81\x3e\x4b\xf1\xe8\xea\xb0\x14\xfa\x2a\xf9\x1e\x1d\xc8\x18\xc8\x66\x6e\x3c\xb9\xba\x47\x11\xe8\xf0\x58\x14\x16\xeb\xe1\x24\x8a\x09\x2a\xf7\xe9\x22\xec\x61\x4d\xe7\x04\xb3\x99\xea\x86\x23\x9a\xcc\xb5\xfa\x4c\xbe\xb3\x83\xe6\xf2\x09\xde\xe7\x7e\xaf\x33\x85\x8f\x50\xd5\xeb\x19\xeb\xd4\x66\x52\x7e\x89\x02\x3b\xe5\x17\x3e\xd7\x8f\xf4\x9b\xdf\x5e\x7f\x7f\x8d\xd1\x74\xd2\xd7\x13\xb9\x78\x92\x2d\xbf\xd7\x85\x9b\x4a\xba\x62\x5f\xbf\x46\x67\x86\x23\x23\x82\xb2\x77\xc1\xb1\x1f\xe5\x1f\xd4\x4d\x23\xc9\xfc\xf6\x01\x9a\x87\xc7\xe3\xcf\x9b\xf3\x88\x8e\xd1\x13\x1c\xab\xad\xa4\x10\x4b\xd7\x7b\x53\x91\xe6\x89\x0b\xcc\x1e\x65\x91\xd9\x53\xca\x62\x73\x86\x0f\x91\xb2\xc8\x31\x2b\xc0\x25\xf0\x90\xa5\x2b\x8b\xdb\x1b\x3c\xdc\xf6\x3e\xe5\xdd\x75\x8f\xa7\xbc\xbb\xf6\xec\x9f\xf2\xee\x9e\xf2\xee\x9e\xf2\xee\x9e\xf2\xee\x9e\xf2\xee\xfe\xeb\x72\xe9\xa7\xbc\xbb\xa7\xbc\xbb\x64\xaa\x4f\x79\x77\x4f\x79\x77\x7f\xc9\x79\x77\x09\x5f\xa7\x4e\x9b\x34\x5d\xf2\x73\xc9\xe8\x9a\x34\x4c\x4d\x02\xe2\x13\x15\xe3\x29\x15\xd5\x29\xa5\xcb\x2e\xa9\x1f\x6b\x1b\x9b\x69\x84\xe6\xa9\x5d\x58\x13\x9c\x18\x5f\x0e\x71\x89\x78\xed\xc6\x51\x95\x92\x70\x94\xd2\x1a\xb0\xfa\xcd\x1e\xdb\xeb\x3e\xac\xa4\x01\xfc\xa3\x11\x92\x09\xe8\x48\x74\x48\x0f\xb2\x5f\xea\x01\x31\x8f\x88\xdb\x3c\xee\x9c\x7c\x40\x24\xa3\x84\xfb\x40\x5e\xb2\x84\xf7\x24\x20\x12\x51\x31\x88\xda\xb8\x42\x23\xa7\xaa\x13\x75\x68\x0c\x49\x68\x84\x66\x1d\xf7\x7a\x58\xec\xa0\x14\xb4\xa0\x80\x00\x34\x26\xb3\x46\xf0\x81\x3a\x30\x7f\x46\x29\xb6\x11\x81\x1e\x06\xe5\x67\xbc\xac\xfe\xd1\xaf\xfd\x89\x68\x3d\xc4\x8b\x30\xbe\x08\x09\x18\x3c\x31\x88\xcc\xd8\x86\xf5\xa1\xee\xf4\x23\xe9\x8c\x6a\x55\x01\x67\xe7\x81\xb0\x73\x88\x68\x39\x2d\x04\x1c\x02\xd1\x6e\x7c\x9c\x7e\xcc\x9b\x11\x92\x31\x22\xce\xfd\x51\x6e\xe8\x55\x0c\x09\xb5\x0b\xc4\x8a\x05\x6a\xa6\xe2\x9d\xb0\x2b\x43\xd4\x47\x86\x1f\xd9\x64\xf1\xbf\x03\xc2\xad\x13\xbe\xd3\xca\x6e\x87\xc4\x64\x50\x9f\x06\x31\xb2\x29\x2e\x76\xe6\xad\xf8\x88\x9f\xe5\x35\xfc\x1c\xf8\x0a\xed\x89\x54\xdb\xdd\x7e\xbc\xad\x31\x37\xee\xcd\xcf\xcf\xcc\x7e\x0b\xbe\xe1\xa2\x70\x1f\x99\x90\x94\x56\x83\x6a\x1b\x70\x11\x8e\xb6\x54\xb1\x87\xb1\x54\xe5\xec\x8f\x42\x2b\x67\x8e\x4f\x1d\xce\xb3\x73\x47\x18\xb5\x15\x4c\xec\x8c\x2c\x2c\x2b\x1d\x07\x5e\xb2\xef\x2b\x3e\xf3\xac\x8a\xd7\xce\xa7\x91\x01\xe1\x5c\xec\x04\x26\xe8\x39\x38\xe4\x9d\x16\x99\x34\xe3\x26\x3e\x2f\x8f\x12\x1b\x90\x95\x9b\x39\x73\xbb\xe7\x01\xa1\xd9\x4e\xe8\xcc\x7e\x6d\x3d\x76\x83\x5c\xf2\x20\x73\xab\xea\x57\x34\x57\x02\x49\x95\x02\xf7\x51\xfc\x61\xcf\x0b\x76\xf1\xf2\x25\x41\x20\xbf\x5b\x31\x55\x16\x07\xa6\x4a\x51\xe3\x27\xc7\x29\x59\xf6\xa1\xb2\x62\x1b\x6e\xf9\x15\x3e\x72\x84\xe4\x5a\x0b\xee\xe2\xe2\x25\x7b\x39\xb5\x13\xf9\x6b\xaf\x7a\x54\x9a\xaf\x56\x32\xb3\x8f\x88\x8f\x1e\x45\x12\x87\xe3\xf8\xce\xbf\x7a\x04\x4b\xfd\xd2\xf2\xb7\x40\x9d\x84\xa4\x0c\x20\xef\x7e\x0a\x81\xc3\x43\xe3\x1c\x78\x46\x43\xf3\x21\xbd\x78\x1e\xe9\xef\x17\xb1\xfc\xae\xc9\x03\x67\x63\xb7\x1c\xfa\xde\x2c\xf9\x78\x38\xdc\x9d\xbb\x4c\x95\x95\xf8\x5c\x39\xf4\x7b\x28\xe1\x19\x16\xf8\x27\xf0\xc7\x8b\x97\x30\x68\x1c\x72\xf8\x6b\x34\x0e\x39\xee\x61\x18\xc1\xec\x22\x78\x15\x08\xfe\x84\x31\x4f\x82\x4b\xfc\xeb\x9b\x65\x93\x35\xbb\xd4\x55\x9f\xde\x57\xa7\xb6\x99\x3a\x53\x95\xef\x76\x85\x1c\x3e\xf7\xcd\x2c\x36\xef\xef\xb7\xfa\xc6\xbe\xc0\x6a\x8f\x8f\x96\x79\xad\x56\x22\xab\x8c\xbd\x5c\x4a\x5b\xf9\x3a\xa0\x44\xa9\xa8\xfd\x94\x8f\x27\xb9\x8e\x91\x7b\x6d\xc5\x70\x71\x88\x8f\xbc\xe3\xfa\xd9\x00\x38\x57\xb6\xe1\xe5\x5a\x78\x3d\xdb\x79\x9b\xe1\x4c\xdb\x53\xbb\x12\x22\xb7\x57\xd6\x87\x03\xa1\x8d\x66\xb1\xdb\x70\x66\x2c\xab\xeb\xe7\xf6\xae\x4b\x9d\x4b\x3e\x9d\x61\xf2\x29\x83\x76\x97\xd2\x60\x2e\x6a\x23\xdf\x37\x3c\x71\x48\x55\x6a\x66\xed\x63\x5a\x3c\xbb\xfa\xfe\xfb\x46\x7a\x77\xe8\x1d\x15\xa7\x0f\xf7\x92\xb4\x42\xad\xe5\xc0\x9e\xb3\xd9\x50\x6a\x68\x94\x01\xdd\x4b\xf5\x38\x33\x3a\x22\xd9\xca\xe3\x6c\x26\xa6\xf6\x92\x84\xec\xc7\x52\xa1\x2f\x68\xcf\xad\xd9\x21\x84\xf1\x29\xc8\x47\x5e\x78\x64\x5c\xd8\x98\x6c\xe8\x40\xf1\x78\xed\xea\xb3\x55\xc9\xad\x30\x20\x2e\x62\xd7\x55\x9d\x46\x1b\x25\x16\x0f\x9e\x81\xab\xa2\x08\xfb\x02\xcb\xf8\x79\x27\xb2\x0a\x17\x11\x52\x9e\xb7\x3b\x5e\xc9\x65\xe1\xe2\xd9\x82\x67\xae\xac\x62\x60\x69\xc1\x6a\xf3\xe9\x81\x51\x0e\x98\x95\x71\x6d\xe4\x3b\xf7\xec\x29\x46\xca\x7b\x89\x5a\xd5\xc3\xb5\x0c\xc9\xd4\x76\x69\x4f\x24\x48\x8f\x63\x05\x20\xe3\x0e\xc6\x7a\xe4\x04\xa0\xc2\x8d\xc4\x5c\x5c\x24\x1c\x5c\xd4\x78\x0e\x18\x81\xc8\x0a\xc1\x75\x71\x08\x26\x64\xff\xe1\xb7\x3c\xa4\x90\x5b\xe9\xdb\x1a\xbc\x2b\xe1\xf4\x5a\x0b\xc3\x38\x91\x02\x50\x5e\x7e\x45\x95\xb6\x9b\xe7\x2f\x41\x2f\xdd\x78\x7b\x22\x59\xd9\x8e\xea\xc0\xad\xe2\x79\x6e\xf5\x07\xae\xcb\xa1\x33\x55\xb7\x9f\xb0\x57\x05\x62\x17\x74\x00\xb9\x91\xce\x8f\x47\x9d\x1e\xc1\x07\xe7\x0a\x5e\x02\x46\x1a\xe6\x07\x5b\x86\x65\x2a\xb1\x33\x63\xc1\x7b\xdf\xd8\xc5\x2e\x5e\x21\xec\xf1\x8c\xd8\x9d\xcf\x57\x88\x12\x84\x59\x21\x57\x22\x3b\x64\xc5\x20\x70\x6b\x6b\x76\xb8\xc2\x5b\xc1\xcb\xca\x2a\xd7\xdc\x25\xf5\x1b\xb4\xc0\x64\x59\x61\xa6\xf8\x4e\x0b\x33\xa4\xef\x47\xef\xe6\xa4\x0a\x68\xcd\xb9\x55\xfd\x64\xe9\x5b\xd1\x1c\xb1\x83\x01\x8a\x1f\x40\xe1\x46\xaf\xa7\xc1\xb2\x83\xbc\xfb\xb5\x31\xc8\x89\x35\xd1\x43\x8e\xeb\xf0\x70\xc8\x20\xd9\x57\x1b\xfb\xcf\xcc\x69\xd0\x95\xe6\x95\x58\x4b\xab\xf7\xdb\x7f\xcd\xe0\x48\xcb\x72\x3d\xb5\x17\x78\x80\x68\xad\x16\xf2\x9d\x2c\xd7\xf3\x26\x27\x3c\x8f\x4b\x1d\xa4\x69\xca\x95\x01\xaa\x4e\x33\xf3\x92\xa5\x96\xf4\xfd\x2b\x46\x4b\x20\x13\x51\xd2\x6c\x8a\xe3\x2f\x4e\xb6\x05\xf7\x42\xc9\xd4\x0e\xe3\xc9\xed\x4b\x19\x64\xc8\x88\xf6\x59\x9f\x33\x67\x1e\x2e\x26\xf8\x8e\x8b\x49\x5d\x45\xc0\x52\x22\x1d\xc1\xd6\x5f\x4c\xb6\x07\x6d\xcf\x78\x20\x28\x4b\x17\xaa\x58\xc4\xe1\x10\x47\x77\x5e\x8a\x6a\x31\x19\x35\x12\x1b\x6b\x10\x17\x13\x40\xc5\x2c\x54\x73\x58\xa1\x65\x19\xbe\x97\xb4\x63\x16\x72\x54\xf6\x11\xd8\x50\x8f\x44\x1e\x56\xc9\xe9\xe9\x83\xc4\x3e\x25\xa7\x44\xa4\x08\x31\xc2\xf1\xee\x22\x1d\x51\x29\x02\xdd\x9e\x9e\x22\x69\x7d\x42\x12\x53\x6c\xbf\x6c\x4f\x90\x84\xe0\x30\xad\xff\xc7\xa3\x04\xa0\xd8\x50\x10\x2a\x65\x03\x08\x98\xf0\x49\xc9\xcd\x0f\xdc\x3c\x23\x61\x37\x68\xd9\xee\x0f\xdc\x1e\x23\xf1\x28\x27\x2d\x25\xf9\xdd\x69\x51\xfe\x19\xa1\xfd\xcf\x0c\x0e\xe6\xc8\x57\x46\x11\x85\x89\x89\x02\xba\xab\x4e\x26\x45\x58\x76\x16\xda\x9c\x02\x77\xcd\xbb\xcb\x40\xbc\x12\x84\x05\x0b\x0f\x1c\xcd\xa1\x4b\x12\x9e\xa7\x72\x99\xc9\x95\xd5\xd4\xf3\xdc\x09\x92\xa8\xbf\xfd\x99\x79\xee\x5a\xdc\x13\x18\x8c\x6b\x82\xdf\xc2\xfb\xae\x7b\xe2\x87\x5e\xf7\xef\x2a\xc6\x77\x3b\x51\xe6\x94\xd4\x50\xe8\xc4\x77\x60\xbe\x13\x9f\xcf\xca\xe2\xc6\xa8\x4c\x72\xab\x7e\x87\x36\x73\x64\x3c\x6c\xfb\x46\x0f\xdc\x72\xff\xa8\xd9\xbe\xdd\x86\xbe\x66\xfb\xf5\x72\x51\x48\x0f\x76\xd9\xbf\xd7\x84\xd3\x1b\xee\x93\x5b\xed\xd3\x9b\xec\xbb\x6e\xc8\x04\x9a\x6c\xb4\xbd\x3e\xb9\x69\x7e\x6a\x5d\xc7\xe9\xb5\x51\x7d\x42\x23\xf5\xd5\x19\xde\x85\xde\xe6\xf8\x8d\x76\xf7\x64\x8a\x5f\xb2\x2d\xfe\xc3\x37\xc4\x27\xb5\xc2\x3f\x85\xf0\x40\x13\xfc\xae\xb6\xf6\x64\xba\xad\xf6\xf7\x43\x0d\xed\xc9\x34\xa3\xc6\xf7\xc3\xad\xec\xc9\x14\x43\xcb\xfb\x47\x68\x62\x7f\x42\xfb\xfa\x93\x1a\xd7\xdf\xaf\xc4\xee\x61\x9a\xd5\x27\x27\x8e\x26\x35\xa8\x27\xb6\xa6\xbf\x1f\x8f\x49\xdf\xa2\x84\x76\xf4\x27\xec\x51\xe2\x92\xa6\x35\x69\x21\xf6\xbe\xa0\x37\x9c\x4f\xca\xd4\x4d\x6a\x32\x9f\xd2\x5e\xfe\x3e\x8d\xe5\x89\x8b\x72\x7a\x33\x79\x2d\xb6\xea\x36\xd5\x10\x9b\x5c\xc3\xaf\x3a\xd5\x55\x9f\x6b\x42\xd8\x1e\xd7\x5e\xa6\x57\x4f\xfd\x18\xdf\x25\x7c\x24\x81\x2a\x64\xf9\xf8\x0a\x28\x78\x44\xcc\x4c\xe7\x51\x3e\x5c\xb2\xce\xea\x82\x77\x4d\xce\x2e\xd8\x99\x89\xe4\x76\xce\x2b\x5e\x69\x9e\x7d\x12\xba\x96\xde\xb9\xca\x82\x04\x7f\xf5\xf5\xc5\xd7\x41\x82\x7f\x45\x94\xe0\x64\x5d\xf9\xe2\xd2\x6a\x96\x14\x8a\xd1\x8f\x5e\x81\xf6\x19\x93\x79\x6d\x3f\xf9\x63\xa4\x51\xd3\x28\xba\xd3\xc4\x7e\x1f\xa9\xdb\x17\x8b\xc9\x34\x56\xbf\x5f\x2f\x26\x3f\x47\xba\x34\x8d\xf0\xe0\x3b\xbf\x7a\x68\xe5\x39\x89\xcb\x3d\x12\xdf\x30\x82\xb0\x36\x2d\xcc\x43\x51\x31\x75\x2b\x34\x44\xd8\x0c\x3b\xea\xfa\x44\xbb\x95\xf1\x85\x76\xc6\xa7\x37\x2d\x3b\xee\x28\xa9\x3c\x9c\x68\xe6\xb5\x8c\x38\xda\xc9\xb0\xeb\x44\xb0\xf3\xbc\x15\x47\xbb\x6b\x54\x3b\xef\xc9\x68\x1b\x7b\xf0\x93\xd1\xf6\x64\xb4\x3d\x19\x6d\x4f\x46\xdb\x93\xd1\x76\x34\x9e\x8c\xb6\x81\xd9\x3e\x19\x6d\x23\xaf\x41\x8d\xd7\x20\x3a\xd9\x09\x71\x1a\xfc\x61\x0f\x58\x17\x0d\x8b\x17\xe3\x33\x40\x27\x84\x67\xcc\xdc\xe7\x7d\xb9\x2c\x26\x81\xc9\x34\x90\x65\xed\x23\xdc\x23\x74\xa3\x7a\x08\x04\x55\xf0\x49\x2f\xc6\x9b\x9f\xbc\x6a\x14\x4d\x8c\x83\xfc\x06\x69\x90\xde\xe7\x81\xae\x16\xd5\x5d\x68\x53\x55\xfb\x3a\x75\xbf\x2e\x17\x40\xe0\x33\x97\xdb\x01\x29\x65\x84\xdb\x85\xbb\x21\xf2\x3a\xdd\xd5\x6f\xc2\xdc\xe9\x1a\x8d\x3a\x11\x32\xbe\x24\xa4\x76\xef\x4b\xa8\x58\x6b\x94\x1a\x60\xae\xc1\x2d\x2f\x24\x26\xb6\xbb\xf4\x2d\x8a\x36\xac\xd5\x6e\x17\x57\xaf\xb8\x74\x29\x74\x0c\x64\xaa\xac\xb4\x2a\x0a\x48\x84\x0c\x18\x06\x14\xfe\x02\x39\x35\xd7\x0e\x0a\xf3\x5a\xac\xcc\x62\x12\x65\xc1\xb9\x1c\x23\xac\xe7\x27\xc3\xc5\xd7\x69\xf1\xad\xfa\x7f\x78\x67\xc0\x44\x70\xc8\xad\x02\x16\x88\xb2\xa2\xbe\x34\x00\x27\xb4\x2f\x73\xa1\x8b\x83\x55\x5a\x9b\x89\x45\x6e\xdf\x68\x6f\xae\x05\xfa\x47\x20\x11\x75\x56\xd7\xe7\x35\x91\x46\x4b\xf6\xc2\xc7\xfb\x5e\x10\xe8\xba\x4a\x40\xb8\x75\xbe\xc4\xa2\x28\xd4\x1d\x5a\x18\xed\xb2\x42\x4a\x28\xb3\xea\xdd\xe0\xce\xed\x23\x59\x8a\x3d\x5b\xdc\xbb\x73\x94\x79\x86\xd0\xa7\x9d\xd1\xea\x47\x55\xbd\x17\x7a\x2b\xab\x0a\xb0\xa0\x35\xc2\xc4\x1f\x1d\x00\xd2\xfb\x4b\x93\x74\x00\x48\x46\x38\x13\x12\x12\x5d\x11\x40\x35\x14\xbb\xb1\x1f\x84\x31\x7c\x5d\x77\x52\x89\x17\xf7\x86\x40\xb9\x46\xce\xa8\x31\x80\x7d\x4f\xd9\x9d\x56\xb7\x32\x17\x6c\xab\x20\x7f\xbc\xe2\x92\x02\x74\xc6\x97\xca\x43\xe5\x68\xb5\x2c\xc4\xb6\xa7\x7b\x8a\x95\x45\x75\x41\x1f\x81\xb0\x4b\xba\x69\x26\xb8\xba\x9c\x6e\x2b\xd7\xca\x43\xab\xfa\x6e\xfc\x6c\xa5\x59\xc5\xc4\x3c\x33\x96\x80\x92\x50\x7f\x3f\x2d\x37\x8d\xa8\x3d\x36\x60\x96\x48\xf9\x69\x44\xc2\x2d\x6c\x85\x7b\xe5\xa8\xb1\xd3\xa0\x20\xbf\x6c\xae\x1a\x4b\xd7\xc5\x69\x39\x6b\x2c\x15\x65\xa1\xfe\x51\x4a\xb2\x1b\x71\x5f\xdd\x61\xa1\xa1\x2e\x10\x69\x36\xb1\x19\x52\xd0\x17\xfc\x48\x4b\xa2\x63\xa7\x58\x5a\x0f\x9c\x4c\xc7\xd2\x8f\x0b\xdd\xe3\xf6\xc0\x89\x75\xec\xb4\xfb\x97\xbc\xc4\x27\xac\x07\x01\xcd\xc1\x8f\x44\x54\x07\xe2\xd9\x0d\x55\x94\x24\x74\x07\x22\xd1\x16\x06\xc4\x30\xca\x03\x91\xe6\x00\x16\x44\x07\xda\x03\x75\xa2\xa3\x98\x10\x47\xa8\x0f\x44\xca\xe3\xd8\x10\x1d\xe8\x0f\x54\x3f\x11\x09\x23\x82\x90\x37\xe8\xc7\x17\x67\x3f\x27\xa2\x43\xf8\x91\x78\xd1\xe8\xad\x25\x53\x51\x23\x88\x1b\xe6\xd0\x18\xe8\xe8\x11\x44\xba\x1e\x63\x82\x84\x22\x41\xf5\xc7\x35\xb0\x26\xc6\xd0\x24\x92\x16\xa0\x8d\x39\x31\x80\x2a\x41\xf7\x98\x76\x63\x4f\xf4\xa3\x4b\x10\x29\x9f\x82\x41\xe1\x47\x7a\x47\xcd\x13\xfa\x69\x26\x76\xd3\x4c\xeb\xa6\x45\xf7\xb2\x12\xdd\x89\x64\xbf\x29\x35\xff\xbc\xf6\x56\x3d\xa0\x3b\xd2\x17\x7b\x9e\xe0\x90\x0c\x75\xa2\xf7\x76\x49\xba\x2e\x50\xa6\x9d\x2b\xed\x23\x4c\x2e\x31\x05\x1f\x67\x2d\xec\x11\xa2\x69\x22\x81\x6e\x30\xd2\xbb\x02\x0c\xf7\x03\xf0\x74\xd2\x5a\x02\xa4\x74\x59\xad\xdb\xb1\x10\x08\xb7\xfb\xab\x86\xe9\xf5\xf4\xde\xa5\xc5\xec\x13\x85\xf2\x63\x96\x82\x7c\xc1\x66\x01\x09\x72\x9a\xd6\x20\x60\xa0\x35\xc0\x8e\x6b\xbe\x15\x50\x1d\xeb\xdd\x3b\x50\x7c\x41\x09\x92\x06\xd8\x63\xb7\xc7\x50\xfc\x2c\xcb\xb5\xdf\x6c\x74\xea\x06\x54\x6f\x22\xa4\x2f\x9e\xef\x32\x4c\x27\x53\xa5\xa9\xf4\x3e\xab\xba\x0f\xeb\x29\x87\xd3\x1f\x46\x98\xbc\x3b\x91\x8c\x9b\x99\x4c\x2a\x30\x61\xbe\x50\xf2\x9e\x5d\x11\xd2\x9c\x4d\x27\x75\x42\x20\xf6\x40\xa8\x79\x03\x55\x93\x1a\xec\x7e\x70\xdc\xd1\x80\xaa\x9f\x1c\x43\xdf\x3f\x5c\x2f\x83\x53\xf0\xb1\x93\xa3\xad\xa7\x75\x2e\xa0\xf7\x2c\x48\x30\x55\x69\xdd\x0a\x30\xd0\x4d\xb5\xd2\x46\xfa\x14\x34\x7b\x0f\xa4\xb9\x98\x06\x3a\x14\x34\xbb\x0e\x90\x23\xf2\x9d\xbd\x09\x7a\xfb\x0d\x10\xc9\x36\xcc\xf3\xb1\x4e\x03\x44\x9a\x75\x3f\x02\x42\x8f\x01\xea\xaa\xfa\x4e\x04\xe3\xdd\x05\xe8\x9b\x8f\x3d\x08\x1e\xb8\xaf\x00\xbd\xa3\xc0\x29\x87\xaa\xbf\x97\x40\xab\x3f\x00\x95\xf3\xf5\x76\x11\xe8\xec\x0c\x40\xa4\x7a\xdc\x3f\xe0\x2f\x80\xdb\xd1\x3b\x00\x24\x60\xff\xd7\x78\xfe\xc4\xa5\x1b\x44\xfd\xef\x42\xf2\xa7\x1f\xf7\x36\xde\x7f\x2f\x86\x3f\xd5\x57\x30\xd4\x97\xf0\x08\xbd\x9f\x48\x74\xb0\x33\xe1\x3d\x70\xfb\x1f\x03\xb1\x9f\x86\xd5\x8f\xc1\x5c\xfa\x9a\x0e\xa3\xf4\xf7\x20\xef\xd3\xd9\xfd\x7d\x6e\x21\x1d\x99\xff\x34\x4c\xfe\x93\xd1\xf8\x93\xae\x7a\x8a\x7b\x83\x84\xbd\x9f\x90\x16\x46\x53\xc8\x5b\x86\x8e\x73\x0f\x06\x87\x5c\xb3\xeb\x7f\x8a\xb2\x4b\x36\x95\x63\x5b\x83\xe8\x63\x65\x67\x72\x55\x0b\xbe\xe7\x7d\x16\xf3\x89\x96\xc9\xf8\x01\x4d\xf3\xbb\x25\xfa\xdc\x12\xfc\x6d\x29\xbe\x36\x70\x12\x25\xfb\x50\x3e\xc0\xaf\x82\x43\x16\xff\xeb\xe8\x50\x10\x16\xf7\xf1\xfd\x27\x6e\x72\xfd\x67\x81\x92\x18\xd1\xd5\xbb\xef\xbe\x02\x2c\x4d\x78\x25\xb4\x9e\x21\x0b\x2e\xf7\x4d\x02\x49\x9a\xd0\x8a\xc5\x11\x81\xe8\x98\xc0\xba\x4f\xda\xd1\x88\xb0\x1a\xbf\xcb\x34\x41\x33\x83\xe2\x06\xe2\xd7\xc6\x17\x3a\x41\x88\xe0\xba\xbc\x51\x39\xe9\xee\xba\xec\x87\xd7\x2f\xc7\xd9\x52\xeb\xa2\x87\xc7\xf8\xcb\x0e\xee\x5f\x7c\x3a\xcb\xec\xe7\xa4\x34\x85\x88\x31\xc4\xbd\xa9\x9b\x7e\xc9\xd4\x0e\x75\x8f\xd1\xaa\x3a\xad\x51\x35\xa9\x31\x6f\x4a\x9b\x6a\xe2\xd5\x49\x6a\x52\x4d\x00\x8d\x61\xbe\x19\x00\xad\x51\xd3\xa3\xdf\xaa\xd7\x2f\xc7\xa5\xdc\x8c\x74\x9c\xe9\xb2\x90\xa8\x43\x8d\x1b\x69\x1d\xc6\x99\xcc\x45\x59\xd5\x9e\xc1\x26\xfa\x2b\x44\xe9\x77\xbb\xe2\x30\x26\xde\xae\x5c\x99\x0f\x06\x2b\xaf\xde\xbf\xc3\xa0\xa0\x99\x3a\x43\x0d\x0a\x68\x0a\x6e\x0c\x3a\x63\x64\x49\x00\xb2\xd6\x42\xc4\x10\xa8\x88\x67\x6b\x1c\x20\xad\xbd\x94\x97\xec\x6d\xdd\x52\xdf\x8c\x20\x1b\x22\x4d\x21\x01\xd6\xce\x05\x92\xec\xc1\xf4\xe9\x9d\xbc\x01\x69\xbe\x3c\x00\x80\x4c\x02\x0c\x11\xa2\xf2\xc1\x05\xdf\xf1\xec\x13\x5f\x8b\x29\x13\xf3\xf5\x1c\x52\x4c\x3b\x00\x94\xc6\xdd\x50\x57\x45\xd1\xd7\xf8\xcd\x1d\xef\x06\x24\x2f\x41\x61\x98\x05\x2d\xe1\x78\xe9\xc6\x17\x67\x84\x78\xcf\xd2\x85\x47\x76\x2c\xd0\x08\xc5\xe6\xf2\x61\x5d\xc3\x62\x32\x6f\xe2\x06\xb3\x16\x72\xf0\xd8\x11\x08\xb8\xc2\x1d\xf8\xc1\x78\xb2\x20\xad\xd4\x2f\xd0\x28\xac\x29\x73\x33\xf0\xaf\x6f\x97\x32\x06\x45\x66\x01\x83\xf8\x56\x94\xb9\xb2\x8f\x61\xe3\x29\x07\x35\x4c\xf4\x34\x60\xc7\x9a\x8d\xba\x73\x9b\x72\x2b\xf4\x1a\xb2\xbe\x65\x19\xfc\x90\x63\x73\x44\x0c\xe3\x50\x91\x78\x7c\xb2\x40\x7e\x2c\x13\x0a\xdd\xac\x4a\x04\x48\xa6\x00\x7b\x29\xcb\x7a\x45\x3d\x78\x24\xeb\xb8\xc0\xa3\xcd\x0b\xe0\x75\x23\xe8\xe6\xc6\x05\xb5\xcf\x34\xfb\x6c\x13\x56\x85\x8d\xe7\x49\xd5\x00\x8c\x7b\xe3\x65\x51\x03\xfd\x12\x13\x18\xd8\x8d\x65\x88\x37\x64\x48\x7c\x97\x7e\x6e\x0f\x7b\x4c\x6d\x31\x41\xf0\xcc\x06\xe2\x34\xa5\xbd\xc0\x30\x1a\xb6\x43\x49\x77\x64\x93\x5c\x32\x78\xc7\x01\xf8\xd6\xee\x8f\xcb\xd2\x77\x49\xbb\xc0\xb6\x4f\x83\x3c\xad\x61\x4d\xb1\x02\x85\xb7\xca\x11\x9a\x6b\x40\x71\x17\x60\xd9\x8a\x5d\x5c\xed\x72\xd9\xa7\x11\x5a\x6c\x03\xa5\xd4\x7c\x92\xbb\xdd\x78\x90\xf9\x5d\x69\x2a\xc1\xf3\x69\x0b\x26\x1e\x9d\xaf\x00\xf7\xbd\x14\xa2\xf4\x80\xbf\xc3\x30\xe6\x6e\x35\xed\xef\xe3\x09\x69\x91\x09\x79\x6b\xcd\x18\x50\x40\x31\x4b\xbf\xa1\x4a\x12\x1a\x88\xd2\x5a\x86\x26\x6a\x8d\xa9\x1a\xa3\xd3\x07\xc7\xb3\x26\x68\xda\x62\xda\x29\x4d\x71\x18\xc6\x7a\xe0\x18\x3b\x49\xd0\x12\xed\xab\x0d\x6b\x8a\xe3\x5a\xe2\x8c\x75\x8a\x7b\xda\x6f\x50\xc6\xd1\xbe\xeb\xd3\x6a\x46\xbe\x5d\x63\xb7\x8f\x7c\x31\xe6\x61\x04\x6d\x74\xd4\x14\xdc\xeb\xc2\x3d\x38\x45\x27\x8d\xa0\xe6\xef\x5f\xc1\xe8\x11\x26\x8f\x02\x99\xae\x9b\x09\x20\x5c\xd3\x5d\x6e\xf7\x4d\x04\xf8\xf2\x09\x44\xe8\xc3\x8a\xbc\x5f\x24\x8b\x38\x8e\x1c\x5b\x8a\xde\xe5\x85\xd4\x8e\x97\x90\x40\xb2\xb3\x0a\xe8\x1e\x0e\xf7\xa7\x2c\xa0\xee\x31\x90\x05\xc4\x31\xe6\xe6\x22\xf8\x4f\x49\x30\x4f\x49\x30\x1d\xe3\x29\x09\xa6\x31\x9e\x92\x60\x9e\x92\x60\x9e\x92\x60\x9e\x92\x60\xa2\xaf\x9f\xc0\xdf\x9e\x92\x60\x9e\x92\x60\x9e\x92\x60\x5a\xe3\x29\x09\xe6\xe4\x2f\x52\x9a\x41\x0e\x4e\xeb\xcb\x34\x83\x74\x92\xbc\xbf\x19\x24\x86\x7e\x7b\xfe\x3c\x1b\xb5\x78\xf0\xf9\xb5\x2e\x31\xf0\x55\x87\x25\x79\xde\x3b\x95\x98\x5d\xff\xe0\x34\x10\xef\x71\xf5\xd7\xd5\xd4\x9d\x91\x02\x0e\xe1\x90\xce\xa3\xf7\x85\x60\x7c\xcd\x65\x69\xaa\xba\x6e\x22\x06\xcf\x35\x73\xf6\x2d\xcf\x36\x4e\xb2\x42\x69\x30\xb6\xd1\x15\x43\x70\x2b\x72\x2e\xe6\x75\x87\xcb\xe0\xb6\x77\x28\x66\x4c\xae\xd8\x8b\x17\xbc\x3c\xbc\x78\x01\x9d\x6a\x1d\x5b\x77\x9b\xd1\x4f\xd4\x30\xc3\x2b\x69\xb0\xa1\xe5\xa2\x6c\xc2\x47\x54\xfc\x93\xb3\x76\x54\x51\x60\x14\xc2\xeb\x69\x0d\xf7\x7c\xff\x76\x2d\x4a\x76\x73\x73\x13\xce\x84\xdf\xde\x78\x77\x82\xde\xea\xb1\x0e\x0d\x00\x84\xf6\x92\xf4\xc0\xa1\xb7\x42\x1b\xa9\xca\x36\x6c\xe8\xed\xab\xc5\xa4\xe7\x31\xb7\xaf\xf0\x49\xbd\xa4\xed\x54\xdd\x1a\x34\x94\x74\xdc\x28\xbf\xa7\x61\x0f\xa6\x04\xc3\x0f\xe3\x76\xb0\xc4\x07\xf6\xed\xbb\x8f\xdf\x7d\x7b\x1d\x3a\xfd\xde\xa9\xe8\x94\xb9\x00\x27\xe8\x06\xa8\x68\x0d\xc8\x5b\xe0\xfc\x37\xf6\x6d\x6e\xd8\xd5\x8f\xdf\x00\xf8\x8e\x9d\x5c\x84\x91\xcc\x6e\xdc\x02\x5d\xb2\xdb\x57\x37\x4d\xca\xbd\x74\xad\x0c\x71\xcb\x04\x2b\xe1\x8b\xb2\x8f\xeb\xab\x03\x58\x04\x1a\x6e\x03\xa2\x71\xa3\xee\x20\xfc\xe6\x20\x30\x43\x24\x0a\x17\x35\xba\x66\xa0\x75\xd4\x90\x34\x57\x3f\x7e\x33\xb0\x02\x95\x5a\x8b\x6a\x23\x42\x10\xa2\x54\xe1\x68\xb6\x9a\x2d\x62\x95\x32\x30\x1d\x28\x06\xee\x25\xe9\xd4\x5b\xd4\xce\xdc\x5b\xd9\x63\xb3\x98\xb8\x16\x97\xd0\xb3\xb3\x0a\x5d\x65\xa1\x61\xac\xe3\x08\xbd\x44\xc5\xad\xd0\x87\xc6\xed\x87\x19\xbf\xd7\xea\xf3\xc1\x5a\x92\xdf\x2b\x9e\xb3\x7f\xe4\x05\x2f\x33\xa1\x99\x56\xfb\x8a\x1e\x80\x5d\x8b\x52\x68\xe8\xe9\x02\x35\xbd\x61\x4b\x5c\x43\xc9\x9d\x96\x4a\xcb\x4a\xfe\x51\xc0\x69\x35\xb4\x3e\xb0\xf5\x55\xcf\xac\xb5\xab\x25\x9f\xc2\xf1\x92\xe5\xde\x77\xf9\x96\xc2\xcc\xd9\x7b\x2d\x32\x91\x43\xd0\x67\x0c\x23\x0c\x21\x8a\x9d\x25\x76\xbd\xf7\x0d\x49\xc1\x2e\xe3\x7a\x6d\x2f\x99\xab\xa7\x56\x2b\xb8\x06\x2f\xd8\x9b\x0d\xd7\x3c\x1b\x6c\xda\x0a\x2a\x6f\xe0\xc8\xa5\x2a\x67\x77\xb2\xc8\x33\xae\xf3\xe0\x47\x9d\x37\x28\x35\x7f\x31\x70\x5e\xc7\x7f\x0c\x87\xc4\x7e\xc1\x21\xfe\xba\xa3\xd7\xaf\x6d\xbd\x60\xff\x7b\x6f\x0f\x02\xd4\xe4\x85\xaf\x7b\x08\x37\x80\x88\xad\x2c\x43\x07\x1c\xaf\x76\xd0\xb6\x97\x2a\xee\xf6\x34\x9a\x56\xbd\x29\x1e\xd9\x35\x17\x95\xd0\x5b\x88\x51\xcb\x12\x9b\x20\x33\xd5\xef\xe9\x6f\x72\xfb\xa1\x23\xe0\x76\xea\xe3\x46\x30\x55\xe4\x43\x3c\x10\x63\x37\xe1\xf4\x65\x5a\x20\x1f\x81\x46\xb8\x15\xdf\xee\xe6\x8e\x0e\x7e\x91\xef\x76\x82\xa3\xb3\x59\xea\x01\xb2\x76\x47\x8a\xdd\x86\x2f\x45\x25\x33\x5e\xb8\x77\x73\x79\x08\xff\x11\x00\x2a\xfe\x74\x0e\xff\xfe\xd3\x62\x12\xaf\x77\x2f\xd5\x78\x1f\xec\x31\x95\x31\xfa\x18\xb0\x28\xcb\x05\x20\x7a\x88\xe7\xba\x5e\xf3\x7e\xd9\x3d\xb4\x41\x6b\x68\xb2\x99\xfb\xfb\xf1\xf6\xdd\xf5\x87\x8f\xe3\xa7\x14\x74\x80\x33\x59\x3a\xe8\x7c\xfb\xea\xcf\xd9\x56\x88\x60\x77\xf0\xa5\xba\x15\x61\x03\xe1\xd5\x7f\x87\x58\x3c\x83\x34\x4d\x3d\xd7\x5a\x04\xd6\x01\x53\xb3\xcf\x32\x61\xcc\x6a\x5f\x14\x07\xc6\xbd\x69\x33\x10\x5e\x40\x07\x01\x20\x31\xf0\x38\xd7\xd5\xa9\x45\x96\x71\x4d\x7d\x08\xf5\xab\x97\x5f\xc5\x79\x7c\xbd\x34\xfd\xca\x69\x51\xed\x75\x39\xd0\xe8\x3d\xa5\xdf\xed\xa4\x25\xd1\x62\xc3\x7d\xa7\x45\x2e\x33\x5e\x51\xa2\x29\x28\x39\xea\xb0\xb3\x62\xdc\x1d\x14\x8f\xc1\xfe\x43\x53\x02\x86\x4c\xa9\x01\xa2\x20\x0b\x83\xcc\x9b\x7a\x5d\xd0\x93\x00\x5d\x50\x58\x45\x87\x63\x90\xb4\xd2\x7b\xc1\x54\x59\x0c\x05\xb5\xe5\x0a\x5b\x1c\xd7\x02\x18\x04\xe7\x80\x36\xe8\x9f\x37\x40\x74\x29\x0a\x75\x87\xf3\x71\x4a\x53\xb3\x6d\x84\x9d\x93\x7d\xb2\xac\x8c\xf3\xab\x55\x5c\x57\x43\x01\xed\xb6\xaa\x23\xab\xa6\xb6\x13\xa9\x39\x17\x3e\x4b\xfb\x72\x38\xed\x22\x68\xa4\x97\x3e\xc0\x02\x1f\x0f\xeb\xa3\xa3\x60\x4d\x9d\x1a\xa9\xfd\xf4\x62\x31\xb1\x8f\xec\x57\x3b\x69\x01\x12\x3f\x19\x7a\x54\x15\x85\x93\x89\xbc\xea\x8d\xbd\xd8\xc4\xb2\x4b\x8f\x26\xe8\xb4\x8e\xad\x6f\x2c\xa7\xc5\xd1\xe9\xdc\x0a\x5e\x62\xd3\xe1\x11\x92\x7e\x26\xa0\x40\xb8\xf3\x52\x14\x4d\x6c\x59\xff\xde\xa0\x43\x8a\x62\xbc\x9c\x04\x92\xea\xed\x3d\x1e\x7e\x21\x12\xca\x7f\x0f\xc2\xbf\xe7\x10\xf6\x8f\x4b\x61\x82\x8a\x4b\x99\x1e\x0b\x57\x02\xa5\xe2\xa1\x66\xb8\x1d\xbb\x33\xba\x2b\x29\xc1\x35\x2a\xdc\xd8\xe3\x80\xfb\x93\x81\xfd\x1b\x80\xfd\x24\xd2\x8f\x08\xea\x4f\x06\xf4\xa7\xb7\xa6\x61\x1e\x72\x1e\x98\xe1\x03\x21\xfa\x3f\x06\x9a\x7f\x02\x92\x3f\x0d\x22\x98\x11\x51\xfc\x6b\x74\xfe\x94\xe5\x1c\x47\xf0\x8f\x91\xf9\xa9\xbb\xff\x3b\xc4\x67\xf3\xe5\x3f\x86\x69\xb1\x13\x60\x74\x59\xfd\xb3\x6c\x5c\x5a\x1a\x48\x93\x04\x05\xa8\x27\xf7\xae\x0e\xad\x71\x60\x79\x1b\x75\x47\xbb\x5d\x1b\x4b\xd3\xd4\xbd\x47\xec\x22\xff\x06\x0c\xc4\xa2\x38\x4c\x2d\x9f\xf8\x0c\x07\x97\x92\xe5\x88\x03\xcd\x00\x44\x24\xdd\xcb\x1c\x72\x39\x03\x78\xd4\xf5\xdb\x37\x97\xe1\xca\xdd\xdd\xdd\xcd\xf5\x2a\x9b\x89\x5c\x56\x4a\xc3\xb5\xd3\xab\xcc\xdf\xba\xb9\xbd\x82\xf1\xd5\x9b\xd3\x20\xa0\xb4\x58\x63\xa6\x49\xdc\x97\x9f\xd7\xeb\x8f\x5b\xe2\xdc\xe0\xb0\x7e\x9c\x02\x56\xcb\xd8\x86\x97\x79\xe1\x92\x59\xfe\x5f\xf6\xae\xbc\xb9\x6d\xe3\x8a\xff\x9f\x4f\xb1\x65\xd3\x8a\x72\x78\xd4\xf6\xc4\x49\xd5\xf1\x64\x34\xb2\x1c\x7b\x1c\xcb\xaa\xac\x74\xda\x98\x9a\x64\x45\x2e\x29\xc4\x20\x96\x01\x40\xc9\x9c\x34\xfd\xec\x9d\x7d\xef\xed\x81\x6b\x77\x21\xcb\x39\xda\xf0\x8f\xc4\x22\x81\x87\xc5\x1e\xef\xf8\xbd\x8b\xcd\x06\xaf\x45\x39\x3e\x92\xf2\x6d\x22\x66\x83\xa8\x86\x0d\xbd\x9b\x35\xf4\xac\x0d\x77\xa7\x4d\x1a\x7a\x21\xe0\xb1\xae\x2e\x93\xbf\x73\xfc\x8e\x47\x48\xbc\x56\xcf\x98\xd5\x4a\x48\x7c\x56\x50\xb6\xc8\x4d\x5f\xab\x77\x44\x75\x63\x9a\x79\x3c\x43\x18\xe8\x7e\xec\xa1\xaf\x17\x1b\x1e\x9e\x89\xd5\x36\xe5\xf9\xf1\x3b\x75\xba\x94\x92\xb7\x0f\x97\x25\x59\x64\x05\xc8\xc6\xfd\xcc\xd1\x24\x60\x3a\x94\x55\x49\x81\xb3\x4e\xf0\x74\x24\x47\xa9\xb9\xd8\xe6\x3c\x33\xe1\xee\xa7\xaf\x5e\x3f\xff\xe7\x88\x9d\x1e\x9d\x1d\x33\x2c\x99\x1c\x45\x12\x33\x3a\x16\x09\x57\x2a\x4d\xa1\xe6\x37\xc7\x57\x60\xc2\xbc\x43\x31\x61\xa7\xf1\xae\xc6\x5c\xf0\x45\x8b\x4b\x6d\xaf\xa8\xa1\x8b\x10\xf4\x4c\x98\x45\xf4\x2e\xb0\xa1\xf7\x34\xe4\xa8\x83\x1c\xeb\xb6\x1a\x47\xef\xf3\x71\x73\xa5\xef\xfa\x8c\x46\x37\x50\xe9\xd7\x3c\x25\xb6\xb8\x6f\xbf\xc6\x29\xfd\x9b\xa6\xf4\xe4\x95\x3d\xa6\x2e\xd6\xbd\x17\x55\xc0\x2f\xae\x41\x4a\xb4\x03\x30\xba\x31\x4a\x6c\x53\x94\xdb\x36\x44\x89\x78\xf9\xdb\x35\x42\x59\x8b\xf2\x4a\x06\xe6\xbe\xe6\x90\x83\x3b\xea\xd6\x2b\xd2\xd1\x56\x2b\x26\xe5\x07\x56\xa1\xe2\x0c\x50\x3a\x12\x58\x5e\x75\x07\x9a\x86\x26\x9c\xa4\xec\x00\x5d\xed\x0e\xb0\xb6\x2a\x0e\xee\x36\x5d\x49\x62\x22\xcc\xbf\x3c\xf6\x77\xcc\x1a\xb3\x67\xc7\x87\x4f\x02\x97\x9c\xbe\x0a\xf4\xdd\x1a\xb3\xd3\xaf\x43\x57\x3c\x39\xfe\xea\xf8\xfc\x38\x70\xd1\xd1\xab\x93\x93\xe3\xa3\x10\xa9\x57\xa7\xe7\xcf\x5f\x9d\xbc\x0e\x5c\x75\x7e\x76\x78\x14\x7a\xde\xe9\xe1\xf9\xd1\xb3\x88\xc3\x13\x64\x16\xe1\x98\xdb\x80\x13\xbb\xfa\xbc\x28\x57\x35\x0b\xbb\xab\xf5\xa3\xdd\x82\xbc\xd5\xf0\xd6\x1a\xd8\x66\x3d\x59\xe1\x30\x23\xe8\x24\xa3\x8b\xba\xea\xb6\x20\x95\x68\x35\xed\x43\xeb\x11\x4f\x49\x9d\x3b\x06\xd3\x81\xa9\xc7\x47\x0d\x26\x02\xc2\x23\x1e\xd5\x88\xd3\x58\x8d\xbe\x1a\xbd\x16\x1f\x46\x65\x35\xe1\x84\x20\x8e\x3b\xf5\xd4\x91\x33\xce\x18\x9d\x35\x4e\x63\xbd\xbb\x64\xe8\x38\x6d\x68\xdc\x67\xb6\x6f\xa3\x38\xf5\x90\xfd\x91\x4a\x93\xd9\x27\xfe\x33\xc8\xda\xb5\x2b\x17\x18\x83\x55\xae\xef\x90\xb0\xc6\xd4\x37\x9c\x31\x7a\x0a\x22\x35\x91\x1f\xb6\x22\xdf\x9d\xf2\x9c\x87\xb0\xd1\xca\xeb\xff\xdd\xde\x55\x17\xd7\x3f\x58\xb7\xa7\x08\xe7\xef\x18\x2c\x3a\x1e\x6d\x0e\x51\x34\x58\x74\x1c\xda\x0c\xe3\x0d\x61\xae\xb6\xb0\xaa\x41\x7d\x3f\x2c\xec\x6c\x27\xf8\x43\x42\xcf\xb5\xb5\xfa\xb5\x63\xcf\x31\x4b\x45\x03\x05\xaf\x7b\x0d\x80\xc6\xb0\x73\x0c\x5d\x00\x74\x53\x31\xb5\x3e\x9d\x2c\x09\x54\xed\x0d\x3e\x3f\x98\x7c\x36\x79\x78\xe7\xf0\x73\xdf\xd9\xf8\xed\x63\xd0\xce\x76\xed\xd9\x52\xd6\x6d\x27\xab\x73\x98\x5d\x6a\x55\x94\x37\x8a\x64\x1d\x09\xae\xa6\x49\x28\xc5\x67\x9b\x6f\x64\x21\xd2\x1d\x4b\xc5\x32\xee\xdd\xb7\x19\x55\x17\x18\xb1\x22\xc9\xe6\x82\x2d\x92\x25\x75\x35\x58\xf0\x92\xb3\x4d\xca\x33\xc5\x02\xf8\xb5\xf3\x53\x14\xe5\x39\xdf\xf0\xcb\x24\x4d\x30\x94\xe7\x99\xbc\x11\xd7\xe0\x56\x2e\xf7\x0a\x76\x2f\x17\x73\xb9\x5e\x83\xcd\x72\x2f\x3e\x42\xbb\x8e\x41\x51\x20\x57\x3d\x74\x4e\x04\x82\x3a\xdc\x4f\x05\xda\xa3\x95\xc1\x3f\xec\xeb\x6b\xe4\x27\xae\x0b\x49\x52\x8e\x00\x57\x87\x7e\x6d\xce\xe2\x88\x77\x1b\x31\x27\x4c\x1f\x91\xaf\x54\xf2\x38\x94\xfc\x12\x62\xb7\x28\x68\xab\x14\xef\xca\x82\xc9\x6d\xa9\xb6\xbe\x1e\x39\xf5\x41\x84\x10\xfb\x28\x92\x5f\x17\x54\xf7\x81\x92\x24\x88\x5f\x97\x39\x5f\x82\x87\x40\x07\xd2\xe8\x3d\x1a\x45\xd4\xd9\xdf\x20\xb6\x56\x5b\x9e\x03\x1e\xb7\x2e\x44\x7a\xad\x64\x2b\xad\xd1\x46\x96\x22\x2b\x63\xb1\x74\xbd\xef\xe6\xa2\x68\x0f\x99\x2f\x7e\x15\x90\xfa\xff\x15\x0a\x5e\x93\xe3\x7d\x73\x3e\x9d\xac\x4f\x82\xcd\x23\x0d\x8c\x68\x74\x1d\x98\x59\x13\x12\xaf\x69\x39\xe7\x31\x21\xf6\x8c\x70\x98\x16\xe8\xdc\x07\x8b\x47\xd1\x6d\x42\xe7\x91\xb0\x78\x1c\x75\x80\xce\x63\x61\xf1\x58\x17\xbb\x81\xce\x7f\x87\xc5\x3b\x3e\xb1\xb0\xb8\x73\x8a\x62\x27\xff\xd6\xd8\x78\x64\xea\xda\xef\xd8\xf8\xff\x22\x36\xde\x2b\x2d\xe7\xf3\x8e\x2b\xfc\xef\xee\x7d\x84\x77\x7e\xbb\xe8\x76\x50\x6c\x2b\xce\x52\x39\x70\x58\xbe\xb1\x12\x5d\x39\xdf\xe6\xa0\xd3\xaa\x7b\xcd\xf1\x3b\x6b\x9a\xd2\xdd\xe6\x26\x06\x98\xb6\xac\x5e\xbd\x2e\x02\x5c\x86\x2d\xc1\x30\x6e\x76\xa9\x83\x53\x4d\xa3\x2d\x36\xdc\x16\x5b\x9e\xa6\x3b\xad\xb7\x15\x6d\x72\x0d\x02\x81\x79\x2e\x18\x2f\x0a\x39\x4f\xc0\x52\x30\x41\xed\xa0\xae\x8d\x74\x75\x35\x1d\xd2\xaa\xeb\xbd\x76\x24\xfd\xc1\xdd\xb9\x50\xfa\x00\xe4\x9c\x08\x3e\xbf\xa2\xc1\x51\xe5\x61\xc7\x77\x41\x91\xb7\x14\x5e\x8a\x57\xb5\x21\x21\x65\xb5\x31\x33\x96\x47\xe1\x19\x5f\xe9\xc0\x56\x7c\x79\xb0\x82\xf9\x62\x01\x06\x16\x58\x80\x94\xc2\xd9\x42\x12\xe6\xcd\xb4\x59\x73\x88\xa3\x01\x59\x08\x22\x4d\x03\xcd\x16\x5a\x91\xdd\x6e\x16\xbc\xf5\xcd\x21\xa3\x02\x9e\xca\x0b\xc6\x37\x6a\x99\x73\x35\xa3\x4e\x33\x37\xa0\x25\x73\x46\x29\x8a\x6a\x05\x75\x72\x7b\x1b\xa7\xad\xe4\xb1\x9a\x05\x36\x7a\x2a\x7c\xdd\xac\x39\x05\xdd\xaf\xb3\x70\xc6\xa7\x24\xa8\x1c\xcb\x68\x51\x1a\x6a\xa3\x70\x93\x9a\x27\xa7\x66\x1d\xa9\x20\x74\x6f\x0b\x55\x45\x4d\x29\x28\x60\x90\x6f\xe4\x66\x9b\xaa\x29\x70\xfb\x9a\x9b\xbc\x51\xbd\x31\xa7\xf5\xbd\xdb\x3e\xb9\x3b\xd8\xa8\x54\x99\x2a\xb9\x4c\xa1\xdf\x1e\x28\x85\x87\xba\xe4\xb3\x1a\xd7\xc3\x07\x86\xb0\xf1\x8d\x39\xd1\x44\x2d\xb4\x75\x5d\x3f\x7c\xd5\x43\x2a\x72\x8c\x3b\x64\x2d\x78\xe6\x6e\x04\xa5\xa3\xe1\x3c\x89\xcc\x04\x8e\xb7\x8d\x57\x82\x9e\xa5\x7b\xc7\x37\xd5\x95\x4e\x00\xad\x72\xd6\x61\xde\xf0\xbc\x1b\x8e\xa3\x21\xb3\xea\x99\xe4\xc6\x1d\xd8\x91\x8b\xea\x9c\x49\x9e\xb9\xe7\x1d\xc9\xb7\xed\xbf\x10\x30\xe6\x64\x7d\x75\xb0\xf3\x2a\xe3\x3a\xb2\x31\xda\x5d\xaf\x61\x67\xba\xf3\x45\x6a\x2f\x53\xba\x2d\xfa\xdd\x5a\x0f\x44\x68\xaf\x60\xfc\x9a\x27\x29\x02\x05\xdd\x12\x55\x71\xd3\xb4\x90\xac\xd8\x52\x5f\xf9\x0a\xe9\xbd\x82\xc9\x9b\xcc\x86\xf5\xdb\x60\x73\x4f\xd9\x4e\xb5\x83\x44\x26\x72\xba\xcd\xe4\x6d\xe8\x3c\x8c\xbd\x82\x26\xff\x4c\x2c\x5d\xf7\x57\xb7\x52\xa9\xfb\xe3\x1b\x63\x1c\x93\xcd\x08\x3b\xa0\x44\x1a\x73\xb2\xa1\xa5\xf2\xe1\xc9\x13\x3f\xfa\x61\xdf\xd0\xe1\x82\x6a\x9f\x17\x5b\x65\xa7\x27\x90\xf3\x00\xe9\x12\x80\x06\x65\xf8\x4c\x73\x57\x27\x5d\x87\x1a\x80\x69\x50\x70\x10\x9a\xd6\x1f\x42\xe7\x54\xa8\xa9\xd9\xde\x1e\xbf\x1b\x0d\x2f\x25\x4b\x32\x4a\x62\xb8\xb9\x02\xe8\xbc\x76\x3a\xf1\x64\xd2\x13\xb0\xc8\xc9\xf7\x00\x8a\x74\xd2\xa4\x6a\x18\xf4\x46\x28\xf0\x6e\xae\x76\xc4\x5a\x90\x75\xb5\xc0\x81\xee\x7b\x74\xef\xaa\x25\xe3\x25\x53\x26\x52\xe9\xe6\xb3\xea\xe5\xc7\x54\x15\x37\x8c\x12\xf9\xb7\x2f\xb3\xcd\x6c\xf6\x59\xc6\xce\x21\xdf\x1f\x04\xb8\xcd\x3d\x83\x48\xd4\x42\x4d\x4f\x2e\x1a\x33\xee\x5b\x2e\x5a\x89\x35\xdf\x69\x59\xa0\xd6\x6c\x81\x21\xae\x29\x9f\xbf\x05\xe2\x76\x59\xaf\x93\x22\xc1\x53\xe5\x59\x30\xb5\x59\xa0\xcc\xe6\x02\xc7\x94\x39\x09\x57\x38\xb7\xb6\xc4\x09\x87\xfc\x37\xd8\xe4\x3e\x08\x50\xab\x13\x2e\x91\x84\xb8\x20\x14\xa7\x30\x1c\xc0\x19\xec\x42\x7a\xb2\xa5\xc0\x4b\x8c\xa7\xa8\x41\x36\xa9\xf6\x35\xae\x92\xed\xa4\xa8\x1e\x07\x64\x01\xd6\xc4\xf3\xc3\x4a\x79\x37\x39\x3e\xb6\x06\x83\xc9\x21\xa1\x46\xc1\x20\x5c\xd5\x46\xe3\xc8\x20\x3d\x29\x72\xac\x5d\x6b\x35\x3a\xc1\x99\x69\x62\x3b\x1e\x8f\xd1\xcd\x80\x5d\xee\x3c\x14\x61\xba\x74\x5d\x5a\x99\x33\x6a\x9d\x09\xa5\x2d\x0a\x90\x3b\x4a\x03\x67\x5c\x43\xa8\x22\x0d\x36\xdd\x9b\x10\xf3\xb4\x3c\x77\xc2\x6a\x09\x3d\x6a\xc9\x9f\x4a\x49\x12\x12\x07\xf9\xa3\x87\xe4\x4c\xfd\x67\x3a\x65\x67\x5a\x2d\x40\x29\x24\x2f\x0b\x91\x5f\x5b\x0d\x87\xb3\xa5\x94\x8a\x2d\xba\x53\xe4\xb3\x88\x35\xdd\x17\x50\xe1\xa3\x65\xe0\x30\x52\x9e\x43\x76\xce\x21\x0a\xa5\x54\xcc\x06\x3e\xe7\xdf\x6c\x70\x9a\xcb\x55\x8e\x61\xc3\xb3\xc1\x88\xc2\xc2\x9f\x88\x55\xce\xb1\x2c\x31\x3d\xf4\x93\x8d\x32\xd9\x5f\x8a\x7c\x25\x5e\x88\xdd\xe3\x40\x61\x87\x59\xe5\xae\xd7\x65\xce\x4b\xb1\xda\x3d\x5e\xab\xdb\x0d\x45\x25\xbf\xce\x77\x1b\xf1\x78\xcd\x37\xf4\xa5\x87\x24\x5c\xfe\x92\x6f\xf4\xd3\xe1\x4b\x47\xe4\xbf\xb9\x58\x8b\x92\x5f\xdf\x9f\xd8\xdd\xfb\xdd\xf7\x85\xcc\x0e\x66\x03\x3b\x45\x23\xb9\x56\x27\x61\x53\xee\x3c\xac\x0a\x42\x5b\xec\xa8\x0f\x66\x03\x18\xf7\x6c\xc0\x2a\x73\x70\x30\x1b\xa8\x71\xa8\xaf\x73\x59\xca\xcb\xed\xf2\x60\x36\xb8\xdc\x95\xa2\x18\xdd\x1f\xe5\x62\x33\x52\x87\xfa\xb1\x7d\xf6\x6c\xe0\xab\x2a\x34\xcb\xf4\xbc\x20\x78\x86\x15\xc2\xd9\x4f\xef\x9b\x0f\x95\xf2\xa2\x3c\xcf\x39\x24\x0d\xc8\xec\x3c\x09\xf9\x17\x2b\x9c\xa0\x79\xb3\x06\x81\xd4\x2f\x90\x99\xaa\x19\x16\xbe\x64\x08\xcc\x30\xb4\x74\x36\xb6\xe2\x25\xa4\xf5\x80\xe6\x28\x31\x5b\x1d\xd9\x41\x64\xa9\x61\x63\x00\x6d\xb3\x85\xc8\xd3\x1d\x79\x19\x34\x0b\xbb\xe2\xd9\x4a\x2c\x26\x14\xbc\xa3\xc4\x45\xc8\x0b\xa2\xf8\x2a\x14\xc7\x21\x8d\xc4\x16\x46\x86\x37\x36\xcf\x33\x95\xdc\xf5\x43\x02\x74\x95\x0e\x08\x92\x52\x9d\x4b\x3f\xf6\xa5\x5b\xd2\x28\x63\x70\xac\x9e\x1a\x01\xe9\x04\x21\xac\xb5\x28\x0a\xbe\xea\xb3\x01\xe8\x0e\xc4\x02\xae\xb6\x6b\x9e\x01\x12\xab\xc6\x6f\x7f\x43\x85\x29\x8c\x9e\x69\x19\xc2\x2f\x25\xd5\xc4\xb2\xfb\xc1\xd4\x37\xdb\x69\x3f\x33\x18\x49\xf8\x4a\xfe\xa9\x72\x00\xc2\x87\x0f\x3e\x7b\xd4\x05\xfd\xf4\x9a\x29\xe4\xd5\x62\x81\xa9\x21\xfe\xe2\x1d\x8d\x49\x6b\xde\x6c\x2d\x44\x3c\x3d\x13\xc5\xaa\x16\xbc\xe4\x93\x95\xb9\x26\x74\x74\x1c\x9d\x83\x76\xf6\x8d\x52\xa2\x45\x49\x9e\xae\xed\x46\xcd\xe2\x53\xa8\x3a\x5e\x94\x31\x51\xf1\xc9\xb2\x75\x20\x90\x77\x8c\x32\x29\xdd\xb1\xfb\x0f\x6c\x09\xb3\xa6\xc8\x79\xf3\xee\x62\xd2\x7c\xdd\xf0\x31\xf8\xeb\xa8\xf6\x2e\x09\xf8\x03\x95\x58\x5c\x70\xb2\xce\x6a\x56\x58\x80\x68\x8b\xa2\x21\xcc\x4c\xc4\x9d\xb5\x24\x2b\x1f\xf9\xf1\x65\xd3\xcb\xe9\x2f\x11\x9b\x2c\xdc\xbb\x22\x87\x92\x54\x3d\x76\x16\xde\x60\xb5\x32\xae\x84\xc0\x2a\xe7\xeb\x35\x2f\x93\xb9\xed\x56\x11\x0a\x20\xb2\x47\x96\xe2\x78\x81\xac\x06\x4e\xcc\xaa\xec\x15\xc4\xe7\xed\x31\x0d\x10\x3e\xcd\xe5\x62\x3b\x57\xea\xb6\x5c\x32\xb7\x48\x3d\x2d\xb3\xad\xc9\x46\xf5\x83\xb4\x4b\x39\x40\x57\x07\x36\x65\x0b\x1d\xaa\xa4\x71\x1e\x1d\x8c\xa9\xed\x2a\x63\xb3\x45\x52\xac\x66\xbe\x71\x70\xf8\xf2\xac\x14\x62\x81\xc5\xde\xce\x8d\xc7\x23\x56\x1c\x71\x76\xc4\xd7\x22\x3d\xe2\x85\xd0\xfc\x0b\x99\x1b\x8a\x0a\xc7\xfc\x01\x1e\x17\xcd\xdc\x82\xde\x8f\x68\xbf\x47\x23\x73\xea\x62\x68\x53\xa8\xbe\x1d\x1d\x5c\xdc\x73\xfe\xbc\xd8\xff\xc2\x9f\x40\x15\xc9\x52\x63\x0a\x92\x57\x36\x7b\x15\xb5\x31\x7b\x68\xa4\x0d\xdd\xf3\x7c\x2b\x46\x58\xe5\x2d\xc4\xe9\xa8\xd6\x9d\x7f\xaa\x63\x62\xcb\x07\xea\xa1\x7e\xe7\xe0\x98\x0d\x60\x4c\xa1\xab\x62\xea\xef\x45\x4e\x6d\xcf\xd6\x36\xba\xc0\xa2\xc3\x7d\x33\x67\xcf\x82\x04\x51\xb6\xc9\x84\x4c\xa0\xc9\x5c\xae\xa7\xe6\xf7\x10\x0b\x50\xd6\xdc\x4b\x9e\xed\x98\x15\x13\x68\x98\xd4\x4f\x1c\x18\xe1\x54\xc4\x25\xe8\x77\xd3\x6e\x87\x34\x79\x2b\x98\xb1\x6d\x50\x34\x5d\x0a\xaa\x6e\x98\x5f\x26\x65\xce\xf3\x9d\x03\xa0\x85\xa4\x06\xcf\xa8\xfa\xf7\x72\x9b\xb2\x61\x21\x04\x9b\x64\x72\x21\x9a\x92\x6e\x7f\x44\xf5\x42\xfc\x30\x1f\x7e\xc0\xc3\x3c\x97\xd9\x32\x4d\xe6\x3a\x8d\x55\xe6\x25\xcf\xa8\x23\x7c\x2e\x56\xe2\x1d\x4b\x4a\x53\x8c\x29\xa8\x92\x0e\x17\x59\x71\xff\xfe\x83\x87\xaf\xb7\x97\x0b\xb9\xe6\x49\xf6\x74\x5d\x4e\xf7\xbf\x18\xfe\xb0\xe5\x29\x00\xfc\x27\x7c\x2d\x9e\xae\x03\xb9\x7b\xae\xaa\x14\xf0\x12\x5a\x1e\x31\x7c\xcf\x42\xdf\x6a\x98\x0e\x7f\xb9\x78\x33\xb6\xcc\x65\x72\x71\x6f\xff\x0b\xe7\xb7\xfd\x3b\x60\x35\x31\x05\x00\x9b\x86\x8d\xe7\x62\x52\x74\x3d\x57\xa0\x00\xf5\x5c\x80\xdb\xc9\x73\xc1\xdd\x55\x24\xec\xd2\x7f\xd7\x49\xa6\xfd\x97\xb7\x72\x8e\xb2\x5b\xb9\x84\xbd\x6f\xd6\xd7\x0d\x6c\x71\xb1\x13\x4f\x9c\x6c\x03\xcb\x72\xee\x41\x43\x06\x4f\xd0\x94\x2a\xab\xe4\xa8\x06\x01\x8e\x88\xd0\x6f\xf7\x42\xd5\x23\x6c\xeb\x5e\xc3\x9b\x1c\x3d\x04\x00\x66\x21\x28\x0f\xa2\xdf\x36\x8e\xea\xa6\x6d\x1c\xa3\xd5\xd7\x24\xb5\x41\x66\x1a\x99\x3d\x4a\x79\x81\x60\xff\x31\xf2\x67\x4f\x5d\xc1\x81\x66\xe1\x99\x28\xa7\xe4\x16\x1c\x5b\xfa\x54\xec\xe9\x1c\xaa\x59\x29\x25\xd8\xe3\x79\xc3\x8f\x49\x7c\x79\xf2\xea\xe5\xe1\xf3\x13\x2c\xfc\xc6\x4e\x0f\xcf\x9f\x8d\x08\x11\xa6\x1f\x94\x36\xa6\xbe\x06\x7e\x7f\xcd\xd3\xa4\x5b\x73\x7a\x61\x36\x01\xe2\xa0\x6c\xa8\xe3\x84\xed\xf6\x98\x24\x72\xba\x90\xf3\x62\x3a\x97\x99\xb2\xa0\x8b\xa9\xbc\x16\xf9\x75\x22\x6e\xa6\x37\x32\x7f\x9b\x64\xab\xb1\x9a\xbf\x31\x1e\x92\x62\x0a\x84\xa6\x7f\x84\xff\x79\x82\x88\x67\x19\xb3\x1b\x44\x17\x84\xd3\x5e\x45\x27\xd3\x07\x4c\xfe\x9b\x3c\x01\x95\x99\x56\xb6\x93\xa8\x4b\x91\xbc\xba\x6e\x9b\x19\x1d\xab\x5b\x4a\xad\xe2\xe8\x27\x06\x2a\x19\x62\x0f\xb2\xda\x86\xc6\xde\x71\x82\x67\x60\x02\x1a\x6c\x02\xbd\x99\x9e\x2a\x56\xa9\xcc\x56\x22\x67\x99\x98\x2b\xee\x96\xb7\xf9\x10\xf1\x13\xd5\x4c\x22\x42\xf5\xbc\xb3\xc6\x11\xb3\xa9\x15\x18\xb3\xe9\x6c\x3c\xf9\xf6\x3f\x7f\xfa\xc3\xc7\x7f\xde\x1b\xee\xdf\xfb\x64\xf4\xb7\xc7\x07\xdd\x09\xff\x41\xf1\xb1\xd1\xee\xb2\x28\xde\x62\x9d\x6b\xce\xf1\xd6\xe5\x86\xed\x8f\x14\xef\xa9\xac\x21\xbf\x1b\x03\xf6\x5b\xd3\x25\x8b\x80\x73\x97\x4b\xb3\x6b\x1b\xc6\xa0\x83\xab\x5c\x6e\x37\x3e\xc5\xd1\x84\x6e\x12\xeb\x50\x6c\x84\x8e\xdb\xe4\xed\xe7\xea\x50\x7a\x6f\x76\xf9\xf0\x97\xea\x59\x1a\x3d\x84\x07\xdb\xd6\xbe\x18\x92\x1d\x1f\x80\x79\x24\x73\xaf\x7a\x1d\xdd\xff\xc4\xee\xc9\x8f\xff\xfd\x21\xfb\x99\x44\xe9\x2d\x6f\x93\xcc\x1b\x58\x66\x16\x83\xe4\x40\xf4\xd4\xbf\x48\x32\x60\xd9\xe0\xaf\x7d\xaf\x49\x67\x43\x7a\x76\x7b\xac\xeb\x2b\xb0\xbd\xb5\x63\xa7\xf0\xa6\xd2\x39\x6b\xf4\xc8\xb7\x44\x91\x46\x6d\x95\xbb\x1c\x8e\xbf\xa1\x65\x3a\x1c\x7f\x63\x56\x8a\xfe\xed\xb7\x67\xa3\x96\x2a\x94\xa6\x13\x97\x9e\xf3\x0b\x6e\xfc\xc8\x59\x8d\x9e\x0c\xf0\x5d\xf6\x9b\x11\x74\x77\x3a\xd3\x82\x5f\xd4\xe7\xc6\x3b\x1f\x10\xf0\xb5\xcd\x1a\x99\xeb\xd5\xa6\x16\x72\xce\xd3\xca\x13\xfc\x36\x86\x76\xce\x36\xf3\x4e\x7f\xb1\xfd\xdc\xc9\x76\xde\x7b\x27\x87\xf6\x5c\x2d\x34\x50\xe6\xa5\x59\x32\x14\x05\xd8\xc0\xdf\x8a\x2e\x56\xf2\x7c\x25\xca\x40\x74\xf7\xf3\x52\x9b\xde\x49\x56\x8a\x7c\x93\x0b\x8c\xbe\xa6\xec\x9c\x74\x57\xa9\xc2\xab\x11\x8b\x80\xc1\x5a\x89\xf2\xb2\xa5\x3c\x9d\x08\x3e\xfd\x23\x9a\x01\x3a\x22\x23\xb0\x1d\xd4\xfb\xe2\x3b\x41\x22\xa4\x8e\xba\x29\xe8\x5f\xba\xd6\xab\x9b\x1f\xe9\x1f\x28\x4e\x18\x2f\x75\x40\xd0\xc6\x4e\xa1\x66\xd1\x30\x95\x43\x08\x0b\xd4\x79\x93\x01\x88\x00\xee\xd8\x9f\xb0\xe7\xe5\x1e\x06\x06\x38\xf9\x49\x98\xfa\x58\xb2\xef\xd4\xfa\x7d\xc7\xb6\x59\x0a\xd1\x02\x01\x8c\xd4\xca\x7a\x93\x04\x54\x38\x29\xa0\x10\xb7\x80\x4b\x8e\x81\x91\x9b\x4d\xba\x0b\x95\x47\xe1\x16\x14\x86\x97\xe6\x05\x93\x9b\x8d\xc4\x72\xa1\x14\x6e\xaa\x26\x77\x58\xec\xb3\x9b\x2b\x59\x08\xb8\x6c\xd8\x1a\x5c\x6a\x3f\xe4\x35\x32\x9e\x3e\x58\xf6\x4b\x59\x5e\x31\xd8\xb0\x6a\x1a\x5f\x63\x56\xa1\x51\x99\x2d\xcb\x08\x32\x03\x60\xd9\x8a\x06\x8c\x98\xf8\x13\x2e\x8b\x58\xd8\x20\x2c\x9b\x2f\xeb\xa5\x08\xc3\xb2\xb3\x88\xa0\x18\x86\x6e\xd5\x82\x20\x5f\x1e\xfe\x8b\xcd\xaf\xa4\x9a\x84\xc0\xac\xea\x2d\x84\x9e\xe3\x7a\xb8\x63\x33\xbc\x92\xae\x0f\x79\xec\x90\x1c\x42\xf6\x6d\x21\xc0\x60\x2d\x29\xdb\x23\x4f\x77\x26\x0d\xc3\x4b\xf1\x4a\xde\x4c\x93\x25\xd3\x6c\xc4\x39\xfb\xa6\x8e\x2a\x9c\x56\x4c\x02\x04\x1f\x02\xe8\xb9\xfe\x45\xe2\x3a\x54\x12\x3a\x1a\x81\xb5\x6d\x00\x7d\x5b\x89\x57\xed\x35\x65\xf4\x60\x66\x9b\x7f\xeb\xd7\xd9\x05\x7a\x6d\x0b\x96\x40\x9c\x6c\x99\xf0\x34\xdd\x4d\xaa\x51\x22\x61\xa5\x8c\x39\xac\x63\x0e\x8e\x54\xc5\x9b\xe7\x25\x55\x4d\xa7\xe0\xba\xb9\x79\x1b\x92\x5f\xfe\xb4\x8a\xcb\x1d\x9d\x41\xc5\x39\x46\x56\xca\x8d\x98\xcc\x9d\x1a\xdd\xcf\x97\xec\xbe\x9a\xce\x07\x3d\xc7\x89\x2f\xee\x4e\xaf\x29\x6d\xa7\x23\x85\x15\x7f\x08\x44\xd5\xb1\x4a\x97\xfa\x96\x58\xb7\xd6\x7a\xc9\x6a\xd4\x7e\x06\x25\x4d\x9c\x62\xc4\x88\xb5\x80\x7a\x8f\x61\x2e\x04\x55\x72\x36\x93\xa0\x83\xe5\xbc\x34\xef\xae\xbd\xa3\xe3\xa9\x7c\xe8\xab\x0e\x48\xf1\xca\x07\xec\xd1\xa7\x9f\x3e\xfc\xd4\xaf\x8d\xe0\x85\x61\x2d\x30\xe4\xce\x2c\x2c\x87\x8d\x57\x28\x5c\xb6\x5c\xd3\x90\xb9\xa6\x48\xf5\xc5\x83\xcb\x86\x42\xda\x51\x00\x9e\x67\xb5\x3a\xed\x86\x75\x8d\x5c\x79\xe0\x25\x5c\xe5\x52\xc4\x3b\x2c\x49\x0a\x36\xa4\x6d\x70\xc0\xbe\xa2\x7d\xe8\xa5\x79\x02\x47\xb2\x26\xa4\x86\xee\x26\xd8\x6f\x93\x59\x7e\x11\x50\xed\xe4\x10\x27\xb3\xfc\x42\xd5\xd6\x7f\xe8\x25\xb3\xbc\x44\x8d\x3c\x33\x32\x0b\x0f\xaa\x61\x22\xa0\xb5\xa3\xe0\xb1\x02\xcc\xaf\x4a\x9a\xa8\x1e\x53\x26\x75\x84\x08\x58\xab\x7c\x82\x04\xd2\xdb\xad\xbe\x55\x29\x1d\x93\x83\x0d\xdd\x48\x95\xfd\x51\x58\x53\x83\xac\x01\xa7\x17\x38\xe6\x75\x24\x98\x7c\x40\x5b\xb7\x29\x09\xfd\xab\x8f\x52\x32\x56\x12\x3a\x51\xc3\x7e\x05\x20\x13\xe6\x10\x26\xed\x8a\xb4\x95\x8c\x55\x79\xe8\xa5\xdb\xe4\xda\x31\xf2\xd0\xcf\x00\x50\x56\xf6\x94\x87\x5e\x92\x0f\xfa\x48\x97\x8a\x3c\x0c\x2b\xea\xa3\xdb\xc8\xc3\xd0\x31\xf8\x2d\xca\xc3\x9f\x1b\xd1\xf8\x59\xda\x17\x47\x58\xde\x21\x27\xa5\x37\x89\x32\xe0\x0f\xf4\xd1\x1e\xd7\xbc\x4b\xad\x97\x18\x18\xbc\xe5\xd7\xc8\x1c\xc9\x16\xf5\xa4\xcb\xbd\xd8\x3e\x5c\x3d\x8a\x2a\x2f\x6d\x7d\x7a\x93\xc0\xb8\x8a\xb6\x37\xee\xc2\x80\xb5\x03\x68\x00\x81\x5f\x94\x32\xe7\x2b\xe1\x7e\xb3\xbd\x34\x02\x48\x13\xd6\x9d\x05\x7f\xfc\xe9\x23\x1b\xcd\xa2\x73\x41\x00\xd3\xc2\x2b\x01\xc9\x65\x03\xdc\xd7\x9b\x74\x9b\xf3\x94\xfe\x74\x1b\x59\xbd\xb9\xf8\x08\x1f\x2c\x16\xff\xc0\x96\x08\xf8\xe5\x7f\x03\x00\x00\xff\xff\x9a\xd6\x90\xbb\x78\x4e\x03\x00") + +func assetsGatewayApiGatewayNetworkingK8sIo_httproutesYamlBytes() ([]byte, error) { + return bindataRead( + _assetsGatewayApiGatewayNetworkingK8sIo_httproutesYaml, + "assets/gateway-api/gateway.networking.k8s.io_httproutes.yaml", + ) +} + +func assetsGatewayApiGatewayNetworkingK8sIo_httproutesYaml() (*asset, error) { + bytes, err := assetsGatewayApiGatewayNetworkingK8sIo_httproutesYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "assets/gateway-api/gateway.networking.k8s.io_httproutes.yaml", size: 216696, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xba, 0xce, 0xd0, 0x7b, 0x2e, 0x5c, 0x87, 0x39, 0xf1, 0x4e, 0x1c, 0x49, 0x2, 0xb4, 0x13, 0x82, 0x1, 0x84, 0x29, 0x98, 0x2a, 0xa0, 0x58, 0xae, 0x7b, 0x1b, 0x10, 0x20, 0x9d, 0x18, 0xff, 0xb}} + return a, nil +} + +var _assetsGatewayApiGatewayNetworkingK8sIo_referencegrantsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x59\x6d\x6f\xdc\xc6\x11\xfe\x7e\xbf\x62\xa0\x06\x88\x6d\x88\x3c\x2b\x41\x8d\x94\x5f\x82\xab\x92\xba\x82\xdd\x46\x90\x54\x17\x88\x95\x00\x7b\xcb\xb9\xe3\x46\xe4\xee\x66\x77\x78\xd2\xa5\xed\x7f\x2f\x66\x97\x2f\x47\x1e\x69\x2b\x6a\x13\x14\x45\xf8\xe9\xb8\x2f\xcf\x0e\xe7\xe5\x99\x87\x3c\x61\xd5\x3b\x74\x5e\x19\x9d\x81\xb0\x0a\x1f\x08\x35\xdf\xf9\xf4\xee\x0b\x9f\x2a\xb3\xdc\x9d\x2d\xee\x94\xce\x33\x38\xaf\x3d\x99\xea\x0a\xbd\xa9\x9d\xc4\xaf\x70\xa3\xb4\x22\x65\xf4\xa2\x42\x12\xb9\x20\x91\x2d\x00\x84\xd6\x86\x04\x0f\x7b\xbe\x05\xc6\x4c\x84\xb5\xce\xec\x30\x4f\xef\xea\x35\x3a\x8d\x84\x8c\x9c\x41\x41\x64\x7d\xb6\x5c\x6e\x15\x15\xf5\x3a\x95\xa6\x5a\xf6\x2b\x12\xaf\xb6\x7e\xb9\x15\x84\xf7\x62\x9f\x08\xab\x96\xb6\x2e\xcb\xe5\xd9\xcb\x2f\x5e\x05\xe0\x66\x26\xd5\x48\xf7\xc6\xdd\x29\xbd\x6d\x2d\x5e\xd7\x3a\x2f\x31\xd9\xb5\x8f\xb5\x7b\x99\xbe\x4a\x5f\x26\x39\xee\x3e\xb2\x51\x16\x42\x6b\x2c\x33\xc0\x07\x8b\x4e\x55\xa8\x49\x94\x0b\x00\xe9\x30\x3c\xd2\x8d\xaa\xd0\x93\xa8\x6c\x06\xba\x2e\x79\x46\x8b\x0a\x33\x70\xb8\x41\x87\x5a\xe2\xd6\x09\x4d\x3e\x9d\x3d\x61\xe1\x2d\x4a\xf6\xcb\xd6\x99\xda\x66\xf3\xa6\x34\xd0\x8d\x0f\xa5\x20\xdc\x1a\xa7\xda\xfb\x04\x0e\xdc\x12\x46\x62\x84\xae\x5a\x3b\x5e\xb3\x1d\x61\xa2\x54\x9e\xde\x4c\x4c\xbe\x55\x3e\x2e\xb0\x65\xed\x44\x79\xf4\x0c\x61\xce\x17\xc6\xd1\x5f\x7b\x3b\x12\x5e\xb5\xed\xb0\xbd\xd2\xdb\xba\x14\x6e\xbc\x79\x01\xe0\xa5\xb1\x98\x41\xd8\x6b\x85\xc4\x7c\x01\xd0\xc4\x23\x60\x25\x20\xf2\x3c\x64\x8f\x28\x2f\x9d\xd2\x84\xee\xdc\x94\x75\xa5\xbb\x93\x7e\xf0\x46\x5f\x0a\x2a\x32\x48\xdb\xfc\x4a\x8f\xe2\x10\xd6\xb6\x51\x58\x6d\xb1\xb9\xa7\x3d\x1f\x9e\x0b\x8a\x03\x71\x7a\x77\x26\x4a\x5b\x88\xcf\xa2\xe9\xb2\xc0\x4a\x64\xcd\x7a\x63\x51\xaf\x2e\x2f\xde\x7d\x7e\x3d\x18\x06\xc8\xd1\x4b\xa7\x2c\x85\x34\x3a\x19\x7a\x10\x54\x8e\x9a\xd4\x46\xa1\x0f\xee\xf7\x60\x36\xe0\x9a\xea\xf0\xa0\x34\x18\x2a\xd0\xc5\x38\xb2\x0f\x7c\x07\x0b\x40\x85\x20\x10\x0e\x81\x5c\xed\x09\x73\x20\xd3\x3b\x11\xa8\x40\xe0\x4c\x61\xf0\x7c\x06\x3c\xac\x11\x15\x1e\x80\x76\x27\x81\xf0\x61\xde\x9a\x52\xc9\x7d\x0a\xb7\x1a\xbe\x16\xb2\x18\xa5\x00\x48\xa1\x61\x8d\x50\xfb\xf6\x7c\xeb\xd0\x63\x13\xdc\x78\x09\xa8\xb5\xfa\xb1\x6e\xec\x04\x87\x65\xac\xed\x42\xd9\x14\x56\x5d\x08\x7b\x64\x08\xd0\x7e\x84\x7d\x88\x98\x87\xc3\x82\xf9\x48\xfc\x58\xad\x0b\xda\x87\x33\x1b\x50\x7a\x6d\x6a\x9d\xf7\x2e\xf1\xb0\x31\x2e\x6c\xea\x1e\x72\xe0\x4d\xdc\x07\x6f\xe6\x4c\x4a\x98\xc3\xbd\xa2\x42\xe9\xf0\xe0\xab\xb2\x04\xe9\x8c\xf7\x49\xef\x9e\x03\x58\xa5\xe1\x75\xac\x25\x58\x5d\x5e\x1c\x60\x3e\x63\x8c\x70\x22\x3e\x48\x0c\x29\xc0\x96\x8d\xa1\x9a\xcd\x89\x33\x35\x21\x08\x22\x21\x0b\xe6\x8d\xe7\xe0\xf0\xc7\x5a\x39\x1c\x38\x73\x18\x80\x60\xdf\x75\x6d\xad\x71\x94\xc1\xb9\x71\x78\xd2\xad\xb6\xce\x58\x74\xd4\x95\x7c\x83\xd0\x93\xf5\xc1\xe8\x28\x4f\x3f\xe5\x54\x8e\xab\x1a\x87\xc4\x6c\x68\xea\x8f\x3d\x1d\xd2\x3c\xf8\xbe\x50\xbe\x0f\x7c\x88\xed\x00\x18\x78\x91\xd0\x60\xd6\x3f\xa0\xa4\x14\xae\xd1\x31\x0c\x33\x43\x5d\xe6\x20\x8d\xde\xa1\xe3\xbc\x90\x66\xab\xd5\x4f\x1d\xb6\x6f\x63\x5c\x0a\x42\x4f\x23\xcc\x50\xef\x9c\x36\x3b\x51\xd6\x78\x0a\x42\xe7\x50\x89\x3d\x38\xe4\x53\xa0\xd6\x07\x78\x61\x89\x4f\xe1\x2f\xc6\x21\x28\xbd\x19\xb6\x8d\x8e\xb9\x4d\x55\xd5\x5a\xd1\x7e\x29\x8d\x26\xa7\xd6\x35\x19\xe7\x97\x39\xee\xb0\x5c\x7a\xb5\x4d\x84\x93\x85\x22\x94\x54\x3b\x5c\x72\x4f\x0a\xa6\xeb\x90\xcc\x69\x95\xff\xae\xab\xad\x4f\x07\xb6\x46\x26\xf1\xe4\x94\xde\x1e\x4c\x04\xba\xfd\x40\x04\x98\x71\x41\x79\x10\xcd\xd6\xf8\x14\xbd\xa3\x79\x88\xbd\x73\xf5\xf5\xf5\x4d\x57\xd6\x21\x18\x63\xef\x07\xbf\xf7\x1b\x7d\x1f\x02\x76\x98\xd2\x1b\x74\x31\x88\x1b\x67\xaa\x98\xae\x3a\xb7\x46\x69\x0a\x37\xb2\x54\xc3\x82\xe6\xcb\xd7\xeb\x4a\x91\x0f\x19\x8a\x9e\x38\x56\x29\x9c\x87\xce\x1d\x6a\xd6\x32\x73\xe6\x29\x5c\x68\x38\x17\x15\x96\xe7\xc2\xe3\x2f\x1e\x00\xf6\xb4\x4f\x02\xd7\x3d\x2a\x04\x87\xa2\x63\xbc\x38\x7a\xed\x60\xa2\x6d\xbb\x33\xf1\xba\xb6\x28\x07\xa5\x92\xa3\x57\x8e\x93\x99\x04\x21\x97\xc0\xa8\x70\x07\x50\xd3\xa5\xca\x17\xc7\x64\x3c\x36\x6e\x2a\x7f\xe2\xb8\xc5\xa1\x75\x73\x7a\x4b\x88\x7d\xe7\x08\x15\x12\xfb\x00\x77\x8e\x23\x48\x08\x7c\x3b\x6c\x20\x7d\xb7\x68\xd1\x73\x66\xbb\xdb\x93\x1b\x73\x7b\x92\xc6\x86\x80\x9a\xdc\x3e\x76\x93\xa3\xd4\x83\x46\x3d\x40\xc5\xcc\xbf\x46\x2e\x76\xaf\x72\x74\xb1\x5b\xac\x91\x79\xa1\xef\xe2\x60\x4b\x11\x4e\x16\x74\xc0\xaf\x33\x96\xae\x91\x2b\x42\xe5\xc1\x43\xa7\xc0\xd4\x6e\xc0\xd6\x14\x53\x59\xe8\xd8\x39\xef\xc5\xfe\x34\x98\xc8\x2d\xb6\xb7\xa2\x5a\x33\xc7\x4f\x20\xd7\x2c\x48\xe0\x9b\xab\x0f\xf1\x6a\x7b\x29\xc2\xea\x28\x5e\x47\xd1\x19\x86\x7d\x1c\xaa\xc9\x30\x4d\x40\x46\xbe\xf0\xe9\xc4\xd4\x7c\xee\xc4\x2b\xea\xc4\xc9\xa9\x71\x22\xbd\xe6\xa5\x4c\x3a\x1c\xfc\xb0\x2f\x12\x7c\xd7\xee\x28\x85\xbf\x17\xa8\x01\x2b\x4b\xfb\xd3\x19\xcc\xd0\x4c\xe1\x4d\xa7\xc2\x41\x72\xd9\xaf\x2e\x2f\x1a\x48\xe5\x23\xe9\x38\x26\x88\x8f\xbb\x39\x5e\x95\x78\x78\x8b\x7a\xcb\x62\xee\xb3\xdf\x7f\x3e\xb3\xc8\x0a\xe2\xae\x90\xc1\xf7\x9f\xfc\xf3\xfb\xf7\x22\xf9\xe9\x65\xf2\x87\xef\x9e\xbd\x4f\x9a\x5f\x2f\xda\xa1\xe7\x5f\x3e\xbb\x4d\x3f\x38\xff\xfc\xc5\x27\x33\x67\xcc\x70\x49\x7f\x1d\x13\xfb\x9c\xbb\x5b\x8a\x67\x77\xf1\xae\x63\x67\xaf\x4a\x2a\x4c\xbd\x2d\x40\x55\xb6\xc4\xaa\xed\xaf\x53\x35\xd1\xba\x69\x0f\x3e\xfa\xf3\xb0\xb0\xba\x42\x3e\x0d\x07\x6c\x4c\x59\x9a\xfb\xd0\x41\x98\x32\x59\xf7\xcc\x22\x5a\xe1\xa8\x35\xec\xf6\x84\x43\x74\x7b\xd2\x1d\x51\x32\x37\x37\xba\x8a\x1b\x88\xc2\x32\xc6\x94\xb3\x64\x16\xb2\x55\x8b\x16\x5d\xa5\x08\x04\x5c\xa3\x74\x48\xdf\x04\xca\xed\xea\x25\x63\x9c\x17\x9d\xb4\xfa\xd9\xa0\x7f\x14\xf2\x0e\x75\x3e\x8d\xfa\xe7\x9b\x9b\xcb\xab\xa0\xb7\x5e\xcc\x22\xde\x9c\xb7\x4b\xe0\xe6\xed\x75\xfb\xf3\x6f\x5f\xc5\xd1\x47\x24\xea\xab\xb9\x3c\xad\x94\x6e\xd7\x9c\x7d\x34\x95\x39\x29\x57\xc9\xb7\x4d\x9e\xae\x92\x6f\xbb\x54\x6d\x7e\x3f\xff\xf2\xc9\xb9\xda\xf1\xce\xe3\x12\xb6\x7b\x17\x6b\xb3\xb6\x17\xb1\x47\xa9\x7b\x3b\x1f\xaa\x9f\x5b\xf0\xff\x3d\x3f\xce\xd6\xfb\x13\x3d\xd8\x08\xf4\xc9\x7a\x4f\x22\xdd\x4d\xce\x70\xb5\x4f\x4e\x4c\xbd\x9a\x0c\x6d\x39\x12\x26\x8d\x2b\xc4\xc3\x45\xe8\x47\x70\xf6\xea\x78\x52\xe9\x76\xf2\x68\x2e\xa2\x0a\xe7\xc4\x7e\x34\x47\xe6\x63\xc2\xe3\xc6\x8c\x64\x47\x2f\x18\x42\x13\x67\x36\x5a\x1f\xbc\x2b\xe5\xb0\x1e\x1f\x02\x4d\xbb\x98\x95\x1a\xdc\x31\xa7\xc5\x46\x2f\x2d\x26\x30\x9f\x28\x36\x06\xd2\x62\xca\x54\xf3\x34\xa9\xd1\x0b\x8b\x09\xd0\x5f\x46\x6a\x0c\x82\x73\xcf\x8f\xf9\x26\xa8\x3f\x7e\xc9\x15\xcc\xff\x98\x83\x98\xee\x24\x24\xdc\x16\xc9\x8f\x8a\x5a\xe2\x6f\xfa\xe3\x37\xfd\xf1\x3f\xaf\x3f\x9a\x0e\x1f\x35\xc5\x2c\xec\x3d\xa7\xd1\xe3\x84\x48\x00\x73\x3b\x25\x31\xec\xfa\x4f\x15\xc8\xff\x8d\x70\x78\x54\x92\xb1\x64\x38\x54\x0b\x33\x05\x5d\xeb\xee\x63\xe5\x87\xca\x5a\xf9\xe6\x83\x64\xdc\x1f\x3e\x11\x89\xf2\x20\xbf\x5a\xf8\xfe\xd3\xe7\xeb\x99\x26\x1c\x2f\x7e\x29\x8e\x65\x10\x3f\x87\x96\x46\x8a\xb2\xef\xc2\x53\x7c\x07\x8f\x65\x83\x47\x04\xeb\xd7\x95\x17\xbf\xae\x80\x98\x36\x3e\x09\xef\xeb\xa3\xa1\xc1\xd7\xdd\x19\x3b\x8f\x06\x3d\xba\x1d\xe6\x19\xbf\x43\x47\xf6\xf0\x64\x9c\xd8\xe2\xe1\x48\xbd\xee\x32\x23\x83\x7f\xfc\x6b\xe1\x49\x50\x1d\xfa\x94\x90\x12\x2d\x61\x7e\xf0\xd7\x44\xfc\x03\xe4\xe4\x64\xf0\x9f\x46\xb8\x95\x46\x47\x2a\xf3\x19\xbc\xff\x6e\x11\x8f\xc2\xfc\x5d\xfb\x6f\x04\x0f\xfe\x3b\x00\x00\xff\xff\xa7\x60\x48\x70\x05\x1b\x00\x00") + +func assetsGatewayApiGatewayNetworkingK8sIo_referencegrantsYamlBytes() ([]byte, error) { + return bindataRead( + _assetsGatewayApiGatewayNetworkingK8sIo_referencegrantsYaml, + "assets/gateway-api/gateway.networking.k8s.io_referencegrants.yaml", + ) +} + +func assetsGatewayApiGatewayNetworkingK8sIo_referencegrantsYaml() (*asset, error) { + bytes, err := assetsGatewayApiGatewayNetworkingK8sIo_referencegrantsYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "assets/gateway-api/gateway.networking.k8s.io_referencegrants.yaml", size: 6917, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe2, 0x9, 0x86, 0x25, 0x3, 0xd5, 0x4c, 0xc0, 0x18, 0x62, 0xa6, 0xbd, 0x3a, 0x38, 0x2e, 0x3c, 0x39, 0xcc, 0xae, 0xe7, 0x3a, 0xb0, 0x2e, 0x22, 0x37, 0xb1, 0x60, 0x9c, 0x86, 0x95, 0x72, 0x32}} + return a, nil +} + var _assetsRouterClusterRoleBindingYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8f\x31\x4e\xc4\x40\x0c\x45\xfb\x39\x85\x25\xea\x0c\xa2\x43\xd3\x01\x37\x58\x24\x7a\xef\xc4\xbb\x31\x49\xec\xc8\xf6\xa4\xe0\xf4\x28\x4a\x44\xc3\x4a\x29\x2d\xf9\xbf\xff\xfe\x13\xbc\xb3\xf4\x0e\x31\x10\x98\xb6\x20\x03\xd3\x89\x20\x14\x38\x1c\x3e\xc9\x56\xae\x04\x6f\xb5\x6a\x93\xc8\x69\x64\xe9\x0b\x7c\x4c\xcd\x83\xec\xa2\x13\x6d\x71\x96\x7b\xc2\x85\xbf\xc8\x9c\x55\x0a\xd8\x15\x6b\xc6\x16\x83\x1a\xff\x60\xb0\x4a\x1e\x5f\x3d\xb3\x3e\xaf\x2f\x69\xa6\xc0\x1e\x03\x4b\x02\x10\x9c\xa9\x80\x2e\x24\x3e\xf0\x2d\x3a\x96\xbb\x91\x7b\xb7\x9b\x24\x6f\xd7\x6f\xaa\xe1\x25\x75\xb0\x17\x1f\x3e\x87\xce\x1f\xe1\xf8\xdf\x4f\x5f\xb0\x3e\xa2\xa6\x6d\xd8\x85\x6e\x5b\xf1\xbf\x19\xe7\x32\x27\xf0\xdf\x00\x00\x00\xff\xff\x83\x13\xa9\xa6\x49\x01\x00\x00") func assetsRouterClusterRoleBindingYamlBytes() ([]byte, error) { @@ -402,7 +486,7 @@ func assetsRouterServiceInternalYaml() (*asset, error) { return a, nil } -var _manifests00ClusterRoleYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x56\x4d\x8f\xe3\x36\x0c\xbd\xfb\x57\x08\x33\x87\x05\x16\xb0\x83\xde\x8a\xdc\x8a\x16\xe8\xa9\x5d\xa0\x28\x7a\x67\x24\x26\x66\x47\x16\x0d\x92\xca\xac\xfb\xeb\x0b\xf9\x63\xb2\x93\xef\xd9\xcd\x29\x91\x4c\x3e\x3e\xf2\x91\x84\x9e\xdd\xaf\x31\xab\xa1\x38\xe1\x88\x6e\xcb\xe2\xac\x45\xc7\x3d\x0a\x18\x8b\x23\x53\x8c\xdb\xa6\x7a\x76\x7f\x7f\xf9\xed\xcb\xda\xfd\xe2\x22\x9b\xe3\x6d\xb1\x52\x74\xda\x72\x8e\xc1\x6d\xd0\x09\xf6\x11\x3c\x06\xb7\x19\x46\x28\x75\x94\x46\xa8\x04\x1d\x6a\x0f\x1e\x75\x44\x7f\x6d\xc9\xb7\xd5\xf3\xfb\x28\xe0\x2d\x43\x8c\x83\x4b\x88\x41\x1d\x78\x8f\xaa\x4d\xf5\x42\x29\xac\x17\x82\x7f\x71\xc4\x0a\x7a\xfa\x07\x45\x89\xd3\xda\xc9\x06\x7c\x03\xd9\x5a\x16\xfa\x0f\x8c\x38\x35\x2f\x3f\x6b\x43\xbc\xda\xff\x54\x75\x68\x10\xc0\x60\x5d\xb9\x91\xc1\xba\x04\x4b\xda\xd2\xd6\x6a\x4a\x3b\x41\xd5\x7a\x09\x5f\x39\x07\x29\xb1\x8d\x18\x5a\x3c\x9c\xa3\xe4\x63\x0e\xd8\x08\x46\x04\xc5\xe6\xcd\xbb\xe0\xd3\xa6\xab\x7d\xe4\x1c\xea\x0e\x12\xec\x30\xac\xdd\x93\x49\xc6\xa7\xdb\xae\xa5\x9a\x8b\x57\xdd\xd2\xae\xad\x61\x0f\x14\x61\x43\x91\x6c\xf8\x00\x0e\xa5\x5d\xc4\x3a\x71\xc0\x3a\xe0\x1e\x63\x49\xe6\xcd\x5d\x72\x44\x5d\x57\xb5\x83\x9e\x7e\x17\xce\xfd\x98\x55\xed\x9e\x0a\xb2\xa0\x72\x16\x8f\xf3\x9d\xe7\xb4\xa5\x5d\x07\xbd\x8e\xc7\x83\x5c\xe3\x51\x51\xf6\xe4\x11\xbc\xe7\x9c\x6c\xba\xc3\x14\x7a\xa6\xe5\x34\x5b\x2c\x07\x2f\x38\x7f\xe8\x39\xcc\xf6\x7b\x9c\x8c\xf7\x28\x9b\x85\xc9\xe7\xa7\xea\x3e\x7e\x05\x66\x85\x7b\xf2\x45\x9d\x23\x10\x2f\x08\x86\xf7\x22\x95\x62\x1d\xd1\x88\xa4\x76\xc6\x1b\xfa\xb1\x1a\x47\xfe\x01\xfb\xc8\x43\x87\x4b\xe6\x01\xb0\xe3\xa4\x78\x5f\x6e\x3d\x47\xf2\xc3\xd9\xfc\x02\xa9\xe4\xbe\xe4\xb7\xc9\x61\x77\x27\x5e\xc7\x89\x8c\x85\xd2\xae\xf1\x2c\xc8\xda\x78\xee\x4e\xe1\x67\x79\x66\xeb\x23\xe4\xa9\x7e\xe3\xdf\x1d\xda\xf8\x9b\xfb\x50\xae\x4e\xe3\x5d\x1c\xb7\x33\x2d\x35\x4d\xec\xb8\x06\x8e\x2f\x36\x94\x02\xa5\xdd\x74\x7f\xb0\x38\xfa\x74\x9d\xe3\xa8\x5a\xf9\xf3\x0a\xe6\xdb\xeb\xb4\x97\x21\x7f\x37\x3e\xa7\x94\xe7\x9d\xe0\x39\x99\x70\x8c\x28\x7a\xe1\x7a\xa5\x06\x96\xef\x52\x68\x76\x6e\xee\xa4\x10\x92\x0a\x7a\x96\x79\x6a\x0e\xc7\x0f\x84\x9c\x86\xf9\x66\xae\x5b\x01\x35\xc9\xde\xb2\xe0\xbb\x44\xf1\x2d\xf6\xfc\x0f\x7a\x2a\x1d\xb4\xd4\x23\xa1\xbd\xb2\xbc\x1c\x71\x29\xba\x7c\x27\x97\x43\xa4\x5b\xac\x8e\xa7\xf6\xa0\xff\x77\x86\x9e\x9b\x72\x51\xe7\xc3\x6d\xf7\xa0\xb0\x67\xd5\xbd\xd8\xce\x77\x0a\x3c\x97\xed\x2c\x76\x7f\x81\xfd\xac\x6d\x59\x28\x97\x06\x7b\x19\x87\x08\xa7\xa2\x7c\xfa\xfc\xa9\xaa\x9e\xdd\x1f\x24\xc2\x82\xc1\x6d\x85\x3b\x57\xec\x4c\x57\xc2\xd9\x50\x56\x1d\x9a\x90\xd7\xd5\x5c\x82\xba\x0c\x7d\x33\x40\x17\xcf\x6c\x9b\xe2\x71\x23\xcd\x09\x55\x17\xd8\x33\x3d\x79\x9d\xce\x1d\x34\xca\xbe\xc3\x64\xe4\xaf\x2f\x3c\xe3\x17\x4c\x82\x7b\xc2\xd7\xf3\x6d\xf4\x18\x26\xb7\x37\xaf\xe6\xcd\xbf\xe8\x6d\x7a\x40\x3d\x94\xd0\xb3\x83\x14\x1c\x7e\xed\x21\x85\xe2\x33\x3f\x14\x3d\x24\x90\xa1\x3e\x2c\xc8\xe6\x07\xb4\xfc\x78\x47\x3d\xb2\x93\xae\x4f\xe2\x0f\xf3\x50\xf4\x59\xc8\x86\x1b\x54\x16\xb3\x52\x51\xfc\x6a\x9e\x93\x9a\x00\x9d\x3c\xa0\xb2\xe2\x37\xce\x7f\x96\x57\xdb\xf4\xa1\x65\xb5\x79\x94\x1f\xc0\x3a\x90\x7a\xde\xa3\x0c\x17\x5b\xee\xed\x35\x18\xe7\x57\xe0\xe5\x45\xfd\x7f\x00\x00\x00\xff\xff\x82\x99\xe5\x95\x6d\x0c\x00\x00") +var _manifests00ClusterRoleYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x56\x4d\x8f\xe3\x36\x0f\xbe\xe7\x57\x08\x33\x87\x05\x16\xb0\x83\xf7\xf6\x22\xb7\xa2\x05\x7a\x6a\x17\x28\x8a\xde\x19\x89\x89\xd9\x91\x45\x81\xa4\x32\x9b\xfe\xfa\x42\x8e\x9d\x74\x33\x4e\xe2\xd9\x9d\x53\x22\x9a\x7c\xf8\x88\x5f\xe2\xb3\xfb\x39\x16\x35\x14\x27\x1c\xd1\xed\x58\x9c\x75\xe8\x38\xa3\x80\xb1\x38\x32\xc5\xb8\x6b\x57\xcf\xee\xcf\x2f\xbf\x7c\xd9\xb8\x9f\x5c\x64\x73\xbc\xab\x5a\x8a\x4e\x3b\x2e\x31\xb8\x2d\x3a\xc1\x1c\xc1\x63\x70\xdb\xe3\x00\xa5\x8e\xd2\x00\x95\xa0\x47\xcd\xe0\x51\x07\xf4\xd7\x8e\x7c\xb7\x7a\xfe\xd6\x0b\x78\x2b\x10\xe3\xd1\x25\xc4\xa0\x0e\xbc\x47\xd5\x76\xf5\x42\x29\x6c\x26\x82\x7f\x70\xc4\x15\x64\xfa\x0b\x45\x89\xd3\xc6\xc9\x16\x7c\x0b\xc5\x3a\x16\xfa\x07\x8c\x38\xb5\x2f\xff\xd7\x96\x78\x7d\xf8\xdf\xaa\x47\x83\x00\x06\x9b\x95\x1b\x18\x6c\xaa\xb3\xa4\x1d\xed\xac\xa1\xb4\x17\x54\x6d\x26\xf7\x2b\xe7\x20\x25\xb6\x01\x43\xab\x85\x73\x94\x7c\x2c\x01\x5b\xc1\x88\xa0\xd8\x9e\xad\x2b\x3e\x6d\xfb\xc6\x47\x2e\xa1\xe9\x21\xc1\x1e\xc3\xc6\x3d\x99\x14\x7c\x7a\x6c\x5a\xa3\x39\x59\x35\x1d\xed\xbb\x06\x0e\x40\x11\xb6\x14\xc9\x8e\xef\xc0\xa1\xb4\x8f\xd8\x24\x0e\xd8\x04\x3c\x60\xac\x97\x39\x9b\x4b\x89\xa8\x9b\x55\xe3\x20\xd3\xaf\xc2\x25\x0f\xb7\x6a\xdc\x53\x45\x16\x54\x2e\xe2\x71\x94\x79\x4e\x3b\xda\xf7\x90\x75\x38\x5e\xd2\x35\x1c\x15\xe5\x40\x1e\xc1\x7b\x2e\xc9\x4e\x32\x4c\x21\x33\x4d\xa7\x51\x63\x3a\x78\xc1\xf1\x43\xe6\x30\xea\x1f\xf0\xa4\x7c\x40\xd9\x4e\x4c\x3e\x3f\xad\x96\xf1\xab\x30\x6b\x3c\x90\xaf\xd9\xb9\x02\xf1\x82\x60\xb8\x14\xa9\x06\xeb\x8a\x46\x24\xb5\x19\x6b\xc8\x43\x34\xae\xec\x03\xe6\xc8\xc7\x1e\xa7\x9b\x07\xc0\x9e\x93\xe2\xb2\xbb\x65\x8e\xe4\x8f\xb3\xf7\x0b\xa4\x52\x72\xbd\xdf\xb6\x84\xfd\x42\xbc\x9e\x13\x19\x0b\xa5\x7d\xeb\x59\x90\xb5\xf5\xdc\xbf\x85\x1f\xd3\x33\x6a\x5f\x21\x9f\xe2\x37\xfc\xdd\xa3\x0d\xbf\x25\x87\x2a\x7a\xeb\xef\x66\xbb\xcd\x94\xd4\xa9\x63\x87\x31\x70\x2d\xd8\x52\x0a\x94\xf6\x27\xf9\x45\xe3\xea\xd3\x7d\x8e\x43\xd6\xea\x9f\x57\x30\xdf\xdd\xa7\x3d\x35\xf9\x37\xed\xf3\x96\xf2\x38\x13\x3c\x27\x13\x8e\x11\x45\x6f\x88\xd7\x6a\x60\x65\x51\x86\x46\xe3\x76\x21\x85\x90\x54\xd0\xb3\x8c\x5d\x73\x39\xbe\xc3\xe5\xa9\x99\x1f\xde\x75\x27\xa0\x26\xc5\x5b\x11\xfc\xe6\xa2\x78\xf6\x3d\xfe\xdb\x21\x54\xa5\x3d\xd8\x28\x80\x4c\xb5\xa4\xa6\x00\x25\xb4\x57\x96\x97\x2b\x72\x35\x51\xdf\x49\xee\x8e\xeb\x47\xbc\xaf\xfb\xfa\x52\x21\xdf\xc9\x65\x2c\xdb\x29\x7f\xef\x2e\xcc\x0f\x72\x3b\x9b\xff\x9b\x05\xbf\xb0\x04\xc6\xb0\xcd\x62\xe7\x1b\xec\xc7\x64\xd7\x91\x73\xab\xf5\xa7\x86\x89\xf0\x36\x29\x9f\x3e\x7f\x9a\x01\xad\xf9\x7d\x85\x63\xbb\x00\x7c\x54\xbd\x80\x9f\x45\xa7\x43\x67\x96\x85\x8b\x2d\x73\x0c\x99\xf0\xab\x61\xaa\xdb\x84\xde\x9e\x65\x45\x8d\xfb\x49\x18\x70\x47\x89\x86\x3d\x61\x89\x8b\x73\x0a\xef\x8f\xe8\xb2\x55\x2f\x94\x17\xc3\xf6\x40\x6a\x02\xb3\x7c\xa7\x79\x8f\xda\x8d\x53\x2b\x47\x48\xb3\x11\x79\x76\xbf\x91\x08\x0b\x06\xb7\x13\xee\x5d\x8d\xaa\xe9\x7a\x88\xa0\xac\x7b\x34\x21\xaf\xeb\xb1\x1a\x9b\x3a\xa1\xdb\x23\xf4\x71\xe6\x69\xa8\x16\x0f\x2a\xee\x84\xaa\x13\xec\xcc\xbc\xb8\x4f\x67\x01\x8d\xfa\x38\x61\x32\xf2\xf7\x5f\x27\xe3\x17\x4c\x82\x07\xc2\xd7\xf9\x8e\xfe\x18\x26\x8f\x9f\x49\x2d\xdb\xbf\xd1\xdb\x69\xdb\xfd\x50\x42\xcf\x0e\x52\x70\xf8\x35\x43\x0a\xd5\x66\xdc\xea\x3d\x24\x90\x63\x73\x79\xcd\xda\x1f\xc8\xe5\xfb\x2b\xea\x23\x2b\xe9\xfe\x50\xfc\x61\x1e\x8a\xbe\x08\xd9\xf1\x01\x95\x49\xad\x46\x14\xbf\x9a\xe7\x54\xfb\x92\xde\x6c\xbb\x45\xf1\x3f\xc6\xbf\xd7\x15\xfb\xf4\xa1\x63\xb5\x71\xf0\x7d\x00\xeb\x40\xea\xf9\x80\x72\xbc\x59\x72\xe7\xd5\x3d\x8e\x2b\xfb\xed\x37\xf3\xdf\x00\x00\x00\xff\xff\x8f\x1f\x4f\x3f\x1a\x0e\x00\x00") func manifests00ClusterRoleYamlBytes() ([]byte, error) { return bindataRead( @@ -417,8 +501,8 @@ func manifests00ClusterRoleYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "manifests/00-cluster-role.yaml", size: 3181, mode: os.FileMode(420), modTime: time.Unix(1, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xbc, 0x19, 0xbd, 0x6e, 0x68, 0x84, 0x61, 0xc8, 0x1a, 0x23, 0xe9, 0x91, 0xfb, 0x1f, 0xb2, 0xd9, 0xc2, 0x59, 0x46, 0xc7, 0x74, 0x9b, 0x46, 0x32, 0xe2, 0x96, 0x94, 0xe3, 0xe1, 0xc5, 0x91, 0x53}} + info := bindataFileInfo{name: "manifests/00-cluster-role.yaml", size: 3610, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa0, 0x9d, 0xb9, 0x75, 0x9f, 0x7e, 0xc7, 0xd9, 0x8b, 0x89, 0xb, 0xc, 0xd6, 0x9d, 0xbc, 0x42, 0x3f, 0xa1, 0xaa, 0xed, 0xf, 0xc7, 0x21, 0x52, 0x1c, 0x3b, 0x87, 0x2d, 0x6c, 0x5, 0x48, 0x2a}} return a, nil } @@ -881,6 +965,14 @@ var _bindata = map[string]func() (*asset, error){ "assets/canary/service.yaml": assetsCanaryServiceYaml, + "assets/gateway-api/gateway.networking.k8s.io_gatewayclasses.yaml": assetsGatewayApiGatewayNetworkingK8sIo_gatewayclassesYaml, + + "assets/gateway-api/gateway.networking.k8s.io_gateways.yaml": assetsGatewayApiGatewayNetworkingK8sIo_gatewaysYaml, + + "assets/gateway-api/gateway.networking.k8s.io_httproutes.yaml": assetsGatewayApiGatewayNetworkingK8sIo_httproutesYaml, + + "assets/gateway-api/gateway.networking.k8s.io_referencegrants.yaml": assetsGatewayApiGatewayNetworkingK8sIo_referencegrantsYaml, + "assets/router/cluster-role-binding.yaml": assetsRouterClusterRoleBindingYaml, "assets/router/cluster-role.yaml": assetsRouterClusterRoleYaml, @@ -992,6 +1084,12 @@ var _bintree = &bintree{nil, map[string]*bintree{ "route.yaml": {assetsCanaryRouteYaml, map[string]*bintree{}}, "service.yaml": {assetsCanaryServiceYaml, map[string]*bintree{}}, }}, + "gateway-api": {nil, map[string]*bintree{ + "gateway.networking.k8s.io_gatewayclasses.yaml": {assetsGatewayApiGatewayNetworkingK8sIo_gatewayclassesYaml, map[string]*bintree{}}, + "gateway.networking.k8s.io_gateways.yaml": {assetsGatewayApiGatewayNetworkingK8sIo_gatewaysYaml, map[string]*bintree{}}, + "gateway.networking.k8s.io_httproutes.yaml": {assetsGatewayApiGatewayNetworkingK8sIo_httproutesYaml, map[string]*bintree{}}, + "gateway.networking.k8s.io_referencegrants.yaml": {assetsGatewayApiGatewayNetworkingK8sIo_referencegrantsYaml, map[string]*bintree{}}, + }}, "router": {nil, map[string]*bintree{ "cluster-role-binding.yaml": {assetsRouterClusterRoleBindingYaml, map[string]*bintree{}}, "cluster-role.yaml": {assetsRouterClusterRoleYaml, map[string]*bintree{}}, diff --git a/pkg/manifests/manifests.go b/pkg/manifests/manifests.go index c090b74b87..0324d3d24c 100644 --- a/pkg/manifests/manifests.go +++ b/pkg/manifests/manifests.go @@ -13,6 +13,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/yaml" @@ -40,6 +41,11 @@ const ( CanaryServiceAsset = "assets/canary/service.yaml" CanaryRouteAsset = "assets/canary/route.yaml" + GatewayClassCRDAsset = "assets/gateway-api/gateway.networking.k8s.io_gatewayclasses.yaml" + GatewayCRDAsset = "assets/gateway-api/gateway.networking.k8s.io_gateways.yaml" + HTTPRouteCRDAsset = "assets/gateway-api/gateway.networking.k8s.io_httproutes.yaml" + ReferenceGrantCRDAsset = "assets/gateway-api/gateway.networking.k8s.io_referencegrants.yaml" + // Annotation used to inform the certificate generation service to // generate a cluster-signed certificate and populate the secret. ServingCertSecretAnnotation = "service.alpha.openshift.io/serving-cert-secret-name" @@ -213,6 +219,38 @@ func CanaryRoute() *routev1.Route { return route } +func GatewayClassCRD() *apiextensionsv1.CustomResourceDefinition { + crd, err := NewCustomResourceDefinition(MustAssetReader(GatewayClassCRDAsset)) + if err != nil { + panic(err) + } + return crd +} + +func GatewayCRD() *apiextensionsv1.CustomResourceDefinition { + crd, err := NewCustomResourceDefinition(MustAssetReader(GatewayCRDAsset)) + if err != nil { + panic(err) + } + return crd +} + +func HTTPRouteCRD() *apiextensionsv1.CustomResourceDefinition { + crd, err := NewCustomResourceDefinition(MustAssetReader(HTTPRouteCRDAsset)) + if err != nil { + panic(err) + } + return crd +} + +func ReferenceGrantCRD() *apiextensionsv1.CustomResourceDefinition { + crd, err := NewCustomResourceDefinition(MustAssetReader(ReferenceGrantCRDAsset)) + if err != nil { + panic(err) + } + return crd +} + func NewServiceAccount(manifest io.Reader) (*corev1.ServiceAccount, error) { sa := corev1.ServiceAccount{} if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&sa); err != nil { @@ -302,3 +340,12 @@ func NewRoute(manifest io.Reader) (*routev1.Route, error) { return &o, nil } + +func NewCustomResourceDefinition(manifest io.Reader) (*apiextensionsv1.CustomResourceDefinition, error) { + o := apiextensionsv1.CustomResourceDefinition{} + if err := yaml.NewYAMLOrJSONDecoder(manifest, 100).Decode(&o); err != nil { + return nil, err + } + + return &o, nil +} diff --git a/pkg/manifests/manifests_test.go b/pkg/manifests/manifests_test.go index acdaf15e7a..21f1cb3fd7 100644 --- a/pkg/manifests/manifests_test.go +++ b/pkg/manifests/manifests_test.go @@ -43,4 +43,9 @@ func TestManifests(t *testing.T) { RouterDeployment() InternalIngressControllerService() LoadBalancerService() + + GatewayClassCRD() + GatewayCRD() + HTTPRouteCRD() + ReferenceGrantCRD() } diff --git a/pkg/operator/client/client.go b/pkg/operator/client/client.go index 8d0990d175..fcf3647f4d 100644 --- a/pkg/operator/client/client.go +++ b/pkg/operator/client/client.go @@ -9,6 +9,13 @@ import ( operatorv1 "github.com/openshift/api/operator/v1" routev1 "github.com/openshift/api/route/v1" + maistrav1 "github.com/maistra/istio-operator/pkg/apis/maistra/v1" + maistrav2 "github.com/maistra/istio-operator/pkg/apis/maistra/v2" + operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" + gatewayapiv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" + + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + kscheme "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" @@ -42,6 +49,21 @@ func init() { if err := routev1.Install(scheme); err != nil { panic(err) } + if err := apiextensionsv1.AddToScheme(scheme); err != nil { + panic(err) + } + if err := gatewayapiv1beta1.Install(scheme); err != nil { + panic(err) + } + if err := operatorsv1alpha1.AddToScheme(scheme); err != nil { + panic(err) + } + if err := maistrav1.SchemeBuilder.AddToScheme(scheme); err != nil { + panic(err) + } + if err := maistrav2.SchemeBuilder.AddToScheme(scheme); err != nil { + panic(err) + } } func GetScheme() *runtime.Scheme { diff --git a/pkg/operator/controller/dns/controller.go b/pkg/operator/controller/dns/controller.go index d03e433bd1..6bd5494e9a 100644 --- a/pkg/operator/controller/dns/controller.go +++ b/pkg/operator/controller/dns/controller.go @@ -107,8 +107,9 @@ func New(mgr manager.Manager, config Config) (runtimecontroller.Controller, erro // Config holds all the things necessary for the controller to run. type Config struct { - Namespace string - OperatorReleaseVersion string + CredentialsRequestNamespace string + DNSRecordNamespaces []string + OperatorReleaseVersion string } type reconciler struct { @@ -160,14 +161,6 @@ func (r *reconciler) Reconcile(ctx context.Context, request reconcile.Request) ( return reconcile.Result{}, nil } - // Only process records associated with ingresscontrollers, because this isn't - // intended to be a general purpose DNS management system. - ingressName, ok := record.Labels[manifests.OwningIngressControllerLabel] - if !ok { - log.V(2).Info("warning: dnsrecord is missing owner label", "dnsrecord", record, "ingresscontroller", ingressName) - return reconcile.Result{RequeueAfter: 1 * time.Minute}, nil - } - // Existing 4.1 records will have a zero TTL. Instead of making all the client implementations guard against // zero TTLs, simply ignore the record until the TTL is updated by the ingresscontroller controller. Report // this through events so we can detect problems with our migration. @@ -176,18 +169,6 @@ func (r *reconciler) Reconcile(ctx context.Context, request reconcile.Request) ( return reconcile.Result{}, nil } - if err := r.cache.Get(ctx, types.NamespacedName{Namespace: record.Namespace, Name: ingressName}, &operatorv1.IngressController{}); err != nil { - if errors.IsNotFound(err) { - // TODO: what should we do here? something upstream could detect and delete the orphan? add new conditions? - // is it safe to retry without verifying the owner isn't a new object? - log.V(2).Info("warning: dnsrecord owner not found; the dnsrecord may be orphaned; will retry", "dnsrecord", record, "ingresscontroller", ingressName) - return reconcile.Result{RequeueAfter: 1 * time.Minute}, nil - } else { - log.Error(err, "failed to get ingresscontroller for dnsrecord; will retry", "dnsrecord", record, "ingresscontroller", ingressName) - return reconcile.Result{RequeueAfter: 15 * time.Second}, nil - } - } - var zones []configv1.DNSZone if dnsConfig.Spec.PrivateZone != nil { zones = append(zones, *dnsConfig.Spec.PrivateZone) @@ -204,7 +185,12 @@ func (r *reconciler) Reconcile(ctx context.Context, request reconcile.Request) ( } if !dnsZoneStatusSlicesEqual(statuses, record.Status.Zones) { - updated := record.DeepCopy() + var current iov1.DNSRecord + if err := r.client.Get(ctx, request.NamespacedName, ¤t); err != nil { + log.Error(err, "failed to get dnsrecord; will retry", "dnsrecord", request.NamespacedName) + return reconcile.Result{RequeueAfter: 10 * time.Second}, nil + } + updated := current.DeepCopy() updated.Status.Zones = statuses updated.Status.ObservedGeneration = updated.Generation if err := r.client.Status().Update(ctx, updated); err != nil { @@ -247,7 +233,10 @@ func (r *reconciler) createDNSProviderIfNeeded(dnsConfig *configv1.DNS, record * if platformStatus.Type == configv1.IBMCloudPlatformType && infraConfig.Status.ControlPlaneTopology == configv1.ExternalTopologyMode { break } - name := types.NamespacedName{Namespace: r.config.Namespace, Name: cloudCredentialsSecretName} + name := types.NamespacedName{ + Namespace: r.config.CredentialsRequestNamespace, + Name: cloudCredentialsSecretName, + } if err := r.cache.Get(context.TODO(), name, creds); err != nil { return fmt.Errorf("failed to get cloud credentials from secret %s: %v", name, err) } @@ -567,20 +556,22 @@ func dnsZoneStatusSlicesEqual(a, b []iov1.DNSZoneStatus) bool { // ToDNSRecords returns reconciliation requests for all DNSRecords. func (r *reconciler) ToDNSRecords(o client.Object) []reconcile.Request { var requests []reconcile.Request - records := &iov1.DNSRecordList{} - if err := r.cache.List(context.Background(), records, client.InNamespace(r.config.Namespace)); err != nil { - log.Error(err, "failed to list dnsrecords", "related", o.GetSelfLink()) - return requests - } - for _, record := range records.Items { - log.Info("queueing dnsrecord", "name", record.Name, "related", o.GetSelfLink()) - request := reconcile.Request{ - NamespacedName: types.NamespacedName{ - Namespace: record.Namespace, - Name: record.Name, - }, + for _, ns := range r.config.DNSRecordNamespaces { + records := &iov1.DNSRecordList{} + if err := r.cache.List(context.Background(), records, client.InNamespace(ns)); err != nil { + log.Error(err, "failed to list dnsrecords", "related", o.GetSelfLink()) + continue + } + for _, record := range records.Items { + log.Info("queueing dnsrecord", "name", record.Name, "related", o.GetSelfLink()) + request := reconcile.Request{ + NamespacedName: types.NamespacedName{ + Namespace: record.Namespace, + Name: record.Name, + }, + } + requests = append(requests, request) } - requests = append(requests, request) } return requests } @@ -607,6 +598,7 @@ func (r *reconciler) createDNSProvider(dnsConfig *configv1.DNS, platformStatus * case configv1.AWSPlatformType: cfg := awsdns.Config{ Region: platformStatus.AWS.Region, + Client: r.client, } sharedCredsFile, err := awsutil.SharedCredentialsFileFromSecret(creds) diff --git a/pkg/operator/controller/gateway-service-dns/controller.go b/pkg/operator/controller/gateway-service-dns/controller.go new file mode 100644 index 0000000000..1e86842e37 --- /dev/null +++ b/pkg/operator/controller/gateway-service-dns/controller.go @@ -0,0 +1,256 @@ +package gateway_service_dns + +import ( + "context" + "reflect" + + logf "github.com/openshift/cluster-ingress-operator/pkg/log" + operatorcontroller "github.com/openshift/cluster-ingress-operator/pkg/operator/controller" + "github.com/openshift/cluster-ingress-operator/pkg/resources/dnsrecord" + + gatewayapiv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" + + "k8s.io/client-go/tools/record" + + corev1 "k8s.io/api/core/v1" + + iov1 "github.com/openshift/api/operatoringress/v1" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/sets" + + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + "sigs.k8s.io/controller-runtime/pkg/source" +) + +const ( + controllerName = "service_dns_controller" + + // gatewayNameLabelKey is the key of a label that Istio adds to + // deployments that it creates for gateways that it manages. Istio uses + // this label in the selector of any service that it creates for a + // gateway. + gatewayNameLabelKey = "istio.io/gateway-name" + // managedByIstioLabelKey is the key of a label that Istio adds to + // resources that it manages. + managedByIstioLabelKey = "gateway.istio.io/managed" +) + +var log = logf.Logger.WithName(controllerName) + +// NewUnmanaged creates and returns a controller that watches services that are +// associated with gateways and creates dnsrecord objects for them. This is an +// unmanaged controller, which means that the manager does not start it. +func NewUnmanaged(mgr manager.Manager, config Config) (controller.Controller, error) { + reconciler := &reconciler{ + config: config, + client: mgr.GetClient(), + cache: mgr.GetCache(), + recorder: mgr.GetEventRecorderFor(controllerName), + } + c, err := controller.NewUnmanaged(controllerName, mgr, controller.Options{Reconciler: reconciler}) + if err != nil { + return nil, err + } + isServiceNeedingDNS := predicate.NewPredicateFuncs(func(o client.Object) bool { + _, ok := o.(*corev1.Service).Labels[managedByIstioLabelKey] + return ok + }) + gatewayListenersChanged := predicate.Funcs{ + UpdateFunc: func(e event.UpdateEvent) bool { + old := e.ObjectOld.(*gatewayapiv1beta1.Gateway).Spec.Listeners + new := e.ObjectNew.(*gatewayapiv1beta1.Gateway).Spec.Listeners + // A DNSRecord CR needs to be updated if, and only if, + // the hostname has changed (a listener's port and + // protocol have no bearing on the DNS record). + return gatewayListenersHostnamesChanged(old, new) + }, + } + isInOperandNamespace := predicate.NewPredicateFuncs(func(o client.Object) bool { + return o.GetNamespace() == config.OperandNamespace + }) + gatewayToService := func(o client.Object) []reconcile.Request { + var services corev1.ServiceList + listOpts := []client.ListOption{ + client.MatchingLabels{gatewayNameLabelKey: o.GetName()}, + client.InNamespace(config.OperandNamespace), + } + requests := []reconcile.Request{} + if err := reconciler.cache.List(context.Background(), &services, listOpts...); err != nil { + log.Error(err, "failed to list services for gateway", "gateway", o.GetName()) + return requests + } + for i := range services.Items { + request := reconcile.Request{ + NamespacedName: types.NamespacedName{ + Namespace: services.Items[i].Namespace, + Name: services.Items[i].Name, + }, + } + requests = append(requests, request) + } + return requests + } + if err := c.Watch(&source.Kind{Type: &gatewayapiv1beta1.Gateway{}}, handler.EnqueueRequestsFromMapFunc(gatewayToService), isInOperandNamespace, gatewayListenersChanged); err != nil { + return nil, err + } + if err := c.Watch(&source.Kind{Type: &corev1.Service{}}, &handler.EnqueueRequestForObject{}, isServiceNeedingDNS, isInOperandNamespace); err != nil { + return nil, err + } + if err := c.Watch(&source.Kind{Type: &iov1.DNSRecord{}}, &handler.EnqueueRequestForOwner{OwnerType: &corev1.Service{}}, isInOperandNamespace); err != nil { + return nil, err + } + return c, nil +} + +// gatewayListenersHostnamesChanged returns a Boolean indicating whether any +// hostnames changed in the given gateway listeners. +func gatewayListenersHostnamesChanged(xs, ys []gatewayapiv1beta1.Listener) bool { + x := map[string]string{} + y := map[string]string{} + for i := range xs { + if xs[i].Hostname != nil { + x[string(xs[i].Name)] = string(*xs[i].Hostname) + } + } + for i := range ys { + if ys[i].Hostname != nil { + y[string(ys[i].Name)] = string(*ys[i].Hostname) + } + } + return !reflect.DeepEqual(x, y) +} + +// Config holds all the configuration that must be provided when creating the +// controller. +type Config struct { + // OperandNamespace is the namespace in which to watch for services and + // dnsrecords and in which to create dnsrecords. + OperandNamespace string +} + +// reconciler handles the actual service reconciliation logic. +type reconciler struct { + config Config + + client client.Client + cache cache.Cache + recorder record.EventRecorder +} + +// Reconcile expects request to refer to a service and creates or reconciles a +// dnsrecord. +func (r *reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { + log.Info("reconciling", "request", request) + + var service corev1.Service + if err := r.cache.Get(ctx, request.NamespacedName, &service); err != nil { + if apierrors.IsNotFound(err) { + log.Info("service not found; reconciliation will be skipped", "request", request) + return reconcile.Result{}, nil + } + return reconcile.Result{}, err + } + + if len(service.Spec.Selector[gatewayNameLabelKey]) == 0 { + log.Info(`service selector has no "`+gatewayNameLabelKey+`" label; reconciliation will be skipped`, "request", request) + return reconcile.Result{}, nil + } + + var gateway gatewayapiv1beta1.Gateway + gatewayName := types.NamespacedName{ + Namespace: service.Namespace, + Name: service.Spec.Selector[gatewayNameLabelKey], + } + if err := r.cache.Get(ctx, gatewayName, &gateway); err != nil { + if apierrors.IsNotFound(err) { + log.Info("gateway not found; reconciliation will be skipped", "request", request) + return reconcile.Result{}, nil + } + return reconcile.Result{}, err + } + + domains := getGatewayHostnames(&gateway) + var errs []error + errs = append(errs, r.ensureDNSRecordsForGateway(ctx, &gateway, &service, domains.List())...) + errs = append(errs, r.deleteStaleDNSRecordsForGateway(ctx, &gateway, &service, domains)...) + return reconcile.Result{}, utilerrors.NewAggregate(errs) +} + +// getGatewayHostnames returns a sets.String with the hostnames from the given +// gateway's listeners. +func getGatewayHostnames(gateway *gatewayapiv1beta1.Gateway) sets.String { + domains := sets.NewString() + for _, listener := range gateway.Spec.Listeners { + if listener.Hostname == nil || len(*listener.Hostname) == 0 { + continue + } + domains.Insert(string(*listener.Hostname)) + } + return domains +} + +// ensureDNSRecordsForGateway ensures that a DNSRecord CR exists, associated +// with the given gateway and service, for each of the given domains. It +// returns a list of any errors that result from ensuring those DNSRecord CRs. +func (r *reconciler) ensureDNSRecordsForGateway(ctx context.Context, gateway *gatewayapiv1beta1.Gateway, service *corev1.Service, domains []string) []error { + labels := map[string]string{ + gatewayNameLabelKey: gateway.Name, + } + for k, v := range service.Labels { + labels[k] = v + } + ownerRef := metav1.OwnerReference{ + APIVersion: corev1.SchemeGroupVersion.String(), + Kind: "Service", + Name: service.Name, + UID: service.UID, + } + var errs []error + for _, domain := range domains { + name := operatorcontroller.GatewayDNSRecordName(gateway, domain) + _, _, err := dnsrecord.EnsureDNSRecord(r.client, name, labels, ownerRef, domain, service) + errs = append(errs, err) + } + return errs +} + +// deleteStaleDNSRecordsForGateway deletes any DNSRecord CRs that are associated +// with the given gateway but specify a DNS name that is not in the given set of +// domains. Such DNSRecord CRs may exist if a hostname was modified or deleted +// on the gateway. deleteStaleDNSRecordsForGateway returns a list of any errors +// that result from deleting those DNSRecord CRs. +func (r *reconciler) deleteStaleDNSRecordsForGateway(ctx context.Context, gateway *gatewayapiv1beta1.Gateway, service *corev1.Service, domains sets.String) []error { + listOpts := []client.ListOption{ + client.MatchingLabels{gatewayNameLabelKey: gateway.Name}, + client.InNamespace(r.config.OperandNamespace), + } + var dnsrecords iov1.DNSRecordList + // Use the client rather than the cache to make sure we don't use stale + // data and fail to clean up stale dnsrecords. + if err := r.client.List(ctx, &dnsrecords, listOpts...); err != nil { + return []error{err} + } + var errs []error + for i := range dnsrecords.Items { + if domains.Has(dnsrecords.Items[i].Spec.DNSName) { + continue + } + name := types.NamespacedName{ + Namespace: dnsrecords.Items[i].Namespace, + Name: dnsrecords.Items[i].Name, + } + errs = append(errs, dnsrecord.DeleteDNSRecord(r.client, name)) + } + return errs +} diff --git a/pkg/operator/controller/gateway-service-dns/controller_test.go b/pkg/operator/controller/gateway-service-dns/controller_test.go new file mode 100644 index 0000000000..8716cb42b6 --- /dev/null +++ b/pkg/operator/controller/gateway-service-dns/controller_test.go @@ -0,0 +1,338 @@ +package gateway_service_dns + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/assert" + + gatewayapiv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" + + iov1 "github.com/openshift/api/operatoringress/v1" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/cache/informertest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/reconcile" +) + +func Test_Reconcile(t *testing.T) { + gw := func(name string, listeners ...gatewayapiv1beta1.Listener) *gatewayapiv1beta1.Gateway { + return &gatewayapiv1beta1.Gateway{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "openshift-ingress", + Name: name, + }, + Spec: gatewayapiv1beta1.GatewaySpec{ + Listeners: listeners, + }, + } + } + l := func(name, hostname string, port int) gatewayapiv1beta1.Listener { + h := gatewayapiv1beta1.Hostname(hostname) + return gatewayapiv1beta1.Listener{ + Name: gatewayapiv1beta1.SectionName(name), + Hostname: &h, + Port: gatewayapiv1beta1.PortNumber(port), + } + } + svc := func(name string, labels, selector map[string]string, ingresses ...corev1.LoadBalancerIngress) *corev1.Service { + return &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Labels: labels, + Namespace: "openshift-ingress", + Name: name, + }, + Spec: corev1.ServiceSpec{ + Selector: selector, + }, + Status: corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: ingresses, + }, + }, + } + } + ingHost := func(hostname string) corev1.LoadBalancerIngress { + return corev1.LoadBalancerIngress{ + Hostname: hostname, + } + } + dnsrecord := func(name, dnsName string, targets ...string) *iov1.DNSRecord { + return &iov1.DNSRecord{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "openshift-ingress", + Name: name, + }, + Spec: iov1.DNSRecordSpec{ + DNSName: dnsName, + RecordType: iov1.CNAMERecordType, + Targets: targets, + RecordTTL: 30, + DNSManagementPolicy: iov1.ManagedDNS, + }, + } + } + req := func(ns, name string) reconcile.Request { + return reconcile.Request{ + NamespacedName: types.NamespacedName{ + Namespace: ns, + Name: name, + }, + } + } + tests := []struct { + name string + existingObjects []runtime.Object + reconcileRequest reconcile.Request + expectCreate []client.Object + expectUpdate []client.Object + }{ + { + name: "gateway with no listeners", + existingObjects: []runtime.Object{ + gw("example-gateway"), + svc( + "example-gateway", + map[string]string{ + "gateway.istio.io/managed": "example-gateway", + }, + map[string]string{ + "istio.io/gateway-name": "example-gateway", + }, + ingHost("lb.example.com"), + ), + }, + reconcileRequest: req("openshift-ingress", "example-gateway"), + expectCreate: []client.Object{}, + expectUpdate: []client.Object{}, + }, + { + name: "gateway with three listeners and two unique host names, no dnsrecords", + existingObjects: []runtime.Object{ + gw( + "example-gateway", + l("stage-http", "*.stage.example.com", 80), + l("stage-https", "*.stage.example.com", 443), + l("prod-https", "*.prod.example.com", 443), + ), + svc( + "example-gateway", + map[string]string{ + "gateway.istio.io/managed": "example-gateway", + }, + map[string]string{ + "istio.io/gateway-name": "example-gateway", + }, + ingHost("lb.example.com"), + ), + }, + reconcileRequest: req("openshift-ingress", "example-gateway"), + expectCreate: []client.Object{ + dnsrecord("example-gateway-5bfc88bc87-wildcard", "*.prod.example.com", "lb.example.com"), + dnsrecord("example-gateway-57b76476b6-wildcard", "*.stage.example.com", "lb.example.com"), + }, + expectUpdate: []client.Object{}, + }, + { + name: "gateway with two listeners and one dnsrecord with a stale target", + existingObjects: []runtime.Object{ + gw( + "example-gateway", + l("http", "*.example.com", 80), + l("https", "*.example.com", 443), + ), + svc( + "example-gateway", + map[string]string{ + "gateway.istio.io/managed": "example-gateway", + }, + map[string]string{ + "istio.io/gateway-name": "example-gateway", + }, + ingHost("newlb.example.com"), + ), + dnsrecord("example-gateway-55bcfdb97d-wildcard", "*.example.com", "oldlb.example.com"), + }, + reconcileRequest: req("openshift-ingress", "example-gateway"), + expectCreate: []client.Object{}, + expectUpdate: []client.Object{ + dnsrecord("example-gateway-55bcfdb97d-wildcard", "*.example.com", "newlb.example.com"), + }, + }, + } + + scheme := runtime.NewScheme() + iov1.AddToScheme(scheme) + corev1.AddToScheme(scheme) + gatewayapiv1beta1.AddToScheme(scheme) + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + fakeClient := fake.NewClientBuilder(). + WithScheme(scheme). + WithRuntimeObjects(tc.existingObjects...). + Build() + cl := &fakeClientRecorder{fakeClient, t, []client.Object{}, []client.Object{}} + informer := informertest.FakeInformers{Scheme: scheme} + cache := fakeCache{Informers: &informer, Reader: cl} + reconciler := &reconciler{ + config: Config{ + OperandNamespace: "openshift-ingress", + }, + cache: cache, + client: cl, + } + res, err := reconciler.Reconcile(context.Background(), tc.reconcileRequest) + if assert.NoError(t, err) { + assert.Equal(t, reconcile.Result{}, res) + } + cmpOpts := []cmp.Option{ + cmpopts.IgnoreFields(metav1.ObjectMeta{}, "Finalizers", "Labels", "OwnerReferences", "ResourceVersion"), + cmpopts.IgnoreFields(metav1.TypeMeta{}, "Kind", "APIVersion"), + } + if diff := cmp.Diff(tc.expectCreate, cl.added, cmpOpts...); diff != "" { + t.Fatalf("found diff between expected and actual creates: %s", diff) + } + if diff := cmp.Diff(tc.expectUpdate, cl.updated, cmpOpts...); diff != "" { + t.Fatalf("found diff between expected and actual updates: %s", diff) + } + }) + } +} + +type fakeCache struct { + cache.Informers + client.Reader +} + +type fakeClientRecorder struct { + client.Client + *testing.T + + added []client.Object + updated []client.Object +} + +func (c *fakeClientRecorder) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { + return c.Client.Get(ctx, key, obj, opts...) +} + +func (c *fakeClientRecorder) List(ctx context.Context, obj client.ObjectList, opts ...client.ListOption) error { + return c.Client.List(ctx, obj, opts...) +} + +func (c *fakeClientRecorder) Scheme() *runtime.Scheme { + return c.Client.Scheme() +} + +func (c *fakeClientRecorder) RESTMapper() meta.RESTMapper { + return c.Client.RESTMapper() +} + +func (c *fakeClientRecorder) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { + c.added = append(c.added, obj) + c.T.Log(obj) + return c.Client.Create(ctx, obj, opts...) +} + +func (c *fakeClientRecorder) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error { + return c.Client.Delete(ctx, obj, opts...) +} + +func (c *fakeClientRecorder) DeleteAllOf(ctx context.Context, obj client.Object, opts ...client.DeleteAllOfOption) error { + return c.Client.DeleteAllOf(ctx, obj, opts...) +} + +func (c *fakeClientRecorder) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + c.updated = append(c.updated, obj) + return c.Client.Update(ctx, obj, opts...) +} + +func (c *fakeClientRecorder) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { + return c.Client.Patch(ctx, obj, patch, opts...) +} + +func (c *fakeClientRecorder) Status() client.StatusWriter { + return c.Client.Status() +} + +func Test_gatewayListenersHostnamesChanged(t *testing.T) { + l := func(name, hostname string) gatewayapiv1beta1.Listener { + h := gatewayapiv1beta1.Hostname(hostname) + return gatewayapiv1beta1.Listener{ + Name: gatewayapiv1beta1.SectionName(name), + Hostname: &h, + } + } + tests := []struct { + name string + old, new []gatewayapiv1beta1.Listener + expect bool + }{ + { + name: "no listeners", + old: []gatewayapiv1beta1.Listener{}, + new: []gatewayapiv1beta1.Listener{}, + expect: false, + }, + { + name: "three listeners, no changes", + old: []gatewayapiv1beta1.Listener{ + l("http", "xyz.xyz"), + l("https", "xyz.xyz"), + l("foo", "bar.baz"), + }, + new: []gatewayapiv1beta1.Listener{ + l("http", "xyz.xyz"), + l("https", "xyz.xyz"), + l("foo", "bar.baz"), + }, + expect: false, + }, + { + name: "add a listener", + old: []gatewayapiv1beta1.Listener{}, + new: []gatewayapiv1beta1.Listener{l("http", "xyz.xyz")}, + expect: true, + }, + { + name: "remove a listener", + old: []gatewayapiv1beta1.Listener{l("http", "xyz.xyz")}, + new: []gatewayapiv1beta1.Listener{}, + expect: true, + }, + { + name: "rename a listener", + old: []gatewayapiv1beta1.Listener{l("http", "xyz.xyz")}, + new: []gatewayapiv1beta1.Listener{l("https", "xyz.xyz")}, + expect: true, + }, + { + name: "change a listener's hostname", + old: []gatewayapiv1beta1.Listener{l("https", "xyz.xyz")}, + new: []gatewayapiv1beta1.Listener{l("https", "abc.xyz")}, + expect: true, + }, + { + name: "replace a listener", + old: []gatewayapiv1beta1.Listener{l("http", "xyz.xyz")}, + new: []gatewayapiv1beta1.Listener{l("https", "abc.xyz")}, + expect: true, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + assert.Equal(t, tc.expect, gatewayListenersHostnamesChanged(tc.old, tc.new)) + }) + } +} diff --git a/pkg/operator/controller/gatewayapi/controller.go b/pkg/operator/controller/gatewayapi/controller.go new file mode 100644 index 0000000000..d6d205d376 --- /dev/null +++ b/pkg/operator/controller/gatewayapi/controller.go @@ -0,0 +1,153 @@ +package gatewayapi + +import ( + "context" + "sync" + + logf "github.com/openshift/cluster-ingress-operator/pkg/log" + operatorcontroller "github.com/openshift/cluster-ingress-operator/pkg/operator/controller" + + "k8s.io/client-go/tools/record" + + configv1 "github.com/openshift/api/config/v1" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + "sigs.k8s.io/controller-runtime/pkg/source" +) + +const ( + controllerName = "gatewayapi_controller" + + // featureGateName is the name of the feature gate that enables Gateway + // API support in cluster-ingress-operator. + featureGateName = "GatewayAPI" +) + +var log = logf.Logger.WithName(controllerName) + +// New creates and returns a controller that creates Gateway API CRDs when the +// appropriate featuregate is enabled. +func New(mgr manager.Manager, config Config) (controller.Controller, error) { + reconciler := &reconciler{ + client: mgr.GetClient(), + cache: mgr.GetCache(), + config: config, + } + c, err := controller.New(controllerName, mgr, controller.Options{Reconciler: reconciler}) + if err != nil { + return nil, err + } + clusterNamePredicate := predicate.NewPredicateFuncs(func(o client.Object) bool { + expectedName := operatorcontroller.FeatureGateClusterConfigName() + actualName := types.NamespacedName{ + Namespace: o.GetNamespace(), + Name: o.GetName(), + } + return expectedName == actualName + }) + if err := c.Watch(&source.Kind{Type: &configv1.FeatureGate{}}, &handler.EnqueueRequestForObject{}, clusterNamePredicate); err != nil { + return nil, err + } + return c, nil +} + +// Config holds all the configuration that must be provided when creating the +// controller. +type Config struct { + // DependentControllers is a list of controllers that watch Gateway API + // resources. The gatewayapi controller starts these controllers once + // the Gateway API CRDs have been created. + DependentControllers []controller.Controller +} + +// reconciler reconciles gatewayclasses. +type reconciler struct { + config Config + + client client.Client + cache cache.Cache + recorder record.EventRecorder + startControllers sync.Once +} + +// Reconcile expects request to refer to a FeatureGate and creates or +// reconciles the Gateway API CRDs. +func (r *reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { + log.Info("reconciling", "request", request) + + var fg configv1.FeatureGate + if err := r.cache.Get(ctx, request.NamespacedName, &fg); err != nil { + if apierrors.IsNotFound(err) { + log.Info("featuregate not found; reconciliation will be skipped", "request", request) + return reconcile.Result{}, nil + } + return reconcile.Result{}, err + } + + if !featureIsEnabled(featureGateName, &fg) { + return reconcile.Result{}, nil + } + + if err := r.ensureGatewayAPICRDs(ctx); err != nil { + return reconcile.Result{}, err + } + + r.startControllers.Do(func() { + for i := range r.config.DependentControllers { + c := &r.config.DependentControllers[i] + go func() { + if err := (*c).Start(ctx); err != nil { + log.Error(err, "cannot start controller") + } + }() + } + }) + + return reconcile.Result{}, nil +} + +// featureIsEnabled takes a feature name and a featuregate config API object and +// returns a Boolean indicating whether the named feature is enabled. +// +// This function determines whether a named feature is enabled as follows: +// +// - First, if the featuregate's spec.featureGateSelection.featureSet field is +// set to "CustomNoUpgrade", then the feature is enabled if, and only if, it +// is specified in spec.featureGateSelection.customNoUpgrade.enabled. +// +// - Second, if spec.featureGateSelection.featureSet is set to a value that +// isn't defined in configv1.FeatureSets, then the feature is *not* enabled. +// +// - Finally, the feature is enabled if, and only if, the feature is specified +// in configv1.FeatureSets[spec.featureGateSelection.featureSet].enabled. +func featureIsEnabled(feature string, fg *configv1.FeatureGate) bool { + if fg.Spec.FeatureSet == configv1.CustomNoUpgrade { + if fg.Spec.FeatureGateSelection.CustomNoUpgrade == nil { + return false + } + for _, f := range fg.Spec.FeatureGateSelection.CustomNoUpgrade.Enabled { + if f == feature { + return true + } + } + return false + } + + if fs, ok := configv1.FeatureSets[fg.Spec.FeatureSet]; ok { + for _, f := range fs.Enabled { + if f == feature { + return true + } + } + } + return false +} diff --git a/pkg/operator/controller/gatewayapi/controller_test.go b/pkg/operator/controller/gatewayapi/controller_test.go new file mode 100644 index 0000000000..203829dbf2 --- /dev/null +++ b/pkg/operator/controller/gatewayapi/controller_test.go @@ -0,0 +1,363 @@ +package gatewayapi + +import ( + "context" + "testing" + "time" + + logf "github.com/openshift/cluster-ingress-operator/pkg/log" + + "github.com/go-logr/logr" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/assert" + + configv1 "github.com/openshift/api/config/v1" + + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/cache/informertest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + "sigs.k8s.io/controller-runtime/pkg/source" +) + +func Test_Reconcile(t *testing.T) { + crd := func(name string) *apiextensionsv1.CustomResourceDefinition { + return &apiextensionsv1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{Name: name}, + } + } + tests := []struct { + name string + existingObjects []runtime.Object + expectCreate []client.Object + expectUpdate []client.Object + expectDelete []client.Object + expectStartCtrl bool + }{ + { + name: "featuregates.config.openshift.io/cluster doesn't exist", + existingObjects: []runtime.Object{}, + expectCreate: []client.Object{}, + expectUpdate: []client.Object{}, + expectDelete: []client.Object{}, + expectStartCtrl: false, + }, + { + name: "featuregates.config.openshift.io/cluster specifies CustomNoUpgrade but doesn't specify GatewayAPI", + existingObjects: []runtime.Object{ + &configv1.FeatureGate{ + ObjectMeta: metav1.ObjectMeta{Name: "cluster"}, + Spec: configv1.FeatureGateSpec{ + FeatureGateSelection: configv1.FeatureGateSelection{ + FeatureSet: configv1.CustomNoUpgrade, + CustomNoUpgrade: &configv1.CustomFeatureGates{ + Enabled: []string{"Foo", "Bar", "Baz"}, + }, + }, + }, + }, + }, + expectCreate: []client.Object{}, + expectUpdate: []client.Object{}, + expectDelete: []client.Object{}, + expectStartCtrl: false, + }, + { + name: "featuregates.config.openshift.io/cluster specifies CustomNoUpgrade but disables GatewayAPI", + existingObjects: []runtime.Object{ + &configv1.FeatureGate{ + ObjectMeta: metav1.ObjectMeta{Name: "cluster"}, + Spec: configv1.FeatureGateSpec{ + FeatureGateSelection: configv1.FeatureGateSelection{ + FeatureSet: configv1.CustomNoUpgrade, + CustomNoUpgrade: &configv1.CustomFeatureGates{ + Disabled: []string{"GatewayAPI"}, + }, + }, + }, + }, + }, + expectCreate: []client.Object{}, + expectUpdate: []client.Object{}, + expectDelete: []client.Object{}, + expectStartCtrl: false, + }, + { + name: "featuregates.config.openshift.io/cluster specifies CustomNoUpgrade and enables GatewayAPI", + existingObjects: []runtime.Object{ + &configv1.FeatureGate{ + ObjectMeta: metav1.ObjectMeta{Name: "cluster"}, + Spec: configv1.FeatureGateSpec{ + FeatureGateSelection: configv1.FeatureGateSelection{ + FeatureSet: configv1.CustomNoUpgrade, + CustomNoUpgrade: &configv1.CustomFeatureGates{ + Enabled: []string{"GatewayAPI"}, + }, + }, + }, + }, + }, + expectCreate: []client.Object{ + crd("gatewayclasses.gateway.networking.k8s.io"), + crd("gateways.gateway.networking.k8s.io"), + crd("httproutes.gateway.networking.k8s.io"), + crd("referencegrants.gateway.networking.k8s.io"), + }, + expectUpdate: []client.Object{}, + expectDelete: []client.Object{}, + expectStartCtrl: true, + }, + { + name: "featuregates.config.openshift.io/cluster specifies TechPreviewNoUpgrade", + existingObjects: []runtime.Object{ + &configv1.FeatureGate{ + ObjectMeta: metav1.ObjectMeta{Name: "cluster"}, + Spec: configv1.FeatureGateSpec{ + FeatureGateSelection: configv1.FeatureGateSelection{ + FeatureSet: configv1.TechPreviewNoUpgrade, + }, + }, + }, + }, + // TODO Update expectCreate and expectStartCtrl when + // "GatewayAPI" is added to + // configv1.FeatureSets["TechPreviewNoUpgrade"].Enabled. + expectCreate: []client.Object{}, + expectUpdate: []client.Object{}, + expectDelete: []client.Object{}, + expectStartCtrl: false, + }, + { + name: "featuregates.config.openshift.io/bogus enables GatewayAPI", + existingObjects: []runtime.Object{ + &configv1.FeatureGate{ + ObjectMeta: metav1.ObjectMeta{Name: "bogus"}, + Spec: configv1.FeatureGateSpec{ + FeatureGateSelection: configv1.FeatureGateSelection{ + FeatureSet: configv1.CustomNoUpgrade, + CustomNoUpgrade: &configv1.CustomFeatureGates{ + Enabled: []string{"GatewayAPI"}, + }, + }, + }, + }, + }, + expectCreate: []client.Object{}, + expectUpdate: []client.Object{}, + expectDelete: []client.Object{}, + expectStartCtrl: false, + }, + } + + scheme := runtime.NewScheme() + configv1.Install(scheme) + apiextensionsv1.AddToScheme(scheme) + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + fakeClient := fake.NewClientBuilder(). + WithScheme(scheme). + WithRuntimeObjects(tc.existingObjects...). + Build() + cl := &fakeClientRecorder{fakeClient, t, []client.Object{}, []client.Object{}, []client.Object{}} + informer := informertest.FakeInformers{Scheme: scheme} + cache := fakeCache{Informers: &informer, Reader: cl} + ctrl := &fakeController{t, false, nil} + reconciler := &reconciler{ + cache: cache, + client: cl, + config: Config{ + DependentControllers: []controller.Controller{ctrl}, + }, + } + req := reconcile.Request{ + NamespacedName: types.NamespacedName{ + Name: "cluster", + }, + } + res, err := reconciler.Reconcile(context.Background(), req) + assert.NoError(t, err) + assert.Equal(t, reconcile.Result{}, res) + ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) + defer cancel() + select { + case <-ctrl.startNotificationChan: + t.Log("Start() was called") + case <-ctx.Done(): + t.Log(ctx.Err()) + } + assert.Equal(t, ctrl.started, tc.expectStartCtrl, "fake controller should have been started") + cmpOpts := []cmp.Option{ + cmpopts.EquateEmpty(), + cmpopts.IgnoreFields(metav1.ObjectMeta{}, "Annotations", "ResourceVersion"), + cmpopts.IgnoreFields(metav1.TypeMeta{}, "Kind", "APIVersion"), + cmpopts.IgnoreFields(apiextensionsv1.CustomResourceDefinition{}, "Spec"), + } + if diff := cmp.Diff(tc.expectCreate, cl.added, cmpOpts...); diff != "" { + t.Fatalf("found diff between expected and actual creates: %s", diff) + } + if diff := cmp.Diff(tc.expectUpdate, cl.updated, cmpOpts...); diff != "" { + t.Fatalf("found diff between expected and actual updates: %s", diff) + } + if diff := cmp.Diff(tc.expectDelete, cl.deleted, cmpOpts...); diff != "" { + t.Fatalf("found diff between expected and actual deletes: %s", diff) + } + }) + } +} + +func TestReconcileOnlyStartsControllerOnce(t *testing.T) { + scheme := runtime.NewScheme() + configv1.Install(scheme) + apiextensionsv1.AddToScheme(scheme) + fg := &configv1.FeatureGate{ + ObjectMeta: metav1.ObjectMeta{Name: "cluster"}, + Spec: configv1.FeatureGateSpec{ + FeatureGateSelection: configv1.FeatureGateSelection{ + FeatureSet: configv1.CustomNoUpgrade, + CustomNoUpgrade: &configv1.CustomFeatureGates{ + Enabled: []string{"GatewayAPI"}, + }, + }, + }, + } + fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(fg).Build() + cl := &fakeClientRecorder{fakeClient, t, []client.Object{}, []client.Object{}, []client.Object{}} + informer := informertest.FakeInformers{Scheme: scheme} + cache := fakeCache{Informers: &informer, Reader: cl} + ctrl := &fakeController{t, false, make(chan struct{})} + reconciler := &reconciler{ + cache: cache, + client: cl, + config: Config{ + DependentControllers: []controller.Controller{ctrl}, + }, + } + req := reconcile.Request{NamespacedName: types.NamespacedName{Name: "cluster"}} + + // Reconcile once and verify Start() is called. + res, err := reconciler.Reconcile(context.Background(), req) + assert.NoError(t, err) + assert.Equal(t, reconcile.Result{}, res) + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + select { + case <-ctrl.startNotificationChan: + t.Log("Start() was called for the first reconcile request") + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + assert.True(t, ctrl.started, "fake controller should have been started") + + // Reconcile again and verify Start() isn't called again. + res, err = reconciler.Reconcile(context.Background(), req) + assert.NoError(t, err) + assert.Equal(t, reconcile.Result{}, res) + select { + case <-ctrl.startNotificationChan: + t.Error("Start() was called again for the second reconcile request") + case <-ctx.Done(): + t.Log(ctx.Err()) + } + assert.True(t, ctrl.started, "fake controller should have been started") +} + +type fakeCache struct { + cache.Informers + client.Reader +} + +type fakeClientRecorder struct { + client.Client + *testing.T + + added []client.Object + updated []client.Object + deleted []client.Object +} + +func (c *fakeClientRecorder) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { + return c.Client.Get(ctx, key, obj, opts...) +} + +func (c *fakeClientRecorder) List(ctx context.Context, obj client.ObjectList, opts ...client.ListOption) error { + return c.Client.List(ctx, obj, opts...) +} + +func (c *fakeClientRecorder) Scheme() *runtime.Scheme { + return c.Client.Scheme() +} + +func (c *fakeClientRecorder) RESTMapper() meta.RESTMapper { + return c.Client.RESTMapper() +} + +func (c *fakeClientRecorder) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { + c.added = append(c.added, obj) + return c.Client.Create(ctx, obj, opts...) +} + +func (c *fakeClientRecorder) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error { + c.deleted = append(c.deleted, obj) + return c.Client.Delete(ctx, obj, opts...) +} + +func (c *fakeClientRecorder) DeleteAllOf(ctx context.Context, obj client.Object, opts ...client.DeleteAllOfOption) error { + return c.Client.DeleteAllOf(ctx, obj, opts...) +} + +func (c *fakeClientRecorder) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + c.updated = append(c.updated, obj) + return c.Client.Update(ctx, obj, opts...) +} + +func (c *fakeClientRecorder) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { + return c.Client.Patch(ctx, obj, patch, opts...) +} + +func (c *fakeClientRecorder) Status() client.StatusWriter { + return c.Client.Status() +} + +type fakeController struct { + *testing.T + // started indicates whether Start() has been called. + started bool + // startNotificationChan is an optional channel by which a test can + // receive a notification when Start() is called. + startNotificationChan chan struct{} +} + +func (_ *fakeController) Reconcile(context.Context, reconcile.Request) (reconcile.Result, error) { + return reconcile.Result{}, nil +} + +func (_ *fakeController) Watch(_ source.Source, _ handler.EventHandler, _ ...predicate.Predicate) error { + return nil +} + +func (c *fakeController) Start(_ context.Context) error { + if c.started { + c.T.Fatal("controller was started twice!") + } + c.started = true + if c.startNotificationChan != nil { + c.startNotificationChan <- struct{}{} + } + return nil +} + +func (_ *fakeController) GetLogger() logr.Logger { + return logf.Logger +} diff --git a/pkg/operator/controller/gatewayapi/crds.go b/pkg/operator/controller/gatewayapi/crds.go new file mode 100644 index 0000000000..f88370326f --- /dev/null +++ b/pkg/operator/controller/gatewayapi/crds.go @@ -0,0 +1,129 @@ +package gatewayapi + +import ( + "context" + "fmt" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + + "github.com/openshift/cluster-ingress-operator/pkg/manifests" + + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + utilerrors "k8s.io/apimachinery/pkg/util/errors" +) + +// managedCRDs is a list of CRDs that this controller manages. +var managedCRDs = []*apiextensionsv1.CustomResourceDefinition{ + manifests.GatewayClassCRD(), + manifests.GatewayCRD(), + manifests.HTTPRouteCRD(), + manifests.ReferenceGrantCRD(), +} + +// ensureCRD attempts to ensure that the specified CRD exists and returns a +// Boolean indicating whether it exists, the CRD if it does exist, and an error +// value. +func (r *reconciler) ensureCRD(ctx context.Context, desired *apiextensionsv1.CustomResourceDefinition) (bool, *apiextensionsv1.CustomResourceDefinition, error) { + name := types.NamespacedName{ + Namespace: desired.Namespace, + Name: desired.Name, + } + have, current, err := r.currentCRD(ctx, name) + if err != nil { + return have, current, err + } + + switch { + case !have: + if err := r.createCRD(ctx, desired); err != nil { + return false, nil, err + } + return r.currentCRD(ctx, name) + case have: + if updated, err := r.updateCRD(ctx, current, desired); err != nil { + return have, current, err + } else if updated { + return r.currentCRD(ctx, name) + } + } + return have, current, nil +} + +// ensureGatewayAPICRDs ensures the managed Gateway API CRDs are created and +// returns an error value. For now, the managed CRDs are the GatewayClass, +// Gateway, HTTPRoute, and ReferenceGrant CRDs. +func (r *reconciler) ensureGatewayAPICRDs(ctx context.Context) error { + var errs []error + for i := range managedCRDs { + // The controller-runtime client mutates its argument, so give + // it a copy of the CRD rather than the original. + crd := managedCRDs[i].DeepCopy() + _, _, err := r.ensureCRD(ctx, crd) + errs = append(errs, err) + } + return utilerrors.NewAggregate(errs) +} + +// currentCRD returns a Boolean indicating whether an CRD +// exists for the IngressController with the given name, as well as the +// CRD if it does exist and an error value. +func (r *reconciler) currentCRD(ctx context.Context, name types.NamespacedName) (bool, *apiextensionsv1.CustomResourceDefinition, error) { + var crd apiextensionsv1.CustomResourceDefinition + if err := r.client.Get(ctx, name, &crd); err != nil { + if errors.IsNotFound(err) { + return false, nil, nil + } + return false, nil, fmt.Errorf("failed to get CRD %s: %w", name, err) + } + return true, &crd, nil +} + +// createCRD attempts to create the specified CRD and returns an error value. +func (r *reconciler) createCRD(ctx context.Context, desired *apiextensionsv1.CustomResourceDefinition) error { + if err := r.client.Create(ctx, desired); err != nil { + return fmt.Errorf("failed to create CRD %s: %w", desired.Name, err) + } + + log.Info("created CRD", "name", desired.Name) + + return nil +} + +// updateCRD updates an CRD. Returns a Boolean indicating +// whether the CRD was updated, and an error value. +func (r *reconciler) updateCRD(ctx context.Context, current, desired *apiextensionsv1.CustomResourceDefinition) (bool, error) { + changed, updated := crdChanged(current, desired) + if !changed { + return false, nil + } + + // Diff before updating because the client may mutate the object. + diff := cmp.Diff(current, updated, cmpopts.EquateEmpty()) + if err := r.client.Update(ctx, updated); err != nil { + return false, fmt.Errorf("failed to update CRD %s: %w", updated.Name, err) + } + log.Info("updated CRD", "name", updated.Name, "diff", diff) + return true, nil +} + +// crdChanged checks if the current CRD spec matches +// the expected spec and if not returns an updated one. +func crdChanged(current, expected *apiextensionsv1.CustomResourceDefinition) (bool, *apiextensionsv1.CustomResourceDefinition) { + crdCmpOpts := []cmp.Option{ + // Ignore fields that the API may have modified. + cmpopts.IgnoreFields(apiextensionsv1.CustomResourceDefinitionSpec{}, "Conversion"), + cmpopts.EquateEmpty(), + } + if cmp.Equal(current.Spec, expected.Spec, crdCmpOpts...) { + return false, nil + } + + updated := current.DeepCopy() + updated.Spec = expected.Spec + + return true, updated +} diff --git a/pkg/operator/controller/gatewayclass/controller.go b/pkg/operator/controller/gatewayclass/controller.go new file mode 100644 index 0000000000..5c42e76b47 --- /dev/null +++ b/pkg/operator/controller/gatewayclass/controller.go @@ -0,0 +1,103 @@ +package gatewayclass + +import ( + "context" + + logf "github.com/openshift/cluster-ingress-operator/pkg/log" + + "k8s.io/client-go/tools/record" + + gatewayapiv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" + + utilerrors "k8s.io/apimachinery/pkg/util/errors" + + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + "sigs.k8s.io/controller-runtime/pkg/source" +) + +const ( + controllerName = "gatewayclass_controller" + + // OpenShiftGatewayClassControllerName is the string by which a + // gatewayclass identifies itself as belonging to OpenShift Istio. If a + // gatewayclass's spec.controllerName field is set to this value, then + // the gatewayclass is ours. + OpenShiftGatewayClassControllerName = "openshift.io/gateway-controller" + // OpenShiftDefaultGatewayClassName is the name of the default + // gatewayclass that Istio creates when it is installed. + OpenShiftDefaultGatewayClassName = "openshift-default" +) + +var log = logf.Logger.WithName(controllerName) + +// NewUnmanaged creates and returns a controller that watches gatewayclasses and +// installs and configures Istio. This is an unmanaged controller, which means +// that the manager does not start it. +func NewUnmanaged(mgr manager.Manager, config Config) (controller.Controller, error) { + reconciler := &reconciler{ + config: config, + client: mgr.GetClient(), + cache: mgr.GetCache(), + recorder: mgr.GetEventRecorderFor(controllerName), + } + c, err := controller.NewUnmanaged(controllerName, mgr, controller.Options{Reconciler: reconciler}) + if err != nil { + return nil, err + } + isOurGatewayClass := predicate.NewPredicateFuncs(func(o client.Object) bool { + class := o.(*gatewayapiv1beta1.GatewayClass) + return class.Spec.ControllerName == OpenShiftGatewayClassControllerName + }) + isIstioGatewayClass := predicate.NewPredicateFuncs(func(o client.Object) bool { + return o.GetName() == "istio" + }) + if err := c.Watch(&source.Kind{Type: &gatewayapiv1beta1.GatewayClass{}}, &handler.EnqueueRequestForObject{}, isOurGatewayClass, predicate.Not(isIstioGatewayClass)); err != nil { + return nil, err + } + return c, nil +} + +// Config holds all the configuration that must be provided when creating the +// controller. +type Config struct { + // OperatorNamespace is the namespace in which the operator should + // create the ServiceMeshControlPlane CR. + OperatorNamespace string + // OperandNamespace is the namespace in which Istio should be deployed. + OperandNamespace string +} + +// reconciler reconciles gatewayclasses. +type reconciler struct { + config Config + + client client.Client + cache cache.Cache + recorder record.EventRecorder +} + +// Reconcile expects request to refer to a GatewayClass and creates or +// reconciles an Istio deployment. +func (r *reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { + log.Info("reconciling", "request", request) + + var gatewayclass gatewayapiv1beta1.GatewayClass + if err := r.cache.Get(ctx, request.NamespacedName, &gatewayclass); err != nil { + return reconcile.Result{}, err + } + + var errs []error + if _, _, err := r.ensureServiceMeshOperatorSubscription(ctx); err != nil { + errs = append(errs, err) + } + if _, _, err := r.ensureServiceMeshControlPlane(ctx, &gatewayclass); err != nil { + errs = append(errs, err) + } + return reconcile.Result{}, utilerrors.NewAggregate(errs) +} diff --git a/pkg/operator/controller/gatewayclass/servicemeshcontrolplane.go b/pkg/operator/controller/gatewayclass/servicemeshcontrolplane.go new file mode 100644 index 0000000000..c32ace3c83 --- /dev/null +++ b/pkg/operator/controller/gatewayclass/servicemeshcontrolplane.go @@ -0,0 +1,221 @@ +package gatewayclass + +import ( + "context" + "fmt" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + + gatewayapiv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" + + maistrav1 "github.com/maistra/istio-operator/pkg/apis/maistra/v1" + maistrav2 "github.com/maistra/istio-operator/pkg/apis/maistra/v2" + + "github.com/openshift/cluster-ingress-operator/pkg/operator/controller" + + corev1 "k8s.io/api/core/v1" + + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +// ensureServiceMeshControlPlane attempts to ensure that a +// servicemeshcontrolplane is present and returns a Boolean indicating whether +// it exists, the servicemeshcontrolplane if it exists, and an error value. +func (r *reconciler) ensureServiceMeshControlPlane(ctx context.Context, gatewayclass *gatewayapiv1beta1.GatewayClass) (bool, *maistrav2.ServiceMeshControlPlane, error) { + name := controller.ServiceMeshControlPlaneName(r.config.OperandNamespace) + have, current, err := r.currentServiceMeshControlPlane(ctx, name) + if err != nil { + return false, nil, err + } + + // TODO If we have a current SMCP with a different owner reference, + // should we append the new gatewayclass? + ownerRef := metav1.OwnerReference{ + APIVersion: gatewayapiv1beta1.SchemeGroupVersion.String(), + Kind: "GatewayClass", + Name: gatewayclass.Name, + UID: gatewayclass.UID, + } + desired, err := desiredServiceMeshControlPlane(name, ownerRef) + if err != nil { + return have, current, err + } + + switch { + case !have: + if err := r.createServiceMeshControlPlane(ctx, desired); err != nil { + return false, nil, err + } + return r.currentServiceMeshControlPlane(ctx, name) + case have: + if updated, err := r.updateServiceMeshControlPlane(ctx, current, desired); err != nil { + return have, current, err + } else if updated { + return r.currentServiceMeshControlPlane(ctx, name) + } + } + return true, current, nil +} + +// desiredServiceMeshControlPlane returns the desired servicemeshcontrolplane. +func desiredServiceMeshControlPlane(name types.NamespacedName, ownerRef metav1.OwnerReference) (*maistrav2.ServiceMeshControlPlane, error) { + pilotContainerEnv := map[string]string{ + "PILOT_ENABLE_GATEWAY_API": "true", + "PILOT_ENABLE_GATEWAY_API_DEPLOYMENT_CONTROLLER": "true", + "PILOT_ENABLE_GATEWAY_API_STATUS": "true", + "PILOT_GATEWAY_API_CONTROLLER_NAME": OpenShiftGatewayClassControllerName, + "PILOT_GATEWAY_API_DEFAULT_GATEWAYCLASS": OpenShiftDefaultGatewayClassName, + } + f := false + t := true + smcp := maistrav2.ServiceMeshControlPlane{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: name.Namespace, + Name: name.Name, + OwnerReferences: []metav1.OwnerReference{ownerRef}, + }, + Spec: maistrav2.ControlPlaneSpec{ + Addons: &maistrav2.AddonsConfig{ + // TODO Autodetect when these components have + // been installed and enable them in the SMCP + // if they are present. + Grafana: &maistrav2.GrafanaAddonConfig{ + Enablement: maistrav2.Enablement{Enabled: &f}, + }, + Jaeger: &maistrav2.JaegerAddonConfig{ + Name: "jaeger", + Install: nil, + }, + Kiali: &maistrav2.KialiAddonConfig{ + Enablement: maistrav2.Enablement{Enabled: &f}, + }, + Prometheus: &maistrav2.PrometheusAddonConfig{ + Enablement: maistrav2.Enablement{Enabled: &f}, + }, + }, + Gateways: &maistrav2.GatewaysConfig{ + ClusterIngress: &maistrav2.ClusterIngressGatewayConfig{ + IngressEnabled: &t, + IngressGatewayConfig: maistrav2.IngressGatewayConfig{ + GatewayConfig: maistrav2.GatewayConfig{ + Enablement: maistrav2.Enablement{ + Enabled: &t, + }, + Service: maistrav2.GatewayServiceConfig{ + ServiceSpec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeLoadBalancer, + }, + }, + }, + }, + }, + ClusterEgress: &maistrav2.EgressGatewayConfig{ + GatewayConfig: maistrav2.GatewayConfig{ + Enablement: maistrav2.Enablement{ + Enabled: &f, + }, + }, + }, + }, + Policy: &maistrav2.PolicyConfig{ + Type: maistrav2.PolicyTypeIstiod, + }, + Profiles: []string{"default"}, + Proxy: &maistrav2.ProxyConfig{ + AccessLogging: &maistrav2.ProxyAccessLoggingConfig{ + EnvoyService: &maistrav2.ProxyEnvoyServiceConfig{ + Enablement: maistrav2.Enablement{ + Enabled: &t, + }, + }, + File: &maistrav2.ProxyFileAccessLogConfig{ + Name: "/dev/stdout", + }, + }, + }, + Runtime: &maistrav2.ControlPlaneRuntimeConfig{ + Components: map[maistrav2.ControlPlaneComponentName]*maistrav2.ComponentRuntimeConfig{ + maistrav2.ControlPlaneComponentNamePilot: { + Container: &maistrav2.ContainerConfig{ + Env: pilotContainerEnv, + }, + }, + }, + }, + Security: &maistrav2.SecurityConfig{ + ManageNetworkPolicy: &f, + }, + TechPreview: maistrav1.NewHelmValues(map[string]interface{}{ + "controlPlaneMode": "ClusterScoped", + }), + Tracing: &maistrav2.TracingConfig{ + Type: maistrav2.TracerTypeNone, + }, + Version: "v2.4", + }, + } + return &smcp, nil +} + +// currentServiceMeshControlPlane returns the current servicemeshcontrolplane. +func (r *reconciler) currentServiceMeshControlPlane(ctx context.Context, name types.NamespacedName) (bool, *maistrav2.ServiceMeshControlPlane, error) { + var smcp maistrav2.ServiceMeshControlPlane + if err := r.cache.Get(ctx, name, &smcp); err != nil { + if errors.IsNotFound(err) { + return false, nil, nil + } + return false, nil, fmt.Errorf("failed to get ServiceMeshControlPlane %s: %w", name, err) + } + return true, &smcp, nil +} + +// createServiceMeshControlPlane creates a servicemeshcontrolplane. +func (r *reconciler) createServiceMeshControlPlane(ctx context.Context, smcp *maistrav2.ServiceMeshControlPlane) error { + if err := r.client.Create(ctx, smcp); err != nil { + return fmt.Errorf("failed to create ServiceMeshControlPlane %s/%s: %w", smcp.Namespace, smcp.Name, err) + } + log.Info("created ServiceMeshControlPlane", "namespace", smcp.Namespace, "name", smcp.Name) + return nil +} + +// smcpCmpOpts is an array of options for go-cmp to use when comparing +// ServiceMeshControlPlane CRs. +var smcpCmpOpts = []cmp.Option{ + cmpopts.EquateEmpty(), + cmp.AllowUnexported(maistrav1.HelmValues{}), +} + +// updateServiceMeshControlPlane updates a servicemeshcontrolplane. +func (r *reconciler) updateServiceMeshControlPlane(ctx context.Context, current, desired *maistrav2.ServiceMeshControlPlane) (bool, error) { + changed, updated := serviceMeshControlPlaneChanged(current, desired) + if !changed { + return false, nil + } + + // Diff before updating because the client may mutate the object. + // Only diff spec because status may include unexported fields that + // cause go-cmp to panic. + diff := cmp.Diff(current.Spec, updated.Spec, smcpCmpOpts...) + if err := r.client.Update(ctx, updated); err != nil { + return false, fmt.Errorf("failed to update ServiceMeshControlPlane %s/%s: %w", updated.Namespace, updated.Name, err) + } + log.Info("updated ServiceMeshControlPlane", "namespace", updated.Namespace, "name", updated.Name, "diff", diff) + return true, nil +} + +// serviceMeshControlPlaneChanged returns a Boolean indicating whether the +// current ServiceMeshControlPlane matches the expected servicemeshcontrolplane +// and the updated servicemeshcontrolplane if they do not match. +func serviceMeshControlPlaneChanged(current, expected *maistrav2.ServiceMeshControlPlane) (bool, *maistrav2.ServiceMeshControlPlane) { + if cmp.Equal(current.Spec, expected.Spec, smcpCmpOpts...) { + return false, nil + } + + updated := current.DeepCopy() + updated.Spec = expected.Spec + + return true, updated +} diff --git a/pkg/operator/controller/gatewayclass/subscription.go b/pkg/operator/controller/gatewayclass/subscription.go new file mode 100644 index 0000000000..a37388fa4d --- /dev/null +++ b/pkg/operator/controller/gatewayclass/subscription.go @@ -0,0 +1,117 @@ +package gatewayclass + +import ( + "context" + "fmt" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + + operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" + + operatorcontroller "github.com/openshift/cluster-ingress-operator/pkg/operator/controller" + + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +// ensureServiceMeshOperatorSubscription attempts to ensure that a subscription +// for servicemeshoperator is present and returns a Boolean indicating whether +// it exists, the subscription if it exists, and an error value. +func (r *reconciler) ensureServiceMeshOperatorSubscription(ctx context.Context) (bool, *operatorsv1alpha1.Subscription, error) { + name := operatorcontroller.ServiceMeshSubscriptionName() + have, current, err := r.currentSubscription(ctx, name) + if err != nil { + return false, nil, err + } + + desired, err := desiredSubscription(name) + if err != nil { + return have, current, err + } + + switch { + case !have: + if err := r.createSubscription(ctx, desired); err != nil { + return false, nil, err + } + return r.currentSubscription(ctx, name) + case have: + if updated, err := r.updateSubscription(ctx, current, desired); err != nil { + return have, current, err + } else if updated { + return r.currentSubscription(ctx, name) + } + } + return true, current, nil +} + +// desiredSubscription returns the desired subscription. +func desiredSubscription(name types.NamespacedName) (*operatorsv1alpha1.Subscription, error) { + subscription := operatorsv1alpha1.Subscription{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: name.Namespace, + Name: name.Name, + }, + Spec: &operatorsv1alpha1.SubscriptionSpec{ + Channel: "stable", + InstallPlanApproval: operatorsv1alpha1.ApprovalAutomatic, + Package: "servicemeshoperator", + CatalogSource: "redhat-operators", + CatalogSourceNamespace: "openshift-marketplace", + }, + } + return &subscription, nil +} + +// currentSubscription returns the current subscription. +func (r *reconciler) currentSubscription(ctx context.Context, name types.NamespacedName) (bool, *operatorsv1alpha1.Subscription, error) { + var subscription operatorsv1alpha1.Subscription + if err := r.client.Get(ctx, name, &subscription); err != nil { + if errors.IsNotFound(err) { + return false, nil, nil + } + return false, nil, fmt.Errorf("failed to get subscription %s: %w", name, err) + } + return true, &subscription, nil +} + +// createSubscription creates a subscription. +func (r *reconciler) createSubscription(ctx context.Context, subscription *operatorsv1alpha1.Subscription) error { + if err := r.client.Create(ctx, subscription); err != nil { + return fmt.Errorf("failed to create subscription %s/%s: %w", subscription.Namespace, subscription.Name, err) + } + log.Info("created subscription", "namespace", subscription.Namespace, "name", subscription.Name) + return nil +} + +// updateSubscription updates a subscription. +func (r *reconciler) updateSubscription(ctx context.Context, current, desired *operatorsv1alpha1.Subscription) (bool, error) { + changed, updated := subscriptionChanged(current, desired) + if !changed { + return false, nil + } + + // Diff before updating because the client may mutate the object. + diff := cmp.Diff(current, updated, cmpopts.EquateEmpty()) + if err := r.client.Update(ctx, updated); err != nil { + return false, fmt.Errorf("failed to update subscription %s/%s: %w", updated.Namespace, updated.Name, err) + } + log.Info("updated subscription", "namespace", updated.Namespace, "name", updated.Name, "diff", diff) + return true, nil +} + +// subscriptionChanged returns a Boolean indicating whether the current +// subscription matches the expected subscription and the updated subscription +// if they do not match. +func subscriptionChanged(current, expected *operatorsv1alpha1.Subscription) (bool, *operatorsv1alpha1.Subscription) { + if cmp.Equal(current.Spec, expected.Spec, cmpopts.EquateEmpty()) { + return false, nil + } + + updated := current.DeepCopy() + updated.Spec = expected.Spec + + return true, updated +} diff --git a/pkg/operator/controller/ingress/controller.go b/pkg/operator/controller/ingress/controller.go index 791d18b57f..7e9b155edb 100644 --- a/pkg/operator/controller/ingress/controller.go +++ b/pkg/operator/controller/ingress/controller.go @@ -14,6 +14,7 @@ import ( "github.com/openshift/cluster-ingress-operator/pkg/manifests" operatorcontroller "github.com/openshift/cluster-ingress-operator/pkg/operator/controller" routemetrics "github.com/openshift/cluster-ingress-operator/pkg/operator/controller/route-metrics" + "github.com/openshift/cluster-ingress-operator/pkg/resources/dnsrecord" "github.com/openshift/cluster-ingress-operator/pkg/util/ingresscontroller" retryable "github.com/openshift/cluster-ingress-operator/pkg/util/retryableerror" "github.com/openshift/cluster-ingress-operator/pkg/util/slice" @@ -288,7 +289,7 @@ func (r *reconciler) Reconcile(ctx context.Context, request reconcile.Request) ( // TODO: Remove this in 4.13 if eps := ingress.Status.EndpointPublishingStrategy; eps != nil && eps.Type == operatorv1.LoadBalancerServiceStrategyType && eps.LoadBalancer != nil { - domainMatchesBaseDomain := manageDNSForDomain(ingress.Status.Domain, platformStatus, dnsConfig) + domainMatchesBaseDomain := dnsrecord.ManageDNSForDomain(ingress.Status.Domain, platformStatus, dnsConfig) // Set dnsManagementPolicy based on current domain on the ingresscontroller // and base domain on dns config. This is needed to ensure the correct dnsManagementPolicy @@ -330,7 +331,7 @@ func (r *reconciler) admit(current *operatorv1.IngressController, ingressConfig // To set default publishing strategy we need to verify if the domains match // so that we can set the appropriate dnsManagementPolicy. This can only be // done after status.domain has been updated in setDefaultDomain(). - domainMatchesBaseDomain := manageDNSForDomain(updated.Status.Domain, platformStatus, dnsConfig) + domainMatchesBaseDomain := dnsrecord.ManageDNSForDomain(updated.Status.Domain, platformStatus, dnsConfig) setDefaultPublishingStrategy(updated, platformStatus, domainMatchesBaseDomain, ingressConfig, alreadyAdmitted) // The TLS security profile need not be defaulted. If none is set, we @@ -914,10 +915,11 @@ func (r *reconciler) ensureIngressDeleted(ingress *operatorv1.IngressController) // Delete the wildcard DNS record, and block ingresscontroller finalization // until the dnsrecord has been finalized. - if err := r.deleteWildcardDNSRecord(ingress); err != nil { + dnsRecordName := operatorcontroller.WildcardDNSRecordName(ingress) + if err := dnsrecord.DeleteDNSRecord(r.client, dnsRecordName); err != nil { errs = append(errs, fmt.Errorf("failed to delete wildcard dnsrecord for ingress %s/%s: %v", ingress.Namespace, ingress.Name, err)) } - haveRec, _, err := r.currentWildcardDNSRecord(ingress) + haveRec, _, err := dnsrecord.CurrentDNSRecord(r.client, dnsRecordName) switch { case err != nil: errs = append(errs, fmt.Errorf("failed to get current wildcard dnsrecord for ingress %s/%s: %v", ingress.Namespace, ingress.Name, err)) @@ -1052,7 +1054,19 @@ func (r *reconciler) ensureIngressController(ci *operatorv1.IngressController, d errs = append(errs, fmt.Errorf("failed to ensure load balancer service for %s: %v", ci.Name, err)) } else { lbService = lb - if _, record, err := r.ensureWildcardDNSRecord(ci, lbService, haveLB); err != nil { + dnsRecordName := operatorcontroller.WildcardDNSRecordName(ci) + icRef := metav1.OwnerReference{ + APIVersion: operatorv1.GroupVersion.String(), + Kind: "IngressController", + Name: ci.Name, + UID: ci.UID, + Controller: &trueVar, + BlockOwnerDeletion: &trueVar, + } + dnsRecordLabels := map[string]string{ + manifests.OwningIngressControllerLabel: ci.Name, + } + if _, record, err := dnsrecord.EnsureWildcardDNSRecord(r.client, dnsRecordName, dnsRecordLabels, icRef, ci.Status.Domain, ci.Status.EndpointPublishingStrategy, lbService, haveLB); err != nil { errs = append(errs, fmt.Errorf("failed to ensure wildcard dnsrecord for %s: %v", ci.Name, err)) } else { wildcardRecord = record diff --git a/pkg/operator/controller/ingress/controller_test.go b/pkg/operator/controller/ingress/controller_test.go index 0fa3a3a7bc..ee8da61717 100644 --- a/pkg/operator/controller/ingress/controller_test.go +++ b/pkg/operator/controller/ingress/controller_test.go @@ -9,6 +9,7 @@ import ( configv1 "github.com/openshift/api/config/v1" operatorv1 "github.com/openshift/api/operator/v1" + util "github.com/openshift/cluster-ingress-operator/pkg/util" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -1001,18 +1002,18 @@ func TestTLSProfileSpecForSecurityProfile(t *testing.T) { tlsProfileSpec := tlsProfileSpecForSecurityProfile(ic.Spec.TLSSecurityProfile) err := validateTLSSecurityProfile(ic) if tc.valid && err != nil { - t.Errorf("%q: unexpected error: %v\nprofile:\n%s", tc.description, err, toYaml(tlsProfileSpec)) + t.Errorf("%q: unexpected error: %v\nprofile:\n%s", tc.description, err, util.ToYaml(tlsProfileSpec)) continue } if !tc.valid && err == nil { - t.Errorf("%q: expected error for profile:\n%s", tc.description, toYaml(tlsProfileSpec)) + t.Errorf("%q: expected error for profile:\n%s", tc.description, util.ToYaml(tlsProfileSpec)) continue } if tc.expectedSpec != nil && !reflect.DeepEqual(tc.expectedSpec, tlsProfileSpec) { - t.Errorf("%q: expected profile:\n%s\ngot profile:\n%s", tc.description, toYaml(tc.expectedSpec), toYaml(tlsProfileSpec)) + t.Errorf("%q: expected profile:\n%s\ngot profile:\n%s", tc.description, util.ToYaml(tc.expectedSpec), util.ToYaml(tlsProfileSpec)) continue } - t.Logf("%q: got expected values; profile:\n%s\nerror value: %v", tc.description, toYaml(tlsProfileSpec), err) + t.Logf("%q: got expected values; profile:\n%s\nerror value: %v", tc.description, util.ToYaml(tlsProfileSpec), err) } } @@ -1155,7 +1156,7 @@ func TestTLSProfileSpecForIngressController(t *testing.T) { } tlsProfileSpec := tlsProfileSpecForIngressController(ic, api) if !reflect.DeepEqual(tc.expectedSpec, tlsProfileSpec) { - t.Errorf("%q: expected profile:\n%v\ngot profile:\n%v", tc.description, toYaml(tc.expectedSpec), toYaml(tlsProfileSpec)) + t.Errorf("%q: expected profile:\n%v\ngot profile:\n%v", tc.description, util.ToYaml(tc.expectedSpec), util.ToYaml(tlsProfileSpec)) } } } diff --git a/pkg/operator/controller/ingress/status_test.go b/pkg/operator/controller/ingress/status_test.go index 78da12c3b4..0ed60dfef4 100644 --- a/pkg/operator/controller/ingress/status_test.go +++ b/pkg/operator/controller/ingress/status_test.go @@ -16,6 +16,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + util "github.com/openshift/cluster-ingress-operator/pkg/util" retryable "github.com/openshift/cluster-ingress-operator/pkg/util/retryableerror" "github.com/openshift/cluster-ingress-operator/pkg/manifests" @@ -2088,7 +2089,7 @@ func TestMergeConditions(t *testing.T) { t.Logf("test: %s", name) actual := MergeConditions(test.conditions, test.updates...) if !conditionsEqual(test.expected, actual) { - t.Errorf("expected:\n%v\nactual:\n%v", toYaml(test.expected), toYaml(actual)) + t.Errorf("expected:\n%v\nactual:\n%v", util.ToYaml(test.expected), util.ToYaml(actual)) } } } diff --git a/pkg/operator/controller/names.go b/pkg/operator/controller/names.go index ef353bb5e8..970df92763 100644 --- a/pkg/operator/controller/names.go +++ b/pkg/operator/controller/names.go @@ -5,6 +5,10 @@ import ( operatorv1 "github.com/openshift/api/operator/v1" + gatewayapiv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" + + util "github.com/openshift/cluster-ingress-operator/pkg/util" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" ) @@ -70,6 +74,14 @@ func InfrastructureClusterConfigName() types.NamespacedName { } } +// FeatureGateClusterConfigName returns the namespaced name of the +// featuregates.config.openshift.io resource of the cluster. +func FeatureGateClusterConfigName() types.NamespacedName { + return types.NamespacedName{ + Name: "cluster", + } +} + // RouterDeploymentName returns the namespaced name for the router deployment. func RouterDeploymentName(ci *operatorv1.IngressController) types.NamespacedName { return types.NamespacedName{ @@ -250,3 +262,34 @@ func CanaryRouteName() types.NamespacedName { func IngressClassName(ingressControllerName string) types.NamespacedName { return types.NamespacedName{Name: "openshift-" + ingressControllerName} } + +// ServiceMeshControlPlaneName returns the namespaced name for a +// ServiceMeshControlPlane CR. This CR is created in the operand's namespace +// and has a hard-coded name. Each namespace can have only one gatewayclass, so +// it is simplest to use the same name in every namespace. +func ServiceMeshControlPlaneName(operandNamespace string) types.NamespacedName { + return types.NamespacedName{ + Namespace: operandNamespace, + Name: "openshift-gateway", + } +} + +// ServiceMeshSubscriptionName returns the namespaced name for a Subscription CR +// to install OpenShift Service Mesh. +func ServiceMeshSubscriptionName() types.NamespacedName { + return types.NamespacedName{ + Namespace: "openshift-operators", + Name: "servicemeshoperator", + } +} + +// GatewayDNSRecordName returns the namespaced name for a DNSRecord CR +// associated with a Gateway. This CR is created in the Gateway's namespace and +// is named using the Gateway's name, listener's hashed host name, and the +// suffix "-wildcard". +func GatewayDNSRecordName(gateway *gatewayapiv1beta1.Gateway, host string) types.NamespacedName { + return types.NamespacedName{ + Namespace: gateway.Namespace, + Name: fmt.Sprintf("%s-%s-wildcard", gateway.Name, util.Hash(host)), + } +} diff --git a/pkg/operator/operator.go b/pkg/operator/operator.go index e169bb8ada..6084c1858b 100644 --- a/pkg/operator/operator.go +++ b/pkg/operator/operator.go @@ -28,6 +28,9 @@ import ( configurableroutecontroller "github.com/openshift/cluster-ingress-operator/pkg/operator/controller/configurable-route" crlcontroller "github.com/openshift/cluster-ingress-operator/pkg/operator/controller/crl" dnscontroller "github.com/openshift/cluster-ingress-operator/pkg/operator/controller/dns" + gatewayservicednscontroller "github.com/openshift/cluster-ingress-operator/pkg/operator/controller/gateway-service-dns" + gatewayapicontroller "github.com/openshift/cluster-ingress-operator/pkg/operator/controller/gatewayapi" + gatewayclasscontroller "github.com/openshift/cluster-ingress-operator/pkg/operator/controller/gatewayclass" ingress "github.com/openshift/cluster-ingress-operator/pkg/operator/controller/ingress" ingresscontroller "github.com/openshift/cluster-ingress-operator/pkg/operator/controller/ingress" ingressclasscontroller "github.com/openshift/cluster-ingress-operator/pkg/operator/controller/ingressclass" @@ -43,6 +46,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/manager" ) @@ -184,7 +188,11 @@ func New(config operatorconfig.Config, kubeConfig *rest.Config) (*Operator, erro // Set up the DNS controller if _, err := dnscontroller.New(mgr, dnscontroller.Config{ - Namespace: config.Namespace, + CredentialsRequestNamespace: config.Namespace, + DNSRecordNamespaces: []string{ + config.Namespace, + operatorcontroller.DefaultOperandNamespace, + }, OperatorReleaseVersion: config.OperatorReleaseVersion, }); err != nil { return nil, fmt.Errorf("failed to create dns controller: %v", err) @@ -214,6 +222,37 @@ func New(config operatorconfig.Config, kubeConfig *rest.Config) (*Operator, erro return nil, fmt.Errorf("failed to create route metrics controller: %w", err) } + // Set up the gatewayclass controller. This controller is unmanaged by + // the manager; the gatewayapi controller starts it after it creates the + // Gateway API CRDs. + gatewayClassController, err := gatewayclasscontroller.NewUnmanaged(mgr, gatewayclasscontroller.Config{ + OperatorNamespace: config.Namespace, + OperandNamespace: operatorcontroller.DefaultOperandNamespace, + }) + if err != nil { + return nil, fmt.Errorf("failed to create gatewayclass controller: %w", err) + } + + // Set up the Service DNS controller. This controller is unmanaged by + // the manager; the gatewayapi controller starts it after it creates the + // Gateway API CRDs. + gatewayServiceDNSController, err := gatewayservicednscontroller.NewUnmanaged(mgr, gatewayservicednscontroller.Config{ + OperandNamespace: operatorcontroller.DefaultOperandNamespace, + }) + if err != nil { + return nil, fmt.Errorf("failed to create gateway-service-dns controller: %v", err) + } + + // Set up the gatewayapi controller. + if _, err := gatewayapicontroller.New(mgr, gatewayapicontroller.Config{ + DependentControllers: []controller.Controller{ + gatewayClassController, + gatewayServiceDNSController, + }, + }); err != nil { + return nil, fmt.Errorf("failed to create gatewayapi controller: %w", err) + } + return &Operator{ manager: mgr, // TODO: These are only needed for the default ingress controller stuff, which diff --git a/pkg/operator/controller/ingress/dns.go b/pkg/resources/dnsrecord/dns.go similarity index 54% rename from pkg/operator/controller/ingress/dns.go rename to pkg/resources/dnsrecord/dns.go index 5494b96b15..c27a738963 100644 --- a/pkg/operator/controller/ingress/dns.go +++ b/pkg/resources/dnsrecord/dns.go @@ -1,4 +1,4 @@ -package ingress +package dnsrecord import ( "context" @@ -11,14 +11,19 @@ import ( configv1 "github.com/openshift/api/config/v1" operatorv1 "github.com/openshift/api/operator/v1" iov1 "github.com/openshift/api/operatoringress/v1" + logf "github.com/openshift/cluster-ingress-operator/pkg/log" "github.com/openshift/cluster-ingress-operator/pkg/manifests" - "github.com/openshift/cluster-ingress-operator/pkg/operator/controller" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + "sigs.k8s.io/controller-runtime/pkg/client" ) +var log = logf.Logger.WithName("dnsrecord") + // defaultRecordTTL is the TTL (in seconds) assigned to all new DNS records. // // Note that TTL isn't necessarily honored by clouds providers (for example, @@ -27,31 +32,58 @@ import ( // [1] https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html const defaultRecordTTL int64 = 30 -// ensureWildcardDNSRecord will create DNS records for the given LB service. -// If service is nil (haveLBS is false), nothing is done. -func (r *reconciler) ensureWildcardDNSRecord(ic *operatorv1.IngressController, service *corev1.Service, haveLBS bool) (bool, *iov1.DNSRecord, error) { +// EnsureWildcardDNSRecord will create wildcard DNS records for the given LB +// service. If service is nil (haveLBS is false), nothing is done. +func EnsureWildcardDNSRecord(client client.Client, name types.NamespacedName, dnsRecordLabels map[string]string, ownerRef metav1.OwnerReference, domain string, endpointPublishingStrategy *operatorv1.EndpointPublishingStrategy, service *corev1.Service, haveLBS bool) (bool, *iov1.DNSRecord, error) { if !haveLBS { return false, nil, nil } - wantWC, desired := desiredWildcardDNSRecord(ic, service) - haveWC, current, err := r.currentWildcardDNSRecord(ic) + wantWC, desired := desiredWildcardDNSRecord(name, dnsRecordLabels, ownerRef, domain, endpointPublishingStrategy, service) + haveWC, current, err := CurrentDNSRecord(client, name) if err != nil { return false, nil, err } switch { case wantWC && !haveWC: - if err := r.client.Create(context.TODO(), desired); err != nil { + if err := client.Create(context.TODO(), desired); err != nil { return false, nil, fmt.Errorf("failed to create dnsrecord %s/%s: %v", desired.Namespace, desired.Name, err) } log.Info("created dnsrecord", "dnsrecord", desired) - return r.currentWildcardDNSRecord(ic) + return CurrentDNSRecord(client, name) case wantWC && haveWC: - if updated, err := r.updateDNSRecord(current, desired); err != nil { + if updated, err := updateDNSRecord(client, current, desired); err != nil { return true, current, fmt.Errorf("failed to update dnsrecord %s/%s: %v", desired.Namespace, desired.Name, err) } else if updated { - return r.currentWildcardDNSRecord(ic) + return CurrentDNSRecord(client, name) + } + } + + return haveWC, current, nil +} + +// EnsureDNSRecord will create DNS records for the given LB service. If service +// is nil (haveLBS is false), nothing is done. +func EnsureDNSRecord(client client.Client, name types.NamespacedName, dnsRecordLabels map[string]string, ownerRef metav1.OwnerReference, domain string, service *corev1.Service) (bool, *iov1.DNSRecord, error) { + wantWC, desired := desiredDNSRecord(name, dnsRecordLabels, ownerRef, domain, iov1.ManagedDNS, service) + haveWC, current, err := CurrentDNSRecord(client, name) + if err != nil { + return false, nil, err + } + + switch { + case wantWC && !haveWC: + if err := client.Create(context.TODO(), desired); err != nil { + return false, nil, fmt.Errorf("failed to create dnsrecord %s/%s: %v", desired.Namespace, desired.Name, err) + } + log.Info("created dnsrecord", "dnsrecord", desired) + return CurrentDNSRecord(client, name) + case wantWC && haveWC: + if updated, err := updateDNSRecord(client, current, desired); err != nil { + return true, current, fmt.Errorf("failed to update dnsrecord %s/%s: %v", desired.Namespace, desired.Name, err) + } else if updated { + return CurrentDNSRecord(client, name) } } @@ -59,26 +91,43 @@ func (r *reconciler) ensureWildcardDNSRecord(ic *operatorv1.IngressController, s } // desiredWildcardDNSRecord will return any necessary wildcard DNS records for the -// ingresscontroller. -// -// For now, if the service has more than one .status.loadbalancer.ingress, only -// the first will be used. -// -// TODO: If .status.loadbalancer.ingress is processed once as non-empty and then -// later becomes empty, what should we do? Currently we'll treat it as an intent -// to not have a desired record. -func desiredWildcardDNSRecord(ic *operatorv1.IngressController, service *corev1.Service) (bool, *iov1.DNSRecord) { +// given service. +func desiredWildcardDNSRecord(name types.NamespacedName, dnsRecordLabels map[string]string, ownerRef metav1.OwnerReference, dnsDomain string, endpointPublishingStrategy *operatorv1.EndpointPublishingStrategy, service *corev1.Service) (bool, *iov1.DNSRecord) { // If the ingresscontroller has no ingress domain, we cannot configure any // DNS records. - if len(ic.Status.Domain) == 0 { + if len(dnsDomain) == 0 { return false, nil } // DNS is only managed for LB publishing. - if ic.Status.EndpointPublishingStrategy.Type != operatorv1.LoadBalancerServiceStrategyType { + if endpointPublishingStrategy.Type != operatorv1.LoadBalancerServiceStrategyType { return false, nil } + // Use an absolute name to prevent any ambiguity. + domain := fmt.Sprintf("*.%s.", dnsDomain) + + dnsPolicy := iov1.ManagedDNS + + // Set the DNS management policy on the dnsrecord to "Unmanaged" if ingresscontroller has "Unmanaged" DNS policy or + // if the ingresscontroller domain isn't a subdomain of the cluster's base domain. + if endpointPublishingStrategy.LoadBalancer.DNSManagementPolicy == operatorv1.UnmanagedLoadBalancerDNS { + dnsPolicy = iov1.UnmanagedDNS + } + + return desiredDNSRecord(name, dnsRecordLabels, ownerRef, domain, dnsPolicy, service) +} + +// desiredDNSRecord will return any necessary DNS records for the given domain +// and service. +// +// For now, if the service has more than one .status.loadbalancer.ingress, only +// the first will be used. +// +// TODO: If .status.loadbalancer.ingress is processed once as non-empty and then +// later becomes empty, what should we do? Currently we'll treat it as an intent +// to not have a desired record. +func desiredDNSRecord(name types.NamespacedName, dnsRecordLabels map[string]string, ownerRef metav1.OwnerReference, domain string, dnsPolicy iov1.DNSManagementPolicy, service *corev1.Service) (bool, *iov1.DNSRecord) { // No LB target exists for the domain record to point at. if len(service.Status.LoadBalancer.Ingress) == 0 { return false, nil @@ -92,9 +141,6 @@ func desiredWildcardDNSRecord(ic *operatorv1.IngressController, service *corev1. return false, nil } - name := controller.WildcardDNSRecordName(ic) - // Use an absolute name to prevent any ambiguity. - domain := fmt.Sprintf("*.%s.", ic.Status.Domain) var target string var recordType iov1.DNSRecordType @@ -106,33 +152,13 @@ func desiredWildcardDNSRecord(ic *operatorv1.IngressController, service *corev1. target = ingress.IP } - dnsPolicy := iov1.ManagedDNS - - // Set the DNS management policy on the dnsrecord to "Unmanaged" if ingresscontroller has "Unmanaged" DNS policy or - // if the ingresscontroller domain isn't a subdomain of the cluster's base domain. - if ic.Status.EndpointPublishingStrategy.LoadBalancer.DNSManagementPolicy == operatorv1.UnmanagedLoadBalancerDNS { - dnsPolicy = iov1.UnmanagedDNS - } - - trueVar := true return true, &iov1.DNSRecord{ ObjectMeta: metav1.ObjectMeta{ - Namespace: name.Namespace, - Name: name.Name, - Labels: map[string]string{ - manifests.OwningIngressControllerLabel: ic.Name, - }, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: operatorv1.GroupVersion.String(), - Kind: "IngressController", - Name: ic.Name, - UID: ic.UID, - Controller: &trueVar, - BlockOwnerDeletion: &trueVar, - }, - }, - Finalizers: []string{manifests.DNSRecordFinalizer}, + Namespace: name.Namespace, + Name: name.Name, + Labels: dnsRecordLabels, + OwnerReferences: []metav1.OwnerReference{ownerRef}, + Finalizers: []string{manifests.DNSRecordFinalizer}, }, Spec: iov1.DNSRecordSpec{ DNSName: domain, @@ -144,9 +170,9 @@ func desiredWildcardDNSRecord(ic *operatorv1.IngressController, service *corev1. } } -func (r *reconciler) currentWildcardDNSRecord(ic *operatorv1.IngressController) (bool, *iov1.DNSRecord, error) { +func CurrentDNSRecord(client client.Client, name types.NamespacedName) (bool, *iov1.DNSRecord, error) { current := &iov1.DNSRecord{} - err := r.client.Get(context.TODO(), controller.WildcardDNSRecordName(ic), current) + err := client.Get(context.TODO(), name, current) if err != nil { if errors.IsNotFound(err) { return false, nil, nil @@ -156,12 +182,11 @@ func (r *reconciler) currentWildcardDNSRecord(ic *operatorv1.IngressController) return true, current, nil } -func (r *reconciler) deleteWildcardDNSRecord(ic *operatorv1.IngressController) error { - name := controller.WildcardDNSRecordName(ic) +func DeleteDNSRecord(client client.Client, name types.NamespacedName) error { record := &iov1.DNSRecord{} record.Namespace = name.Namespace record.Name = name.Name - if err := r.client.Delete(context.TODO(), record); err != nil { + if err := client.Delete(context.TODO(), record); err != nil { if errors.IsNotFound(err) { return nil } @@ -172,7 +197,7 @@ func (r *reconciler) deleteWildcardDNSRecord(ic *operatorv1.IngressController) e // updateDNSRecord updates a DNSRecord. Returns a boolean indicating whether // the record was updated, and an error value. -func (r *reconciler) updateDNSRecord(current, desired *iov1.DNSRecord) (bool, error) { +func updateDNSRecord(client client.Client, current, desired *iov1.DNSRecord) (bool, error) { changed, updated := dnsRecordChanged(current, desired) if !changed { return false, nil @@ -180,7 +205,7 @@ func (r *reconciler) updateDNSRecord(current, desired *iov1.DNSRecord) (bool, er // Diff before updating because the client may mutate the object. diff := cmp.Diff(current, updated, cmpopts.EquateEmpty()) - if err := r.client.Update(context.TODO(), updated); err != nil { + if err := client.Update(context.TODO(), updated); err != nil { return false, err } log.Info("updated dnsrecord", "namespace", updated.Namespace, "name", updated.Name, "diff", diff) @@ -199,11 +224,11 @@ func dnsRecordChanged(current, expected *iov1.DNSRecord) (bool, *iov1.DNSRecord) return true, updated } -// manageDNSForDomain returns true if the given domain contains the baseDomain +// ManageDNSForDomain returns true if the given domain contains the baseDomain // of the cluster DNS config. It is only used for AWS and GCP in the beginning, and will be expanded to other clouds // once we know there are no users depending on this. // See https://bugzilla.redhat.com/show_bug.cgi?id=2041616 -func manageDNSForDomain(domain string, status *configv1.PlatformStatus, dnsConfig *configv1.DNS) bool { +func ManageDNSForDomain(domain string, status *configv1.PlatformStatus, dnsConfig *configv1.DNS) bool { if len(domain) == 0 { return false } diff --git a/pkg/operator/controller/ingress/dns_test.go b/pkg/resources/dnsrecord/dns_test.go similarity index 86% rename from pkg/operator/controller/ingress/dns_test.go rename to pkg/resources/dnsrecord/dns_test.go index 5cf9edec73..0f4455f3f4 100644 --- a/pkg/operator/controller/ingress/dns_test.go +++ b/pkg/resources/dnsrecord/dns_test.go @@ -1,19 +1,20 @@ -package ingress +package dnsrecord import ( "testing" "github.com/google/go-cmp/cmp" - "gopkg.in/yaml.v2" - configv1 "github.com/openshift/api/config/v1" operatorv1 "github.com/openshift/api/operator/v1" iov1 "github.com/openshift/api/operatoringress/v1" + "github.com/openshift/cluster-ingress-operator/pkg/manifests" + util "github.com/openshift/cluster-ingress-operator/pkg/util" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" ) func TestDesiredWildcardDNSRecord(t *testing.T) { @@ -124,31 +125,36 @@ func TestDesiredWildcardDNSRecord(t *testing.T) { for _, test := range tests { t.Logf("testing %s", test.description) - controller := &operatorv1.IngressController{ - ObjectMeta: metav1.ObjectMeta{ - Name: "default", - }, - Status: operatorv1.IngressControllerStatus{ - Domain: test.domain, - EndpointPublishingStrategy: &test.publish, - }, + name := types.NamespacedName{ + Namespace: "openshift-ingress-operator", + Name: "default-wildcard", + } + trueVar := true + icRef := metav1.OwnerReference{ + APIVersion: operatorv1.GroupVersion.String(), + Kind: "IngressController", + Name: "default", + Controller: &trueVar, + BlockOwnerDeletion: &trueVar, + } + labels := map[string]string{ + manifests.OwningIngressControllerLabel: "default", } - service := &corev1.Service{} for _, ingress := range test.ingresses { service.Status.LoadBalancer.Ingress = append(service.Status.LoadBalancer.Ingress, ingress) } - haveWC, actual := desiredWildcardDNSRecord(controller, service) + haveWC, actual := desiredWildcardDNSRecord(name, labels, icRef, test.domain, &test.publish, service) switch { case test.expect != nil && haveWC: if !cmp.Equal(actual.Spec, *test.expect) { - t.Errorf("expected:\n%s\n\nactual:\n%s", toYaml(test.expect), toYaml(actual.Spec)) + t.Errorf("expected:\n%s\n\nactual:\n%s", util.ToYaml(test.expect), util.ToYaml(actual.Spec)) } case test.expect == nil && haveWC: - t.Errorf("expected nil record, got:\n%s", toYaml(actual)) + t.Errorf("expected nil record, got:\n%s", util.ToYaml(actual)) case test.expect != nil && !haveWC: - t.Errorf("expected record but got nil:\n%s", toYaml(test.expect)) + t.Errorf("expected record but got nil:\n%s", util.ToYaml(test.expect)) } } } @@ -242,14 +248,9 @@ func TestManageDNSForDomain(t *testing.T) { BaseDomain: tc.baseDomain, }, } - actual := manageDNSForDomain(tc.domain, &status, &dnsConfig) + actual := ManageDNSForDomain(tc.domain, &status, &dnsConfig) if actual != tc.expected { t.Errorf("%q: expected to be %v, got %v", tc.name, tc.expected, actual) } } } - -func toYaml(obj interface{}) string { - yml, _ := yaml.Marshal(obj) - return string(yml) -} diff --git a/pkg/util/yaml.go b/pkg/util/yaml.go new file mode 100644 index 0000000000..13fbdd26e0 --- /dev/null +++ b/pkg/util/yaml.go @@ -0,0 +1,8 @@ +package k8s + +import "gopkg.in/yaml.v2" + +func ToYaml(obj interface{}) string { + yml, _ := yaml.Marshal(obj) + return string(yml) +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2016-04-01/dns/recordsets.go b/vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2016-04-01/dns/recordsets.go index 901c93b67f..67b0e73a09 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2016-04-01/dns/recordsets.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2016-04-01/dns/recordsets.go @@ -131,8 +131,8 @@ func (client RecordSetsClient) CreateOrUpdatePreparer(ctx context.Context, resou // CreateOrUpdateSender sends the CreateOrUpdate request. The method will close the // http.Response Body if it receives an error. func (client RecordSetsClient) CreateOrUpdateSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // CreateOrUpdateResponder handles the response to the CreateOrUpdate request. The method always @@ -229,8 +229,8 @@ func (client RecordSetsClient) DeletePreparer(ctx context.Context, resourceGroup // DeleteSender sends the Delete request. The method will close the // http.Response Body if it receives an error. func (client RecordSetsClient) DeleteSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // DeleteResponder handles the response to the Delete request. The method always @@ -319,8 +319,8 @@ func (client RecordSetsClient) GetPreparer(ctx context.Context, resourceGroupNam // GetSender sends the Get request. The method will close the // http.Response Body if it receives an error. func (client RecordSetsClient) GetSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // GetResponder handles the response to the Get request. The method always @@ -417,8 +417,8 @@ func (client RecordSetsClient) ListByDNSZonePreparer(ctx context.Context, resour // ListByDNSZoneSender sends the ListByDNSZone request. The method will close the // http.Response Body if it receives an error. func (client RecordSetsClient) ListByDNSZoneSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // ListByDNSZoneResponder handles the response to the ListByDNSZone request. The method always @@ -554,8 +554,8 @@ func (client RecordSetsClient) ListByTypePreparer(ctx context.Context, resourceG // ListByTypeSender sends the ListByType request. The method will close the // http.Response Body if it receives an error. func (client RecordSetsClient) ListByTypeSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // ListByTypeResponder handles the response to the ListByType request. The method always @@ -691,8 +691,8 @@ func (client RecordSetsClient) UpdatePreparer(ctx context.Context, resourceGroup // UpdateSender sends the Update request. The method will close the // http.Response Body if it receives an error. func (client RecordSetsClient) UpdateSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // UpdateResponder handles the response to the Update request. The method always diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2016-04-01/dns/zones.go b/vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2016-04-01/dns/zones.go index fcc49e25eb..27e713b923 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2016-04-01/dns/zones.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2016-04-01/dns/zones.go @@ -126,8 +126,8 @@ func (client ZonesClient) CreateOrUpdatePreparer(ctx context.Context, resourceGr // CreateOrUpdateSender sends the CreateOrUpdate request. The method will close the // http.Response Body if it receives an error. func (client ZonesClient) CreateOrUpdateSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // CreateOrUpdateResponder handles the response to the CreateOrUpdate request. The method always @@ -214,9 +214,9 @@ func (client ZonesClient) DeletePreparer(ctx context.Context, resourceGroupName // DeleteSender sends the Delete request. The method will close the // http.Response Body if it receives an error. func (client ZonesClient) DeleteSender(req *http.Request) (future ZonesDeleteFuture, err error) { + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) var resp *http.Response - resp, err = autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + resp, err = autorest.SendWithSender(client, req, sd...) if err != nil { return } @@ -307,8 +307,8 @@ func (client ZonesClient) GetPreparer(ctx context.Context, resourceGroupName str // GetSender sends the Get request. The method will close the // http.Response Body if it receives an error. func (client ZonesClient) GetSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // GetResponder handles the response to the Get request. The method always @@ -391,8 +391,8 @@ func (client ZonesClient) ListPreparer(ctx context.Context, top *int32) (*http.R // ListSender sends the List request. The method will close the // http.Response Body if it receives an error. func (client ZonesClient) ListSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // ListResponder handles the response to the List request. The method always @@ -518,8 +518,8 @@ func (client ZonesClient) ListByResourceGroupPreparer(ctx context.Context, resou // ListByResourceGroupSender sends the ListByResourceGroup request. The method will close the // http.Response Body if it receives an error. func (client ZonesClient) ListByResourceGroupSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // ListByResourceGroupResponder handles the response to the ListByResourceGroup request. The method always diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns/privatezones.go b/vendor/github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns/privatezones.go index ce1f087e49..d5f21fae56 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns/privatezones.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns/privatezones.go @@ -110,9 +110,9 @@ func (client PrivateZonesClient) CreateOrUpdatePreparer(ctx context.Context, res // CreateOrUpdateSender sends the CreateOrUpdate request. The method will close the // http.Response Body if it receives an error. func (client PrivateZonesClient) CreateOrUpdateSender(req *http.Request) (future PrivateZonesCreateOrUpdateFuture, err error) { + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) var resp *http.Response - resp, err = autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + resp, err = autorest.SendWithSender(client, req, sd...) if err != nil { return } @@ -194,9 +194,9 @@ func (client PrivateZonesClient) DeletePreparer(ctx context.Context, resourceGro // DeleteSender sends the Delete request. The method will close the // http.Response Body if it receives an error. func (client PrivateZonesClient) DeleteSender(req *http.Request) (future PrivateZonesDeleteFuture, err error) { + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) var resp *http.Response - resp, err = autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + resp, err = autorest.SendWithSender(client, req, sd...) if err != nil { return } @@ -277,8 +277,8 @@ func (client PrivateZonesClient) GetPreparer(ctx context.Context, resourceGroupN // GetSender sends the Get request. The method will close the // http.Response Body if it receives an error. func (client PrivateZonesClient) GetSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // GetResponder handles the response to the Get request. The method always @@ -355,8 +355,8 @@ func (client PrivateZonesClient) ListPreparer(ctx context.Context, top *int32) ( // ListSender sends the List request. The method will close the // http.Response Body if it receives an error. func (client PrivateZonesClient) ListSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // ListResponder handles the response to the List request. The method always @@ -472,8 +472,8 @@ func (client PrivateZonesClient) ListByResourceGroupPreparer(ctx context.Context // ListByResourceGroupSender sends the ListByResourceGroup request. The method will close the // http.Response Body if it receives an error. func (client PrivateZonesClient) ListByResourceGroupSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // ListByResourceGroupResponder handles the response to the ListByResourceGroup request. The method always @@ -589,9 +589,9 @@ func (client PrivateZonesClient) UpdatePreparer(ctx context.Context, resourceGro // UpdateSender sends the Update request. The method will close the // http.Response Body if it receives an error. func (client PrivateZonesClient) UpdateSender(req *http.Request) (future PrivateZonesUpdateFuture, err error) { + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) var resp *http.Response - resp, err = autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + resp, err = autorest.SendWithSender(client, req, sd...) if err != nil { return } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns/recordsets.go b/vendor/github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns/recordsets.go index 1a2b1a82b9..cfc5aa630e 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns/recordsets.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns/recordsets.go @@ -120,8 +120,8 @@ func (client RecordSetsClient) CreateOrUpdatePreparer(ctx context.Context, resou // CreateOrUpdateSender sends the CreateOrUpdate request. The method will close the // http.Response Body if it receives an error. func (client RecordSetsClient) CreateOrUpdateSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // CreateOrUpdateResponder handles the response to the CreateOrUpdate request. The method always @@ -208,8 +208,8 @@ func (client RecordSetsClient) DeletePreparer(ctx context.Context, resourceGroup // DeleteSender sends the Delete request. The method will close the // http.Response Body if it receives an error. func (client RecordSetsClient) DeleteSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // DeleteResponder handles the response to the Delete request. The method always @@ -288,8 +288,8 @@ func (client RecordSetsClient) GetPreparer(ctx context.Context, resourceGroupNam // GetSender sends the Get request. The method will close the // http.Response Body if it receives an error. func (client RecordSetsClient) GetSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // GetResponder handles the response to the Get request. The method always @@ -376,8 +376,8 @@ func (client RecordSetsClient) ListPreparer(ctx context.Context, resourceGroupNa // ListSender sends the List request. The method will close the // http.Response Body if it receives an error. func (client RecordSetsClient) ListSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // ListResponder handles the response to the List request. The method always @@ -503,8 +503,8 @@ func (client RecordSetsClient) ListByTypePreparer(ctx context.Context, resourceG // ListByTypeSender sends the ListByType request. The method will close the // http.Response Body if it receives an error. func (client RecordSetsClient) ListByTypeSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // ListByTypeResponder handles the response to the ListByType request. The method always @@ -630,8 +630,8 @@ func (client RecordSetsClient) UpdatePreparer(ctx context.Context, resourceGroup // UpdateSender sends the Update request. The method will close the // http.Response Body if it receives an error. func (client RecordSetsClient) UpdateSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // UpdateResponder handles the response to the Update request. The method always diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns/virtualnetworklinks.go b/vendor/github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns/virtualnetworklinks.go index d5f8897288..dfa7de0dff 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns/virtualnetworklinks.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns/virtualnetworklinks.go @@ -112,9 +112,9 @@ func (client VirtualNetworkLinksClient) CreateOrUpdatePreparer(ctx context.Conte // CreateOrUpdateSender sends the CreateOrUpdate request. The method will close the // http.Response Body if it receives an error. func (client VirtualNetworkLinksClient) CreateOrUpdateSender(req *http.Request) (future VirtualNetworkLinksCreateOrUpdateFuture, err error) { + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) var resp *http.Response - resp, err = autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + resp, err = autorest.SendWithSender(client, req, sd...) if err != nil { return } @@ -199,9 +199,9 @@ func (client VirtualNetworkLinksClient) DeletePreparer(ctx context.Context, reso // DeleteSender sends the Delete request. The method will close the // http.Response Body if it receives an error. func (client VirtualNetworkLinksClient) DeleteSender(req *http.Request) (future VirtualNetworkLinksDeleteFuture, err error) { + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) var resp *http.Response - resp, err = autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + resp, err = autorest.SendWithSender(client, req, sd...) if err != nil { return } @@ -283,8 +283,8 @@ func (client VirtualNetworkLinksClient) GetPreparer(ctx context.Context, resourc // GetSender sends the Get request. The method will close the // http.Response Body if it receives an error. func (client VirtualNetworkLinksClient) GetSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // GetResponder handles the response to the Get request. The method always @@ -366,8 +366,8 @@ func (client VirtualNetworkLinksClient) ListPreparer(ctx context.Context, resour // ListSender sends the List request. The method will close the // http.Response Body if it receives an error. func (client VirtualNetworkLinksClient) ListSender(req *http.Request) (*http.Response, error) { - return autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) } // ListResponder handles the response to the List request. The method always @@ -486,9 +486,9 @@ func (client VirtualNetworkLinksClient) UpdatePreparer(ctx context.Context, reso // UpdateSender sends the Update request. The method will close the // http.Response Body if it receives an error. func (client VirtualNetworkLinksClient) UpdateSender(req *http.Request) (future VirtualNetworkLinksUpdateFuture, err error) { + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) var resp *http.Response - resp, err = autorest.SendWithSender(client, req, - azure.DoRetryWithRegistration(client.Client)) + resp, err = autorest.SendWithSender(client, req, sd...) if err != nil { return } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/version/version.go b/vendor/github.com/Azure/azure-sdk-for-go/version/version.go index fa206bf213..e92b783805 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/version/version.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/version/version.go @@ -18,4 +18,4 @@ package version // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Number contains the semantic version of this SDK. -const Number = "v30.0.0" +const Number = "v36.1.0" diff --git a/vendor/github.com/Azure/go-autorest/autorest/to/go_mod_tidy_hack.go b/vendor/github.com/Azure/go-autorest/autorest/to/go_mod_tidy_hack.go new file mode 100644 index 0000000000..8e82921070 --- /dev/null +++ b/vendor/github.com/Azure/go-autorest/autorest/to/go_mod_tidy_hack.go @@ -0,0 +1,24 @@ +// +build modhack + +package to + +// Copyright 2017 Microsoft Corporation +// +// 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. + +// This file, and the github.com/Azure/go-autorest/autorest import, won't actually become part of +// the resultant binary. + +// Necessary for safely adding multi-module repo. +// See: https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository +import _ "github.com/Azure/go-autorest/autorest" diff --git a/vendor/github.com/Azure/go-autorest/autorest/validation/go_mod_tidy_hack.go b/vendor/github.com/Azure/go-autorest/autorest/validation/go_mod_tidy_hack.go new file mode 100644 index 0000000000..2b2668581e --- /dev/null +++ b/vendor/github.com/Azure/go-autorest/autorest/validation/go_mod_tidy_hack.go @@ -0,0 +1,24 @@ +// +build modhack + +package validation + +// Copyright 2017 Microsoft Corporation +// +// 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. + +// This file, and the github.com/Azure/go-autorest/autorest import, won't actually become part of +// the resultant binary. + +// Necessary for safely adding multi-module repo. +// See: https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository +import _ "github.com/Azure/go-autorest/autorest" diff --git a/vendor/github.com/blang/semver/.travis.yml b/vendor/github.com/blang/semver/.travis.yml new file mode 100644 index 0000000000..102fb9a691 --- /dev/null +++ b/vendor/github.com/blang/semver/.travis.yml @@ -0,0 +1,21 @@ +language: go +matrix: + include: + - go: 1.4.3 + - go: 1.5.4 + - go: 1.6.3 + - go: 1.7 + - go: tip + allow_failures: + - go: tip +install: +- go get golang.org/x/tools/cmd/cover +- go get github.com/mattn/goveralls +script: +- echo "Test and track coverage" ; $HOME/gopath/bin/goveralls -package "." -service=travis-ci + -repotoken $COVERALLS_TOKEN +- echo "Build examples" ; cd examples && go build +- echo "Check if gofmt'd" ; diff -u <(echo -n) <(gofmt -d -s .) +env: + global: + secure: HroGEAUQpVq9zX1b1VIkraLiywhGbzvNnTZq2TMxgK7JHP8xqNplAeF1izrR2i4QLL9nsY+9WtYss4QuPvEtZcVHUobw6XnL6radF7jS1LgfYZ9Y7oF+zogZ2I5QUMRLGA7rcxQ05s7mKq3XZQfeqaNts4bms/eZRefWuaFZbkw= diff --git a/vendor/github.com/blang/semver/LICENSE b/vendor/github.com/blang/semver/LICENSE new file mode 100644 index 0000000000..5ba5c86fcb --- /dev/null +++ b/vendor/github.com/blang/semver/LICENSE @@ -0,0 +1,22 @@ +The MIT License + +Copyright (c) 2014 Benedikt Lang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/vendor/github.com/blang/semver/README.md b/vendor/github.com/blang/semver/README.md new file mode 100644 index 0000000000..08b2e4a3d7 --- /dev/null +++ b/vendor/github.com/blang/semver/README.md @@ -0,0 +1,194 @@ +semver for golang [![Build Status](https://travis-ci.org/blang/semver.svg?branch=master)](https://travis-ci.org/blang/semver) [![GoDoc](https://godoc.org/github.com/blang/semver?status.png)](https://godoc.org/github.com/blang/semver) [![Coverage Status](https://img.shields.io/coveralls/blang/semver.svg)](https://coveralls.io/r/blang/semver?branch=master) +====== + +semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`. + +Usage +----- +```bash +$ go get github.com/blang/semver +``` +Note: Always vendor your dependencies or fix on a specific version tag. + +```go +import github.com/blang/semver +v1, err := semver.Make("1.0.0-beta") +v2, err := semver.Make("2.0.0-beta") +v1.Compare(v2) +``` + +Also check the [GoDocs](http://godoc.org/github.com/blang/semver). + +Why should I use this lib? +----- + +- Fully spec compatible +- No reflection +- No regex +- Fully tested (Coverage >99%) +- Readable parsing/validation errors +- Fast (See [Benchmarks](#benchmarks)) +- Only Stdlib +- Uses values instead of pointers +- Many features, see below + + +Features +----- + +- Parsing and validation at all levels +- Comparator-like comparisons +- Compare Helper Methods +- InPlace manipulation +- Ranges `>=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1` +- Wildcards `>=1.x`, `<=2.5.x` +- Sortable (implements sort.Interface) +- database/sql compatible (sql.Scanner/Valuer) +- encoding/json compatible (json.Marshaler/Unmarshaler) + +Ranges +------ + +A `Range` is a set of conditions which specify which versions satisfy the range. + +A condition is composed of an operator and a version. The supported operators are: + +- `<1.0.0` Less than `1.0.0` +- `<=1.0.0` Less than or equal to `1.0.0` +- `>1.0.0` Greater than `1.0.0` +- `>=1.0.0` Greater than or equal to `1.0.0` +- `1.0.0`, `=1.0.0`, `==1.0.0` Equal to `1.0.0` +- `!1.0.0`, `!=1.0.0` Not equal to `1.0.0`. Excludes version `1.0.0`. + +Note that spaces between the operator and the version will be gracefully tolerated. + +A `Range` can link multiple `Ranges` separated by space: + +Ranges can be linked by logical AND: + + - `>1.0.0 <2.0.0` would match between both ranges, so `1.1.1` and `1.8.7` but not `1.0.0` or `2.0.0` + - `>1.0.0 <3.0.0 !2.0.3-beta.2` would match every version between `1.0.0` and `3.0.0` except `2.0.3-beta.2` + +Ranges can also be linked by logical OR: + + - `<2.0.0 || >=3.0.0` would match `1.x.x` and `3.x.x` but not `2.x.x` + +AND has a higher precedence than OR. It's not possible to use brackets. + +Ranges can be combined by both AND and OR + + - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1` + +Range usage: + +``` +v, err := semver.Parse("1.2.3") +range, err := semver.ParseRange(">1.0.0 <2.0.0 || >=3.0.0") +if range(v) { + //valid +} + +``` + +Example +----- + +Have a look at full examples in [examples/main.go](examples/main.go) + +```go +import github.com/blang/semver + +v, err := semver.Make("0.0.1-alpha.preview+123.github") +fmt.Printf("Major: %d\n", v.Major) +fmt.Printf("Minor: %d\n", v.Minor) +fmt.Printf("Patch: %d\n", v.Patch) +fmt.Printf("Pre: %s\n", v.Pre) +fmt.Printf("Build: %s\n", v.Build) + +// Prerelease versions array +if len(v.Pre) > 0 { + fmt.Println("Prerelease versions:") + for i, pre := range v.Pre { + fmt.Printf("%d: %q\n", i, pre) + } +} + +// Build meta data array +if len(v.Build) > 0 { + fmt.Println("Build meta data:") + for i, build := range v.Build { + fmt.Printf("%d: %q\n", i, build) + } +} + +v001, err := semver.Make("0.0.1") +// Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE +v001.GT(v) == true +v.LT(v001) == true +v.GTE(v) == true +v.LTE(v) == true + +// Or use v.Compare(v2) for comparisons (-1, 0, 1): +v001.Compare(v) == 1 +v.Compare(v001) == -1 +v.Compare(v) == 0 + +// Manipulate Version in place: +v.Pre[0], err = semver.NewPRVersion("beta") +if err != nil { + fmt.Printf("Error parsing pre release version: %q", err) +} + +fmt.Println("\nValidate versions:") +v.Build[0] = "?" + +err = v.Validate() +if err != nil { + fmt.Printf("Validation failed: %s\n", err) +} +``` + + +Benchmarks +----- + + BenchmarkParseSimple-4 5000000 390 ns/op 48 B/op 1 allocs/op + BenchmarkParseComplex-4 1000000 1813 ns/op 256 B/op 7 allocs/op + BenchmarkParseAverage-4 1000000 1171 ns/op 163 B/op 4 allocs/op + BenchmarkStringSimple-4 20000000 119 ns/op 16 B/op 1 allocs/op + BenchmarkStringLarger-4 10000000 206 ns/op 32 B/op 2 allocs/op + BenchmarkStringComplex-4 5000000 324 ns/op 80 B/op 3 allocs/op + BenchmarkStringAverage-4 5000000 273 ns/op 53 B/op 2 allocs/op + BenchmarkValidateSimple-4 200000000 9.33 ns/op 0 B/op 0 allocs/op + BenchmarkValidateComplex-4 3000000 469 ns/op 0 B/op 0 allocs/op + BenchmarkValidateAverage-4 5000000 256 ns/op 0 B/op 0 allocs/op + BenchmarkCompareSimple-4 100000000 11.8 ns/op 0 B/op 0 allocs/op + BenchmarkCompareComplex-4 50000000 30.8 ns/op 0 B/op 0 allocs/op + BenchmarkCompareAverage-4 30000000 41.5 ns/op 0 B/op 0 allocs/op + BenchmarkSort-4 3000000 419 ns/op 256 B/op 2 allocs/op + BenchmarkRangeParseSimple-4 2000000 850 ns/op 192 B/op 5 allocs/op + BenchmarkRangeParseAverage-4 1000000 1677 ns/op 400 B/op 10 allocs/op + BenchmarkRangeParseComplex-4 300000 5214 ns/op 1440 B/op 30 allocs/op + BenchmarkRangeMatchSimple-4 50000000 25.6 ns/op 0 B/op 0 allocs/op + BenchmarkRangeMatchAverage-4 30000000 56.4 ns/op 0 B/op 0 allocs/op + BenchmarkRangeMatchComplex-4 10000000 153 ns/op 0 B/op 0 allocs/op + +See benchmark cases at [semver_test.go](semver_test.go) + + +Motivation +----- + +I simply couldn't find any lib supporting the full spec. Others were just wrong or used reflection and regex which i don't like. + + +Contribution +----- + +Feel free to make a pull request. For bigger changes create a issue first to discuss about it. + + +License +----- + +See [LICENSE](LICENSE) file. diff --git a/vendor/github.com/blang/semver/json.go b/vendor/github.com/blang/semver/json.go new file mode 100644 index 0000000000..a74bf7c449 --- /dev/null +++ b/vendor/github.com/blang/semver/json.go @@ -0,0 +1,23 @@ +package semver + +import ( + "encoding/json" +) + +// MarshalJSON implements the encoding/json.Marshaler interface. +func (v Version) MarshalJSON() ([]byte, error) { + return json.Marshal(v.String()) +} + +// UnmarshalJSON implements the encoding/json.Unmarshaler interface. +func (v *Version) UnmarshalJSON(data []byte) (err error) { + var versionString string + + if err = json.Unmarshal(data, &versionString); err != nil { + return + } + + *v, err = Parse(versionString) + + return +} diff --git a/vendor/github.com/blang/semver/package.json b/vendor/github.com/blang/semver/package.json new file mode 100644 index 0000000000..1cf8ebdd9c --- /dev/null +++ b/vendor/github.com/blang/semver/package.json @@ -0,0 +1,17 @@ +{ + "author": "blang", + "bugs": { + "URL": "https://github.com/blang/semver/issues", + "url": "https://github.com/blang/semver/issues" + }, + "gx": { + "dvcsimport": "github.com/blang/semver" + }, + "gxVersion": "0.10.0", + "language": "go", + "license": "MIT", + "name": "semver", + "releaseCmd": "git commit -a -m \"gx publish $VERSION\"", + "version": "3.5.1" +} + diff --git a/vendor/github.com/blang/semver/range.go b/vendor/github.com/blang/semver/range.go new file mode 100644 index 0000000000..fca406d479 --- /dev/null +++ b/vendor/github.com/blang/semver/range.go @@ -0,0 +1,416 @@ +package semver + +import ( + "fmt" + "strconv" + "strings" + "unicode" +) + +type wildcardType int + +const ( + noneWildcard wildcardType = iota + majorWildcard wildcardType = 1 + minorWildcard wildcardType = 2 + patchWildcard wildcardType = 3 +) + +func wildcardTypefromInt(i int) wildcardType { + switch i { + case 1: + return majorWildcard + case 2: + return minorWildcard + case 3: + return patchWildcard + default: + return noneWildcard + } +} + +type comparator func(Version, Version) bool + +var ( + compEQ comparator = func(v1 Version, v2 Version) bool { + return v1.Compare(v2) == 0 + } + compNE = func(v1 Version, v2 Version) bool { + return v1.Compare(v2) != 0 + } + compGT = func(v1 Version, v2 Version) bool { + return v1.Compare(v2) == 1 + } + compGE = func(v1 Version, v2 Version) bool { + return v1.Compare(v2) >= 0 + } + compLT = func(v1 Version, v2 Version) bool { + return v1.Compare(v2) == -1 + } + compLE = func(v1 Version, v2 Version) bool { + return v1.Compare(v2) <= 0 + } +) + +type versionRange struct { + v Version + c comparator +} + +// rangeFunc creates a Range from the given versionRange. +func (vr *versionRange) rangeFunc() Range { + return Range(func(v Version) bool { + return vr.c(v, vr.v) + }) +} + +// Range represents a range of versions. +// A Range can be used to check if a Version satisfies it: +// +// range, err := semver.ParseRange(">1.0.0 <2.0.0") +// range(semver.MustParse("1.1.1") // returns true +type Range func(Version) bool + +// OR combines the existing Range with another Range using logical OR. +func (rf Range) OR(f Range) Range { + return Range(func(v Version) bool { + return rf(v) || f(v) + }) +} + +// AND combines the existing Range with another Range using logical AND. +func (rf Range) AND(f Range) Range { + return Range(func(v Version) bool { + return rf(v) && f(v) + }) +} + +// ParseRange parses a range and returns a Range. +// If the range could not be parsed an error is returned. +// +// Valid ranges are: +// - "<1.0.0" +// - "<=1.0.0" +// - ">1.0.0" +// - ">=1.0.0" +// - "1.0.0", "=1.0.0", "==1.0.0" +// - "!1.0.0", "!=1.0.0" +// +// A Range can consist of multiple ranges separated by space: +// Ranges can be linked by logical AND: +// - ">1.0.0 <2.0.0" would match between both ranges, so "1.1.1" and "1.8.7" but not "1.0.0" or "2.0.0" +// - ">1.0.0 <3.0.0 !2.0.3-beta.2" would match every version between 1.0.0 and 3.0.0 except 2.0.3-beta.2 +// +// Ranges can also be linked by logical OR: +// - "<2.0.0 || >=3.0.0" would match "1.x.x" and "3.x.x" but not "2.x.x" +// +// AND has a higher precedence than OR. It's not possible to use brackets. +// +// Ranges can be combined by both AND and OR +// +// - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1` +func ParseRange(s string) (Range, error) { + parts := splitAndTrim(s) + orParts, err := splitORParts(parts) + if err != nil { + return nil, err + } + expandedParts, err := expandWildcardVersion(orParts) + if err != nil { + return nil, err + } + var orFn Range + for _, p := range expandedParts { + var andFn Range + for _, ap := range p { + opStr, vStr, err := splitComparatorVersion(ap) + if err != nil { + return nil, err + } + vr, err := buildVersionRange(opStr, vStr) + if err != nil { + return nil, fmt.Errorf("Could not parse Range %q: %s", ap, err) + } + rf := vr.rangeFunc() + + // Set function + if andFn == nil { + andFn = rf + } else { // Combine with existing function + andFn = andFn.AND(rf) + } + } + if orFn == nil { + orFn = andFn + } else { + orFn = orFn.OR(andFn) + } + + } + return orFn, nil +} + +// splitORParts splits the already cleaned parts by '||'. +// Checks for invalid positions of the operator and returns an +// error if found. +func splitORParts(parts []string) ([][]string, error) { + var ORparts [][]string + last := 0 + for i, p := range parts { + if p == "||" { + if i == 0 { + return nil, fmt.Errorf("First element in range is '||'") + } + ORparts = append(ORparts, parts[last:i]) + last = i + 1 + } + } + if last == len(parts) { + return nil, fmt.Errorf("Last element in range is '||'") + } + ORparts = append(ORparts, parts[last:]) + return ORparts, nil +} + +// buildVersionRange takes a slice of 2: operator and version +// and builds a versionRange, otherwise an error. +func buildVersionRange(opStr, vStr string) (*versionRange, error) { + c := parseComparator(opStr) + if c == nil { + return nil, fmt.Errorf("Could not parse comparator %q in %q", opStr, strings.Join([]string{opStr, vStr}, "")) + } + v, err := Parse(vStr) + if err != nil { + return nil, fmt.Errorf("Could not parse version %q in %q: %s", vStr, strings.Join([]string{opStr, vStr}, ""), err) + } + + return &versionRange{ + v: v, + c: c, + }, nil + +} + +// inArray checks if a byte is contained in an array of bytes +func inArray(s byte, list []byte) bool { + for _, el := range list { + if el == s { + return true + } + } + return false +} + +// splitAndTrim splits a range string by spaces and cleans whitespaces +func splitAndTrim(s string) (result []string) { + last := 0 + var lastChar byte + excludeFromSplit := []byte{'>', '<', '='} + for i := 0; i < len(s); i++ { + if s[i] == ' ' && !inArray(lastChar, excludeFromSplit) { + if last < i-1 { + result = append(result, s[last:i]) + } + last = i + 1 + } else if s[i] != ' ' { + lastChar = s[i] + } + } + if last < len(s)-1 { + result = append(result, s[last:]) + } + + for i, v := range result { + result[i] = strings.Replace(v, " ", "", -1) + } + + // parts := strings.Split(s, " ") + // for _, x := range parts { + // if s := strings.TrimSpace(x); len(s) != 0 { + // result = append(result, s) + // } + // } + return +} + +// splitComparatorVersion splits the comparator from the version. +// Input must be free of leading or trailing spaces. +func splitComparatorVersion(s string) (string, string, error) { + i := strings.IndexFunc(s, unicode.IsDigit) + if i == -1 { + return "", "", fmt.Errorf("Could not get version from string: %q", s) + } + return strings.TrimSpace(s[0:i]), s[i:], nil +} + +// getWildcardType will return the type of wildcard that the +// passed version contains +func getWildcardType(vStr string) wildcardType { + parts := strings.Split(vStr, ".") + nparts := len(parts) + wildcard := parts[nparts-1] + + possibleWildcardType := wildcardTypefromInt(nparts) + if wildcard == "x" { + return possibleWildcardType + } + + return noneWildcard +} + +// createVersionFromWildcard will convert a wildcard version +// into a regular version, replacing 'x's with '0's, handling +// special cases like '1.x.x' and '1.x' +func createVersionFromWildcard(vStr string) string { + // handle 1.x.x + vStr2 := strings.Replace(vStr, ".x.x", ".x", 1) + vStr2 = strings.Replace(vStr2, ".x", ".0", 1) + parts := strings.Split(vStr2, ".") + + // handle 1.x + if len(parts) == 2 { + return vStr2 + ".0" + } + + return vStr2 +} + +// incrementMajorVersion will increment the major version +// of the passed version +func incrementMajorVersion(vStr string) (string, error) { + parts := strings.Split(vStr, ".") + i, err := strconv.Atoi(parts[0]) + if err != nil { + return "", err + } + parts[0] = strconv.Itoa(i + 1) + + return strings.Join(parts, "."), nil +} + +// incrementMajorVersion will increment the minor version +// of the passed version +func incrementMinorVersion(vStr string) (string, error) { + parts := strings.Split(vStr, ".") + i, err := strconv.Atoi(parts[1]) + if err != nil { + return "", err + } + parts[1] = strconv.Itoa(i + 1) + + return strings.Join(parts, "."), nil +} + +// expandWildcardVersion will expand wildcards inside versions +// following these rules: +// +// * when dealing with patch wildcards: +// >= 1.2.x will become >= 1.2.0 +// <= 1.2.x will become < 1.3.0 +// > 1.2.x will become >= 1.3.0 +// < 1.2.x will become < 1.2.0 +// != 1.2.x will become < 1.2.0 >= 1.3.0 +// +// * when dealing with minor wildcards: +// >= 1.x will become >= 1.0.0 +// <= 1.x will become < 2.0.0 +// > 1.x will become >= 2.0.0 +// < 1.0 will become < 1.0.0 +// != 1.x will become < 1.0.0 >= 2.0.0 +// +// * when dealing with wildcards without +// version operator: +// 1.2.x will become >= 1.2.0 < 1.3.0 +// 1.x will become >= 1.0.0 < 2.0.0 +func expandWildcardVersion(parts [][]string) ([][]string, error) { + var expandedParts [][]string + for _, p := range parts { + var newParts []string + for _, ap := range p { + if strings.Index(ap, "x") != -1 { + opStr, vStr, err := splitComparatorVersion(ap) + if err != nil { + return nil, err + } + + versionWildcardType := getWildcardType(vStr) + flatVersion := createVersionFromWildcard(vStr) + + var resultOperator string + var shouldIncrementVersion bool + switch opStr { + case ">": + resultOperator = ">=" + shouldIncrementVersion = true + case ">=": + resultOperator = ">=" + case "<": + resultOperator = "<" + case "<=": + resultOperator = "<" + shouldIncrementVersion = true + case "", "=", "==": + newParts = append(newParts, ">="+flatVersion) + resultOperator = "<" + shouldIncrementVersion = true + case "!=", "!": + newParts = append(newParts, "<"+flatVersion) + resultOperator = ">=" + shouldIncrementVersion = true + } + + var resultVersion string + if shouldIncrementVersion { + switch versionWildcardType { + case patchWildcard: + resultVersion, _ = incrementMinorVersion(flatVersion) + case minorWildcard: + resultVersion, _ = incrementMajorVersion(flatVersion) + } + } else { + resultVersion = flatVersion + } + + ap = resultOperator + resultVersion + } + newParts = append(newParts, ap) + } + expandedParts = append(expandedParts, newParts) + } + + return expandedParts, nil +} + +func parseComparator(s string) comparator { + switch s { + case "==": + fallthrough + case "": + fallthrough + case "=": + return compEQ + case ">": + return compGT + case ">=": + return compGE + case "<": + return compLT + case "<=": + return compLE + case "!": + fallthrough + case "!=": + return compNE + } + + return nil +} + +// MustParseRange is like ParseRange but panics if the range cannot be parsed. +func MustParseRange(s string) Range { + r, err := ParseRange(s) + if err != nil { + panic(`semver: ParseRange(` + s + `): ` + err.Error()) + } + return r +} diff --git a/vendor/github.com/blang/semver/semver.go b/vendor/github.com/blang/semver/semver.go new file mode 100644 index 0000000000..8ee0842e6a --- /dev/null +++ b/vendor/github.com/blang/semver/semver.go @@ -0,0 +1,418 @@ +package semver + +import ( + "errors" + "fmt" + "strconv" + "strings" +) + +const ( + numbers string = "0123456789" + alphas = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" + alphanum = alphas + numbers +) + +// SpecVersion is the latest fully supported spec version of semver +var SpecVersion = Version{ + Major: 2, + Minor: 0, + Patch: 0, +} + +// Version represents a semver compatible version +type Version struct { + Major uint64 + Minor uint64 + Patch uint64 + Pre []PRVersion + Build []string //No Precendence +} + +// Version to string +func (v Version) String() string { + b := make([]byte, 0, 5) + b = strconv.AppendUint(b, v.Major, 10) + b = append(b, '.') + b = strconv.AppendUint(b, v.Minor, 10) + b = append(b, '.') + b = strconv.AppendUint(b, v.Patch, 10) + + if len(v.Pre) > 0 { + b = append(b, '-') + b = append(b, v.Pre[0].String()...) + + for _, pre := range v.Pre[1:] { + b = append(b, '.') + b = append(b, pre.String()...) + } + } + + if len(v.Build) > 0 { + b = append(b, '+') + b = append(b, v.Build[0]...) + + for _, build := range v.Build[1:] { + b = append(b, '.') + b = append(b, build...) + } + } + + return string(b) +} + +// Equals checks if v is equal to o. +func (v Version) Equals(o Version) bool { + return (v.Compare(o) == 0) +} + +// EQ checks if v is equal to o. +func (v Version) EQ(o Version) bool { + return (v.Compare(o) == 0) +} + +// NE checks if v is not equal to o. +func (v Version) NE(o Version) bool { + return (v.Compare(o) != 0) +} + +// GT checks if v is greater than o. +func (v Version) GT(o Version) bool { + return (v.Compare(o) == 1) +} + +// GTE checks if v is greater than or equal to o. +func (v Version) GTE(o Version) bool { + return (v.Compare(o) >= 0) +} + +// GE checks if v is greater than or equal to o. +func (v Version) GE(o Version) bool { + return (v.Compare(o) >= 0) +} + +// LT checks if v is less than o. +func (v Version) LT(o Version) bool { + return (v.Compare(o) == -1) +} + +// LTE checks if v is less than or equal to o. +func (v Version) LTE(o Version) bool { + return (v.Compare(o) <= 0) +} + +// LE checks if v is less than or equal to o. +func (v Version) LE(o Version) bool { + return (v.Compare(o) <= 0) +} + +// Compare compares Versions v to o: +// -1 == v is less than o +// 0 == v is equal to o +// 1 == v is greater than o +func (v Version) Compare(o Version) int { + if v.Major != o.Major { + if v.Major > o.Major { + return 1 + } + return -1 + } + if v.Minor != o.Minor { + if v.Minor > o.Minor { + return 1 + } + return -1 + } + if v.Patch != o.Patch { + if v.Patch > o.Patch { + return 1 + } + return -1 + } + + // Quick comparison if a version has no prerelease versions + if len(v.Pre) == 0 && len(o.Pre) == 0 { + return 0 + } else if len(v.Pre) == 0 && len(o.Pre) > 0 { + return 1 + } else if len(v.Pre) > 0 && len(o.Pre) == 0 { + return -1 + } + + i := 0 + for ; i < len(v.Pre) && i < len(o.Pre); i++ { + if comp := v.Pre[i].Compare(o.Pre[i]); comp == 0 { + continue + } else if comp == 1 { + return 1 + } else { + return -1 + } + } + + // If all pr versions are the equal but one has further prversion, this one greater + if i == len(v.Pre) && i == len(o.Pre) { + return 0 + } else if i == len(v.Pre) && i < len(o.Pre) { + return -1 + } else { + return 1 + } + +} + +// Validate validates v and returns error in case +func (v Version) Validate() error { + // Major, Minor, Patch already validated using uint64 + + for _, pre := range v.Pre { + if !pre.IsNum { //Numeric prerelease versions already uint64 + if len(pre.VersionStr) == 0 { + return fmt.Errorf("Prerelease can not be empty %q", pre.VersionStr) + } + if !containsOnly(pre.VersionStr, alphanum) { + return fmt.Errorf("Invalid character(s) found in prerelease %q", pre.VersionStr) + } + } + } + + for _, build := range v.Build { + if len(build) == 0 { + return fmt.Errorf("Build meta data can not be empty %q", build) + } + if !containsOnly(build, alphanum) { + return fmt.Errorf("Invalid character(s) found in build meta data %q", build) + } + } + + return nil +} + +// New is an alias for Parse and returns a pointer, parses version string and returns a validated Version or error +func New(s string) (vp *Version, err error) { + v, err := Parse(s) + vp = &v + return +} + +// Make is an alias for Parse, parses version string and returns a validated Version or error +func Make(s string) (Version, error) { + return Parse(s) +} + +// ParseTolerant allows for certain version specifications that do not strictly adhere to semver +// specs to be parsed by this library. It does so by normalizing versions before passing them to +// Parse(). It currently trims spaces, removes a "v" prefix, and adds a 0 patch number to versions +// with only major and minor components specified +func ParseTolerant(s string) (Version, error) { + s = strings.TrimSpace(s) + s = strings.TrimPrefix(s, "v") + + // Split into major.minor.(patch+pr+meta) + parts := strings.SplitN(s, ".", 3) + if len(parts) < 3 { + if strings.ContainsAny(parts[len(parts)-1], "+-") { + return Version{}, errors.New("Short version cannot contain PreRelease/Build meta data") + } + for len(parts) < 3 { + parts = append(parts, "0") + } + s = strings.Join(parts, ".") + } + + return Parse(s) +} + +// Parse parses version string and returns a validated Version or error +func Parse(s string) (Version, error) { + if len(s) == 0 { + return Version{}, errors.New("Version string empty") + } + + // Split into major.minor.(patch+pr+meta) + parts := strings.SplitN(s, ".", 3) + if len(parts) != 3 { + return Version{}, errors.New("No Major.Minor.Patch elements found") + } + + // Major + if !containsOnly(parts[0], numbers) { + return Version{}, fmt.Errorf("Invalid character(s) found in major number %q", parts[0]) + } + if hasLeadingZeroes(parts[0]) { + return Version{}, fmt.Errorf("Major number must not contain leading zeroes %q", parts[0]) + } + major, err := strconv.ParseUint(parts[0], 10, 64) + if err != nil { + return Version{}, err + } + + // Minor + if !containsOnly(parts[1], numbers) { + return Version{}, fmt.Errorf("Invalid character(s) found in minor number %q", parts[1]) + } + if hasLeadingZeroes(parts[1]) { + return Version{}, fmt.Errorf("Minor number must not contain leading zeroes %q", parts[1]) + } + minor, err := strconv.ParseUint(parts[1], 10, 64) + if err != nil { + return Version{}, err + } + + v := Version{} + v.Major = major + v.Minor = minor + + var build, prerelease []string + patchStr := parts[2] + + if buildIndex := strings.IndexRune(patchStr, '+'); buildIndex != -1 { + build = strings.Split(patchStr[buildIndex+1:], ".") + patchStr = patchStr[:buildIndex] + } + + if preIndex := strings.IndexRune(patchStr, '-'); preIndex != -1 { + prerelease = strings.Split(patchStr[preIndex+1:], ".") + patchStr = patchStr[:preIndex] + } + + if !containsOnly(patchStr, numbers) { + return Version{}, fmt.Errorf("Invalid character(s) found in patch number %q", patchStr) + } + if hasLeadingZeroes(patchStr) { + return Version{}, fmt.Errorf("Patch number must not contain leading zeroes %q", patchStr) + } + patch, err := strconv.ParseUint(patchStr, 10, 64) + if err != nil { + return Version{}, err + } + + v.Patch = patch + + // Prerelease + for _, prstr := range prerelease { + parsedPR, err := NewPRVersion(prstr) + if err != nil { + return Version{}, err + } + v.Pre = append(v.Pre, parsedPR) + } + + // Build meta data + for _, str := range build { + if len(str) == 0 { + return Version{}, errors.New("Build meta data is empty") + } + if !containsOnly(str, alphanum) { + return Version{}, fmt.Errorf("Invalid character(s) found in build meta data %q", str) + } + v.Build = append(v.Build, str) + } + + return v, nil +} + +// MustParse is like Parse but panics if the version cannot be parsed. +func MustParse(s string) Version { + v, err := Parse(s) + if err != nil { + panic(`semver: Parse(` + s + `): ` + err.Error()) + } + return v +} + +// PRVersion represents a PreRelease Version +type PRVersion struct { + VersionStr string + VersionNum uint64 + IsNum bool +} + +// NewPRVersion creates a new valid prerelease version +func NewPRVersion(s string) (PRVersion, error) { + if len(s) == 0 { + return PRVersion{}, errors.New("Prerelease is empty") + } + v := PRVersion{} + if containsOnly(s, numbers) { + if hasLeadingZeroes(s) { + return PRVersion{}, fmt.Errorf("Numeric PreRelease version must not contain leading zeroes %q", s) + } + num, err := strconv.ParseUint(s, 10, 64) + + // Might never be hit, but just in case + if err != nil { + return PRVersion{}, err + } + v.VersionNum = num + v.IsNum = true + } else if containsOnly(s, alphanum) { + v.VersionStr = s + v.IsNum = false + } else { + return PRVersion{}, fmt.Errorf("Invalid character(s) found in prerelease %q", s) + } + return v, nil +} + +// IsNumeric checks if prerelease-version is numeric +func (v PRVersion) IsNumeric() bool { + return v.IsNum +} + +// Compare compares two PreRelease Versions v and o: +// -1 == v is less than o +// 0 == v is equal to o +// 1 == v is greater than o +func (v PRVersion) Compare(o PRVersion) int { + if v.IsNum && !o.IsNum { + return -1 + } else if !v.IsNum && o.IsNum { + return 1 + } else if v.IsNum && o.IsNum { + if v.VersionNum == o.VersionNum { + return 0 + } else if v.VersionNum > o.VersionNum { + return 1 + } else { + return -1 + } + } else { // both are Alphas + if v.VersionStr == o.VersionStr { + return 0 + } else if v.VersionStr > o.VersionStr { + return 1 + } else { + return -1 + } + } +} + +// PreRelease version to string +func (v PRVersion) String() string { + if v.IsNum { + return strconv.FormatUint(v.VersionNum, 10) + } + return v.VersionStr +} + +func containsOnly(s string, set string) bool { + return strings.IndexFunc(s, func(r rune) bool { + return !strings.ContainsRune(set, r) + }) == -1 +} + +func hasLeadingZeroes(s string) bool { + return len(s) > 1 && s[0] == '0' +} + +// NewBuildVersion creates a new valid build version +func NewBuildVersion(s string) (string, error) { + if len(s) == 0 { + return "", errors.New("Buildversion is empty") + } + if !containsOnly(s, alphanum) { + return "", fmt.Errorf("Invalid character(s) found in build meta data %q", s) + } + return s, nil +} diff --git a/vendor/github.com/blang/semver/sort.go b/vendor/github.com/blang/semver/sort.go new file mode 100644 index 0000000000..e18f880826 --- /dev/null +++ b/vendor/github.com/blang/semver/sort.go @@ -0,0 +1,28 @@ +package semver + +import ( + "sort" +) + +// Versions represents multiple versions. +type Versions []Version + +// Len returns length of version collection +func (s Versions) Len() int { + return len(s) +} + +// Swap swaps two versions inside the collection by its indices +func (s Versions) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +// Less checks if version at index i is less than version at index j +func (s Versions) Less(i, j int) bool { + return s[i].LT(s[j]) +} + +// Sort sorts a slice of versions +func Sort(versions []Version) { + sort.Sort(Versions(versions)) +} diff --git a/vendor/github.com/blang/semver/sql.go b/vendor/github.com/blang/semver/sql.go new file mode 100644 index 0000000000..eb4d802666 --- /dev/null +++ b/vendor/github.com/blang/semver/sql.go @@ -0,0 +1,30 @@ +package semver + +import ( + "database/sql/driver" + "fmt" +) + +// Scan implements the database/sql.Scanner interface. +func (v *Version) Scan(src interface{}) (err error) { + var str string + switch src := src.(type) { + case string: + str = src + case []byte: + str = string(src) + default: + return fmt.Errorf("Version.Scan: cannot convert %T to string.", src) + } + + if t, err := Parse(str); err == nil { + *v = t + } + + return +} + +// Value implements the database/sql/driver.Valuer interface. +func (v Version) Value() (driver.Value, error) { + return v.String(), nil +} diff --git a/vendor/github.com/fatih/color/.travis.yml b/vendor/github.com/fatih/color/.travis.yml deleted file mode 100644 index 95f8a1ff5c..0000000000 --- a/vendor/github.com/fatih/color/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: go -go: - - 1.8.x - - tip - diff --git a/vendor/github.com/fatih/color/Gopkg.lock b/vendor/github.com/fatih/color/Gopkg.lock deleted file mode 100644 index 7d879e9caf..0000000000 --- a/vendor/github.com/fatih/color/Gopkg.lock +++ /dev/null @@ -1,27 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - name = "github.com/mattn/go-colorable" - packages = ["."] - revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072" - version = "v0.0.9" - -[[projects]] - name = "github.com/mattn/go-isatty" - packages = ["."] - revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" - version = "v0.0.3" - -[[projects]] - branch = "master" - name = "golang.org/x/sys" - packages = ["unix"] - revision = "37707fdb30a5b38865cfb95e5aab41707daec7fd" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - inputs-digest = "e8a50671c3cb93ea935bf210b1cd20702876b9d9226129be581ef646d1565cdc" - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/vendor/github.com/fatih/color/Gopkg.toml b/vendor/github.com/fatih/color/Gopkg.toml deleted file mode 100644 index ff1617f71d..0000000000 --- a/vendor/github.com/fatih/color/Gopkg.toml +++ /dev/null @@ -1,30 +0,0 @@ - -# Gopkg.toml example -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" - - -[[constraint]] - name = "github.com/mattn/go-colorable" - version = "0.0.9" - -[[constraint]] - name = "github.com/mattn/go-isatty" - version = "0.0.3" diff --git a/vendor/github.com/fatih/color/README.md b/vendor/github.com/fatih/color/README.md index 3fc9544602..5c751f2158 100644 --- a/vendor/github.com/fatih/color/README.md +++ b/vendor/github.com/fatih/color/README.md @@ -1,14 +1,11 @@ -# Color [![GoDoc](https://godoc.org/github.com/fatih/color?status.svg)](https://godoc.org/github.com/fatih/color) [![Build Status](https://img.shields.io/travis/fatih/color.svg?style=flat-square)](https://travis-ci.org/fatih/color) - - +# color [![](https://github.com/fatih/color/workflows/build/badge.svg)](https://github.com/fatih/color/actions) [![PkgGoDev](https://pkg.go.dev/badge/github.com/fatih/color)](https://pkg.go.dev/github.com/fatih/color) Color lets you use colorized outputs in terms of [ANSI Escape Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It has support for Windows too! The API can be used in several ways, pick one that suits you. - -![Color](https://i.imgur.com/c1JI0lA.png) +![Color](https://user-images.githubusercontent.com/438920/96832689-03b3e000-13f4-11eb-9803-46f4c4de3406.jpg) ## Install @@ -17,9 +14,6 @@ suits you. go get github.com/fatih/color ``` -Note that the `vendor` folder is here for stability. Remove the folder if you -already have the dependencies in your GOPATH. - ## Examples ### Standard colors @@ -133,14 +127,16 @@ fmt.Println("All text will now be bold magenta.") There might be a case where you want to explicitly disable/enable color output. the `go-isatty` package will automatically disable color output for non-tty output streams -(for example if the output were piped directly to `less`) +(for example if the output were piped directly to `less`). -`Color` has support to disable/enable colors both globally and for single color -definitions. For example suppose you have a CLI app and a `--no-color` bool flag. You -can easily disable the color output with: +The `color` package also disables color output if the [`NO_COLOR`](https://no-color.org) environment +variable is set (regardless of its value). -```go +`Color` has support to disable/enable colors programatically both globally and +for single color definitions. For example suppose you have a CLI app and a +`--no-color` bool flag. You can easily disable the color output with: +```go var flagNoColor = flag.Bool("no-color", false, "Disable color output") if *flagNoColor { @@ -162,6 +158,10 @@ c.EnableColor() c.Println("This prints again cyan...") ``` +## GitHub Actions + +To output color in GitHub Actions (or other CI systems that support ANSI colors), make sure to set `color.NoColor = false` so that it bypasses the check for non-tty output streams. + ## Todo * Save/Return previous values @@ -176,4 +176,3 @@ c.Println("This prints again cyan...") ## License The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details - diff --git a/vendor/github.com/fatih/color/color.go b/vendor/github.com/fatih/color/color.go index 91c8e9f062..98a60f3c88 100644 --- a/vendor/github.com/fatih/color/color.go +++ b/vendor/github.com/fatih/color/color.go @@ -15,9 +15,11 @@ import ( var ( // NoColor defines if the output is colorized or not. It's dynamically set to // false or true based on the stdout's file descriptor referring to a terminal - // or not. This is a global option and affects all colors. For more control - // over each color block use the methods DisableColor() individually. - NoColor = os.Getenv("TERM") == "dumb" || + // or not. It's also set to true if the NO_COLOR environment variable is + // set (regardless of its value). This is a global option and affects all + // colors. For more control over each color block use the methods + // DisableColor() individually. + NoColor = noColorExists() || os.Getenv("TERM") == "dumb" || (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd())) // Output defines the standard output of the print functions. By default @@ -33,6 +35,12 @@ var ( colorsCacheMu sync.Mutex // protects colorsCache ) +// noColorExists returns true if the environment variable NO_COLOR exists. +func noColorExists() bool { + _, exists := os.LookupEnv("NO_COLOR") + return exists +} + // Color defines a custom color object which is defined by SGR parameters. type Color struct { params []Attribute @@ -108,7 +116,14 @@ const ( // New returns a newly created color object. func New(value ...Attribute) *Color { - c := &Color{params: make([]Attribute, 0)} + c := &Color{ + params: make([]Attribute, 0), + } + + if noColorExists() { + c.noColor = boolPtr(true) + } + c.Add(value...) return c } @@ -387,7 +402,7 @@ func (c *Color) EnableColor() { } func (c *Color) isNoColorSet() bool { - // check first if we have user setted action + // check first if we have user set action if c.noColor != nil { return *c.noColor } diff --git a/vendor/github.com/fatih/color/doc.go b/vendor/github.com/fatih/color/doc.go index cf1e96500f..04541de786 100644 --- a/vendor/github.com/fatih/color/doc.go +++ b/vendor/github.com/fatih/color/doc.go @@ -118,6 +118,8 @@ the color output with: color.NoColor = true // disables colorized output } +You can also disable the color by setting the NO_COLOR environment variable to any value. + It also has support for single color definitions (local). You can disable/enable color output on the fly: diff --git a/vendor/github.com/ghodss/yaml/.travis.yml b/vendor/github.com/ghodss/yaml/.travis.yml index 0e9d6edc01..98ad417e22 100644 --- a/vendor/github.com/ghodss/yaml/.travis.yml +++ b/vendor/github.com/ghodss/yaml/.travis.yml @@ -1,7 +1,8 @@ language: go go: - - 1.3 - - 1.4 + - "1.9" + - "1.10" + - "1.11" script: - go test - go build diff --git a/vendor/github.com/ghodss/yaml/yaml.go b/vendor/github.com/ghodss/yaml/yaml.go index 4fb4054a8b..dfd264d6c5 100644 --- a/vendor/github.com/ghodss/yaml/yaml.go +++ b/vendor/github.com/ghodss/yaml/yaml.go @@ -1,9 +1,20 @@ -package yaml +// Package yaml provides a wrapper around go-yaml designed to enable a better +// way of handling YAML when marshaling to and from structs. +// +// In short, this package first converts YAML to JSON using go-yaml and then +// uses json.Marshal and json.Unmarshal to convert to or from the struct. This +// means that it effectively reuses the JSON struct tags as well as the custom +// JSON methods MarshalJSON and UnmarshalJSON unlike go-yaml. +// +// See also http://ghodss.com/2014/the-right-way-to-handle-yaml-in-golang +// +package yaml // import "github.com/ghodss/yaml" import ( "bytes" "encoding/json" "fmt" + "io" "reflect" "strconv" @@ -26,15 +37,30 @@ func Marshal(o interface{}) ([]byte, error) { return y, nil } -// Converts YAML to JSON then uses JSON to unmarshal into an object. -func Unmarshal(y []byte, o interface{}) error { +// JSONOpt is a decoding option for decoding from JSON format. +type JSONOpt func(*json.Decoder) *json.Decoder + +// Unmarshal converts YAML to JSON then uses JSON to unmarshal into an object, +// optionally configuring the behavior of the JSON unmarshal. +func Unmarshal(y []byte, o interface{}, opts ...JSONOpt) error { + return unmarshal(yaml.Unmarshal, y, o, opts) +} + +// UnmarshalStrict is like Unmarshal except that any mapping keys that are +// duplicates will result in an error. +// To also be strict about unknown fields, add the DisallowUnknownFields option. +func UnmarshalStrict(y []byte, o interface{}, opts ...JSONOpt) error { + return unmarshal(yaml.UnmarshalStrict, y, o, opts) +} + +func unmarshal(f func(in []byte, out interface{}) (err error), y []byte, o interface{}, opts []JSONOpt) error { vo := reflect.ValueOf(o) - j, err := yamlToJSON(y, &vo) + j, err := yamlToJSON(y, &vo, f) if err != nil { return fmt.Errorf("error converting YAML to JSON: %v", err) } - err = json.Unmarshal(j, o) + err = jsonUnmarshal(bytes.NewReader(j), o, opts...) if err != nil { return fmt.Errorf("error unmarshaling JSON: %v", err) } @@ -42,6 +68,21 @@ func Unmarshal(y []byte, o interface{}) error { return nil } +// jsonUnmarshal unmarshals the JSON byte stream from the given reader into the +// object, optionally applying decoder options prior to decoding. We are not +// using json.Unmarshal directly as we want the chance to pass in non-default +// options. +func jsonUnmarshal(r io.Reader, o interface{}, opts ...JSONOpt) error { + d := json.NewDecoder(r) + for _, opt := range opts { + d = opt(d) + } + if err := d.Decode(&o); err != nil { + return fmt.Errorf("while decoding JSON: %v", err) + } + return nil +} + // Convert JSON to YAML. func JSONToYAML(j []byte) ([]byte, error) { // Convert the JSON to an object. @@ -60,8 +101,8 @@ func JSONToYAML(j []byte) ([]byte, error) { return yaml.Marshal(jsonObj) } -// Convert YAML to JSON. Since JSON is a subset of YAML, passing JSON through -// this method should be a no-op. +// YAMLToJSON converts YAML to JSON. Since JSON is a subset of YAML, +// passing JSON through this method should be a no-op. // // Things YAML can do that are not supported by JSON: // * In YAML you can have binary and null keys in your maps. These are invalid @@ -70,14 +111,22 @@ func JSONToYAML(j []byte) ([]byte, error) { // use binary data with this library, encode the data as base64 as usual but do // not use the !!binary tag in your YAML. This will ensure the original base64 // encoded data makes it all the way through to the JSON. +// +// For strict decoding of YAML, use YAMLToJSONStrict. func YAMLToJSON(y []byte) ([]byte, error) { - return yamlToJSON(y, nil) + return yamlToJSON(y, nil, yaml.Unmarshal) +} + +// YAMLToJSONStrict is like YAMLToJSON but enables strict YAML decoding, +// returning an error on any duplicate field names. +func YAMLToJSONStrict(y []byte) ([]byte, error) { + return yamlToJSON(y, nil, yaml.UnmarshalStrict) } -func yamlToJSON(y []byte, jsonTarget *reflect.Value) ([]byte, error) { +func yamlToJSON(y []byte, jsonTarget *reflect.Value, yamlUnmarshal func([]byte, interface{}) error) ([]byte, error) { // Convert the YAML to an object. var yamlObj interface{} - err := yaml.Unmarshal(y, &yamlObj) + err := yamlUnmarshal(y, &yamlObj) if err != nil { return nil, err } @@ -85,7 +134,7 @@ func yamlToJSON(y []byte, jsonTarget *reflect.Value) ([]byte, error) { // YAML objects are not completely compatible with JSON objects (e.g. you // can have non-string keys in YAML). So, convert the YAML-compatible object // to a JSON-compatible object, failing with an error if irrecoverable - // incompatibilties happen along the way. + // incompatibilities happen along the way. jsonObj, err := convertToJSONableObject(yamlObj, jsonTarget) if err != nil { return nil, err diff --git a/vendor/github.com/ghodss/yaml/yaml_go110.go b/vendor/github.com/ghodss/yaml/yaml_go110.go new file mode 100644 index 0000000000..ab3e06a222 --- /dev/null +++ b/vendor/github.com/ghodss/yaml/yaml_go110.go @@ -0,0 +1,14 @@ +// This file contains changes that are only compatible with go 1.10 and onwards. + +// +build go1.10 + +package yaml + +import "encoding/json" + +// DisallowUnknownFields configures the JSON decoder to error out if unknown +// fields come along, instead of dropping them by default. +func DisallowUnknownFields(d *json.Decoder) *json.Decoder { + d.DisallowUnknownFields() + return d +} diff --git a/vendor/github.com/maistra/istio-operator/LICENSE b/vendor/github.com/maistra/istio-operator/LICENSE new file mode 100644 index 0000000000..b085857dfb --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Red Hat Inc + + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/status/doc.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/status/doc.go new file mode 100644 index 0000000000..edbaf0f5c6 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/status/doc.go @@ -0,0 +1,3 @@ +// Package status contains common status types used in maistra API +// +k8s:deepcopy-gen=package +package status diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/status/status.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/status/status.go new file mode 100644 index 0000000000..192ce136a4 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/status/status.go @@ -0,0 +1,279 @@ +package status + +import ( + "fmt" + "strings" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + + "github.com/maistra/istio-operator/pkg/version" +) + +type StatusBase struct { + // Annotations is an unstructured key value map used to store additional, + // usually redundant status information, such as the number of components + // deployed by the ServiceMeshControlPlane (number is redundant because + // you could just as easily count the elements in the ComponentStatus + // array). The reason to add this redundant information is to make it + // available to kubectl, which does not yet allow counting objects in + // JSONPath expressions. + // +optional + Annotations map[string]string `json:"annotations,omitempty"` +} + +func (s *StatusBase) GetAnnotation(name string) string { + if s.Annotations == nil { + return "" + } + return s.Annotations[name] +} + +func (s *StatusBase) SetAnnotation(name string, value string) { + if s.Annotations == nil { + s.Annotations = map[string]string{} + } + s.Annotations[name] = value +} + +func (s *StatusBase) RemoveAnnotation(name string) { + if s.Annotations != nil { + delete(s.Annotations, name) + } +} + +// StatusType represents the status for a control plane, component, or resource +type StatusType struct { + // Represents the latest available observations of the object's current state. + Conditions []Condition `json:"conditions,omitempty"` +} + +// NewStatus returns a new StatusType object +func NewStatus() StatusType { + return StatusType{Conditions: make([]Condition, 0, 3)} +} + +type ComponentStatusList struct { + // +optional + ComponentStatus []ComponentStatus `json:"components,omitempty"` +} + +// FindComponentByName returns the status for a specific component +func (s *ComponentStatusList) FindComponentByName(name string) *ComponentStatus { + for i, status := range s.ComponentStatus { + if status.Resource == name { + return &s.ComponentStatus[i] + } + } + return nil +} + +// NewComponentStatus returns a new ComponentStatus object +func NewComponentStatus() *ComponentStatus { + return &ComponentStatus{StatusType: NewStatus()} +} + +// ComponentStatus represents the status of an object with children +type ComponentStatus struct { + StatusType `json:",inline"` + + // The name of the component this status pertains to. + Resource string `json:"resource,omitempty"` + + // TODO: can we remove this? it's not used anywhere + // The status of each resource that comprises this component. + Resources []*StatusType `json:"children,omitempty"` +} + +// ConditionType represents the type of the condition. Condition stages are: +// Installed, Reconciled, Ready +type ConditionType string + +const ( + // ConditionTypeInstalled signifies the whether or not the controller has + // installed the resources defined through the CR. + ConditionTypeInstalled ConditionType = "Installed" + // ConditionTypeReconciled signifies the whether or not the controller has + // reconciled the resources defined through the CR. + ConditionTypeReconciled ConditionType = "Reconciled" + // ConditionTypeReady signifies the whether or not any Deployment, StatefulSet, + // etc. resources are Ready. + ConditionTypeReady ConditionType = "Ready" +) + +// ConditionStatus represents the status of the condition +type ConditionStatus string + +const ( + // ConditionStatusTrue represents completion of the condition, e.g. + // Initialized=True signifies that initialization has occurred. + ConditionStatusTrue ConditionStatus = "True" + // ConditionStatusFalse represents incomplete status of the condition, e.g. + // Initialized=False signifies that initialization has not occurred or has + // failed. + ConditionStatusFalse ConditionStatus = "False" + // ConditionStatusUnknown represents unknown completion of the condition, e.g. + // Initialized=Unknown signifies that initialization may or may not have been + // completed. + ConditionStatusUnknown ConditionStatus = "Unknown" +) + +// ConditionReason represents a short message indicating how the condition came +// to be in its present state. +type ConditionReason string + +const ( + // ConditionReasonDeletionError ... + ConditionReasonDeletionError ConditionReason = "DeletionError" + // ConditionReasonInstallSuccessful ... + ConditionReasonInstallSuccessful ConditionReason = "InstallSuccessful" + // ConditionReasonInstallError ... + ConditionReasonInstallError ConditionReason = "InstallError" + // ConditionReasonReconcileSuccessful ... + ConditionReasonReconcileSuccessful ConditionReason = "ReconcileSuccessful" + // ConditionReasonValidationError ... + ConditionReasonValidationError ConditionReason = "ValidationError" + // ConditionReasonValidationError ... + ConditionReasonMultipleSMCPs ConditionReason = "ErrMultipleSMCPs" + // ConditionReasonDependencyMissingError ... + ConditionReasonDependencyMissingError ConditionReason = "DependencyMissingError" + // ConditionReasonReconcileError ... + ConditionReasonReconcileError ConditionReason = "ReconcileError" + // ConditionReasonResourceCreated ... + ConditionReasonResourceCreated ConditionReason = "ResourceCreated" + // ConditionReasonSpecUpdated ... + ConditionReasonSpecUpdated ConditionReason = "SpecUpdated" + // ConditionReasonOperatorUpdated indicates that the SMCP is being reconciled + // because the operator was upgraded + ConditionReasonOperatorUpdated ConditionReason = "OperatorUpdated" + // ConditionReasonUpdateSuccessful ... + ConditionReasonUpdateSuccessful ConditionReason = "UpdateSuccessful" + // ConditionReasonComponentsReady ... + ConditionReasonComponentsReady ConditionReason = "ComponentsReady" + // ConditionReasonComponentsNotReady ... + ConditionReasonComponentsNotReady ConditionReason = "ComponentsNotReady" + // ConditionReasonProbeError ... + ConditionReasonProbeError ConditionReason = "ProbeError" + // ConditionReasonPausingInstall ... + ConditionReasonPausingInstall ConditionReason = "PausingInstall" + // ConditionReasonPausingUpdate ... + ConditionReasonPausingUpdate ConditionReason = "PausingUpdate" + // ConditionReasonDeleting ... + ConditionReasonDeleting ConditionReason = "Deleting" + // ConditionReasonDeleted ... + ConditionReasonDeleted ConditionReason = "Deleted" +) + +// A Condition represents a specific observation of the object's state. +type Condition struct { + // The type of this condition. + Type ConditionType `json:"type,omitempty"` + + // The status of this condition. Can be True, False or Unknown. + Status ConditionStatus `json:"status,omitempty"` + + // Unique, single-word, CamelCase reason for the condition's last transition. + Reason ConditionReason `json:"reason,omitempty"` + + // Human-readable message indicating details about the last transition. + Message string `json:"message,omitempty"` + + // Last time the condition transitioned from one status to another. + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` +} + +func (c *Condition) Matches(status ConditionStatus, reason ConditionReason, message string) bool { + return c.Status == status && c.Reason == reason && c.Message == message +} + +// CurrentReconciledVersion returns a ReconciledVersion for this release of the operator +func CurrentReconciledVersion(generation int64) string { + return ComposeReconciledVersion(version.Info.Version, generation) +} + +// ComposeReconciledVersion returns a string for use in ReconciledVersion fields +func ComposeReconciledVersion(operatorVersion string, generation int64) string { + return fmt.Sprintf("%s-%d", operatorVersion, generation) +} + +// GetCondition removes a condition for the list of conditions +func (s *StatusType) GetCondition(conditionType ConditionType) Condition { + if s == nil { + return Condition{Type: conditionType, Status: ConditionStatusUnknown} + } + for i := range s.Conditions { + if s.Conditions[i].Type == conditionType { + return s.Conditions[i] + } + } + return Condition{Type: conditionType, Status: ConditionStatusUnknown} +} + +// SetCondition sets a specific condition in the list of conditions +func (s *StatusType) SetCondition(condition Condition) *StatusType { + if s == nil { + return nil + } + // These only get serialized out to the second. This can break update + // skipping, as the time in the resource returned from the client may not + // match the time in our cached status during a reconcile. We truncate here + // to save any problems down the line. + now := metav1.NewTime(time.Now().Truncate(time.Second)) + for i, prevCondition := range s.Conditions { + if prevCondition.Type == condition.Type { + if prevCondition.Status != condition.Status { + condition.LastTransitionTime = now + } else { + condition.LastTransitionTime = prevCondition.LastTransitionTime + } + s.Conditions[i] = condition + return s + } + } + + // If the condition does not exist, + // initialize the lastTransitionTime + condition.LastTransitionTime = now + s.Conditions = append(s.Conditions, condition) + return s +} + +// RemoveCondition removes a condition for the list of conditions +func (s *StatusType) RemoveCondition(conditionType ConditionType) *StatusType { + if s == nil { + return nil + } + for i := range s.Conditions { + if s.Conditions[i].Type == conditionType { + s.Conditions = append(s.Conditions[:i], s.Conditions[i+1:]...) + return s + } + } + return s +} + +// ResourceKey is a typedef for key used in ManagedGenerations. It is a string +// with the format: namespace/name=group/version,kind +type ResourceKey string + +// NewResourceKey for the object and type +func NewResourceKey(o metav1.Object, t metav1.Type) ResourceKey { + return ResourceKey(fmt.Sprintf("%s/%s=%s,Kind=%s", o.GetNamespace(), o.GetName(), t.GetAPIVersion(), t.GetKind())) +} + +// ToUnstructured returns a an Unstructured object initialized with Namespace, +// Name, APIVersion, and Kind fields from the ResourceKey +func (key ResourceKey) ToUnstructured() *unstructured.Unstructured { + // ResourceKey is guaranteed to be at least "/=," meaning we are guaranteed + // to get two elements in all of the splits + retval := &unstructured.Unstructured{} + parts := strings.SplitN(string(key), "=", 2) + nn := strings.SplitN(parts[0], "/", 2) + gvk := strings.SplitN(parts[1], ",Kind=", 2) + retval.SetNamespace(nn[0]) + retval.SetName(nn[1]) + retval.SetAPIVersion(gvk[0]) + retval.SetKind(gvk[1]) + return retval +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/status/zz_generated.deepcopy.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/status/zz_generated.deepcopy.go new file mode 100644 index 0000000000..27bcbe7b9e --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/status/zz_generated.deepcopy.go @@ -0,0 +1,120 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package status + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentStatus) DeepCopyInto(out *ComponentStatus) { + *out = *in + in.StatusType.DeepCopyInto(&out.StatusType) + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]*StatusType, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(StatusType) + (*in).DeepCopyInto(*out) + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentStatus. +func (in *ComponentStatus) DeepCopy() *ComponentStatus { + if in == nil { + return nil + } + out := new(ComponentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentStatusList) DeepCopyInto(out *ComponentStatusList) { + *out = *in + if in.ComponentStatus != nil { + in, out := &in.ComponentStatus, &out.ComponentStatus + *out = make([]ComponentStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentStatusList. +func (in *ComponentStatusList) DeepCopy() *ComponentStatusList { + if in == nil { + return nil + } + out := new(ComponentStatusList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Condition) DeepCopyInto(out *Condition) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition. +func (in *Condition) DeepCopy() *Condition { + if in == nil { + return nil + } + out := new(Condition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StatusBase) DeepCopyInto(out *StatusBase) { + *out = *in + 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 StatusBase. +func (in *StatusBase) DeepCopy() *StatusBase { + if in == nil { + return nil + } + out := new(StatusBase) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StatusType) DeepCopyInto(out *StatusType) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatusType. +func (in *StatusType) DeepCopy() *StatusType { + if in == nil { + return nil + } + out := new(StatusType) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/conversion.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/conversion.go new file mode 100644 index 0000000000..01d39480e6 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/conversion.go @@ -0,0 +1,25 @@ +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +var _ conversion.Convertible = (*ServiceMeshControlPlane)(nil) + +// ConverterV1V2 and ConverterV2V1 functions are really hacky, but allow us to avoid circular imports. +// The alternative is to move the entire conversion package into here. +var ( + ConverterV1V2 func(src, dst runtime.Object) error + ConverterV2V1 func(src, dst runtime.Object) error +) + +// ConvertTo v2 SMCP resource +func (smcp *ServiceMeshControlPlane) ConvertTo(dst conversion.Hub) error { + return ConverterV1V2(smcp, dst) +} + +// ConvertFrom v2 SMCP resource +func (smcp *ServiceMeshControlPlane) ConvertFrom(src conversion.Hub) error { + return ConverterV2V1(src, smcp) +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/doc.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/doc.go new file mode 100644 index 0000000000..dd899f3e57 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/doc.go @@ -0,0 +1,4 @@ +// Package v1 contains API Schema definitions for the maistra v1 API group +// +k8s:deepcopy-gen=package,register +// +groupName=maistra.io +package v1 diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/helmvalues.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/helmvalues.go new file mode 100644 index 0000000000..7f58c1f538 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/helmvalues.go @@ -0,0 +1,344 @@ +package v1 + +import ( + "fmt" + "strconv" + "strings" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/json" +) + +// HelmValues is typedef for Helm .Values +// +kubebuilder:validation:Type=object +// +kubebuilder:validation:XPreserveUnknownFields +type HelmValues struct { + data map[string]interface{} `json:"-"` +} + +func NewHelmValues(values map[string]interface{}) *HelmValues { + if values == nil { + values = make(map[string]interface{}) + } + return &HelmValues{data: values} +} + +func (h *HelmValues) GetContent() map[string]interface{} { + if h == nil { + return nil + } + return h.data +} + +func (h *HelmValues) GetFieldNoCopy(path string) (interface{}, bool, error) { + if h == nil || h.data == nil { + return nil, false, nil + } + return unstructured.NestedFieldNoCopy(h.data, strings.Split(path, ".")...) +} + +func (h *HelmValues) GetBool(path string) (bool, bool, error) { + if h == nil || h.data == nil { + return false, false, nil + } + val, found, err := unstructured.NestedFieldNoCopy(h.data, strings.Split(path, ".")...) + if !found || err != nil { + return false, found, err + } + b, ok := val.(bool) + if !ok { + if val == nil { + return false, false, nil + } + return false, false, fmt.Errorf("%v accessor error: %v is of the type %T, expected bool", path, val, val) + } + return b, true, nil +} + +func (h *HelmValues) GetAndRemoveBool(path string) (bool, bool, error) { + value, ok, err := h.GetBool(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetString(path string) (string, bool, error) { + if h == nil || h.data == nil { + return "", false, nil + } + val, found, err := unstructured.NestedFieldNoCopy(h.data, strings.Split(path, ".")...) + if !found || err != nil { + return "", found, err + } + s, ok := val.(string) + if !ok { + if val == nil { + return "", false, nil + } + return "", false, fmt.Errorf("%v accessor error: %v is of the type %T, expected string", path, val, val) + } + return s, true, nil +} + +func (h *HelmValues) GetForceNumberToString(path string) (string, bool, error) { + if h == nil || h.data == nil { + return "", false, nil + } + value, ok, err := unstructured.NestedFieldNoCopy(h.data, strings.Split(path, ".")...) + if err != nil { + return "", false, err + } else if !ok { + return "", false, nil + } + switch typeValue := value.(type) { + case int64: + return strconv.FormatInt(typeValue, 10), ok, nil + case float64: + return strconv.FormatFloat(typeValue, 'f', -1, 64), ok, nil + case string: + return typeValue, ok, nil + case nil: + return "", false, nil + } + return "", false, fmt.Errorf("could not convert type to string: %T=%s", value, value) +} + +func (h *HelmValues) GetAndRemoveString(path string) (string, bool, error) { + value, ok, err := h.GetString(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetAndRemoveForceNumberToString(path string) (string, bool, error) { + value, ok, err := h.GetForceNumberToString(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetInt64(path string) (int64, bool, error) { + if h == nil || h.data == nil { + return 0, false, nil + } + val, found, err := unstructured.NestedFieldNoCopy(h.data, strings.Split(path, ".")...) + if !found || err != nil { + return 0, found, err + } + i, ok := val.(int64) + if !ok { + if val == nil { + return 0, false, nil + } + return 0, false, fmt.Errorf("%v accessor error: %v is of the type %T, expected int64", path, val, val) + } + return i, true, nil +} + +func (h *HelmValues) GetAndRemoveInt64(path string) (int64, bool, error) { + value, ok, err := h.GetInt64(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetFloat64(path string) (float64, bool, error) { + if h == nil || h.data == nil { + return 0, false, nil + } + val, found, err := unstructured.NestedFieldNoCopy(h.data, strings.Split(path, ".")...) + if !found || err != nil { + return 0, found, err + } + f, ok := val.(float64) + if !ok { + if val == nil { + return 0, false, nil + } + return 0, false, fmt.Errorf("%v accessor error: %v is of the type %T, expected float64", path, val, val) + } + return f, true, nil +} + +func (h *HelmValues) GetAndRemoveFloat64(path string) (float64, bool, error) { + value, ok, err := h.GetFloat64(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetStringSlice(path string) ([]string, bool, error) { + if h == nil || h.data == nil { + return nil, false, nil + } + slice, ok, err := unstructured.NestedStringSlice(h.data, strings.Split(path, ".")...) + if err != nil { + if val, _, _ := h.GetFieldNoCopy(path); val == nil { + return nil, false, nil + } + } + return slice, ok, err +} + +func (h *HelmValues) GetAndRemoveStringSlice(path string) ([]string, bool, error) { + value, ok, err := h.GetStringSlice(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetSlice(path string) ([]interface{}, bool, error) { + if h == nil || h.data == nil { + return nil, false, nil + } + slice, ok, err := unstructured.NestedSlice(h.data, strings.Split(path, ".")...) + if err != nil { + if val, _, _ := h.GetFieldNoCopy(path); val == nil { + return nil, false, nil + } + } + return slice, ok, err +} + +func (h *HelmValues) GetAndRemoveSlice(path string) ([]interface{}, bool, error) { + value, ok, err := h.GetSlice(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetAndRemoveStringToStringMap(path string) (map[string]string, bool, error) { + var stringToStringMap map[string]string + var found bool + if rawValues, ok, err := h.GetMap(path); ok { + if len(rawValues) > 0 { + stringToStringMap = make(map[string]string) + for name, rawValue := range rawValues { + if rawValue == nil { + continue + } + switch value := rawValue.(type) { + case string: + stringToStringMap[name] = value + default: + return nil, false, fmt.Errorf("unknown type for %s.%s value, expected string: %T", path, name, rawValue) + } + } + if len(stringToStringMap) == 0 { + // this can happen if there are nil values + stringToStringMap = nil + } else { + found = true + } + } + } else if err != nil { + return nil, false, err + } + h.RemoveField(path) + return stringToStringMap, found, nil +} + +func (h *HelmValues) GetMap(path string) (map[string]interface{}, bool, error) { + if h == nil || h.data == nil { + return nil, false, nil + } + rawval, ok, err := unstructured.NestedFieldCopy(h.data, strings.Split(path, ".")...) + if ok { + if rawval == nil { + return nil, ok, err + } + if mapval, ok := rawval.(map[string]interface{}); ok { + return mapval, ok, err + } + return nil, false, fmt.Errorf("%v accessor error: %v is of the type %T, expected map[string]interface{}", path, rawval, rawval) + } + return nil, ok, err +} + +func (h *HelmValues) GetAndRemoveMap(path string) (map[string]interface{}, bool, error) { + value, ok, err := h.GetMap(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetStringMap(path string) (map[string]string, bool, error) { + if h == nil || h.data == nil { + return nil, false, nil + } + mapval, ok, err := unstructured.NestedStringMap(h.data, strings.Split(path, ".")...) + if ok { + return mapval, ok, err + } + return nil, ok, err +} + +func (h *HelmValues) GetAndRemoveStringMap(path string) (map[string]string, bool, error) { + value, ok, err := h.GetStringMap(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) SetField(path string, value interface{}) error { + if h == nil { + panic("Tried to invoke SetField on nil *HelmValues") + } + if h.data == nil { + h.data = map[string]interface{}{} + } + return unstructured.SetNestedField(h.data, value, strings.Split(path, ".")...) +} + +func (h *HelmValues) SetStringSlice(path string, value []string) error { + if h == nil { + panic("Tried to invoke SetField on nil *HelmValues") + } + if h.data == nil { + h.data = map[string]interface{}{} + } + return unstructured.SetNestedStringSlice(h.data, value, strings.Split(path, ".")...) +} + +func (h *HelmValues) RemoveField(path string) { + if h == nil || h.data == nil { + return + } + unstructured.RemoveNestedField(h.data, strings.Split(path, ".")...) +} + +func (h *HelmValues) UnmarshalJSON(in []byte) error { + err := json.Unmarshal(in, &h.data) + if err != nil { + return err + } + return nil +} + +func (h *HelmValues) MarshalJSON() ([]byte, error) { + return json.Marshal(h.data) +} + +func (h *HelmValues) DeepCopyInto(out *HelmValues) { + *out = HelmValues{} + + data, err := json.Marshal(h) + if err != nil { + // panic ??? + return + } + err = json.Unmarshal(data, out) + if err != nil { + // panic ??? + return + } +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/register.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/register.go new file mode 100644 index 0000000000..458024cedd --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/register.go @@ -0,0 +1,24 @@ +// NOTE: Boilerplate only. Ignore this file. + +// Package v1 contains API Schema definitions for the maistra v1 API group +// +k8s:deepcopy-gen=package,register +// +groupName=maistra.io +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +const ( + APIGroup = "maistra.io" + APIVersion = "v1" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: APIGroup, Version: APIVersion} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} +) diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/servicemeshcontrolplane_deepcopy.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/servicemeshcontrolplane_deepcopy.go new file mode 100644 index 0000000000..b7b1f993d5 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/servicemeshcontrolplane_deepcopy.go @@ -0,0 +1 @@ +package v1 diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/servicemeshcontrolplane_types.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/servicemeshcontrolplane_types.go new file mode 100644 index 0000000000..bbea5729e4 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/servicemeshcontrolplane_types.go @@ -0,0 +1,149 @@ +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/maistra/istio-operator/pkg/apis/maistra/status" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +func init() { + SchemeBuilder.Register(&ServiceMeshControlPlane{}, &ServiceMeshControlPlaneList{}) +} + +const DefaultTemplate = "default" + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshControlPlane represents a deployment of the service mesh control +// plane. The control plane components are deployed in the namespace in which +// the ServiceMeshControlPlane resides. The configuration options for the +// components that comprise the control plane are specified in this object. +// +k8s:openapi-gen=true +// +kubebuilder:resource:shortName=smcp,categories=maistra-io +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.annotations.readyComponentCount",description="How many of the total number of components are ready" +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Reconciled\")].reason",description="Whether or not the control plane installation is up to date." +// +kubebuilder:printcolumn:name="Template",type="string",JSONPath=".status.lastAppliedConfiguration.template",description="The configuration template to use as the base." +// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".status.lastAppliedConfiguration.version",description="The actual current version of the control plane installation." +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the object" +// +kubebuilder:printcolumn:name="Image HUB",type="string",JSONPath=".status.lastAppliedConfiguration.istio.global.hub",description="The image hub used as the base for all component images.",priority=1 +type ServiceMeshControlPlane struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // The specification of the desired state of this ServiceMeshControlPlane. + // This includes the configuration options for all components that comprise + // the control plane. + // +kubebuilder:validation:Required + Spec ControlPlaneSpec `json:"spec"` + + // The current status of this ServiceMeshControlPlane and the components + // that comprise the control plane. This data may be out of date by some + // window of time. + Status ControlPlaneStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshControlPlaneList contains a list of ServiceMeshControlPlane +type ServiceMeshControlPlaneList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ServiceMeshControlPlane `json:"items"` +} + +// ControlPlaneStatus represents the current state of a ServiceMeshControlPlane. +type ControlPlaneStatus struct { + status.StatusBase `json:",inline"` + + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file + status.StatusType `json:",inline"` + + // The generation observed by the controller during the most recent + // reconciliation. The information in the status pertains to this particular + // generation of the object. + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + + // The last version that was reconciled. + ReconciledVersion string `json:"reconciledVersion,omitempty"` + + // The list of components comprising the control plane and their statuses. + // +nullable + status.ComponentStatusList `json:",inline"` + + // The full specification of the configuration options that were applied + // to the components of the control plane during the most recent reconciliation. + // +optional + LastAppliedConfiguration ControlPlaneSpec `json:"lastAppliedConfiguration"` +} + +// GetReconciledVersion returns the reconciled version, or a default for older resources +func (s *ControlPlaneStatus) GetReconciledVersion() string { + if s == nil { + return status.ComposeReconciledVersion("0.0.0", 0) + } + if s.ReconciledVersion == "" { + return status.ComposeReconciledVersion("1.0.0", s.ObservedGeneration) + } + return s.ReconciledVersion +} + +// ControlPlaneSpec represents the configuration for installing a control plane. +type ControlPlaneSpec struct { + // Template selects the template to use for default values. Defaults to + // "default" when not set. + // DEPRECATED - use Profiles instead + // +optional + Template string `json:"template,omitempty"` + + // Profiles selects the profile to use for default values. Defaults to + // "default" when not set. Takes precedence over Template. + // +optional + Profiles []string `json:"profiles,omitempty"` + + // Version specifies what Maistra version of the control plane to install. + // When creating a new ServiceMeshControlPlane with an empty version, the + // admission webhook sets the version to the latest version supported by + // the operator. + // +optional + Version string `json:"version,omitempty"` + + // Deprecated: No longer used anywhere. + // Previously used to specify the NetworkType of the cluster. Defaults to "subnet". + // +optional + NetworkType NetworkType `json:"networkType,omitempty"` + + // Specifies the Istio configuration options that are passed to Helm when the + // Istio charts are rendered. These options are usually populated from the + // template specified in the spec.template field, but individual values can + // be overridden here. + // More info: https://maistra.io/docs/installation/installation-options/ + // +optional + // +kubebuilder:validation:Optional + Istio *HelmValues `json:"istio,omitempty"` + + // Specifies the 3Scale configuration options that are passed to Helm when the + // 3Scale charts are rendered. These values are usually populated from the + // template specified in the spec.template field, but individual values can + // be overridden here. + // More info: https://maistra.io/docs/installation/installation-options/#_3scale + // +optional + // +kubebuilder:validation:Optional + ThreeScale *HelmValues `json:"threeScale,omitempty"` +} + +// NetworkType is type definition representing the network type of the cluster +type NetworkType string + +const ( + // NetworkTypeSubnet when using ovs-subnet + NetworkTypeSubnet NetworkType = "subnet" + // NetworkTypeMultitenant when using ovs-multitenant + NetworkTypeMultitenant NetworkType = "multitenant" + // NetworkTypeNetworkPolicy when using ovs-networkpolicy + NetworkTypeNetworkPolicy NetworkType = "networkpolicy" +) diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/servicemeshmember_types.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/servicemeshmember_types.go new file mode 100644 index 0000000000..f2f080bc9f --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/servicemeshmember_types.go @@ -0,0 +1,177 @@ +package v1 + +import ( + "fmt" + + core "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/maistra/istio-operator/pkg/apis/maistra/status" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +func init() { + SchemeBuilder.Register(&ServiceMeshMember{}, &ServiceMeshMemberList{}) +} + +// A ServiceMeshMember object marks the namespace in which it lives as a member +// of the Service Mesh Control Plane referenced in the object. +// The ServiceMeshMember object should be created in each application namespace +// that must be part of the service mesh and must be named "default". +// +// When the ServiceMeshMember object is created, it causes the namespace to be +// added to the ServiceMeshMemberRoll within the namespace of the +// ServiceMeshControlPlane object the ServiceMeshMember references. +// +// To reference a ServiceMeshControlPlane, the user creating the ServiceMeshMember +// object must have the "use" permission on the referenced ServiceMeshControlPlane +// object. This permission is given via the mesh-users RoleBinding (and mesh-user +// Role) in the namespace of the referenced ServiceMeshControlPlane object. +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:storageversion +// +kubebuilder:resource:shortName=smm,categories=maistra-io +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Control Plane",type="string",JSONPath=".status.annotations.controlPlaneRef",description="The ServiceMeshControlPlane this namespace belongs to" +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="Whether or not namespace is configured as a member of the mesh." +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the object" +type ServiceMeshMember struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // The desired state of this ServiceMeshMember. + // +kubebuilder:validation:Required + Spec ServiceMeshMemberSpec `json:"spec"` + + // The current status of this ServiceMeshMember. This data may be out of + // date by some window of time. + // +optional + Status ServiceMeshMemberStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshMemberList contains a list of ServiceMeshMember objects +type ServiceMeshMemberList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ServiceMeshMember `json:"items"` +} + +// ServiceMeshMemberSpec defines the member of the mesh +type ServiceMeshMemberSpec struct { + // A reference to the ServiceMeshControlPlane object. + ControlPlaneRef ServiceMeshControlPlaneRef `json:"controlPlaneRef"` +} + +// ServiceMeshControlPlaneRef is a reference to a ServiceMeshControlPlane object +type ServiceMeshControlPlaneRef struct { + // The name of the referenced ServiceMeshControlPlane object. + Name string `json:"name"` + + // The namespace of the referenced ServiceMeshControlPlane object. + Namespace string `json:"namespace"` +} + +func (s ServiceMeshControlPlaneRef) String() string { + return fmt.Sprintf("%s%c%s", s.Namespace, '/', s.Name) +} + +// ServiceMeshMemberStatus represents the current state of a ServiceMeshMember. +type ServiceMeshMemberStatus struct { + status.StatusBase `json:",inline"` + + // The generation observed by the controller during the most recent + // reconciliation. The information in the status pertains to this particular + // generation of the object. + ObservedGeneration int64 `json:"observedGeneration"` + + // The generation of the ServiceMeshControlPlane object observed by the + // controller during the most recent reconciliation of this + // ServiceMeshMember. + ServiceMeshGeneration int64 `json:"meshGeneration,omitempty"` // TODO: do we need this field at all? + + // The reconciled version of the ServiceMeshControlPlane object observed by + // the controller during the most recent reconciliation of this + // ServiceMeshMember. + ServiceMeshReconciledVersion string `json:"meshReconciledVersion,omitempty"` // TODO: do we need this field at all? + + // Represents the latest available observations of a ServiceMeshMember's + // current state. + Conditions []ServiceMeshMemberCondition `json:"conditions"` +} + +// ServiceMeshMemberConditionType represents the type of the condition. Condition types are: +// Reconciled, NamespaceConfigured +type ServiceMeshMemberConditionType string + +const ( + // ConditionTypeReconciled signifies whether or not the controller has + // updated the ServiceMeshMemberRoll object based on this ServiceMeshMember. + ConditionTypeMemberReconciled ServiceMeshMemberConditionType = "Reconciled" + // ConditionTypeReady signifies whether the namespace has been configured + // to use the mesh + ConditionTypeMemberReady ServiceMeshMemberConditionType = "Ready" // TODO: remove the Ready condition in v2 +) + +type ServiceMeshMemberConditionReason string + +const ( + // ConditionReasonDeletionError ... + ConditionReasonMemberCannotCreateMemberRoll ServiceMeshMemberConditionReason = "CreateMemberRollFailed" + ConditionReasonMemberCannotUpdateMemberRoll ServiceMeshMemberConditionReason = "UpdateMemberRollFailed" + ConditionReasonMemberCannotDeleteMemberRoll ServiceMeshMemberConditionReason = "DeleteMemberRollFailed" + ConditionReasonMemberNamespaceNotExists ServiceMeshMemberConditionReason = "NamespaceNotExists" + ConditionReasonMemberReferencesDifferentControlPlane ServiceMeshMemberConditionReason = "ReferencesDifferentControlPlane" + ConditionReasonMemberTerminating ServiceMeshMemberConditionReason = "Terminating" + ConditionReasonMemberNameInvalid ServiceMeshMemberConditionReason = "InvalidName" +) + +// Condition represents a specific condition on a resource +type ServiceMeshMemberCondition struct { + Type ServiceMeshMemberConditionType `json:"type,omitempty"` + Status core.ConditionStatus `json:"status,omitempty"` + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + Reason ServiceMeshMemberConditionReason `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +// GetCondition removes a condition for the list of conditions +func (s *ServiceMeshMemberStatus) GetCondition(conditionType ServiceMeshMemberConditionType) ServiceMeshMemberCondition { + if s == nil { + return ServiceMeshMemberCondition{Type: conditionType, Status: core.ConditionUnknown} + } + for i := range s.Conditions { + if s.Conditions[i].Type == conditionType { + return s.Conditions[i] + } + } + return ServiceMeshMemberCondition{Type: conditionType, Status: core.ConditionUnknown} +} + +// SetCondition sets a specific condition in the list of conditions +func (s *ServiceMeshMemberStatus) SetCondition(condition ServiceMeshMemberCondition) *ServiceMeshMemberStatus { + if s == nil { + return nil + } + now := metav1.Now() + for i := range s.Conditions { + if s.Conditions[i].Type == condition.Type { + if s.Conditions[i].Status != condition.Status { + condition.LastTransitionTime = now + } else { + condition.LastTransitionTime = s.Conditions[i].LastTransitionTime + } + s.Conditions[i] = condition + return s + } + } + + // If the condition does not exist, + // initialize the lastTransitionTime + condition.LastTransitionTime = now + s.Conditions = append(s.Conditions, condition) + return s +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/servicemeshmemberroll_types.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/servicemeshmemberroll_types.go new file mode 100644 index 0000000000..fa245f3d97 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/servicemeshmemberroll_types.go @@ -0,0 +1,206 @@ +package v1 + +import ( + core "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/maistra/istio-operator/pkg/apis/maistra/status" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +func init() { + SchemeBuilder.Register(&ServiceMeshMemberRoll{}, &ServiceMeshMemberRollList{}) +} + +// The ServiceMeshMemberRoll object configures which namespaces belong to a +// service mesh. Only namespaces listed in the ServiceMeshMemberRoll will be +// affected by the control plane. Any number of namespaces can be added, but a +// namespace may not exist in more than one service mesh. The +// ServiceMeshMemberRoll object must be created in the same namespace as +// the ServiceMeshControlPlane object and must be named "default". +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:storageversion +// +kubebuilder:resource:shortName=smmr,categories=maistra-io +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.annotations.configuredMemberCount",description="How many of the total number of member namespaces are configured" +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].reason",description="Whether all member namespaces have been configured or why that's not the case" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the object" +// +kubebuilder:printcolumn:name="Members",type="string",JSONPath=".status.members",description="Namespaces that are members of this Control Plane",priority=1 +type ServiceMeshMemberRoll struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Specification of the desired list of members of the service mesh. + // +kubebuilder:validation:Required + Spec ServiceMeshMemberRollSpec `json:"spec"` + + // The current status of this ServiceMeshMemberRoll. This data may be out + // of date by some window of time. + Status ServiceMeshMemberRollStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshMemberRollList contains a list of ServiceMeshMemberRoll +type ServiceMeshMemberRollList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ServiceMeshMemberRoll `json:"items"` +} + +// ServiceMeshMemberRollSpec is the specification of the desired list of +// members of the service mesh. +type ServiceMeshMemberRollSpec struct { + // List of namespaces that should be members of the service mesh. + // +optional + // +nullable + Members []string `json:"members,omitempty"` +} + +func (s *ServiceMeshMemberRollSpec) IsClusterScoped() bool { + for _, ns := range s.Members { + if ns == "*" { + return true + } + } + return false +} + +// ServiceMeshMemberRollStatus represents the current state of a ServiceMeshMemberRoll. +type ServiceMeshMemberRollStatus struct { + status.StatusBase `json:",inline"` + + // The generation observed by the controller during the most recent + // reconciliation. The information in the status pertains to this particular + // generation of the object. + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + + // The generation of the ServiceMeshControlPlane object observed by the + // controller during the most recent reconciliation of this + // ServiceMeshMemberRoll. + ServiceMeshGeneration int64 `json:"meshGeneration,omitempty"` + + // The reconciled version of the ServiceMeshControlPlane object observed by + // the controller during the most recent reconciliation of this + // ServiceMeshMemberRoll. + ServiceMeshReconciledVersion string `json:"meshReconciledVersion,omitempty"` + + // Complete list of namespaces that are configured as members of the service + // mesh - this includes namespaces specified in spec.members and those that + // contain a ServiceMeshMember object + // +optional + // +nullable + Members []string `json:"members"` + + // List of namespaces that are configured as members of the service mesh. + // +optional + // +nullable + ConfiguredMembers []string `json:"configuredMembers"` + + // List of namespaces that haven't been configured as members of the service + // mesh yet. + // +optional + // +nullable + PendingMembers []string `json:"pendingMembers"` + + // List of namespaces that are being removed as members of the service + // mesh. + // +optional + // +nullable + TerminatingMembers []string `json:"terminatingMembers"` + + // Represents the latest available observations of this ServiceMeshMemberRoll's + // current state. + // +optional + // +nullable + Conditions []ServiceMeshMemberRollCondition `json:"conditions"` + + // Represents the latest available observations of each member's + // current state. + // +optional + // +nullable + MemberStatuses []ServiceMeshMemberStatusSummary `json:"memberStatuses"` +} + +// ServiceMeshMemberStatusSummary represents a summary status of a ServiceMeshMember. +type ServiceMeshMemberStatusSummary struct { + Namespace string `json:"namespace"` + Conditions []ServiceMeshMemberCondition `json:"conditions"` +} + +// ServiceMeshMemberRollConditionType represents the type of the condition. Condition types are: +// Reconciled, NamespaceConfigured +type ServiceMeshMemberRollConditionType string + +const ( + // ConditionTypeMemberRollReady signifies whether the namespace has been configured + // to use the mesh + ConditionTypeMemberRollReady ServiceMeshMemberRollConditionType = "Ready" +) + +type ServiceMeshMemberRollConditionReason string + +const ( + // ConditionReasonConfigured indicates that all namespaces were configured + ConditionReasonConfigured ServiceMeshMemberRollConditionReason = "Configured" + // ConditionReasonReconcileError indicates that one of the namespaces to configure could not be configured + ConditionReasonReconcileError ServiceMeshMemberRollConditionReason = "ReconcileError" + // ConditionReasonSMCPMissing indicates that the ServiceMeshControlPlane resource does not exist + ConditionReasonSMCPMissing ServiceMeshMemberRollConditionReason = "ErrSMCPMissing" + // ConditionReasonMultipleSMCP indicates that multiple ServiceMeshControlPlane resources exist in the namespace + ConditionReasonMultipleSMCP ServiceMeshMemberRollConditionReason = "ErrMultipleSMCPs" + // ConditionReasonInvalidName indicates that the ServiceMeshMemberRoll name is invalid (only "default" is allowed) + ConditionReasonInvalidName ServiceMeshMemberRollConditionReason = "ErrInvalidName" + // ConditionReasonSMCPNotReconciled indicates that reconciliation of the SMMR was skipped because the SMCP has not been reconciled + ConditionReasonSMCPNotReconciled ServiceMeshMemberRollConditionReason = "SMCPReconciling" +) + +// Condition represents a specific condition on a resource +type ServiceMeshMemberRollCondition struct { + Type ServiceMeshMemberRollConditionType `json:"type,omitempty"` + Status core.ConditionStatus `json:"status,omitempty"` + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + Reason ServiceMeshMemberRollConditionReason `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +// GetCondition removes a condition for the list of conditions +func (s *ServiceMeshMemberRollStatus) GetCondition(conditionType ServiceMeshMemberRollConditionType) ServiceMeshMemberRollCondition { + if s == nil { + return ServiceMeshMemberRollCondition{Type: conditionType, Status: core.ConditionUnknown} + } + for i := range s.Conditions { + if s.Conditions[i].Type == conditionType { + return s.Conditions[i] + } + } + return ServiceMeshMemberRollCondition{Type: conditionType, Status: core.ConditionUnknown} +} + +// SetCondition sets a specific condition in the list of conditions +func (s *ServiceMeshMemberRollStatus) SetCondition(condition ServiceMeshMemberRollCondition) *ServiceMeshMemberRollStatus { + if s == nil { + return nil + } + now := metav1.Now() + for i := range s.Conditions { + if s.Conditions[i].Type == condition.Type { + if s.Conditions[i].Status != condition.Status { + condition.LastTransitionTime = now + } else { + condition.LastTransitionTime = s.Conditions[i].LastTransitionTime + } + s.Conditions[i] = condition + return s + } + } + + // If the condition does not exist, + // initialize the lastTransitionTime + condition.LastTransitionTime = now + s.Conditions = append(s.Conditions, condition) + return s +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/zz_generated.deepcopy.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..5c125d2dd3 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v1/zz_generated.deepcopy.go @@ -0,0 +1,438 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneSpec) DeepCopyInto(out *ControlPlaneSpec) { + *out = *in + if in.Profiles != nil { + in, out := &in.Profiles, &out.Profiles + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Istio != nil { + in, out := &in.Istio, &out.Istio + *out = (*in).DeepCopy() + } + if in.ThreeScale != nil { + in, out := &in.ThreeScale, &out.ThreeScale + *out = (*in).DeepCopy() + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneSpec. +func (in *ControlPlaneSpec) DeepCopy() *ControlPlaneSpec { + if in == nil { + return nil + } + out := new(ControlPlaneSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneStatus) DeepCopyInto(out *ControlPlaneStatus) { + *out = *in + in.StatusBase.DeepCopyInto(&out.StatusBase) + in.StatusType.DeepCopyInto(&out.StatusType) + in.ComponentStatusList.DeepCopyInto(&out.ComponentStatusList) + in.LastAppliedConfiguration.DeepCopyInto(&out.LastAppliedConfiguration) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneStatus. +func (in *ControlPlaneStatus) DeepCopy() *ControlPlaneStatus { + if in == nil { + return nil + } + out := new(ControlPlaneStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmValues. +func (in *HelmValues) DeepCopy() *HelmValues { + if in == nil { + return nil + } + out := new(HelmValues) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshControlPlane) DeepCopyInto(out *ServiceMeshControlPlane) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshControlPlane. +func (in *ServiceMeshControlPlane) DeepCopy() *ServiceMeshControlPlane { + if in == nil { + return nil + } + out := new(ServiceMeshControlPlane) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshControlPlane) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshControlPlaneList) DeepCopyInto(out *ServiceMeshControlPlaneList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServiceMeshControlPlane, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshControlPlaneList. +func (in *ServiceMeshControlPlaneList) DeepCopy() *ServiceMeshControlPlaneList { + if in == nil { + return nil + } + out := new(ServiceMeshControlPlaneList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshControlPlaneList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshControlPlaneRef) DeepCopyInto(out *ServiceMeshControlPlaneRef) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshControlPlaneRef. +func (in *ServiceMeshControlPlaneRef) DeepCopy() *ServiceMeshControlPlaneRef { + if in == nil { + return nil + } + out := new(ServiceMeshControlPlaneRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMember) DeepCopyInto(out *ServiceMeshMember) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMember. +func (in *ServiceMeshMember) DeepCopy() *ServiceMeshMember { + if in == nil { + return nil + } + out := new(ServiceMeshMember) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshMember) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberCondition) DeepCopyInto(out *ServiceMeshMemberCondition) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberCondition. +func (in *ServiceMeshMemberCondition) DeepCopy() *ServiceMeshMemberCondition { + if in == nil { + return nil + } + out := new(ServiceMeshMemberCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberList) DeepCopyInto(out *ServiceMeshMemberList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServiceMeshMember, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberList. +func (in *ServiceMeshMemberList) DeepCopy() *ServiceMeshMemberList { + if in == nil { + return nil + } + out := new(ServiceMeshMemberList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshMemberList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberRoll) DeepCopyInto(out *ServiceMeshMemberRoll) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberRoll. +func (in *ServiceMeshMemberRoll) DeepCopy() *ServiceMeshMemberRoll { + if in == nil { + return nil + } + out := new(ServiceMeshMemberRoll) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshMemberRoll) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberRollCondition) DeepCopyInto(out *ServiceMeshMemberRollCondition) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberRollCondition. +func (in *ServiceMeshMemberRollCondition) DeepCopy() *ServiceMeshMemberRollCondition { + if in == nil { + return nil + } + out := new(ServiceMeshMemberRollCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberRollList) DeepCopyInto(out *ServiceMeshMemberRollList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServiceMeshMemberRoll, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberRollList. +func (in *ServiceMeshMemberRollList) DeepCopy() *ServiceMeshMemberRollList { + if in == nil { + return nil + } + out := new(ServiceMeshMemberRollList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshMemberRollList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberRollSpec) DeepCopyInto(out *ServiceMeshMemberRollSpec) { + *out = *in + if in.Members != nil { + in, out := &in.Members, &out.Members + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberRollSpec. +func (in *ServiceMeshMemberRollSpec) DeepCopy() *ServiceMeshMemberRollSpec { + if in == nil { + return nil + } + out := new(ServiceMeshMemberRollSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberRollStatus) DeepCopyInto(out *ServiceMeshMemberRollStatus) { + *out = *in + in.StatusBase.DeepCopyInto(&out.StatusBase) + if in.Members != nil { + in, out := &in.Members, &out.Members + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ConfiguredMembers != nil { + in, out := &in.ConfiguredMembers, &out.ConfiguredMembers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.PendingMembers != nil { + in, out := &in.PendingMembers, &out.PendingMembers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.TerminatingMembers != nil { + in, out := &in.TerminatingMembers, &out.TerminatingMembers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]ServiceMeshMemberRollCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.MemberStatuses != nil { + in, out := &in.MemberStatuses, &out.MemberStatuses + *out = make([]ServiceMeshMemberStatusSummary, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberRollStatus. +func (in *ServiceMeshMemberRollStatus) DeepCopy() *ServiceMeshMemberRollStatus { + if in == nil { + return nil + } + out := new(ServiceMeshMemberRollStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberSpec) DeepCopyInto(out *ServiceMeshMemberSpec) { + *out = *in + out.ControlPlaneRef = in.ControlPlaneRef + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberSpec. +func (in *ServiceMeshMemberSpec) DeepCopy() *ServiceMeshMemberSpec { + if in == nil { + return nil + } + out := new(ServiceMeshMemberSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberStatus) DeepCopyInto(out *ServiceMeshMemberStatus) { + *out = *in + in.StatusBase.DeepCopyInto(&out.StatusBase) + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]ServiceMeshMemberCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberStatus. +func (in *ServiceMeshMemberStatus) DeepCopy() *ServiceMeshMemberStatus { + if in == nil { + return nil + } + out := new(ServiceMeshMemberStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberStatusSummary) DeepCopyInto(out *ServiceMeshMemberStatusSummary) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]ServiceMeshMemberCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberStatusSummary. +func (in *ServiceMeshMemberStatusSummary) DeepCopy() *ServiceMeshMemberStatusSummary { + if in == nil { + return nil + } + out := new(ServiceMeshMemberStatusSummary) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/addons.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/addons.go new file mode 100644 index 0000000000..2fec5a6fad --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/addons.go @@ -0,0 +1,22 @@ +package v2 + +// AddonsConfig configures additional features for use with the mesh +type AddonsConfig struct { + // Prometheus configures Prometheus specific addon capabilities + Prometheus *PrometheusAddonConfig `json:"prometheus,omitempty"` + // Stackdriver configures Stackdriver specific addon capabilities + Stackdriver *StackdriverAddonConfig `json:"stackdriver,omitempty"` + // Jaeger configures Jaeger specific addon capabilities + Jaeger *JaegerAddonConfig `json:"jaeger,omitempty"` + // Grafana configures a grafana instance to use with the mesh + // .Values.grafana.enabled, true if not null + // +optional + Grafana *GrafanaAddonConfig `json:"grafana,omitempty"` + // Kiali configures a kiali instance to use with the mesh + // .Values.kiali.enabled, true if not null + // +optional + Kiali *KialiAddonConfig `json:"kiali,omitempty"` + // ThreeScale configures the 3scale adapter + // +optional + ThreeScale *ThreeScaleAddonConfig `json:"3scale,omitempty"` +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/cluster.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/cluster.go new file mode 100644 index 0000000000..d8a9c31e1f --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/cluster.go @@ -0,0 +1,76 @@ +package v2 + +// ControlPlaneClusterConfig configures aspects related to clustering. +type ControlPlaneClusterConfig struct { + // .Values.global.multiCluster.clusterName, defaults to Kubernetes + // +optional + Name string `json:"name,omitempty"` + // .Values.global.network + // XXX: not sure what the difference is between this and cluster name + // +optional + Network string `json:"network,omitempty"` + // .Values.global.multiCluster.enabled, if not null + // +optional + MultiCluster *MultiClusterConfig `json:"multiCluster,omitempty"` + // .Values.global.meshExpansion.enabled, if not null + // XXX: it's not clear whether or not there is any overlap with MultiCluster, + // i.e. does MultiCluster require mesh expansion ports to be configured on + // the ingress gateway? + // +optional + MeshExpansion *MeshExpansionConfig `json:"meshExpansion,omitempty"` +} + +// MultiClusterConfig configures aspects related to multi-cluster. +// implies the following: +// adds external to RequestedNetworkView (ISTIO_META_REQUESTED_NETWORK_VIEW) for egress gateway +// adds "global" and "{{ valueOrDefault .DeploymentMeta.Namespace \"default\" }}.global" to pod dns search suffixes +type MultiClusterConfig struct { + Enablement `json:",inline"` + // .Values.global.meshNetworks + // XXX: if non-empty, local cluster network should be configured as: + // : + // endpoints: + // - fromRegistry: + // gateways: + // - service: + // port: 443 # mtls port + // +optional + MeshNetworks map[string]MeshNetworkConfig `json:"meshNetworks,omitempty"` +} + +// MeshExpansionConfig configures aspects related to mesh expansion +type MeshExpansionConfig struct { + Enablement `json:",inline"` + // .Values.global.meshExpansion.useILB, true if not null, otherwise uses ingress gateway + // +optional + ILBGateway *GatewayConfig `json:"ilbGateway,omitempty"` +} + +// MeshNetworkConfig configures mesh networks for a multi-cluster mesh. +type MeshNetworkConfig struct { + Endpoints []MeshEndpointConfig `json:"endpoints,omitempty"` + Gateways []MeshGatewayConfig `json:"gateways,omitempty"` +} + +// MeshEndpointConfig specifies the endpoint of a mesh network. Only one of +// FromRegistry or FromCIDR may be specified +type MeshEndpointConfig struct { + // +optional + FromRegistry string `json:"fromRegistry,omitempty"` + // +optional + FromCIDR string `json:"fromCIDR,omitempty"` +} + +// MeshGatewayConfig specifies the gateway which should be used for accessing +// the network +type MeshGatewayConfig struct { + // +optional + // +deprecated + Service string `json:"service,omitempty"` + // +optional + RegistryServiceName string `json:"registryServiceName,omitempty"` + // +optional + Address string `json:"address,omitempty"` + // +optional + Port int32 `json:"port,omitempty"` +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/conversion.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/conversion.go new file mode 100644 index 0000000000..18da386467 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/conversion.go @@ -0,0 +1,10 @@ +package v2 + +import ( + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +var _ conversion.Hub = (*ServiceMeshControlPlane)(nil) + +// Hub marks v2 SMCP resource as the storage version +func (smcp *ServiceMeshControlPlane) Hub() {} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/datadog.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/datadog.go new file mode 100644 index 0000000000..7d05654328 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/datadog.go @@ -0,0 +1,6 @@ +package v2 + +// DatadogTracerConfig configures a Datadog tracer for use with the mesh +type DatadogTracerConfig struct { + // TODO.... +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/doc.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/doc.go new file mode 100644 index 0000000000..dcd2663b96 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/doc.go @@ -0,0 +1,4 @@ +// Package v2 contains API Schema definitions for the maistra v2 API group +// +k8s:deepcopy-gen=package,register +// +groupName=maistra.io +package v2 diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/gateways.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/gateways.go new file mode 100644 index 0000000000..2c742f4960 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/gateways.go @@ -0,0 +1,165 @@ +package v2 + +import ( + corev1 "k8s.io/api/core/v1" +) + +// GatewaysConfig configures gateways for the mesh +type GatewaysConfig struct { + Enablement `json:",inline"` + // ClusterIngress configures the istio-ingressgateway for the mesh + // works in conjunction with cluster.meshExpansion.ingress configuration + // (for enabling ILB gateway and mesh expansion ports) + // .Values.gateways.istio-ingressgateway + // +optional + ClusterIngress *ClusterIngressGatewayConfig `json:"ingress,omitempty"` + // ClusterEgress configures the istio-egressgateway for the mesh. + // .Values.gateways.istio-egressgateway + // +optional + ClusterEgress *EgressGatewayConfig `json:"egress,omitempty"` + // Other user defined ingress gateways + // .Values.gateways. + // +optional + IngressGateways map[string]*IngressGatewayConfig `json:"additionalIngress,omitempty"` + // Other user defined egress gateways + // .Values.gateways. + // +optional + EgressGateways map[string]*EgressGatewayConfig `json:"additionalEgress,omitempty"` + // Route configures the Gateway ↔ OpenShift Route integration + OpenShiftRoute *OpenShiftRouteConfig `json:"openshiftRoute,omitempty"` +} + +// OpenShiftRouteConfig represents the Gateway ↔ OpenShift Route integration +type OpenShiftRouteConfig struct { + Enablement `json:",inline"` +} + +// GatewayConfig represents the configuration for a gateway +// XXX: should standard istio secrets be configured automatically, i.e. should +// the user be forced to add these manually? +type GatewayConfig struct { + Enablement `json:",inline"` + // Namespace is the namespace within which the gateway will be installed, + // defaults to control plane namespace. + // .Values.gateways..namespace + // XXX: for the standard gateways, it might be possible that related + // resources could be installed in control plane namespace instead of the + // gateway namespace. not sure if this is a problem or not. + // +optional + Namespace string `json:"namespace,omitempty"` + // Service configures the service associated with the gateway, e.g. port + // mappings, service type, annotations/labels, etc. + // .Values.gateways..ports, .Values.gateways..type, + // .Values.gateways..loadBalancerIP, + // .Values.gateways..serviceAnnotations, + // .Values.gateways..serviceLabels + // XXX: currently there is no distinction between labels and serviceLabels + // +optional + Service GatewayServiceConfig `json:"service,omitempty"` + // The router mode to be used by the gateway. + // .Values.gateways..env.ISTIO_META_ROUTER_MODE, defaults to sni-dnat + // +optional + RouterMode RouterModeType `json:"routerMode,omitempty"` + // Volumes is used to configure additional Secret and ConfigMap volumes that + // should be mounted for the gateway's pod. + // .Values.gateways..secretVolumes, .Values.gateways..configMapVolumes + // +optional + Volumes []VolumeConfig `json:"volumes,omitempty"` + // Runtime is used to configure execution parameters for the pod/containers + // e.g. resources, replicas, etc. + // +optional + Runtime *ComponentRuntimeConfig `json:"runtime,omitempty"` + // XXX: do we need to support additionalContainers??? +} + +// EgressGatewayConfig represents gateway configuration for egress +type EgressGatewayConfig struct { + GatewayConfig `json:",inline"` + // RequestedNetworkView is a list of networks whose services should be made + // available to the gateway. This is used primarily for mesh expansion/multi-cluster. + // .Values.gateways..env.ISTIO_META_REQUESTED_NETWORK_VIEW env, defaults to empty list + // XXX: I think this is only applicable to egress gateways + // +optional + RequestedNetworkView []string `json:"requestedNetworkView,omitempty"` +} + +// IngressGatewayConfig represents gateway configuration for ingress +type IngressGatewayConfig struct { + GatewayConfig `json:",inline"` + // EnableSDS for the gateway. + // .Values.gateways..sds.enabled + // +optional + SDS *SecretDiscoveryService `json:"sds,omitempty"` +} + +// SecretDiscoveryService configures whether or not SDS is configured for the gateway +type SecretDiscoveryService struct { + Enablement `json:",inline"` + // Runtime configuration for sds sidecar + Runtime *ContainerConfig `json:"runtime,omitempty"` +} + +// ClusterIngressGatewayConfig represents gateway configuration for cluster ingress +type ClusterIngressGatewayConfig struct { + IngressGatewayConfig `json:",inline"` + // .Values.global.k8sIngress.enabled + // implies the following: + // .Values.global.k8sIngress.gatewayName will match the ingress gateway + // .Values.global.k8sIngress.enableHttps will be true if gateway service exposes port 443 + // XXX: not sure whether or not this is specific to multicluster, mesh expansion, or both + // +optional + IngressEnabled *bool `json:"ingress,omitempty"` + // MeshExpansionPorts define the port set used with multi-cluster/mesh expansion + // +optional + MeshExpansionPorts []corev1.ServicePort `json:"meshExpansionPorts,omitempty"` + // RouteConfig specifies whether to create an OpenShift Route for istio-ingressgateway deployment + // +optional + RouteConfig *Enablement `json:"routeConfig,omitempty"` +} + +// RouterModeType represents the router modes available. +type RouterModeType string + +const ( + // RouterModeTypeSNIDNAT represents sni-dnat router mode + RouterModeTypeSNIDNAT RouterModeType = "sni-dnat" + // RouterModeTypeStandard represents standard router mode + RouterModeTypeStandard RouterModeType = "standard" +) + +// GatewayServiceConfig configures the k8s Service associated with the gateway +type GatewayServiceConfig struct { + // XXX: selector is ignored + // Service details used to configure the gateway's Service resource + // +optional + corev1.ServiceSpec `json:",inline"` + // metadata to be applied to the gateway's service (annotations and labels) + // +optional + Metadata *MetadataConfig `json:"metadata,omitempty"` +} + +// VolumeConfig is used to specify volumes that should be mounted on the pod. +type VolumeConfig struct { + // Volume.Name maps to .Values.gateways... (type-name is configMapName or secretName) + // .configVolumes -> .configMapName = volume.name + // .secretVolumes -> .secretName = volume.name + // Only ConfigMap and Secret fields are supported + Volume GatewayVolume `json:"volume,omitempty"` + // Mount.Name maps to .Values.gateways...name + // .configVolumes -> .name = mount.name, .mountPath = mount.mountPath + // .secretVolumes -> .name = mount.name, .mountPath = mount.mountPath + // Only Name and MountPath fields are supported + Mount corev1.VolumeMount `json:"volumeMount,omitempty"` +} + +// GatewayVolume is a pared down version of corev1.Volume, which only supports +// specifying ConfigMap and Secret volume types. +type GatewayVolume struct { + // ConfigMap represents a configMap that should populate this volume + // +optional + ConfigMap *corev1.ConfigMapVolumeSource `json:"configMap,omitempty"` + // Secret represents a secret that should populate this volume. + // More info: https://kubernetes.io/docs/concepts/storage/volumes#secret + // +optional + Secret *corev1.SecretVolumeSource `json:"secret,omitempty"` +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/general.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/general.go new file mode 100644 index 0000000000..ff3838a58b --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/general.go @@ -0,0 +1,16 @@ +package v2 + +// GeneralConfig for control plane +type GeneralConfig struct { + // Logging represents the logging configuration for the control plane components + // XXX: Should this be separate from Proxy.Logging? + // +optional + Logging *LoggingConfig `json:"logging,omitempty"` + + // ValidationMessages configures the control plane to add validationMessages + // to the status fields of istio.io resources. This can be usefule for + // detecting configuration errors in resources. + // .Values.galley.enableAnalysis (=v2.0) + ValidationMessages *bool `json:"validationMessages,omitempty"` +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/grafana.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/grafana.go new file mode 100644 index 0000000000..4d783db691 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/grafana.go @@ -0,0 +1,68 @@ +package v2 + +// GrafanaAddonConfig configures a grafana instance for use with the mesh. Only +// one of install or address may be specified +type GrafanaAddonConfig struct { + Enablement `json:",inline"` + // Install a new grafana instance and manage with control plane + // +optional + Install *GrafanaInstallConfig `json:"install,omitempty"` + // Address is the address of an existing grafana installation + // implies .Values.kiali.dashboard.grafanaURL + // +optional + Address *string `json:"address,omitempty"` +} + +// GrafanaInstallConfig is used to configure a new installation of grafana. +type GrafanaInstallConfig struct { + // SelfManaged, true if the entire install should be managed by Maistra, false if using grafana CR (not supported) + // +optional + SelfManaged bool `json:"selfManaged,omitempty"` + // Config configures the behavior of the grafana installation + // +optional + Config *GrafanaConfig `json:"config,omitempty"` + // Service configures the k8s Service associated with the grafana installation + // XXX: grafana service config does not follow other addon components' structure + // +optional + Service *ComponentServiceConfig `json:"service,omitempty"` + // Persistence configures a PersistentVolume associated with the grafana installation + // .Values.grafana.persist, true if not null + // +optional + Persistence *ComponentPersistenceConfig `json:"persistence,omitempty"` + // Security is used to secure the grafana service. + // .Values.grafana.security.enabled, true if not null + // XXX: unused for maistra, as we use oauth-proxy + // +optional + Security *GrafanaSecurityConfig `json:"security,omitempty"` +} + +// GrafanaConfig configures the behavior of the grafana installation +type GrafanaConfig struct { + // Env allows specification of various grafana environment variables to be + // configured on the grafana container. + // .Values.grafana.env + // XXX: This is pretty cheesy... + // +optional + Env map[string]string `json:"env,omitempty"` + // EnvSecrets allows specification of secret fields into grafana environment + // variables to be configured on the grafana container + // .Values.grafana.envSecrets + // XXX: This is pretty cheesy... + // +optional + EnvSecrets map[string]string `json:"envSecrets,omitempty"` +} + +// GrafanaSecurityConfig is used to secure access to grafana +type GrafanaSecurityConfig struct { + Enablement `json:",inline"` + // SecretName is the name of a secret containing the username/password that + // should be used to access grafana. + // +optional + SecretName string `json:"secretName,omitempty"` + // UsernameKey is the name of the key within the secret identifying the username. + // +optional + UsernameKey string `json:"usernameKey,omitempty"` + // PassphraseKey is the name of the key within the secret identifying the password. + // +optional + PassphraseKey string `json:"passphraseKey,omitempty"` +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/jaeger.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/jaeger.go new file mode 100644 index 0000000000..f38c8e4905 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/jaeger.go @@ -0,0 +1,98 @@ +package v2 + +import v1 "github.com/maistra/istio-operator/pkg/apis/maistra/v1" + +// JaegerAddonConfig configuration specific to Jaeger integration. +// XXX: this currently deviates from upstream, which creates a jaeger all-in-one deployment manually +type JaegerAddonConfig struct { + // Name of Jaeger CR, Namespace must match control plane namespace + Name string `json:"name,omitempty"` + // Install configures a Jaeger installation, which will be created if the + // named Jaeger resource is not present. If null, the named Jaeger resource + // must exist. + // +optional + Install *JaegerInstallConfig `json:"install,omitempty"` +} + +// JaegerInstallConfig configures a Jaeger installation. +type JaegerInstallConfig struct { + // Config represents the configuration of Jaeger behavior. + // +optional + Storage *JaegerStorageConfig `json:"storage,omitempty"` + // Ingress configures k8s Ingress or OpenShift Route for Jaeger services + // .Values.tracing.jaeger.ingress.enabled, false if null + // +optional + Ingress *JaegerIngressConfig `json:"ingress,omitempty"` +} + +// JaegerStorageConfig configures the storage used by the Jaeger installation. +type JaegerStorageConfig struct { + // Type of storage to use + Type JaegerStorageType `json:"type,omitempty"` + // Memory represents configuration of in-memory storage + // implies .Values.tracing.jaeger.template=all-in-one + // +optional + Memory *JaegerMemoryStorageConfig `json:"memory,omitempty"` + // Elasticsearch represents configuration of elasticsearch storage + // implies .Values.tracing.jaeger.template=production-elasticsearch + // +optional + Elasticsearch *JaegerElasticsearchStorageConfig `json:"elasticsearch,omitempty"` +} + +// JaegerStorageType represents the type of storage configured for Jaeger +type JaegerStorageType string + +const ( + // JaegerStorageTypeMemory represents in-memory storage + JaegerStorageTypeMemory JaegerStorageType = "Memory" + // JaegerStorageTypeElasticsearch represents Elasticsearch storage + JaegerStorageTypeElasticsearch JaegerStorageType = "Elasticsearch" +) + +// JaegerMemoryStorageConfig configures in-memory storage parameters for Jaeger +type JaegerMemoryStorageConfig struct { + // MaxTraces to store + // .Values.tracing.jaeger.memory.max_traces, defaults to 100000 + // +optional + MaxTraces *int64 `json:"maxTraces,omitempty"` +} + +// JaegerElasticsearchStorageConfig configures elasticsearch storage parameters for Jaeger +type JaegerElasticsearchStorageConfig struct { + // NodeCount represents the number of elasticsearch nodes to create. + // .Values.tracing.jaeger.elasticsearch.nodeCount, defaults to 3 + // +optional + NodeCount *int32 `json:"nodeCount,omitempty"` + // Storage represents storage configuration for elasticsearch. + // .Values.tracing.jaeger.elasticsearch.storage, raw yaml + // XXX: RawExtension? + // +optional + Storage *v1.HelmValues `json:"storage,omitempty"` + // RedundancyPolicy configures the redundancy policy for elasticsearch + // .Values.tracing.jaeger.elasticsearch.redundancyPolicy, raw yaml + // +optional + RedundancyPolicy string `json:"redundancyPolicy,omitempty"` + // IndexCleaner represents the configuration for the elasticsearch index cleaner + // .Values.tracing.jaeger.elasticsearch.esIndexCleaner, raw yaml + // XXX: RawExtension? + // +optional + IndexCleaner *v1.HelmValues `json:"indexCleaner,omitempty"` +} + +// JaegerIngressConfig configures k8s Ingress or OpenShift Route for exposing +// Jaeger services. +type JaegerIngressConfig struct { + Enablement `json:",inline"` + // Metadata represents additional annotations/labels to be applied to the ingress/route. + // +optional + Metadata *MetadataConfig `json:"metadata,omitempty"` +} + +// ResourceName returns the resource name for the Jaeger resource, returning a +// sensible default if the Name field is not set ("jaeger"). +func (c JaegerAddonConfig) ResourceName() string { + if c.Name == "" { + return "jaeger" + } + return c.Name +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/kiali.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/kiali.go new file mode 100644 index 0000000000..41027aca49 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/kiali.go @@ -0,0 +1,80 @@ +package v2 + +import corev1 "k8s.io/api/core/v1" + +// KialiAddonConfig is used to configure a kiali instance for use with the mesh +type KialiAddonConfig struct { + Enablement `json:",inline"` + // Name of Kiali CR, Namespace must match control plane namespace + Name string `json:"name,omitempty"` + // Install a Kiali resource if the named Kiali resource is not present. + // +optional + Install *KialiInstallConfig `json:"install,omitempty"` +} + +// KialiInstallConfig is used to configure a kiali installation +type KialiInstallConfig struct { + // Dashboard configures the behavior of the kiali dashboard. + // +optional + Dashboard *KialiDashboardConfig `json:"dashboard,omitempty"` + // Service is used to configure the k8s Service associated with the kiali + // installation. + // XXX: provided for upstream support, only ingress is used, and then only + // for enablement and contextPath + // +optional + Service *ComponentServiceConfig `json:"service,omitempty"` + + // Deployment configures the kiali deployment. + // +optional + // +deprecated + Deployment *KialiDeploymentConfig `json:"deployment,omitempty"` +} + +// KialiDashboardConfig configures the behavior of the kiali dashboard +type KialiDashboardConfig struct { + // ViewOnly configures view_only_mode for the dashboard + // .Values.kiali.dashboard.viewOnlyMode + // +optional + ViewOnly *bool `json:"viewOnly,omitempty"` + // XXX: should the user have a choice here, or should these be configured + // automatically if they are enabled for the control plane installation? + // Grafana endpoint will be configured based on Grafana configuration + // +optional + EnableGrafana *bool `json:"enableGrafana,omitempty"` + // Prometheus endpoint will be configured based on Prometheus configuration + // +optional + EnablePrometheus *bool `json:"enablePrometheus,omitempty"` + // Tracing endpoint will be configured based on Tracing configuration + // +optional + EnableTracing *bool `json:"enableTracing,omitempty"` +} + +// KialiDeploymentConfig configures the kiali deployment +// +deprecated +// Deprecated: Use runtime.components.kiali instead. +type KialiDeploymentConfig struct { + // +optional + Resources *corev1.ResourceRequirements `json:"resources,omitempty"` + + // If specified, the pod's scheduling constraints + // +optional + Affinity *corev1.Affinity `json:"affinity,omitempty"` + + // Selector which must match a node's labels for the pod to be scheduled on that node. + // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + // +optional + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // If specified, the kiali pod's tolerations. + // +optional + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` +} + +// ResourceName returns the resource name for the Kiali resource, returning a +// sensible default if the Name field is not set ("kiali"). +func (c KialiAddonConfig) ResourceName() string { + if c.Name == "" { + return "kiali" + } + return c.Name +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/lightstep.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/lightstep.go new file mode 100644 index 0000000000..3494818cb3 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/lightstep.go @@ -0,0 +1,6 @@ +package v2 + +// LightstepTracerConfig configures a Lightstep tracer for use with the mesh +type LightstepTracerConfig struct { + // TODO.... +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/logging.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/logging.go new file mode 100644 index 0000000000..0a4b804703 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/logging.go @@ -0,0 +1,93 @@ +package v2 + +// LoggingConfig for control plane components +type LoggingConfig struct { + // ComponentLevels configures log level for specific envoy components + // .Values.global.proxy.componentLogLevel, overridden by sidecar.istio.io/componentLogLevel + // map of : + // +optional + ComponentLevels ComponentLogLevels `json:"componentLevels,omitempty"` + // LogAsJSON enables JSON logging + // .Values.global.logAsJson + // +optional + LogAsJSON *bool `json:"logAsJSON,omitempty"` +} + +// ProxyLoggingConfig configures logging for a component +type ProxyLoggingConfig struct { + // Level the log level + // .Values.global.proxy.logLevel, overridden by sidecar.istio.io/logLevel + // +optional + Level LogLevel `json:"level,omitempty"` + // ComponentLevels configures log level for specific envoy components + // .Values.global.proxy.componentLogLevel, overridden by sidecar.istio.io/componentLogLevel + // map of : + // +optional + ComponentLevels ComponentLogLevels `json:"componentLevels,omitempty"` +} + +// ComponentLogLevels represent various logging levels, e.g. trace, debug, etc. +type ComponentLogLevels map[EnvoyComponent]LogLevel + +// LogLevel represents the logging level +type LogLevel string + +const ( + // LogLevelTrace trace logging level + LogLevelTrace LogLevel = "trace" + // LogLevelDebug debug logging level + LogLevelDebug LogLevel = "debug" + // LogLevelInfo info logging level + LogLevelInfo LogLevel = "info" + // LogLevelWarning warning logging level + LogLevelWarning LogLevel = "warn" + // LogLevelWarningProxy proxy warning logging level + LogLevelWarningProxy LogLevel = "warning" + // LogLevelError error logging level + LogLevelError LogLevel = "error" + // LogLevelCritical critical logging level + LogLevelCritical LogLevel = "critical" + // LogLevelOff disable logging + LogLevelOff LogLevel = "off" +) + +// EnvoyComponent represents an envoy component to configure logging +type EnvoyComponent string + +// not a comprehensive list +const ( + EnvoyComponentAdmin EnvoyComponent = "admin" + EnvoyComponentAssert EnvoyComponent = "assert" + EnvoyComponentBacktrace EnvoyComponent = "backtrace" + EnvoyComponentClient EnvoyComponent = "client" + EnvoyComponentConfig EnvoyComponent = "config" + EnvoyComponentConnection EnvoyComponent = "connection" + EnvoyComponentConnHandler EnvoyComponent = "conn_handler" + EnvoyComponentFile EnvoyComponent = "file" + EnvoyComponentFilter EnvoyComponent = "filter" + EnvoyComponentForwardProxy EnvoyComponent = "forward_proxy" + EnvoyComponentGRPC EnvoyComponent = "grpc" + EnvoyComponentHealth EnvoyComponent = "hc" + EnvoyComponentHealthChecker EnvoyComponent = "health_checker" + EnvoyComponentHTTP EnvoyComponent = "http" + EnvoyComponentHTTP2 EnvoyComponent = "http2" + EnvoyComponentInit EnvoyComponent = "init" + EnvoyComponentIO EnvoyComponent = "io" + EnvoyComponentJWT EnvoyComponent = "jwt" + EnvoyComponentLua EnvoyComponent = "lua" + EnvoyComponentMain EnvoyComponent = "main" + EnvoyComponentMisc EnvoyComponent = "misc" + EnvoyComponentQuic EnvoyComponent = "quic" + EnvoyComponentPool EnvoyComponent = "pool" + EnvoyComponentRBAC EnvoyComponent = "rbac" + EnvoyComponentRouter EnvoyComponent = "router" + EnvoyComponentRuntime EnvoyComponent = "runtime" + EnvoyComponentStats EnvoyComponent = "stats" + EnvoyComponentSecret EnvoyComponent = "secret" + EnvoyComponentTap EnvoyComponent = "tap" + EnvoyComponentTesting EnvoyComponent = "testing" + EnvoyComponentTracing EnvoyComponent = "tracing" + EnvoyComponentUpstream EnvoyComponent = "upstream" + EnvoyComponentUDP EnvoyComponent = "udp" + EnvoyComponentWASM EnvoyComponent = "wasm" +) diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/policy.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/policy.go new file mode 100644 index 0000000000..16a87a218e --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/policy.go @@ -0,0 +1,91 @@ +package v2 + +// PolicyConfig configures policy aspects of the mesh. +type PolicyConfig struct { + // Required, the policy implementation + // defaults to Istiod 1.6+, Mixer pre-1.6 + Type PolicyType `json:"type,omitempty"` + // Mixer configuration (legacy, v1) + // .Values.mixer.policy.enabled + // +optional + Mixer *MixerPolicyConfig `json:"mixer,omitempty"` + // Remote mixer configuration (legacy, v1) + // .Values.global.remotePolicyAddress + // +optional + Remote *RemotePolicyConfig `json:"remote,omitempty"` +} + +// PolicyType represents the type of policy implementation used by the mesh. +type PolicyType string + +const ( + // PolicyTypeNone represents disabling of policy + // XXX: note, this doesn't appear to affect Istio 1.6, i.e. no different than Istiod setting + PolicyTypeNone PolicyType = "None" + // PolicyTypeMixer represents mixer, v1 implementation + PolicyTypeMixer PolicyType = "Mixer" + // PolicyTypeRemote represents remote mixer, v1 implementation + PolicyTypeRemote PolicyType = "Remote" + // PolicyTypeIstiod represents istio, v2 implementation + PolicyTypeIstiod PolicyType = "Istiod" +) + +// MixerPolicyConfig configures a mixer implementation for policy +// .Values.mixer.policy.enabled +type MixerPolicyConfig struct { + // EnableChecks configures whether or not policy checks should be enabled. + // .Values.global.disablePolicyChecks | default "true" (false, inverted logic) + // Set the following variable to false to disable policy checks by the Mixer. + // Note that metrics will still be reported to the Mixer. + // +optional + EnableChecks *bool `json:"enableChecks,omitempty"` + // FailOpen configures policy checks to fail if mixer cannot be reached. + // .Values.global.policyCheckFailOpen, maps to MeshConfig.policyCheckFailOpen + // policyCheckFailOpen allows traffic in cases when the mixer policy service cannot be reached. + // Default is false which means the traffic is denied when the client is unable to connect to Mixer. + // +optional + FailOpen *bool `json:"failOpen,omitempty"` + // SessionAffinity configures session affinity for sidecar policy connections. + // .Values.mixer.policy.sessionAffinityEnabled + // +optional + SessionAffinity *bool `json:"sessionAffinity,omitempty"` + // Adapters configures available adapters. + // +optional + Adapters *MixerPolicyAdaptersConfig `json:"adapters,omitempty"` +} + +// MixerPolicyAdaptersConfig configures policy adapters for mixer. +type MixerPolicyAdaptersConfig struct { + // UseAdapterCRDs configures mixer to support deprecated mixer CRDs. + // .Values.mixer.policy.adapters.useAdapterCRDs, removed in istio 1.4, defaults to false + // Only supported in v1.0, where it defaulted to true + // +optional + UseAdapterCRDs *bool `json:"useAdapterCRDs,omitempty"` + // Kubernetesenv configures the use of the kubernetesenv adapter. + // .Values.mixer.policy.adapters.kubernetesenv.enabled, defaults to true + // +optional + KubernetesEnv *bool `json:"kubernetesenv,omitempty"` +} + +// RemotePolicyConfig configures a remote mixer instance for policy +type RemotePolicyConfig struct { + // Address represents the address of the mixer server. + // .Values.global.remotePolicyAddress, maps to MeshConfig.mixerCheckServer + Address string `json:"address,omitempty"` + // CreateServices specifies whether or not a k8s Service should be created for the remote policy server. + // .Values.global.createRemoteSvcEndpoints + // +optional + CreateService *bool `json:"createService,omitempty"` + // EnableChecks configures whether or not policy checks should be enabled. + // .Values.global.disablePolicyChecks | default "true" (false, inverted logic) + // Set the following variable to false to disable policy checks by the Mixer. + // Note that metrics will still be reported to the Mixer. + // +optional + EnableChecks *bool `json:"enableChecks,omitempty"` + // FailOpen configures policy checks to fail if mixer cannot be reached. + // .Values.global.policyCheckFailOpen, maps to MeshConfig.policyCheckFailOpen + // policyCheckFailOpen allows traffic in cases when the mixer policy service cannot be reached. + // Default is false which means the traffic is denied when the client is unable to connect to Mixer. + // +optional + FailOpen *bool `json:"failOpen,omitempty"` +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/prometheus.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/prometheus.go new file mode 100644 index 0000000000..8be51b8886 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/prometheus.go @@ -0,0 +1,58 @@ +package v2 + +// PrometheusAddonConfig configures a prometheus instance to be used by the +// control plane. Only one of Install or Address may be specified +type PrometheusAddonConfig struct { + Enablement `json:",inline"` + // MetricsExpiryDuration is the duration to hold metrics. (mixer/v1 only) + // .Values.mixer.adapters.prometheus.metricsExpiryDuration, defaults to 10m + // +optional + MetricsExpiryDuration string `json:"metricsExpiryDuration,omitempty"` + // Scrape metrics from the pod if true. (maistra-2.0+) + // defaults to true + // .Values.meshConfig.enablePrometheusMerge + // +optional + Scrape *bool `json:"scrape,omitempty"` + // Install configuration if not using an existing prometheus installation. + // .Values.prometheus.enabled, if not null + // +optional + Install *PrometheusInstallConfig `json:"install,omitempty"` + // Address of existing prometheus installation + // implies .Values.kiali.prometheusAddr + // XXX: do we need to do anything to configure credentials for accessing + // the prometheus server? + // +optional + Address *string `json:"address,omitempty"` +} + +// PrometheusInstallConfig represents the configuration to be applied when +// installing a new instance of prometheus for use with the mesh. +type PrometheusInstallConfig struct { + // SelfManaged specifies whether or not the entire install should be managed + // by Maistra (true) or the Prometheus operator (false, not supported). + // Governs use of either prometheus charts or prometheusOperator charts. + // +optional + SelfManaged bool `json:"selfManaged,omitempty"` + // Retention specifies how long metrics should be retained by prometheus. + // .Values.prometheus.retention, defaults to 6h + // +optional + Retention string `json:"retention,omitempty"` + // ScrapeInterval specifies how frequently prometheus should scrape pods for + // metrics. + // .Values.prometheus.scrapeInterval, defaults to 15s + // +optional + ScrapeInterval string `json:"scrapeInterval,omitempty"` + // Service allows for customization of the k8s Service associated with the + // prometheus installation. + // +optional + Service *ComponentServiceConfig `json:"service,omitempty"` + // UseTLS for the prometheus server + // .Values.prometheus.provisionPrometheusCert + // 1.6+ + // ProvisionCert bool + // this seems to overlap with provision cert, as this manifests something similar to the above + // .Values.prometheus.security.enabled, version < 1.6 + // EnableSecurity bool + // +optional + UseTLS *bool `json:"useTLS,omitempty"` +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/proxy.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/proxy.go new file mode 100644 index 0000000000..afb810d016 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/proxy.go @@ -0,0 +1,387 @@ +package v2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ProxyConfig configures the default sidecar behavior for workloads. +type ProxyConfig struct { + // Logging configures logging for the sidecar. + // e.g. .Values.global.proxy.logLevel + // +optional + Logging *ProxyLoggingConfig `json:"logging,omitempty"` + // Networking represents network settings to be configured for the sidecars. + // +optional + Networking *ProxyNetworkingConfig `json:"networking,omitempty"` + // Runtime is used to customize runtime configuration for the sidecar container. + // +optional + Runtime *ProxyRuntimeConfig `json:"runtime,omitempty"` + // Injection is used to customize sidecar injection for the mesh. + // +optional + Injection *ProxyInjectionConfig `json:"injection,omitempty"` + // AdminPort configures the admin port exposed by the sidecar. + // maps to defaultConfig.proxyAdminPort, defaults to 15000 + // XXX: currently not configurable in charts + // +optional + AdminPort int32 `json:"adminPort,omitempty"` + // Concurrency configures the number of threads that should be run by the sidecar. + // .Values.global.proxy.concurrency, maps to defaultConfig.concurrency + // XXX: removed in 1.7 + // XXX: this is defaulted to 2 in our values.yaml, but should probably be 0 + // +optional + Concurrency *int32 `json:"concurrency,omitempty"` + // AccessLogging configures access logging for proxies. + // +optional + AccessLogging *ProxyAccessLoggingConfig `json:"accessLogging,omitempty"` + // EnvoyMetricsService configures reporting of Envoy metrics to an external + // service. + // .Values.global.proxy.envoyMetricsService + // +optional + EnvoyMetricsService *ProxyEnvoyServiceConfig `json:"envoyMetricsService,omitempty"` +} + +// ProxyNetworkingConfig is used to configure networking aspects of the sidecar. +type ProxyNetworkingConfig struct { + // ClusterDomain represents the domain for the cluster, defaults to cluster.local + // .Values.global.proxy.clusterDomain + // +optional + ClusterDomain string `json:"clusterDomain,omitempty"` + // maps to meshConfig.defaultConfig.connectionTimeout, defaults to 10s + // XXX: currently not exposed through values.yaml + // +optional + ConnectionTimeout string `json:"connectionTimeout,omitempty"` + // MaxConnectionAge limits how long a sidecar can be connected to pilot. + // This may be used to balance load across pilot instances, at the cost of + // system churn. + // .Values.pilot.keepaliveMaxServerConnectionAge + // +optional + MaxConnectionAge string `json:"maxConnectionAge,omitempty"` + // Initialization is used to specify how the pod's networking through the + // proxy is initialized. This configures the use of CNI or an init container. + // +optional + Initialization *ProxyNetworkInitConfig `json:"initialization,omitempty"` + // TrafficControl configures what network traffic is routed through the proxy. + // +optional + TrafficControl *ProxyTrafficControlConfig `json:"trafficControl,omitempty"` + // Protocol configures how the sidecar works with application protocols. + // +optional + Protocol *ProxyNetworkProtocolConfig `json:"protocol,omitempty"` + // DNS configures aspects of the sidecar's usage of DNS + // +optional + DNS *ProxyDNSConfig `json:"dns,omitempty"` +} + +// ProxyNetworkInitConfig is used to configure how the pod's networking through +// the proxy is initialized. +type ProxyNetworkInitConfig struct { + // Type of the network initialization implementation. + Type ProxyNetworkInitType `json:"type,omitempty"` + // InitContainer configures the use of a pod init container for initializing + // the pod's networking. + // istio_cni.enabled = false, if InitContainer is used + // +optional + InitContainer *ProxyInitContainerConfig `json:"initContainer,omitempty"` +} + +// ProxyNetworkInitType represents the type of initializer to use for network initialization +type ProxyNetworkInitType string + +const ( + // ProxyNetworkInitTypeCNI to use CNI for network initialization + ProxyNetworkInitTypeCNI ProxyNetworkInitType = "CNI" + // ProxyNetworkInitTypeInitContainer to use an init container for network initialization + ProxyNetworkInitTypeInitContainer ProxyNetworkInitType = "InitContainer" +) + +// ProxyInitContainerConfig configures execution aspects for the init container +type ProxyInitContainerConfig struct { + // Runtime configures customization of the init container (e.g. resources) + // +optional + Runtime *ContainerConfig `json:"runtime,omitempty"` +} + +// ProxyTrafficControlConfig configures what and how traffic is routed through +// the sidecar. +type ProxyTrafficControlConfig struct { + // Inbound configures what inbound traffic is routed through the sidecar + // traffic.sidecar.istio.io/includeInboundPorts defaults to * (all ports) + // +optional + Inbound ProxyInboundTrafficControlConfig `json:"inbound,omitempty"` + // Outbound configures what outbound traffic is routed through the sidecar. + // +optional + Outbound ProxyOutboundTrafficControlConfig `json:"outbound,omitempty"` +} + +// ProxyNetworkInterceptionMode represents the InterceptMode types. +type ProxyNetworkInterceptionMode string + +const ( + // ProxyNetworkInterceptionModeRedirect requests iptables use REDIRECT to route inbound traffic through the sidecar. + ProxyNetworkInterceptionModeRedirect ProxyNetworkInterceptionMode = "REDIRECT" + // ProxyNetworkInterceptionModeTProxy requests iptables use TPROXY to route inbound traffic through the sidecar. + ProxyNetworkInterceptionModeTProxy ProxyNetworkInterceptionMode = "TPROXY" +) + +// ProxyInboundTrafficControlConfig configures what inbound traffic is +// routed through the sidecar. +type ProxyInboundTrafficControlConfig struct { + // InterceptionMode specifies how traffic is directed through the sidecar. + // maps to meshConfig.defaultConfig.interceptionMode, overridden by sidecar.istio.io/interceptionMode + // XXX: currently not configurable through values.yaml + // +optional + InterceptionMode ProxyNetworkInterceptionMode `json:"interceptionMode,omitempty"` + // IncludedPorts to be routed through the sidecar. * or comma separated list of integers + // .Values.global.proxy.includeInboundPorts, defaults to * (all ports), overridden by traffic.sidecar.istio.io/includeInboundPorts + // +optional + IncludedPorts []string `json:"includedPorts,omitempty"` + // ExcludedPorts to be routed around the sidecar. + // .Values.global.proxy.excludeInboundPorts, defaults to empty list, overridden by traffic.sidecar.istio.io/excludeInboundPorts + // +optional + ExcludedPorts []int32 `json:"excludedPorts,omitempty"` +} + +// ProxyOutboundTrafficControlConfig configure what outbound traffic is routed +// through the sidecar +type ProxyOutboundTrafficControlConfig struct { + // IncludedIPRanges specifies which outbound IP ranges should be routed through the sidecar. + // .Values.global.proxy.includeIPRanges, overridden by traffic.sidecar.istio.io/includeOutboundIPRanges + // * or comma separated list of CIDR + // +optional + IncludedIPRanges []string `json:"includedIPRanges,omitempty"` + // ExcludedIPRanges specifies which outbound IP ranges should _not_ be routed through the sidecar. + // .Values.global.proxy.excludeIPRanges, overridden by traffic.sidecar.istio.io/excludeOutboundIPRanges + // * or comma separated list of CIDR + // +optional + ExcludedIPRanges []string `json:"excludedIPRanges,omitempty"` + // ExcludedPorts specifies which outbound ports should _not_ be routed through the sidecar. + // .Values.global.proxy.excludeOutboundPorts, overridden by traffic.sidecar.istio.io/excludeOutboundPorts + // comma separated list of integers + // +optional + ExcludedPorts []int32 `json:"excludedPorts,omitempty"` + // Policy specifies what outbound traffic is allowed through the sidecar. + // .Values.global.outboundTrafficPolicy.mode + // +optional + Policy ProxyOutboundTrafficPolicy `json:"policy,omitempty"` +} + +// ProxyOutboundTrafficPolicy represents the outbound traffic policy type. +type ProxyOutboundTrafficPolicy string + +const ( + // ProxyOutboundTrafficPolicyAllowAny allows all traffic through the sidecar. + ProxyOutboundTrafficPolicyAllowAny ProxyOutboundTrafficPolicy = "ALLOW_ANY" + // ProxyOutboundTrafficPolicyRegistryOnly only allows traffic destined for a + // service in the service registry through the sidecar. This limits outbound + // traffic to only other services in the mesh. + ProxyOutboundTrafficPolicyRegistryOnly ProxyOutboundTrafficPolicy = "REGISTRY_ONLY" +) + +// ProxyNetworkProtocolConfig configures the sidecar's protocol handling. +type ProxyNetworkProtocolConfig struct { + // AutoDetect configures automatic detection of connection protocols. + // +optional + AutoDetect *ProxyNetworkAutoProtocolDetectionConfig `json:"autoDetect,omitempty"` +} + +// ProxyNetworkAutoProtocolDetectionConfig configures automatic protocol detection for the proxies. +type ProxyNetworkAutoProtocolDetectionConfig struct { + // DetectionTimeout specifies how much time the sidecar will spend determining + // the protocol being used for the connection before reverting to raw TCP. + // .Values.global.proxy.protocolDetectionTimeout, maps to protocolDetectionTimeout + // +optional + Timeout string `json:"timeout,omitempty"` + // EnableInboundSniffing enables protocol sniffing on inbound traffic. + // .Values.pilot.enableProtocolSniffingForInbound + // only supported for v1.1 + // +optional + Inbound *bool `json:"inbound,omitempty"` + // EnableOutboundSniffing enables protocol sniffing on outbound traffic. + // .Values.pilot.enableProtocolSniffingForOutbound + // only supported for v1.1 + // +optional + Outbound *bool `json:"outbound,omitempty"` +} + +// ProxyDNSConfig is used to configure aspects of the sidecar's DNS usage. +type ProxyDNSConfig struct { + // SearchSuffixes are additional search suffixes to be used when resolving + // names. + // .Values.global.podDNSSearchNamespaces + // Custom DNS config for the pod to resolve names of services in other + // clusters. Use this to add additional search domains, and other settings. + // see + // https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#dns-config + // This does not apply to gateway pods as they typically need a different + // set of DNS settings than the normal application pods (e.g., in + // multicluster scenarios). + // NOTE: If using templates, follow the pattern in the commented example below. + // podDNSSearchNamespaces: + // - global + // - "{{ valueOrDefault .DeploymentMeta.Namespace \"default\" }}.global" + // +optional + SearchSuffixes []string `json:"searchSuffixes,omitempty"` + // RefreshRate configures the DNS refresh rate for Envoy cluster of type STRICT_DNS + // This must be given it terms of seconds. For example, 300s is valid but 5m is invalid. + // .Values.global.proxy.dnsRefreshRate, default 300s + // +optional + RefreshRate string `json:"refreshRate,omitempty"` +} + +// ProxyRuntimeConfig customizes the runtime parameters of the sidecar container. +type ProxyRuntimeConfig struct { + // Readiness configures the readiness probe behavior for the injected pod. + // +optional + Readiness *ProxyReadinessConfig `json:"readiness,omitempty"` + // Container configures the sidecar container. + // +optional + Container *ContainerConfig `json:"container,omitempty"` +} + +// ProxyReadinessConfig configures the readiness probe for the sidecar. +type ProxyReadinessConfig struct { + // RewriteApplicationProbes specifies whether or not the injector should + // rewrite application container probes to be routed through the sidecar. + // .Values.sidecarInjectorWebhook.rewriteAppHTTPProbe, defaults to false + // rewrite probes for application pods to route through sidecar + // +optional + RewriteApplicationProbes bool `json:"rewriteApplicationProbes,omitempty"` + // StatusPort specifies the port number to be used for status. + // .Values.global.proxy.statusPort, overridden by status.sidecar.istio.io/port, defaults to 15020 + // Default port for Pilot agent health checks. A value of 0 will disable health checking. + // XXX: this has no affect on which port is actually used for status. + // +optional + StatusPort int32 `json:"statusPort,omitempty"` + // InitialDelaySeconds specifies the initial delay for the readiness probe + // .Values.global.proxy.readinessInitialDelaySeconds, overridden by readiness.status.sidecar.istio.io/initialDelaySeconds, defaults to 1 + // +optional + InitialDelaySeconds int32 `json:"initialDelaySeconds,omitempty"` + // PeriodSeconds specifies the period over which the probe is checked. + // .Values.global.proxy.readinessPeriodSeconds, overridden by readiness.status.sidecar.istio.io/periodSeconds, defaults to 2 + // +optional + PeriodSeconds int32 `json:"periodSeconds,omitempty"` + // FailureThreshold represents the number of consecutive failures before the container is marked as not ready. + // .Values.global.proxy.readinessFailureThreshold, overridden by readiness.status.sidecar.istio.io/failureThreshold, defaults to 30 + // +optional + FailureThreshold int32 `json:"failureThreshold,omitempty"` +} + +// ProxyInjectionConfig configures sidecar injection for the mesh. +type ProxyInjectionConfig struct { + // AutoInject configures automatic injection of sidecar proxies + // .Values.global.proxy.autoInject + // .Values.sidecarInjectorWebhook.enableNamespacesByDefault + // +optional + AutoInject *bool `json:"autoInject,omitempty"` + // AlwaysInjectSelector allows specification of a label selector that when + // matched will always inject a sidecar into the pod. + // .Values.sidecarInjectorWebhook.alwaysInjectSelector + // +optional + AlwaysInjectSelector []metav1.LabelSelector `json:"alwaysInjectSelector,omitempty"` + // NeverInjectSelector allows specification of a label selector that when + // matched will never inject a sidecar into the pod. This takes precedence + // over AlwaysInjectSelector. + // .Values.sidecarInjectorWebhook.neverInjectSelector + // +optional + NeverInjectSelector []metav1.LabelSelector `json:"neverInjectSelector,omitempty"` + // InjectedAnnotations allows specification of additional annotations to be + // added to pods that have sidecars injected in them. + // .Values.sidecarInjectorWebhook.injectedAnnotations + // +optional + InjectedAnnotations map[string]string `json:"injectedAnnotations,omitempty"` +} + +// ProxyAccessLoggingConfig configures access logging for proxies. Multiple +// access logs can be configured. +type ProxyAccessLoggingConfig struct { + // File configures access logging to the file system + // +optional + File *ProxyFileAccessLogConfig `json:"file,omitempty"` + // File configures access logging to an envoy service + // .Values.global.proxy.envoyAccessLogService + // +optional + EnvoyService *ProxyEnvoyServiceConfig `json:"envoyService,omitempty"` +} + +// ProxyFileAccessLogConfig configures details related to file access log +type ProxyFileAccessLogConfig struct { + // Name is the name of the file to which access log entries will be written. + // If Name is not specified, no log entries will be written to a file. + // .Values.global.proxy.accessLogFile + // +optional + Name string `json:"name,omitempty"` + // Encoding to use when writing access log entries. Currently, JSON or TEXT + // may be specified. + // .Values.global.proxy.accessLogEncoding + // +optional + Encoding string `json:"encoding,omitempty"` + // Format to use when writing access log entries. + // .Values.global.proxy.accessLogFormat + // +optional + Format string `json:"format,omitempty"` +} + +// ProxyEnvoyServiceConfig configures reporting to an external Envoy service. +type ProxyEnvoyServiceConfig struct { + // Enable sending Envoy metrics to the service. + // .Values.global.proxy.(envoyAccessLogService|envoyMetricsService).enabled + Enablement `json:",inline"` + // Address of the service specified as host:port. + // .Values.global.proxy.(envoyAccessLogService|envoyMetricsService).host + // .Values.global.proxy.(envoyAccessLogService|envoyMetricsService).port + // +optional + Address string `json:"address,omitempty"` + // TCPKeepalive configures keepalive settings to use when connecting to the + // service. + // .Values.global.proxy.(envoyAccessLogService|envoyMetricsService).tcpKeepalive + // +optional + TCPKeepalive *EnvoyServiceTCPKeepalive `json:"tcpKeepalive,omitempty"` + // TLSSettings configures TLS settings to use when connecting to the service. + // .Values.global.proxy.(envoyAccessLogService|envoyMetricsService).tlsSettings + // +optional + TLSSettings *EnvoyServiceClientTLSSettings `json:"tlsSettings,omitempty"` +} + +// EnvoyServiceTCPKeepalive configures keepalive settings for the Envoy service. +// Provides the same interface as networking.v1alpha3.istio.io, ConnectionPoolSettings_TCPSettings_TcpKeepalive +type EnvoyServiceTCPKeepalive struct { + // Probes represents the number of successive probe failures after which the + // connection should be considered "dead." + // +optional + Probes uint32 `json:"probes,omitempty"` + // Time represents the length of idle time that must elapse before a probe + // is sent. + // +optional + Time string `json:"time,omitempty"` + // Interval represents the interval between probes. + // +optional + Interval string `json:"interval,omitempty"` +} + +// EnvoyServiceClientTLSSettings configures TLS settings for the Envoy service. +// Provides the same interface as networking.v1alpha3.istio.io, ClientTLSSettings +type EnvoyServiceClientTLSSettings struct { + // Mode represents the TLS mode to apply to the connection. The following + // values are supported: DISABLE, SIMPLE, MUTUAL, ISTIO_MUTUAL + // +optional + Mode string `json:"mode,omitempty"` + // ClientCertificate represents the file name containing the client certificate + // to show to the Envoy service, e.g. /etc/istio/als/cert-chain.pem + // +optional + ClientCertificate string `json:"clientCertificate,omitempty"` + // PrivateKey represents the file name containing the private key used by + // the client, e.g. /etc/istio/als/key.pem + // +optional + PrivateKey string `json:"privateKey,omitempty"` + // CACertificates represents the file name containing the root certificates + // for the CA, e.g. /etc/istio/als/root-cert.pem + // +optional + CACertificates string `json:"caCertificates,omitempty"` + // SNIHost represents the host name presented to the server during TLS + // handshake, e.g. als.somedomain + // +optional + SNIHost string `json:"sni,omitempty"` + // SubjectAltNames represents the list of alternative names that may be used + // to verify the servers identity, e.g. [als.someotherdomain] + // +optional + SubjectAltNames []string `json:"subjectAltNames,omitempty"` +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/register.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/register.go new file mode 100644 index 0000000000..5ab21faf7b --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/register.go @@ -0,0 +1,26 @@ +// NOTE: Boilerplate only. Ignore this file. + +// Package v2 contains API Schema definitions for the maistra v2 API group +// +k8s:deepcopy-gen=package,register +// +groupName=maistra.io +package v2 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +const ( + // APIGroup for maistr.io + APIGroup = "maistra.io" + // APIVersion for v2 + APIVersion = "v2" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: APIGroup, Version: APIVersion} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} +) diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/runtime.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/runtime.go new file mode 100644 index 0000000000..df92a9ceaf --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/runtime.go @@ -0,0 +1,344 @@ +package v2 + +import ( + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + + v1 "github.com/maistra/istio-operator/pkg/apis/maistra/v1" +) + +// ControlPlaneRuntimeConfig configures execution parameters for control plane +// componets. +type ControlPlaneRuntimeConfig struct { + // Components allows specifying execution parameters for specific control plane + // componets. The key of the map is the component name to which the settings + // should be applied. + // +optional + Components map[ControlPlaneComponentName]*ComponentRuntimeConfig `json:"components,omitempty"` + // Defaults will be merged into specific component config. + // .Values.global.defaultResources, e.g. + // +optional + Defaults *DefaultRuntimeConfig `json:"defaults,omitempty"` +} + +// ControlPlaneComponentName simple type for control plane component names +type ControlPlaneComponentName string + +const ( + // ControlPlaneComponentNameSecurity - security (citadel) + ControlPlaneComponentNameSecurity ControlPlaneComponentName = "security" + // ControlPlaneComponentNameGalley - galley + ControlPlaneComponentNameGalley ControlPlaneComponentName = "galley" + // ControlPlaneComponentNamePilot - pilot + ControlPlaneComponentNamePilot ControlPlaneComponentName = "pilot" + // ControlPlaneComponentNameMixer - mixer + ControlPlaneComponentNameMixer ControlPlaneComponentName = "mixer" + // ControlPlaneComponentNameMixerPolicy - mixer.policy + ControlPlaneComponentNameMixerPolicy ControlPlaneComponentName = "mixer.policy" + // ControlPlaneComponentNameMixerTelemetry - mixer.telemetry + ControlPlaneComponentNameMixerTelemetry ControlPlaneComponentName = "mixer.telemetry" + // ControlPlaneComponentNameGlobalOauthProxy - global.oauthproxy + ControlPlaneComponentNameGlobalOauthProxy ControlPlaneComponentName = "global.oauthproxy" + // ControlPlaneComponentNameSidecarInjectoryWebhook - sidecarInjectorWebhook + ControlPlaneComponentNameSidecarInjectoryWebhook ControlPlaneComponentName = "sidecarInjectorWebhook" + // ControlPlaneComponentNameTracing - tracing + ControlPlaneComponentNameTracing ControlPlaneComponentName = "tracing" + // ControlPlaneComponentNameTracingJaeger - tracing.jaeger + ControlPlaneComponentNameTracingJaeger ControlPlaneComponentName = "tracing.jaeger" + // ControlPlaneComponentNameTracingJaegerElasticsearch - tracing.jaeger.elasticsearch + ControlPlaneComponentNameTracingJaegerElasticsearch ControlPlaneComponentName = "tracing.jaeger.elasticsearch" + // ControlPlaneComponentNameTracingJaegerAgent - tracing.jaeger.agent + ControlPlaneComponentNameTracingJaegerAgent ControlPlaneComponentName = "tracing.jaeger.agent" + // ControlPlaneComponentNameTracingJaegerAllInOne - tracing.jaeger.allInOne + ControlPlaneComponentNameTracingJaegerAllInOne ControlPlaneComponentName = "tracing.jaeger.allInOne" + // ControlPlaneComponentNameTracingJaegerCollector - tracing.jaeger.collector + ControlPlaneComponentNameTracingJaegerCollector ControlPlaneComponentName = "tracing.jaeger.collector" + // ControlPlaneComponentNameTracingJaegerQuery - tracing.jaeger.query + ControlPlaneComponentNameTracingJaegerQuery ControlPlaneComponentName = "tracing.jaeger.query" + // ControlPlaneComponentNamePrometheus - prometheus + ControlPlaneComponentNamePrometheus ControlPlaneComponentName = "prometheus" + // ControlPlaneComponentNameKiali - kiali + ControlPlaneComponentNameKiali ControlPlaneComponentName = "kiali" + // ControlPlaneComponentNameGrafana - grafana + ControlPlaneComponentNameGrafana ControlPlaneComponentName = "grafana" + // ControlPlaneComponentNameThreeScale - 3scale + ControlPlaneComponentNameThreeScale ControlPlaneComponentName = "3scale" + // ControlPlaneComponentNameWASMCacher - wasm-extensions cacher + ControlPlaneComponentNameWASMCacher ControlPlaneComponentName = "wasmExtensions.cacher" + // ControlPlaneComponentNameRateLimiting - rateLimiting + ControlPlaneComponentNameRateLimiting ControlPlaneComponentName = "rateLimiting.rls" +) + +// ControlPlaneComponentNames - supported runtime components +var ControlPlaneComponentNames = []ControlPlaneComponentName{ + ControlPlaneComponentNameSecurity, + ControlPlaneComponentNameGalley, + ControlPlaneComponentNamePilot, + ControlPlaneComponentNameMixer, + ControlPlaneComponentNameMixerPolicy, + ControlPlaneComponentNameMixerTelemetry, + ControlPlaneComponentNameGlobalOauthProxy, + ControlPlaneComponentNameSidecarInjectoryWebhook, + ControlPlaneComponentNameTracing, + ControlPlaneComponentNameTracingJaeger, + ControlPlaneComponentNameTracingJaegerElasticsearch, + ControlPlaneComponentNameTracingJaegerAgent, + ControlPlaneComponentNameTracingJaegerAllInOne, + ControlPlaneComponentNameTracingJaegerCollector, + ControlPlaneComponentNameTracingJaegerQuery, + ControlPlaneComponentNamePrometheus, + ControlPlaneComponentNameKiali, + ControlPlaneComponentNameGrafana, + ControlPlaneComponentNameThreeScale, + ControlPlaneComponentNameWASMCacher, + ControlPlaneComponentNameRateLimiting, +} + +// ComponentRuntimeConfig allows for partial customization of a component's +// runtime configuration (Deployment, PodTemplate, auto scaling, pod disruption, etc.) +type ComponentRuntimeConfig struct { + // Deployment specific overrides + // +optional + Deployment *DeploymentRuntimeConfig `json:"deployment,omitempty"` + + // Pod specific overrides + // +optional + Pod *PodRuntimeConfig `json:"pod,omitempty"` + + // .Values.*.resource, imagePullPolicy, etc. + // +optional + Container *ContainerConfig `json:"container,omitempty"` +} + +// DeploymentRuntimeConfig allow customization of a component's Deployment +// resource, including additional labels/annotations, replica count, autoscaling, +// rollout strategy, etc. +type DeploymentRuntimeConfig struct { + // Number of desired pods. This is a pointer to distinguish between explicit + // zero and not specified. Defaults to 1. + // +optional + // .Values.*.replicaCount + Replicas *int32 `json:"replicas,omitempty"` + + // The deployment strategy to use to replace existing pods with new ones. + // +optional + // +patchStrategy=retainKeys + // .Values.*.rollingMaxSurge, rollingMaxUnavailable, etc. + Strategy *appsv1.DeploymentStrategy `json:"strategy,omitempty" patchStrategy:"retainKeys"` + + // Autoscaling specifies the configuration for a HorizontalPodAutoscaler + // to be applied to this deployment. Null indicates no auto scaling. + // .Values.*.autoscale* fields + // +optional + AutoScaling *AutoScalerConfig `json:"autoScaling,omitempty"` +} + +// CommonDeploymentRuntimeConfig represents deployment settings common to both +// default and component specific settings +type CommonDeploymentRuntimeConfig struct { + // .Values.global.podDisruptionBudget.enabled, if not null + // XXX: this is currently a global setting, not per component. perhaps + // this should only be available on the defaults? + // +optional + PodDisruption *PodDisruptionBudget `json:"podDisruption,omitempty"` +} + +// AutoScalerConfig is used to configure autoscaling for a deployment +type AutoScalerConfig struct { + Enablement `json:",inline"` + // lower limit for the number of pods that can be set by the autoscaler, default 1. + // +optional + MinReplicas *int32 `json:"minReplicas,omitempty"` + // upper limit for the number of pods that can be set by the autoscaler; cannot be smaller than MinReplicas. + // +optional + MaxReplicas *int32 `json:"maxReplicas,omitempty"` + // target average CPU utilization (represented as a percentage of requested CPU) over all the pods; + // if not specified the default autoscaling policy will be used. + // +optional + TargetCPUUtilizationPercentage *int32 `json:"targetCPUUtilizationPercentage,omitempty"` +} + +// PodRuntimeConfig is used to customize pod configuration for a component +type PodRuntimeConfig struct { + CommonPodRuntimeConfig `json:",inline"` + + // Metadata allows additional annotations/labels to be applied to the pod + // .Values.*.podAnnotations + // XXX: currently, additional lables are not supported + // +optional + Metadata *MetadataConfig `json:"metadata,omitempty"` + + // If specified, the pod's scheduling constraints + // +optional + // .Values.podAntiAffinityLabelSelector, podAntiAffinityTermLabelSelector, nodeSelector + // NodeAffinity is not supported at this time + // PodAffinity is not supported at this time + Affinity *Affinity `json:"affinity,omitempty"` +} + +// CommonPodRuntimeConfig represents pod settings common to both defaults and +// component specific configuration +type CommonPodRuntimeConfig struct { + // NodeSelector is a selector which must be true for the pod to fit on a node. + // Selector which must match a node's labels for the pod to be scheduled on that node. + // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + // +optional + // .Values.nodeSelector + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // If specified, the pod's tolerations. + // +optional + // .Values.tolerations + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + + // .Values.global.priorityClassName + // XXX: currently, this is only a global setting. maybe only allow setting in global runtime defaults? + // +optional + PriorityClassName string `json:"priorityClassName,omitempty"` +} + +// Affinity is the structure used by Istio for specifying Pod affinity +// XXX: istio does not support full corev1.Affinity settings, hence the special +// types here. +type Affinity struct { + // +optional + NodeAffinity *corev1.NodeAffinity `json:"nodeAffinity,omitempty"` + // +optional + PodAffinity *corev1.PodAffinity `json:"podAffinity,omitempty"` + // XXX: use corev1.PodAntiAffinity instead, the only things not supported are namespaces and weighting + // +optional + PodAntiAffinity PodAntiAffinity `json:"podAntiAffinity,omitempty"` +} + +// PodAntiAffinity configures anti affinity for pod scheduling +type PodAntiAffinity struct { + *corev1.PodAntiAffinity `json:",inline"` + + // +optional + RequiredDuringScheduling []PodAntiAffinityTerm `json:"requiredDuringScheduling,omitempty"` + // +optional + PreferredDuringScheduling []PodAntiAffinityTerm `json:"preferredDuringScheduling,omitempty"` +} + +// PodAntiAffinityTerm is a simplified version of corev1.PodAntiAffinityTerm +type PodAntiAffinityTerm struct { + metav1.LabelSelectorRequirement `json:",inline"` + // This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + // the labelSelector in the specified namespaces, where co-located is defined as running on a node + // whose value of the label with key topologyKey matches that of any node on which any of the + // selected pods is running. + // Empty topologyKey is not allowed. + // +optional + TopologyKey string `json:"topologyKey,omitempty"` +} + +// ContainerConfig to be applied to containers in a pod, in a deployment +type ContainerConfig struct { + CommonContainerConfig `json:",inline"` + // +optional + Image string `json:"imageName,omitempty"` + // +optional + Env map[string]string `json:"env,omitempty"` +} + +// CommonContainerConfig represents container settings common to both defaults +// and component specific configuration. +type CommonContainerConfig struct { + // +optional + ImageRegistry string `json:"imageRegistry,omitempty"` + // +optional + ImageTag string `json:"imageTag,omitempty"` + // +optional + ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + // +optional + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + // +optional + Resources *corev1.ResourceRequirements `json:"resources,omitempty"` +} + +// PodDisruptionBudget details +// XXX: currently only configurable globally (i.e. no component values.yaml equivalent) +type PodDisruptionBudget struct { + Enablement `json:",inline"` + // +optional + MinAvailable *intstr.IntOrString `json:"minAvailable,omitempty"` + // +optional + MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"` +} + +// DefaultRuntimeConfig specifies default execution parameters to apply to +// control plane deployments/pods when no specific component overrides have been +// specified. These settings will be merged with component specific settings. +type DefaultRuntimeConfig struct { + // Deployment defaults + // +optional + Deployment *CommonDeploymentRuntimeConfig `json:"deployment,omitempty"` + // Pod defaults + // +optional + Pod *CommonPodRuntimeConfig `json:"pod,omitempty"` + // Container overrides to be merged with component specific overrides. + // +optional + Container *CommonContainerConfig `json:"container,omitempty"` +} + +// MetadataConfig represents additional metadata to be applied to resources +type MetadataConfig struct { + // +optional + Labels map[string]string `json:"labels,omitempty"` + // +optional + Annotations map[string]string `json:"annotations,omitempty"` +} + +// ComponentServiceConfig is used to customize the service associated with a component. +type ComponentServiceConfig struct { + // Metadata represents additional annotations/labels to be applied to the + // component's service. + // +optional + Metadata *MetadataConfig `json:"metadata,omitempty"` + // NodePort specifies a NodePort for the component's Service. + // .Values..service.nodePort.port, ...enabled is true if not null + // +optional + NodePort *int32 `json:"nodePort,omitempty"` + // Ingress specifies details for accessing the component's service through + // a k8s Ingress or OpenShift Route. + // +optional + Ingress *ComponentIngressConfig `json:"ingress,omitempty"` +} + +// ComponentIngressConfig is used to customize a k8s Ingress or OpenShift Route +// for the service associated with a component. +type ComponentIngressConfig struct { + Enablement `json:",inline"` + // Metadata represents additional metadata to be applied to the ingress/route. + // +optional + Metadata *MetadataConfig `json:"metadata,omitempty"` + // Hosts represents a list of host names to configure. Note, OpenShift route + // only supports a single host name per route. An empty host name implies + // a default host name for the Route. + // XXX: is a host name required for k8s Ingress? + // +optional + Hosts []string `json:"hosts,omitempty"` + // ContextPath represents the context path to the service. + // +optional + ContextPath string `json:"contextPath,omitempty"` + // TLS is used to configure TLS for the Ingress/Route + // XXX: should this be something like RawExtension, as the configuration differs between Route and Ingress? + // +optional + TLS *v1.HelmValues `json:"tls,omitempty"` +} + +// ComponentPersistenceConfig is used to configure persistence for a component. +type ComponentPersistenceConfig struct { + Enablement `json:",inline"` + // StorageClassName for the PersistentVolumeClaim + // +optional + StorageClassName string `json:"storageClassName,omitempty"` + // AccessMode for the PersistentVolumeClaim + // +optional + AccessMode corev1.PersistentVolumeAccessMode `json:"accessMode,omitempty"` + // Resources to request for the PersistentVolumeClaim + // +optional + Resources *corev1.ResourceRequirements `json:"capacity,omitempty"` +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/security.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/security.go new file mode 100644 index 0000000000..5b56c8b236 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/security.go @@ -0,0 +1,302 @@ +package v2 + +// SecurityConfig specifies security aspects of the control plane. +type SecurityConfig struct { + // Trust configures trust aspects associated with mutual TLS clients. + // +optional + Trust *TrustConfig `json:"trust,omitempty"` + // CertificateAuthority configures the certificate authority used by the + // control plane to create and sign client certs and server keys. + // +optional + CertificateAuthority *CertificateAuthorityConfig `json:"certificateAuthority,omitempty"` + // Identity configures the types of user tokens used by clients. + // +optional + Identity *IdentityConfig `json:"identity,omitempty"` + // ControlPlane configures mutual TLS for control plane communication. + // +optional + ControlPlane *ControlPlaneSecurityConfig `json:"controlPlane,omitempty"` + // DataPlane configures mutual TLS for data plane communication. + // +optional + DataPlane *DataPlaneSecurityConfig `json:"dataPlane,omitempty"` + // Manages network policies that allows communication between namespace members and control plane, defaults to `true` + // If false, operator does not create any NetworkPolicy resource, and users are responsible for managing them + // .Values.global.manageNetworkPolicy + // +optional + ManageNetworkPolicy *bool `json:"manageNetworkPolicy,omitempty"` + // JwksResolverCA is the configuration for injecting a trusted CA into the JWKSResolver. + // +optional + JwksResolverCA string `json:"jwksResolverCA,omitempty"` +} + +// TrustConfig configures trust aspects associated with mutual TLS clients +type TrustConfig struct { + // Domain specifies the trust domain to be used by the mesh. + // .Values.global.trustDomain, maps to trustDomain + // The trust domain corresponds to the trust root of a system. + // Refer to https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md#21-trust-domain + // +optional + Domain string `json:"domain,omitempty"` + // AdditionalDomains are additional SPIFFE trust domains that are accepted as trusted. + // .Values.global.trustDomainAliases, maps to trustDomainAliases + // Any service with the identity "td1/ns/foo/sa/a-service-account", "td2/ns/foo/sa/a-service-account", + // or "td3/ns/foo/sa/a-service-account" will be treated the same in the Istio mesh. + // +optional + AdditionalDomains []string `json:"additionalDomains,omitempty"` +} + +// CertificateAuthorityConfig configures the certificate authority implementation +// used by the control plane. +type CertificateAuthorityConfig struct { + // Type is the certificate authority to use. + Type CertificateAuthorityType `json:"type,omitempty"` + // Istiod is the configuration for Istio's internal certificate authority implementation. + // each of these produces a CAEndpoint, i.e. CA_ADDR + // +optional + Istiod *IstiodCertificateAuthorityConfig `json:"istiod,omitempty"` + // Custom is the configuration for a custom certificate authority. + // +optional + Custom *CustomCertificateAuthorityConfig `json:"custom,omitempty"` + CertManager *CertManagerCertificateAuthorityConfig `json:"cert-manager,omitempty"` +} + +// CertificateAuthorityType represents the type of CertificateAuthority implementation. +type CertificateAuthorityType string + +const ( + // CertificateAuthorityTypeIstiod represents Istio's internal certificate authority implementation + CertificateAuthorityTypeIstiod CertificateAuthorityType = "Istiod" + // CertificateAuthorityTypeCustom represents a custom certificate authority implementation + CertificateAuthorityTypeCustom CertificateAuthorityType = "Custom" + // CertificateAuthorityTypeCertManager represents a cert-manager istio-csr certificate authority implementation + CertificateAuthorityTypeCertManager CertificateAuthorityType = "cert-manager" +) + +// IstiodCertificateAuthorityConfig is the configuration for Istio's internal +// certificate authority implementation. +type IstiodCertificateAuthorityConfig struct { + // Type of certificate signer to use. + Type IstioCertificateSignerType `json:"type,omitempty"` + // SelfSigned configures istiod to generate and use a self-signed certificate for the root. + // +optional + SelfSigned *IstioSelfSignedCertificateSignerConfig `json:"selfSigned,omitempty"` + // PrivateKey configures istiod to use a user specified private key/cert when signing certificates. + // +optional + PrivateKey *IstioPrivateKeyCertificateSignerConfig `json:"privateKey,omitempty"` + // WorkloadCertTTLDefault is the default TTL for generated workload + // certificates. Used if not specified in CSR (<= 0) + // env DEFAULT_WORKLOAD_CERT_TTL, 1.6 + // --workload-cert-ttl, citadel, pre-1.6 + // defaults to 24 hours + // +optional + WorkloadCertTTLDefault string `json:"workloadCertTTLDefault,omitempty"` + // WorkloadCertTTLMax is the maximum TTL for generated workload certificates. + // env MAX_WORKLOAD_CERT_TTL + // --max-workload-cert-ttl, citadel, pre-1.6 + // defaults to 90 days + // +optional + WorkloadCertTTLMax string `json:"workloadCertTTLMax,omitempty"` +} + +// IstioCertificateSignerType represents the certificate signer implementation used by istiod. +type IstioCertificateSignerType string + +const ( + // IstioCertificateSignerTypePrivateKey is the signer type used when signing with a user specified private key. + IstioCertificateSignerTypePrivateKey IstioCertificateSignerType = "PrivateKey" + // IstioCertificateSignerTypeSelfSigned is the signer type used when signing with a generated, self-signed certificate. + IstioCertificateSignerTypeSelfSigned IstioCertificateSignerType = "SelfSigned" +) + +// IstioSelfSignedCertificateSignerConfig is the configuration for using a +// self-signed root certificate. +type IstioSelfSignedCertificateSignerConfig struct { + // TTL for self-signed root certificate + // env CITADEL_SELF_SIGNED_CA_CERT_TTL + // default is 10 years + // +optional + TTL string `json:"ttl,omitempty"` + // GracePeriod percentile for self-signed cert + // env CITADEL_SELF_SIGNED_ROOT_CERT_GRACE_PERIOD_PERCENTILE + // default is 20% + // +optional + GracePeriod string `json:"gracePeriod,omitempty"` + // CheckPeriod is the interval with which certificate is checked for rotation + // env CITADEL_SELF_SIGNED_ROOT_CERT_CHECK_INTERVAL + // default is 1 hour, zero or negative value disables cert rotation + // +optional + CheckPeriod string `json:"checkPeriod,omitempty"` + // EnableJitter to use jitter for cert rotation + // env CITADEL_ENABLE_JITTER_FOR_ROOT_CERT_ROTATOR + // defaults to true + // +optional + EnableJitter *bool `json:"enableJitter,omitempty"` + // Org is the Org value in the certificate. + // XXX: currently uses TrustDomain. I don't think this is configurable. + // +optional + // Org string `json:"org,omitempty"` +} + +// IstioPrivateKeyCertificateSignerConfig is the configuration when using a user +// supplied private key/cert for signing. +// XXX: nothing in here is currently configurable, except RootCADir +type IstioPrivateKeyCertificateSignerConfig struct { + // hard coded to use a secret named cacerts + // +optional + // EncryptionSecret string `json:"encryptionSecret,omitempty"` + // ROOT_CA_DIR, defaults to /etc/cacerts + // Mount directory for encryption secret + // XXX: currently, not configurable in the charts + // +optional + RootCADir string `json:"rootCADir,omitempty"` + // hard coded to ca-key.pem + // +optional + // SigningKeyFile string `json:"signingKeyFile,omitempty"` + // hard coded to ca-cert.pem + // +optional + // SigningCertFile string `json:"signingCertFile,omitempty"` + // hard coded to root-cert.pem + // +optional + // RootCertFile string `json:"rootCertFile,omitempty"` + // hard coded to cert-chain.pem + // +optional + // CertChainFile string `json:"certChainFile,omitempty"` +} + +// CustomCertificateAuthorityConfig is the configuration for a custom +// certificate authority. +type CustomCertificateAuthorityConfig struct { + // Address is the grpc address for an Istio compatible certificate authority endpoint. + // .Values.global.caAddress + // XXX: assumption is this is a grpc endpoint that provides methods like istio.v1.auth.IstioCertificateService/CreateCertificate + Address string `json:"address,omitempty"` +} + +type CertManagerCertificateAuthorityConfig struct { + // Address is the grpc address for an Istio compatible certificate authority endpoint. + // .Values.global.caAddress + Address string `json:"address,omitempty"` + PilotCertSecretName string `json:"pilotSecretName,omitempty"` + RootCAConfigMapName string `json:"rootCAConfigMapName,omitempty"` +} + +func (c *CertManagerCertificateAuthorityConfig) GetRootCAConfigMapName() string { + if c.RootCAConfigMapName == "" { + return "istio-ca-root-cert" + } + return c.RootCAConfigMapName +} + +// IdentityConfig configures the types of user tokens used by clients +type IdentityConfig struct { + // Type is the type of identity tokens being used. + // .Values.global.jwtPolicy + Type IdentityConfigType `json:"type,omitempty"` + // ThirdParty configures istiod to use a third-party token provider for + // identifying users. (basically uses a custom audience, e.g. istio-ca) + // XXX: this is only supported on OCP 4.4+ + // +optional + ThirdParty *ThirdPartyIdentityConfig `json:"thirdParty,omitempty"` +} + +// IdentityConfigType represents the identity implementation being used. +type IdentityConfigType string + +const ( + // IdentityConfigTypeKubernetes specifies Kubernetes as the token provider. + IdentityConfigTypeKubernetes IdentityConfigType = "Kubernetes" // first-party-jwt + // IdentityConfigTypeThirdParty specifies a third-party token provider. + IdentityConfigTypeThirdParty IdentityConfigType = "ThirdParty" // third-party-jwt +) + +// ThirdPartyIdentityConfig configures a third-party token provider for use with +// istiod. +type ThirdPartyIdentityConfig struct { + // TokenPath is the path to the token used to identify the workload. + // default /var/run/secrets/tokens/istio-token + // XXX: projects service account token with specified audience (istio-ca) + // XXX: not configurable + // +optional + // TokenPath string `json:"tokenPath,omitempty"` + + // Issuer is the URL of the issuer. + // env TOKEN_ISSUER, defaults to iss in specified token + // only supported in 1.6+ + // +optional + Issuer string `json:"issuer,omitempty"` + // Audience is the audience for whom the token is intended. + // env AUDIENCE + // .Values.global.sds.token.aud, defaults to istio-ca + // +optional + Audience string `json:"audience,omitempty"` +} + +// ControlPlaneSecurityConfig is the mutual TLS configuration specific to the +// control plane. +type ControlPlaneSecurityConfig struct { + // Enable mutual TLS for the control plane components. + // .Values.global.controlPlaneSecurityEnabled + // +optional + MTLS *bool `json:"mtls,omitempty"` + // CertProvider is the certificate authority used to generate the serving + // certificates for the control plane components. + // .Values.global.pilotCertProvider + // Provider used to generate serving certs for istiod (pilot) + // +optional + CertProvider ControlPlaneCertProviderType `json:"certProvider,omitempty"` + + // TLS configures aspects of TLS listeners created by control plane components. + // +optional + TLS *ControlPlaneTLSConfig `json:"tls,omitempty"` +} + +// DataPlaneSecurityConfig is the mutual TLS configuration specific to the +// control plane. +type DataPlaneSecurityConfig struct { + // Enable mutual TLS by default. + // .Values.global.mtls.enabled + MTLS *bool `json:"mtls,omitempty"` + // Auto configures the mesh to automatically detect whether or not mutual + // TLS is required for a specific connection. + // .Values.global.mtls.auto + // +optional + AutoMTLS *bool `json:"automtls,omitempty"` +} + +// ControlPlaneCertProviderType represents the provider used to generate serving +// certificates for the control plane. +type ControlPlaneCertProviderType string + +const ( + // ControlPlaneCertProviderTypeIstiod identifies istiod as the provider generating the serving certifications. + ControlPlaneCertProviderTypeIstiod ControlPlaneCertProviderType = "Istiod" + // ControlPlaneCertProviderTypeKubernetes identifies Kubernetes as the provider generating the serving certificates. + ControlPlaneCertProviderTypeKubernetes ControlPlaneCertProviderType = "Kubernetes" + // ControlPlaneCertProviderTypeCustom identifies a custom provider has generated the serving certificates. + // XXX: Not quite sure what this means. Presumably, the key and cert chain have been mounted specially + ControlPlaneCertProviderTypeCustom ControlPlaneCertProviderType = "Custom" +) + +// ControlPlaneTLSConfig configures settings on TLS listeners created by +// control plane components, e.g. webhooks, grpc (if mtls is enabled), etc. +type ControlPlaneTLSConfig struct { + // CipherSuites configures the cipher suites that are available for use by + // TLS listeners. + // .Values.global.tls.cipherSuites + // +optional + CipherSuites []string `json:"cipherSuites,omitempty"` + // ECDHCurves configures the ECDH curves that are available for use by + // TLS listeners. + // .Values.global.tls.ecdhCurves + // +optional + ECDHCurves []string `json:"ecdhCurves,omitempty"` + // MinProtocolVersion the minimum TLS version that should be supported by + // the listeners. + // .Values.global.tls.minProtocolVersion + // +optional + MinProtocolVersion string `json:"minProtocolVersion,omitempty"` + // MaxProtocolVersion the maximum TLS version that should be supported by + // the listeners. + // .Values.global.tls.maxProtocolVersion + // +optional + MaxProtocolVersion string `json:"maxProtocolVersion,omitempty"` +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/servicemeshcontrolplane_types.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/servicemeshcontrolplane_types.go new file mode 100644 index 0000000000..e451a7898b --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/servicemeshcontrolplane_types.go @@ -0,0 +1,204 @@ +package v2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/maistra/istio-operator/pkg/apis/maistra/status" + v1 "github.com/maistra/istio-operator/pkg/apis/maistra/v1" +) + +const ( + ControlPlaneModeKey = "controlPlaneMode" + ControlPlaneModeValueClusterScoped = "ClusterScoped" + ControlPlaneModeValueMultiTenant = "MultiTenant" +) + +func init() { + SchemeBuilder.Register(&ServiceMeshControlPlane{}, &ServiceMeshControlPlaneList{}) +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshControlPlane is the Schema for the controlplanes API +// +k8s:openapi-gen=true +// +kubebuilder:storageversion +// +kubebuilder:resource:shortName=smcp,categories=maistra-io +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.annotations.readyComponentCount",description="How many of the total number of components are ready" +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].reason",description="Whether or not the control plane installation is up to date and ready to handle requests." +// +kubebuilder:printcolumn:name="Profiles",type="string",JSONPath=".status.appliedSpec.profiles",description="The configuration profiles applied to the configuration." +// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".status.chartVersion",description="The actual current version of the control plane installation." +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the object" +// +kubebuilder:printcolumn:name="Image Registry",type="string",JSONPath=".status.appliedSpec.runtime.defaults.container.registry",description="The image registry used as the base for all component images.",priority=1 +type ServiceMeshControlPlane struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // The specification of the desired state of this ServiceMeshControlPlane. + // This includes the configuration options for all components that comprise + // the control plane. + // +kubebuilder:validation:Required + Spec ControlPlaneSpec `json:"spec"` + + // The current status of this ServiceMeshControlPlane and the components + // that comprise the control plane. This data may be out of date by some + // window of time. + // +optional + Status ControlPlaneStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshControlPlaneList contains a list of ServiceMeshControlPlane +type ServiceMeshControlPlaneList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ServiceMeshControlPlane `json:"items"` +} + +// ControlPlaneStatus defines the observed state of ServiceMeshControlPlane +// ControlPlaneStatus represents the current state of a ServiceMeshControlPlane. +type ControlPlaneStatus struct { + status.StatusBase `json:",inline"` + + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file + status.StatusType `json:",inline"` + + // The generation observed by the controller during the most recent + // reconciliation. The information in the status pertains to this particular + // generation of the object. + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + + // The version of the operator that last processed this resource. + OperatorVersion string `json:"operatorVersion,omitempty"` + + // The version of the charts that were last processed for this resource. + ChartVersion string `json:"chartVersion,omitempty"` + + // The list of components comprising the control plane and their statuses. + status.ComponentStatusList `json:",inline"` + + // The readiness status of components & owned resources + Readiness ReadinessStatus `json:"readiness"` + + // The resulting specification of the configuration options after all profiles + // have been applied. + // +optional + AppliedSpec ControlPlaneSpec `json:"appliedSpec,omitempty"` + + // The resulting values.yaml used to generate the charts. + // +optional + AppliedValues v1.ControlPlaneSpec `json:"appliedValues,omitempty"` +} + +// ReadinessStatus contains readiness information for each deployed component. +type ReadinessStatus struct { + // The readiness status of components + // +optional + Components ReadinessMap `json:"components,omitempty"` +} + +type ReadinessMap map[string][]string + +// GetReconciledVersion returns the reconciled version, or a default for older resources +func (s *ControlPlaneStatus) GetReconciledVersion() string { + if s == nil { + return status.ComposeReconciledVersion("0.0.0", 0) + } + return status.ComposeReconciledVersion(s.OperatorVersion, s.ObservedGeneration) +} + +// ControlPlaneSpec represents the configuration for installing a control plane +type ControlPlaneSpec struct { + // XXX: the resource name is intended to be used as the revision name, which + // is used by istio.io/rev labels/annotations to specify which control plane + // workloads should be connecting with. + + // Profiles selects the profile to use for default values. Defaults to + // "default" when not set. + // +optional + Profiles []string `json:"profiles,omitempty"` + + // Version specifies what Maistra version of the control plane to install. + // When creating a new ServiceMeshControlPlane with an empty version, the + // admission webhook sets the version to the current version. + // +optional + Version string `json:"version,omitempty"` + // Cluster is the general configuration of the cluster (cluster name, + // network name, multi-cluster, mesh expansion, etc.) + // +optional + Cluster *ControlPlaneClusterConfig `json:"cluster,omitempty"` + // General represents general control plane configuration that does not + // logically fit in another area. + // +optional + General *GeneralConfig `json:"general,omitempty"` + // Policy configures policy checking for the control plane. + // .Values.policy.enabled, true if not null + // +optional + Policy *PolicyConfig `json:"policy,omitempty"` + // Proxy configures the default behavior for sidecars. Many values were + // previously exposed through .Values.global.proxy + // +optional + Proxy *ProxyConfig `json:"proxy,omitempty"` + // Security configures aspects of security for the control plane. + // +optional + Security *SecurityConfig `json:"security,omitempty"` + // Telemetry configures telemetry for the mesh. + // .Values.mixer.telemetry.enabled, true if not null. 1.6, .Values.telemetry.enabled + // +optional + Telemetry *TelemetryConfig `json:"telemetry,omitempty"` + // Tracing configures tracing for the mesh. + // +optional + Tracing *TracingConfig `json:"tracing,omitempty"` + // Gateways configures gateways for the mesh + // .Values.gateways.* + // +optional + Gateways *GatewaysConfig `json:"gateways,omitempty"` + // Runtime configuration for pilot (and galley, etc., pre 2.0) + // +optional + Runtime *ControlPlaneRuntimeConfig `json:"runtime,omitempty"` + // Addons is used to configure additional features beyond core control plane + // components, e.g. visualization, metric storage, etc. + // +optional + Addons *AddonsConfig `json:"addons,omitempty"` + // TechPreview contains switches for features that are not GA yet. + // +optional + TechPreview *v1.HelmValues `json:"techPreview,omitempty"` +} + +// Enablement is a common definition for features that can be enabled +type Enablement struct { + // Enabled specifies whether or not this feature is enabled + Enabled *bool `json:"enabled,omitempty"` +} + +func (s ControlPlaneSpec) IsKialiEnabled() bool { + return s.Addons != nil && + s.Addons.Kiali != nil && + s.Addons.Kiali.Enabled != nil && + *s.Addons.Kiali.Enabled +} + +func (s ControlPlaneSpec) IsPrometheusEnabled() bool { + return s.Addons != nil && + s.Addons.Prometheus != nil && + s.Addons.Prometheus.Enabled != nil && + *s.Addons.Prometheus.Enabled +} + +func (s ControlPlaneSpec) IsGrafanaEnabled() bool { + return s.Addons != nil && s.Addons.Grafana != nil && s.Addons.Grafana.Enabled != nil && *s.Addons.Grafana.Enabled +} + +func (s ControlPlaneSpec) IsJaegerEnabled() bool { + return s.Tracing != nil && s.Tracing.Type == TracerTypeJaeger +} + +func (s ControlPlaneSpec) IsClusterScoped() (bool, error) { + controlPlaneMode, _, err := s.TechPreview.GetString(ControlPlaneModeKey) + if err != nil { + return false, err + } + return controlPlaneMode == ControlPlaneModeValueClusterScoped, nil +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/smcp_new.yaml b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/smcp_new.yaml new file mode 100644 index 0000000000..d33892184f --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/smcp_new.yaml @@ -0,0 +1,485 @@ +spec: + template: default + version: v2.1 + cluster: + name: Kubernetes + network: main + multiCluster: # null to disable multi-cluster + meshNetworks: {} + # local cluster network is added automatically by default, e.g. + # main + # endpoints: + # - fromRegistry: Kubernetes + # gateways: + # - service: istio-ingressgateway.istio-system.svc.cluster.local + # port: 443 + ingress: false + # not sure if this should be under multiCluster or not + meshExpansion: # null to disable mesh expansion, note meshExpansion is enabled if multiCluster is configured + ilbGateway: # if null, ingress gateway will be used for expansion and expansion ports will be added to it automatically + # these apply to all gateway definitions, with the following exceptions for ILB gateway: + # * service.type is forced to be LoadBalancer, regardless of user setting + # * mesh expansion ports are added automatically to service.ports + namespace: istio-system # install namespace is default + routerMode: sni-dnat # default + requestedNetworkView: [] # "external" added to egress gateway if multiCluster is enabled + sds: + enabled: false # default + runtime: + resources: {} + # this is corev1.ServiceSpec. not sure if we should create our own, pruning unapplied fields + service: + metadata: + annotations: + cloud.google.com/load-balancer-type: "internal" # default for istio-ilbgateway, from gateways/values.yaml + labels: {} # additional labels. applied to selector + type: LoadBalancer # default is ClusterIP for other gateways. LoadBalancer cannot be overriden for ILB gateway + loadBalancerIP: "" # if any + loadBalancerSourceRanges: [] # if any + externalTrafficPolicy: "" # if any + externalIPs: [] # if any + ports: [] # additional corev1.ServicePort definitions + runtime: + # this applies to most components (i.e. if you see runtime: all these settings will be available) + deployment: + replicas: 1 # default + strategy: + type: RollingUpdate # default, only type supported (i.e. charts apply this setting) + rollingUpdate: + maxUnavailable: 25% # default in values.yaml + maxSurge: 100% # default in values.yaml + autoScaling: # defaults to null, no autoscaling + minReplicas: 1 # default in values.yaml + maxReplicas: 5 # default in values.yaml + targetCPUUtilizationPercentage: 80 # default in values.yaml + pod: + metadata: + annotations: {} # maps to podAnnotations + nodeSelector: {} + tolerations: {} + priorityClassName: "" # i think this can only be applied globally, not per component/deployment + affinity: {} + container: + # container definition also includes image, imagePullPolicy, + # imageRegistry, imageTag, imagePullSecrets, but the following are + # only supported for gateways + resources: {} # limits and requirements for istio-proxy container + volumes: + - volume: + name: some-extra-secret + secret: + secretName: some-secret + mount: + name: some-extra-secret-mount + mountPath: /path/to/secret/files + - volume: # note, config maps are currently not mounted, but can be specified. not sure if this is a bug in the charts + name: some-extra-configmap + configMap: + name: some-configmap + mount: + name: some-extra-configmap-mount + mountPath: /path/to/configmap/files + + + # this would apply to control plane components + general: + logging: + componentLevels: {} + # misc: error + logAsJSON: false + + validationMessages: true + + policy: + type: Istiod # or Mixer or Remote, Mixer is default for pre v2.0 + # one of the following. if omitted, will default to whatever settings are in values.yaml + mixer: # legacy v1 + enableChecks: false # default + failOpen: false # default + sessionAffinity: true + adapters: + useAdapterCRDs: false + kubernetesenv: true + # or + remote: + address: my-remote-policy.example.com + createServices: false # applies to both mixer policy and telemetry, i.e. no separate setting for each + enableChecks: false + failOpen: false + # or v2 + istiod: {} + + telemetry: + type: Istiod # or Mixer or Remote + # one of the following + mixer: # legacy v1 + sessionAffinity: false + batching: + maxEntries: 100 + maxTime: 1s + loadshedding: + mode: enforce + latencyThreshold: 100ms + adapters: + useAdapterCRDs: false # i think this should be removed, as it's not available in istio 1.1, and has been removed from 1.4+ + kubernetesenv: true + stdio: + outputAsJSON: false + # or + remote: + address: my-remote-telemetry.example.com + createServices: false # also applies to policy, as mentioned above + sessionAffinity: false + batching: + maxEntries: 100 + maxTime: 1s + # no config if using istiod + + tracing: + type: Jaeger # or Stackdriver, following not yet configurable: Zipkin, Lightstep, Datadog + sampling: 10000 # scaled integer, 0-100% in 0.01% increments, i.e. 1=.001%, 100=1%, 10000=100% + + proxy: + autoInject: true + adminPort: 15000 + concurrency: 0 + # this would apply only to proxies + logging: + level: info + componentLevel: {} + # misc: error + networking: + clusterDomain: cluster.local + connectionTimeout: 10s + maxConnectionAge: 30m + injection: + autoInject: true + alwaysInjectSelector: [] # label selector + neverInjectSelector: [] # label selector + injectedAnnotations: {} # string:string, annotations to be added to injected pods + trafficControl: + inbound: + interceptionMode: REDIRECT + includedPorts: + - "*" + excludedPorts: [] + outbound: + includedIPRanges: [] + excludedIPRanges: [] + excludedPorts: [] + policy: ALLOW_ANY + protocol: + autoDetect: + timeout: 100ms + inbound: false + outbound: false + dns: + refreshRate: 300s + searchSuffixes: [ + # the following are added automatically, if multiCluster is enabled + # "global", + # "{{ valueOrDefault .DeploymentMeta.Namespace \"istio-system\" }}.global", + ] + initialization: + type: CNI # or InitContainer + initContainer: + runtime: + image: proxy-init + imageRegistry: registry.redhat.io + imageTag: "2.0" + imagePullPolicy: Always + imagePullSecrets: [] + resources: {} + accessLogging: + # both may be specified + file: + name: /dev/stdout # file name + encoding: TEXT # TEXT or JSON + format: cutom-format # format for log messages + envoySerivce: + enabled: false + address: accesslog-service.istio-system:15000 + tlsSettings: + mode: DISABLE # DISABLE, SIMPLE, MUTUAL, ISTIO_MUTUAL + clientCertificate: # example: /etc/istio/als/cert-chain.pem + privateKey: # example: /etc/istio/als/key.pem + caCertificates: # example: /etc/istio/als/root-cert.pem + sni: # example: als.somedomain + subjectAltNames: [] + # - als.somedomain + tcpKeepalive: + probes: 3 + time: 10s + interval: 10s + envoyMetricsService: + enabled: false + address: metrics-service.istio-system:15000 + tlsSettings: + mode: DISABLE # DISABLE, SIMPLE, MUTUAL, ISTIO_MUTUAL + clientCertificate: # example: /etc/istio/ms/cert-chain.pem + privateKey: # example: /etc/istio/ms/key.pem + caCertificates: # example: /etc/istio/ms/root-cert.pem + sni: # example: ms.somedomain + subjectAltNames: [] + # - ms.somedomain + tcpKeepalive: + probes: 3 + time: 10s + interval: 10s + runtime: + readiness: + rewriteApplicationProbes: false + statusPort: 15020 + initialDelaySeconds: 1 + periodSeconds: 2 + failureThreshold: 30 + container: + imageName: proxyv2 + resources: {} # requirements and limits + + security: + trust: + domain: cluster.local + additionalDomains: [some-other.cluster] + certificateAuthority: + workloadCertTTLDefault: 24h + workloadCertTTLMax: 90d + type: Istiod # or Custom + # one of the following + istiod: + type: SelfSigned # or PrivateKey + # one of the following + selfSigned: + ttl: 10y + gracePeriod: 20% + checkPeriod: 1h + enableJitter: true + org: cluster.local # XXX: there is overlap between this and security.trust.domain. this isn't used, so should probably be removed + # or + privateKey: + encryptionSecret: cacerts # currently not configurable + rootCADir: /etc/cacerts + signingKeyFile: ca-key.pem # currently not configurable + signingCertFile: ca-cert.pem # currently not configurable + rootCertFile: root-cert.pem # currently not configurable + certChainFile: cert-chain.pem # currently not configurable + # or + custom: # i have no idea about this + address: some.location.domain + identity: # specifies how service tokens are verified + type: Kubernetes # or ThirdParty + # one of + kubernetes: {} # local k8s token review + # or + thirdParty: # simply mounts service account token to a different directory with a specified audience + tokenPath: /var/run/secrets/tokens/istio-token # currently not configurable + issuer: "" # uses token's iss by default + audience: istio-ca + controlPlane: + mtls: true # enable mtls for control plane + certProvider: Istiod # or Kubernetes or Custom, who's providing the serving cert for the control plane + tls: + cipherSuites: [] + ecdhCurves: [] + minProtocolVersion: TLSv1_2 + maxProtocolVersion: TLSv1_3 + dataPlane: + mlts: true # enable mtls for data plane + automtls: true + manageNetworkPolicy: true # manages network policies that allows communication between namespace members and control plane + # JWKSResolver extra CA + jwksResolverCA: "" # PEM-encoded certificate content to trust an additional CA + gateways: + ingress: # _the_ istio-ingressgateway + # same settings as ilb gateway above + service: + type: ClusterIP + ports: + - name: status-port + port: 15020 + - name: http2 + port: 80 + targetPort: 8080 + - name: https + port: 443 + targetPort: 8443 + meshExpansionPorts: [] # additional expansion ports. default expansion ports will be added automatically if multiCluster is configured + routeConfig: # specifies whether to create an OpenShift Route for istio-ingressgateway + enabled: true + egress: # _the_ istio-egressgateway + service: + type: ClusterIP + ports: + - name: status-port + port: 15020 + - name: http2 + port: 80 + targetPort: 8080 + - name: https + port: 443 + targetPort: 8443 + # requestedNetworkView: [external] set automatically if multi-cluster is enabled + additionalIngress: + some-other-ingress-gateway: {} + additionalEgress: + some-other-egress-gateway: {} + openshiftRoute: # configures the Gateway ↔ OpenShift Route integration + enabled: true + + runtime: + components: + # component specific overrides + pilot: # same as gateway.runtime structure illustrated above + deployment: + replicas: 2 + pod: + affinity: {} + container: + imageName: my-pilot + env: + SOME_ENV: some-value + resources: + limits: {} + requirements: {} + security: {} # for configuring citadel,, similar to pilot above + galley: {} # similar to pilot above + mixer: {} # v1.x mixer, similar to pilot above + mixer.policy: {} # v2.x mixer policy, similar to pilot above + mixer.telemetry: {} # v2.x mixer telemetry, similar to pilot above + sidecarInjectorWebhook: {} # similar to pilot above + tracing: {} # similar to pilot above + tracing.jaeger: {} # similar to pilot above + tracing.jaeger.elasticsearch: {} # similar to pilot above + tracing.jaeger.agent: {} # similar to pilot above + tracing.jaeger.allInOne: {} # similar to pilot above + tracing.jaeger.collector: {} # similar to pilot above + tracing.jaeger.query: {} # similar to pilot above + kiali: {} # similar to pilot above + grafana: {} # similar to pilot above + prometheus: {} # similar to pilot above + # default runtime settings + defaults: # merged into any component specific overrides. component specific overrides take precedence + deployment: {} # similar to gateway.runtime.deployment + pod: + nodeSelector: {} + tolerations: {} + priorityClassName: "" + container: + imageRegistry: registry.redhat.io # old global.hub + imageTag: "2.0" # old global.tag + imagePullPolicy: Always + imagePullSecrets: + - name: registry-token-secret + resources: # old global.defaultResources + limits: {} + requirements: {} + + addons: + prometheus: + enabled: true + scrape: true # configure scraping of telemetry by prometheus + metricsExpiryDuration: 10m + address: some-url-to-prometheus # specify this or install (i'm not sure if we can support this or not) + install: # install prometheus, as opposed to using an existing install at address + selfManaged: true # use prometheus CR, maybe poor naming? + retention: 6h + scrapeInterval: 15s + useTLS: true # .Values.prometheus.security.enabled, i don't think this applies to us + service: + metadata: {} + nodePort: null # use node port if not null + ingress: # enables Ingress/Route if not null + contextPath: /prometheus + tls: # raw yaml, so it can be used with both Route and Ingress resources + termination: reencrypt + + jaeger: + name: jaeger # name of Jaeger CR to reference/create + install: # create a jaeger CR if it doesn't already exist + storage: + type: Memory # or Elasticsearch + memory: # implies tracing.jaeger.template=all-in-one + maxTraces: 100000 + # or + elasticSearch: # implies tracing.jaeger.template=production-elasticsearch + nodeCount: 3 + storage: {} # raw jaeger config, .Values.tracing.jaeger.elasticsearch.storage + redundancyPolicy: {} # raw jaeger config, .Values.tracing.jaeger.elasticsearch.redundancyPolicy + indexCleaner: {} # raw jaeger config, .Values.tracing.jaeger.elasticsearch.esIndexCleaner + runtime: {} # .Values.tracing.jaeger.elasticsearch. + ingress: # configure Ingress/Route if not null + metadata: + labels: {} + annotations: {} + grafana: + address: some-grafana-url # use existing grafana install, or... + install: # install grafana if not null + selfManaged: true # use grafana CR, maybe poor naming? + config: + env: {} # .Values.grafana.env + envSecrets: {} # .Values.grafana.envSecrets + persistence: + storageClassName: "" + accessMode: ReadWriteOnce + capacity: 5Gi # not supported in charts + service: # similar to addons.tracing.jaeger.install.config.service + ingress: + contextPath: /grafana + tls: + termination: reencrypt + kiali: + name: kiali # kiali CR to create/reference + install: # install kiali CR if not present + dashboard: + viewOnly: false + # not sure if the following should be supported or just based on other addon config + enableGrafana: true + enableTracing: true + enablePrometheus: true + service: # similar to addons.tracing.jaeger.install.config.service + ingress: + contextPath: /kiali + 3scale: + enabled: false + listen_addr: 3333 + log_grpc: false + log_json: true + log_level: info + metrics: + port: 8080 + report: true + system: + cache_max_size: 1000 + cache_refresh_retries: 1 + cache_refresh_interval: 180 + cache_ttl: 300 + client: + allow_insecure_connections: false + timeout: 10 + grpc: + max_conn_timeout: 60 + backend: + enable_cache: false + cache_flush_interval: 15 + policy_fail_closed: true + stackdriver: + telemetry: + enabled: false + enableContextGraph: false + enableLogging: false + enableMetrics: false + accessLogging: + logWindowDuration: 12h + auth: + appCredentials: false + apiKey: "" + serviceAccountPath: "" + tracer: + # enables trace output to stdout. + debug: false + # The global default max number of attributes per span. + maxNumberOfAttributes: 200 + # The global default max number of annotation events per span. + maxNumberOfAnnotations: 200 + # The global default max number of message events per span. + maxNumberOfMessageEvents: 200 diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/stackdriver.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/stackdriver.go new file mode 100644 index 0000000000..353299b860 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/stackdriver.go @@ -0,0 +1,97 @@ +package v2 + +import ( + v1 "github.com/maistra/istio-operator/pkg/apis/maistra/v1" +) + +// StackdriverAddonConfig configuration specific to Stackdriver integration. +type StackdriverAddonConfig struct { + // Configuration for Stackdriver tracer. Applies when Addons.Tracer.Type=Stackdriver + Tracer *StackdriverTracerConfig `json:"tracer,omitempty"` + // Configuration for Stackdriver telemetry plugins. Applies when telemetry + // is enabled + Telemetry *StackdriverTelemetryConfig `json:"telemetry,omitempty"` +} + +// StackdriverTracerConfig configures the Stackdriver tracer +type StackdriverTracerConfig struct { + // .Values.global.tracer.stackdriver.debug + // +optional + Debug *bool `json:"debug,omitempty"` + // .Values.global.tracer.stackdriver.maxNumberOfAttributes + // +optional + MaxNumberOfAttributes *int64 `json:"maxNumberOfAttributes,omitempty"` + // .Values.global.tracer.stackdriver.maxNumberOfAnnotations + // +optional + MaxNumberOfAnnotations *int64 `json:"maxNumberOfAnnotations,omitempty"` + // .Values.global.tracer.stackdriver.maxNumberOfMessageEvents + // +optional + MaxNumberOfMessageEvents *int64 `json:"maxNumberOfMessageEvents,omitempty"` +} + +// StackdriverTelemetryConfig adds telemetry filters for Stackdriver. +type StackdriverTelemetryConfig struct { + // Enable installation of Stackdriver telemetry filters (mixer or v2/envoy). + // These will only be installed if this is enabled an telemetry is enabled. + Enablement `json:",inline"` + // Auth configuration for stackdriver adapter (mixer/v1 telemetry only) + // .Values.mixer.adapters.stackdriver.auth + // +optional + Auth *StackdriverAuthConfig `json:"auth,omitempty"` + // EnableContextGraph for stackdriver adapter (edge reporting) + // .Values.mixer.adapters.stackdriver.contextGraph.enabled, defaults to false + // .Values.telemetry.v2.stackdriver.topology, defaults to false + // +optional + EnableContextGraph *bool `json:"enableContextGraph,omitempty"` + // EnableLogging for stackdriver adapter + // .Values.mixer.adapters.stackdriver.logging.enabled, defaults to true + // .Values.telemetry.v2.stackdriver.logging, defaults to false + // +optional + EnableLogging *bool `json:"enableLogging,omitempty"` + // EnableMetrics for stackdriver adapter + // .Values.mixer.adapters.stackdriver.metrics.enabled, defaults to true + // .Values.telemetry.v2.stackdriver.monitoring??? defaults to false + // +optional + EnableMetrics *bool `json:"enableMetrics,omitempty"` + // DisableOutbound disables intallation of sidecar outbound filter + // .Values.telemetry.v2.stackdriver.disableOutbound, defaults to false + // +optional + // DisableOutbound bool `json:"disableOutbound,omitempty"` + // AccessLogging configures access logging for stackdriver + AccessLogging *StackdriverAccessLogTelemetryConfig `json:"accessLogging,omitempty"` + // ConfigOverride apply custom configuration to Stackdriver filters (v2 + // telemetry only) + // .Values.telemetry.v2.stackdriver.configOverride + // +optional + ConfigOverride *v1.HelmValues `json:"configOverride,omitempty"` +} + +// StackdriverAuthConfig is the auth config for stackdriver. Only one field may be set +type StackdriverAuthConfig struct { + // AppCredentials if true, use default app credentials. + // .Values.mixer.adapters.stackdriver.auth.appCredentials, defaults to false + // +optional + AppCredentials *bool `json:"appCredentials,omitempty"` + // APIKey use the specified key. + // .Values.mixer.adapters.stackdriver.auth.apiKey + // +optional + APIKey string `json:"apiKey,omitempty"` + // ServiceAccountPath use the path to the service account. + // .Values.mixer.adapters.stackdriver.auth.serviceAccountPath + // +optional + ServiceAccountPath string `json:"serviceAccountPath,omitempty"` +} + +// StackdriverAccessLogTelemetryConfig for v2 telemetry. +type StackdriverAccessLogTelemetryConfig struct { + // Enable installation of access log filter. + // .Values.telemetry.v2.accessLogPolicy.enabled + Enablement `json:",inline"` + // LogWindowDuration configures the log window duration for access logs. + // defaults to 43200s + // To reduce the number of successful logs, default log window duration is + // set to 12 hours. + // .Values.telemetry.v2.accessLogPolicy.logWindowDuration + // +optional + LogWindowDuration string `json:"logWindowDuration,omitempty"` +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/telemetry.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/telemetry.go new file mode 100644 index 0000000000..eaf5597cca --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/telemetry.go @@ -0,0 +1,119 @@ +package v2 + +// TelemetryConfig for the mesh +type TelemetryConfig struct { + // Type of telemetry implementation to use. + Type TelemetryType `json:"type,omitempty"` + // Mixer represents legacy, v1 telemetry. + // implies .Values.telemetry.v1.enabled, if not null + // +optional + Mixer *MixerTelemetryConfig `json:"mixer,omitempty"` + // Remote represents a remote, legacy, v1 telemetry. + // +optional + Remote *RemoteTelemetryConfig `json:"remote,omitempty"` +} + +// TelemetryType represents the telemetry implementation used. +type TelemetryType string + +const ( + // TelemetryTypeNone disables telemetry + TelemetryTypeNone TelemetryType = "None" + // TelemetryTypeMixer represents mixer telemetry, v1 + TelemetryTypeMixer TelemetryType = "Mixer" + // TelemetryTypeRemote represents remote mixer telemetry server, v1 + TelemetryTypeRemote TelemetryType = "Remote" + // TelemetryTypeIstiod represents istio, v2 + TelemetryTypeIstiod TelemetryType = "Istiod" +) + +// MixerTelemetryConfig is the configuration for legacy, v1 mixer telemetry. +// .Values.telemetry.v1.enabled +type MixerTelemetryConfig struct { + // SessionAffinity configures session affinity for sidecar telemetry connections. + // .Values.mixer.telemetry.sessionAffinityEnabled, maps to MeshConfig.sidecarToTelemetrySessionAffinity + // +optional + SessionAffinity *bool `json:"sessionAffinity,omitempty"` + // Loadshedding configuration for telemetry + // .Values.mixer.telemetry.loadshedding + // +optional + Loadshedding *TelemetryLoadSheddingConfig `json:"loadshedding,omitempty"` + // Batching settings used when sending telemetry. + // +optional + Batching *TelemetryBatchingConfig `json:"batching,omitempty"` + // Adapters configures the adapters used by mixer telemetry. + // +optional + Adapters *MixerTelemetryAdaptersConfig `json:"adapters,omitempty"` +} + +// TelemetryLoadSheddingConfig configures how mixer telemetry loadshedding behaves +type TelemetryLoadSheddingConfig struct { + // Mode represents the loadshedding mode applied to mixer when it becomes + // overloaded. Valid values: disabled, logonly or enforce + // .Values.mixer.telemetry.loadshedding.mode + // +optional + Mode string `json:"mode,omitempty"` + // LatencyThreshold -- + // .Values.mixer.telemetry.loadshedding.latencyThreshold + // +optional + LatencyThreshold string `json:"latencyThreshold,omitempty"` +} + +// TelemetryBatchingConfig configures how telemetry data is batched. +type TelemetryBatchingConfig struct { + // MaxEntries represents the maximum number of entries to collect before sending them to mixer. + // .Values.mixer.telemetry.reportBatchMaxEntries, maps to MeshConfig.reportBatchMaxEntries + // Set reportBatchMaxEntries to 0 to use the default batching behavior (i.e., every 100 requests). + // A positive value indicates the number of requests that are batched before telemetry data + // is sent to the mixer server + // +optional + MaxEntries *int32 `json:"maxEntries,omitempty"` + // MaxTime represents the maximum amount of time to hold entries before sending them to mixer. + // .Values.mixer.telemetry.reportBatchMaxTime, maps to MeshConfig.reportBatchMaxTime + // Set reportBatchMaxTime to 0 to use the default batching behavior (i.e., every 1 second). + // A positive time value indicates the maximum wait time since the last request will telemetry data + // be batched before being sent to the mixer server + // +optional + MaxTime string `json:"maxTime,omitempty"` +} + +// MixerTelemetryAdaptersConfig is the configuration for mixer telemetry adapters. +type MixerTelemetryAdaptersConfig struct { + // UseAdapterCRDs specifies whether or not mixer should support deprecated CRDs. + // .Values.mixer.adapters.useAdapterCRDs, removed in istio 1.4, defaults to false + // XXX: i think this can be removed completely + // +optional + UseAdapterCRDs *bool `json:"useAdapterCRDs,omitempty"` + // KubernetesEnv enables support for the kubernetesenv adapter. + // .Values.mixer.adapters.kubernetesenv.enabled, defaults to true + // +optional + KubernetesEnv *bool `json:"kubernetesenv,omitempty"` + // Stdio enables and configures the stdio adapter. + // +optional + Stdio *MixerTelemetryStdioConfig `json:"stdio,omitempty"` +} + +// MixerTelemetryStdioConfig configures the stdio adapter for mixer telemetry. +type MixerTelemetryStdioConfig struct { + // .Values.mixer.adapters.stdio.enabled + Enablement `json:",inline"` + // OutputAsJSON if true. + // .Values.mixer.adapters.stdio.outputAsJson, defaults to false + // +optional + OutputAsJSON *bool `json:"outputAsJSON,omitempty"` +} + +// RemoteTelemetryConfig configures a remote, legacy, v1 mixer telemetry. +// .Values.telemetry.v1.enabled true +type RemoteTelemetryConfig struct { + // Address is the address of the remote telemetry server + // .Values.global.remoteTelemetryAddress, maps to MeshConfig.mixerReportServer + Address string `json:"address,omitempty"` + // CreateService for the remote server. + // .Values.global.createRemoteSvcEndpoints + // +optional + CreateService *bool `json:"createService,omitempty"` + // Batching settings used when sending telemetry. + // +optional + Batching *TelemetryBatchingConfig `json:"batching,omitempty"` +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/threescale.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/threescale.go new file mode 100644 index 0000000000..890e48a951 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/threescale.go @@ -0,0 +1,130 @@ +package v2 + +// ThreeScaleAddonConfig represents configuration options for the installation of the +// 3scale adapter. The options are structured similarly to what is defined by +// the 3scale ConfigMap. +type ThreeScaleAddonConfig struct { + Enablement `json:",inline"` + + // ListenerAddr sets the listen address for the gRPC server. + // PARAM_THREESCALE_LISTEN_ADDR + // +optional + ListenAddr *int32 `json:"listen_addr,omitempty"` + // LogGRPC controls whether the log includes gRPC info + // PARAM_THREESCALE_LOG_GRPC + // +optional + LogGRPC *bool `json:"log_grpc,omitempty"` + // LogJSON controls whether the log is formatted as JSON + // PARAM_THREESCALE_LOG_JSON + // +optional + LogJSON *bool `json:"log_json,omitempty"` + // LogLevel sets the minimum log output level. Accepted values are one of: + // debug, info, warn, error, none + // PARAM_THREESCALE_LOG_LEVEL + // +optional + LogLevel string `json:"log_level,omitempty"` + + // Metrics configures metrics specific details + // +optional + Metrics *ThreeScaleMetricsConfig `json:"metrics,omitempty"` + + // System configures system specific details + // +optional + System *ThreeScaleSystemConfig `json:"system,omitempty"` + + // Client configures client specific details + // +optional + Client *ThreeScaleClientConfig `json:"client,omitempty"` + + // GRPC configures gRPC specific details + // +optional + GRPC *ThreeScaleGRPCConfig `json:"grpc,omitempty"` + + // Backend configures backend specific details + // +optional + Backend *ThreeScaleBackendConfig `json:"backend,omitempty"` +} + +// ThreeScaleMetricsConfig represents 3scale adapter options for its 'metrics' +// section. +type ThreeScaleMetricsConfig struct { + // Port sets the port which 3scale /metrics endpoint can be scrapped from + // PARAM_THREESCALE_METRICS_PORT + // +optional + Port *int32 `json:"port,omitempty"` + // Report controls whether 3scale system and backend metrics are collected + // and reported to Prometheus + // PARAM_THREESCALE_REPORT_METRICS + // +optional + Report *bool `json:"report,omitempty"` +} + +// ThreeScaleSystemConfig represents 3scale adapter options for its 'system' +// section. +type ThreeScaleSystemConfig struct { + // CacheMaxSize is the max number of items that can be stored in the cache + // at any time. Set to 0 to disable caching + // PARAM_THREESCALE_CACHE_ENTRIES_MAX + // +optional + CacheMaxSize *int64 `json:"cache_max_size,omitempty"` + // CacheRefreshRetries sets the number of times unreachable hosts will be + // retried during a cache update loop + // PARAM_THREESCALE_CACHE_REFRESH_RETRIES + // +optional + CacheRefreshRetries *int32 `json:"cache_refresh_retries,omitempty"` + // CacheRefreshInterval is the time period in seconds, before a background + // process attempts to refresh cached entries + // PARAM_THREESCALE_CACHE_REFRESH_SECONDS + // +optional + CacheRefreshInterval *int32 `json:"cache_refresh_interval,omitempty"` + // CacheTTL is the time period, in seconds, to wait before purging expired + // items from the cache + // PARAM_THREESCALE_CACHE_TTL_SECONDS + // +optional + CacheTTL *int32 `json:"cache_ttl,omitempty"` +} + +// ThreeScaleClientConfig represents 3scale adapter options for its 'client' +// section. +type ThreeScaleClientConfig struct { + // AllowInsecureConnections skips certificate verification when calling + // 3scale API's. Enabling is not recommended + // PARAM_THREESCALE_ALLOW_INSECURE_CONN + // +optional + AllowInsecureConnections *bool `json:"allow_insecure_connections,omitempty"` + // Timeout sets the number of seconds to wait before terminating requests + // to 3scale System and Backend + // PARAM_THREESCALE_CLIENT_TIMEOUT_SECONDS + // +optional + Timeout *int32 `json:"timeout,omitempty"` +} + +// ThreeScaleGRPCConfig represents 3scale adapter options for its 'grpc' +// section. +type ThreeScaleGRPCConfig struct { + // MaxConnTimeout sets the maximum amount of seconds (+/-10% jitter) a + // connection may exist before it will be closed + // PARAM_THREESCALE_GRPC_CONN_MAX_SECONDS + // +optional + MaxConnTimeout *int32 `json:"max_conn_timeout,omitempty"` +} + +// ThreeScaleBackendConfig represents 3scale adapter options for its 'backend' +// section. +type ThreeScaleBackendConfig struct { + // EnableCache if true, attempts to create an in-memory apisonator cache for + // authorization requests + // PARAM_THREESCALE_USE_CACHED_BACKEND + // +optional + EnableCache *bool `json:"enable_cache,omitempty"` + // CacheFlushInterval sets the interval at which metrics get reported from + // the cache to 3scale + // PARAM_THREESCALE_BACKEND_CACHE_FLUSH_INTERVAL_SECONDS + // +optional + CacheFlushInterval *int32 `json:"cache_flush_interval,omitempty"` + // PolicyFailClosed if true, request will fail if 3scale Apisonator is + // unreachable + // PARAM_THREESCALE_BACKEND_CACHE_POLICY_FAIL_CLOSED + // +optional + PolicyFailClosed *bool `json:"policy_fail_closed,omitempty"` +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/tracing.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/tracing.go new file mode 100644 index 0000000000..290bc46932 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/tracing.go @@ -0,0 +1,31 @@ +package v2 + +// TracingConfig configures tracing solutions for the mesh. +// .Values.global.enableTracing +type TracingConfig struct { + // Type represents the type of tracer to be installed. + Type TracerType `json:"type,omitempty"` + // Sampling sets the mesh-wide trace sampling percentage. Should be between + // 0.0 - 100.0. Precision to 0.01, scaled as 0 to 10000, e.g.: 100% = 10000, + // 1% = 100 + // .Values.pilot.traceSampling + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=10000 + // +optional + Sampling *int32 `json:"sampling,omitempty"` +} + +// TracerType represents the tracer type to use +type TracerType string + +const ( + // TracerTypeNone is used to represent no tracer + TracerTypeNone TracerType = "None" + // TracerTypeJaeger is used to represent Jaeger as the tracer + TracerTypeJaeger TracerType = "Jaeger" + // TracerTypeStackdriver is used to represent Stackdriver as the tracer + TracerTypeStackdriver TracerType = "Stackdriver" + // TracerTypeZipkin TracerType = "Zipkin" + // TracerTypeLightstep TracerType = "Lightstep" + // TracerTypeDatadog TracerType = "Datadog" +) diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/zipkin.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/zipkin.go new file mode 100644 index 0000000000..322ad69a47 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/zipkin.go @@ -0,0 +1,6 @@ +package v2 + +// ZipkinTracerConfig configures a Zipkin tracer for use with the mesh +type ZipkinTracerConfig struct { + // TODO.... +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/zz_generated.deepcopy.go b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/zz_generated.deepcopy.go new file mode 100644 index 0000000000..855e76b358 --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/apis/maistra/v2/zz_generated.deepcopy.go @@ -0,0 +1,3234 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v2 + +import ( + appsv1 "k8s.io/api/apps/v1" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + intstr "k8s.io/apimachinery/pkg/util/intstr" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddonsConfig) DeepCopyInto(out *AddonsConfig) { + *out = *in + if in.Prometheus != nil { + in, out := &in.Prometheus, &out.Prometheus + *out = new(PrometheusAddonConfig) + (*in).DeepCopyInto(*out) + } + if in.Stackdriver != nil { + in, out := &in.Stackdriver, &out.Stackdriver + *out = new(StackdriverAddonConfig) + (*in).DeepCopyInto(*out) + } + if in.Jaeger != nil { + in, out := &in.Jaeger, &out.Jaeger + *out = new(JaegerAddonConfig) + (*in).DeepCopyInto(*out) + } + if in.Grafana != nil { + in, out := &in.Grafana, &out.Grafana + *out = new(GrafanaAddonConfig) + (*in).DeepCopyInto(*out) + } + if in.Kiali != nil { + in, out := &in.Kiali, &out.Kiali + *out = new(KialiAddonConfig) + (*in).DeepCopyInto(*out) + } + if in.ThreeScale != nil { + in, out := &in.ThreeScale, &out.ThreeScale + *out = new(ThreeScaleAddonConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonsConfig. +func (in *AddonsConfig) DeepCopy() *AddonsConfig { + if in == nil { + return nil + } + out := new(AddonsConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Affinity) DeepCopyInto(out *Affinity) { + *out = *in + if in.NodeAffinity != nil { + in, out := &in.NodeAffinity, &out.NodeAffinity + *out = new(v1.NodeAffinity) + (*in).DeepCopyInto(*out) + } + if in.PodAffinity != nil { + in, out := &in.PodAffinity, &out.PodAffinity + *out = new(v1.PodAffinity) + (*in).DeepCopyInto(*out) + } + in.PodAntiAffinity.DeepCopyInto(&out.PodAntiAffinity) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Affinity. +func (in *Affinity) DeepCopy() *Affinity { + if in == nil { + return nil + } + out := new(Affinity) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AutoScalerConfig) DeepCopyInto(out *AutoScalerConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.MinReplicas != nil { + in, out := &in.MinReplicas, &out.MinReplicas + *out = new(int32) + **out = **in + } + if in.MaxReplicas != nil { + in, out := &in.MaxReplicas, &out.MaxReplicas + *out = new(int32) + **out = **in + } + if in.TargetCPUUtilizationPercentage != nil { + in, out := &in.TargetCPUUtilizationPercentage, &out.TargetCPUUtilizationPercentage + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoScalerConfig. +func (in *AutoScalerConfig) DeepCopy() *AutoScalerConfig { + if in == nil { + return nil + } + out := new(AutoScalerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CertManagerCertificateAuthorityConfig) DeepCopyInto(out *CertManagerCertificateAuthorityConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertManagerCertificateAuthorityConfig. +func (in *CertManagerCertificateAuthorityConfig) DeepCopy() *CertManagerCertificateAuthorityConfig { + if in == nil { + return nil + } + out := new(CertManagerCertificateAuthorityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CertificateAuthorityConfig) DeepCopyInto(out *CertificateAuthorityConfig) { + *out = *in + if in.Istiod != nil { + in, out := &in.Istiod, &out.Istiod + *out = new(IstiodCertificateAuthorityConfig) + (*in).DeepCopyInto(*out) + } + if in.Custom != nil { + in, out := &in.Custom, &out.Custom + *out = new(CustomCertificateAuthorityConfig) + **out = **in + } + if in.CertManager != nil { + in, out := &in.CertManager, &out.CertManager + *out = new(CertManagerCertificateAuthorityConfig) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateAuthorityConfig. +func (in *CertificateAuthorityConfig) DeepCopy() *CertificateAuthorityConfig { + if in == nil { + return nil + } + out := new(CertificateAuthorityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterIngressGatewayConfig) DeepCopyInto(out *ClusterIngressGatewayConfig) { + *out = *in + in.IngressGatewayConfig.DeepCopyInto(&out.IngressGatewayConfig) + if in.IngressEnabled != nil { + in, out := &in.IngressEnabled, &out.IngressEnabled + *out = new(bool) + **out = **in + } + if in.MeshExpansionPorts != nil { + in, out := &in.MeshExpansionPorts, &out.MeshExpansionPorts + *out = make([]v1.ServicePort, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.RouteConfig != nil { + in, out := &in.RouteConfig, &out.RouteConfig + *out = new(Enablement) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterIngressGatewayConfig. +func (in *ClusterIngressGatewayConfig) DeepCopy() *ClusterIngressGatewayConfig { + if in == nil { + return nil + } + out := new(ClusterIngressGatewayConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CommonContainerConfig) DeepCopyInto(out *CommonContainerConfig) { + *out = *in + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]v1.LocalObjectReference, len(*in)) + copy(*out, *in) + } + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonContainerConfig. +func (in *CommonContainerConfig) DeepCopy() *CommonContainerConfig { + if in == nil { + return nil + } + out := new(CommonContainerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CommonDeploymentRuntimeConfig) DeepCopyInto(out *CommonDeploymentRuntimeConfig) { + *out = *in + if in.PodDisruption != nil { + in, out := &in.PodDisruption, &out.PodDisruption + *out = new(PodDisruptionBudget) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonDeploymentRuntimeConfig. +func (in *CommonDeploymentRuntimeConfig) DeepCopy() *CommonDeploymentRuntimeConfig { + if in == nil { + return nil + } + out := new(CommonDeploymentRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CommonPodRuntimeConfig) DeepCopyInto(out *CommonPodRuntimeConfig) { + *out = *in + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]v1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonPodRuntimeConfig. +func (in *CommonPodRuntimeConfig) DeepCopy() *CommonPodRuntimeConfig { + if in == nil { + return nil + } + out := new(CommonPodRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentIngressConfig) DeepCopyInto(out *ComponentIngressConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = new(MetadataConfig) + (*in).DeepCopyInto(*out) + } + if in.Hosts != nil { + in, out := &in.Hosts, &out.Hosts + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = (*in).DeepCopy() + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentIngressConfig. +func (in *ComponentIngressConfig) DeepCopy() *ComponentIngressConfig { + if in == nil { + return nil + } + out := new(ComponentIngressConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in ComponentLogLevels) DeepCopyInto(out *ComponentLogLevels) { + { + in := &in + *out = make(ComponentLogLevels, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + return + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentLogLevels. +func (in ComponentLogLevels) DeepCopy() ComponentLogLevels { + if in == nil { + return nil + } + out := new(ComponentLogLevels) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentPersistenceConfig) DeepCopyInto(out *ComponentPersistenceConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentPersistenceConfig. +func (in *ComponentPersistenceConfig) DeepCopy() *ComponentPersistenceConfig { + if in == nil { + return nil + } + out := new(ComponentPersistenceConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentRuntimeConfig) DeepCopyInto(out *ComponentRuntimeConfig) { + *out = *in + if in.Deployment != nil { + in, out := &in.Deployment, &out.Deployment + *out = new(DeploymentRuntimeConfig) + (*in).DeepCopyInto(*out) + } + if in.Pod != nil { + in, out := &in.Pod, &out.Pod + *out = new(PodRuntimeConfig) + (*in).DeepCopyInto(*out) + } + if in.Container != nil { + in, out := &in.Container, &out.Container + *out = new(ContainerConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentRuntimeConfig. +func (in *ComponentRuntimeConfig) DeepCopy() *ComponentRuntimeConfig { + if in == nil { + return nil + } + out := new(ComponentRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentServiceConfig) DeepCopyInto(out *ComponentServiceConfig) { + *out = *in + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = new(MetadataConfig) + (*in).DeepCopyInto(*out) + } + if in.NodePort != nil { + in, out := &in.NodePort, &out.NodePort + *out = new(int32) + **out = **in + } + if in.Ingress != nil { + in, out := &in.Ingress, &out.Ingress + *out = new(ComponentIngressConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentServiceConfig. +func (in *ComponentServiceConfig) DeepCopy() *ComponentServiceConfig { + if in == nil { + return nil + } + out := new(ComponentServiceConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ContainerConfig) DeepCopyInto(out *ContainerConfig) { + *out = *in + in.CommonContainerConfig.DeepCopyInto(&out.CommonContainerConfig) + if in.Env != nil { + in, out := &in.Env, &out.Env + *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 ContainerConfig. +func (in *ContainerConfig) DeepCopy() *ContainerConfig { + if in == nil { + return nil + } + out := new(ContainerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneClusterConfig) DeepCopyInto(out *ControlPlaneClusterConfig) { + *out = *in + if in.MultiCluster != nil { + in, out := &in.MultiCluster, &out.MultiCluster + *out = new(MultiClusterConfig) + (*in).DeepCopyInto(*out) + } + if in.MeshExpansion != nil { + in, out := &in.MeshExpansion, &out.MeshExpansion + *out = new(MeshExpansionConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneClusterConfig. +func (in *ControlPlaneClusterConfig) DeepCopy() *ControlPlaneClusterConfig { + if in == nil { + return nil + } + out := new(ControlPlaneClusterConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneRuntimeConfig) DeepCopyInto(out *ControlPlaneRuntimeConfig) { + *out = *in + if in.Components != nil { + in, out := &in.Components, &out.Components + *out = make(map[ControlPlaneComponentName]*ComponentRuntimeConfig, len(*in)) + for key, val := range *in { + var outVal *ComponentRuntimeConfig + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = new(ComponentRuntimeConfig) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } + if in.Defaults != nil { + in, out := &in.Defaults, &out.Defaults + *out = new(DefaultRuntimeConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneRuntimeConfig. +func (in *ControlPlaneRuntimeConfig) DeepCopy() *ControlPlaneRuntimeConfig { + if in == nil { + return nil + } + out := new(ControlPlaneRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneSecurityConfig) DeepCopyInto(out *ControlPlaneSecurityConfig) { + *out = *in + if in.MTLS != nil { + in, out := &in.MTLS, &out.MTLS + *out = new(bool) + **out = **in + } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(ControlPlaneTLSConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneSecurityConfig. +func (in *ControlPlaneSecurityConfig) DeepCopy() *ControlPlaneSecurityConfig { + if in == nil { + return nil + } + out := new(ControlPlaneSecurityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneSpec) DeepCopyInto(out *ControlPlaneSpec) { + *out = *in + if in.Profiles != nil { + in, out := &in.Profiles, &out.Profiles + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Cluster != nil { + in, out := &in.Cluster, &out.Cluster + *out = new(ControlPlaneClusterConfig) + (*in).DeepCopyInto(*out) + } + if in.General != nil { + in, out := &in.General, &out.General + *out = new(GeneralConfig) + (*in).DeepCopyInto(*out) + } + if in.Policy != nil { + in, out := &in.Policy, &out.Policy + *out = new(PolicyConfig) + (*in).DeepCopyInto(*out) + } + if in.Proxy != nil { + in, out := &in.Proxy, &out.Proxy + *out = new(ProxyConfig) + (*in).DeepCopyInto(*out) + } + if in.Security != nil { + in, out := &in.Security, &out.Security + *out = new(SecurityConfig) + (*in).DeepCopyInto(*out) + } + if in.Telemetry != nil { + in, out := &in.Telemetry, &out.Telemetry + *out = new(TelemetryConfig) + (*in).DeepCopyInto(*out) + } + if in.Tracing != nil { + in, out := &in.Tracing, &out.Tracing + *out = new(TracingConfig) + (*in).DeepCopyInto(*out) + } + if in.Gateways != nil { + in, out := &in.Gateways, &out.Gateways + *out = new(GatewaysConfig) + (*in).DeepCopyInto(*out) + } + if in.Runtime != nil { + in, out := &in.Runtime, &out.Runtime + *out = new(ControlPlaneRuntimeConfig) + (*in).DeepCopyInto(*out) + } + if in.Addons != nil { + in, out := &in.Addons, &out.Addons + *out = new(AddonsConfig) + (*in).DeepCopyInto(*out) + } + if in.TechPreview != nil { + in, out := &in.TechPreview, &out.TechPreview + *out = (*in).DeepCopy() + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneSpec. +func (in *ControlPlaneSpec) DeepCopy() *ControlPlaneSpec { + if in == nil { + return nil + } + out := new(ControlPlaneSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneStatus) DeepCopyInto(out *ControlPlaneStatus) { + *out = *in + in.StatusBase.DeepCopyInto(&out.StatusBase) + in.StatusType.DeepCopyInto(&out.StatusType) + in.ComponentStatusList.DeepCopyInto(&out.ComponentStatusList) + in.Readiness.DeepCopyInto(&out.Readiness) + in.AppliedSpec.DeepCopyInto(&out.AppliedSpec) + in.AppliedValues.DeepCopyInto(&out.AppliedValues) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneStatus. +func (in *ControlPlaneStatus) DeepCopy() *ControlPlaneStatus { + if in == nil { + return nil + } + out := new(ControlPlaneStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneTLSConfig) DeepCopyInto(out *ControlPlaneTLSConfig) { + *out = *in + if in.CipherSuites != nil { + in, out := &in.CipherSuites, &out.CipherSuites + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ECDHCurves != nil { + in, out := &in.ECDHCurves, &out.ECDHCurves + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneTLSConfig. +func (in *ControlPlaneTLSConfig) DeepCopy() *ControlPlaneTLSConfig { + if in == nil { + return nil + } + out := new(ControlPlaneTLSConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomCertificateAuthorityConfig) DeepCopyInto(out *CustomCertificateAuthorityConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomCertificateAuthorityConfig. +func (in *CustomCertificateAuthorityConfig) DeepCopy() *CustomCertificateAuthorityConfig { + if in == nil { + return nil + } + out := new(CustomCertificateAuthorityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataPlaneSecurityConfig) DeepCopyInto(out *DataPlaneSecurityConfig) { + *out = *in + if in.MTLS != nil { + in, out := &in.MTLS, &out.MTLS + *out = new(bool) + **out = **in + } + if in.AutoMTLS != nil { + in, out := &in.AutoMTLS, &out.AutoMTLS + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataPlaneSecurityConfig. +func (in *DataPlaneSecurityConfig) DeepCopy() *DataPlaneSecurityConfig { + if in == nil { + return nil + } + out := new(DataPlaneSecurityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DatadogTracerConfig) DeepCopyInto(out *DatadogTracerConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatadogTracerConfig. +func (in *DatadogTracerConfig) DeepCopy() *DatadogTracerConfig { + if in == nil { + return nil + } + out := new(DatadogTracerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DefaultRuntimeConfig) DeepCopyInto(out *DefaultRuntimeConfig) { + *out = *in + if in.Deployment != nil { + in, out := &in.Deployment, &out.Deployment + *out = new(CommonDeploymentRuntimeConfig) + (*in).DeepCopyInto(*out) + } + if in.Pod != nil { + in, out := &in.Pod, &out.Pod + *out = new(CommonPodRuntimeConfig) + (*in).DeepCopyInto(*out) + } + if in.Container != nil { + in, out := &in.Container, &out.Container + *out = new(CommonContainerConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DefaultRuntimeConfig. +func (in *DefaultRuntimeConfig) DeepCopy() *DefaultRuntimeConfig { + if in == nil { + return nil + } + out := new(DefaultRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentRuntimeConfig) DeepCopyInto(out *DeploymentRuntimeConfig) { + *out = *in + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } + if in.Strategy != nil { + in, out := &in.Strategy, &out.Strategy + *out = new(appsv1.DeploymentStrategy) + (*in).DeepCopyInto(*out) + } + if in.AutoScaling != nil { + in, out := &in.AutoScaling, &out.AutoScaling + *out = new(AutoScalerConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentRuntimeConfig. +func (in *DeploymentRuntimeConfig) DeepCopy() *DeploymentRuntimeConfig { + if in == nil { + return nil + } + out := new(DeploymentRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EgressGatewayConfig) DeepCopyInto(out *EgressGatewayConfig) { + *out = *in + in.GatewayConfig.DeepCopyInto(&out.GatewayConfig) + if in.RequestedNetworkView != nil { + in, out := &in.RequestedNetworkView, &out.RequestedNetworkView + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EgressGatewayConfig. +func (in *EgressGatewayConfig) DeepCopy() *EgressGatewayConfig { + if in == nil { + return nil + } + out := new(EgressGatewayConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Enablement) DeepCopyInto(out *Enablement) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Enablement. +func (in *Enablement) DeepCopy() *Enablement { + if in == nil { + return nil + } + out := new(Enablement) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvoyServiceClientTLSSettings) DeepCopyInto(out *EnvoyServiceClientTLSSettings) { + *out = *in + if in.SubjectAltNames != nil { + in, out := &in.SubjectAltNames, &out.SubjectAltNames + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyServiceClientTLSSettings. +func (in *EnvoyServiceClientTLSSettings) DeepCopy() *EnvoyServiceClientTLSSettings { + if in == nil { + return nil + } + out := new(EnvoyServiceClientTLSSettings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvoyServiceTCPKeepalive) DeepCopyInto(out *EnvoyServiceTCPKeepalive) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyServiceTCPKeepalive. +func (in *EnvoyServiceTCPKeepalive) DeepCopy() *EnvoyServiceTCPKeepalive { + if in == nil { + return nil + } + out := new(EnvoyServiceTCPKeepalive) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayConfig) DeepCopyInto(out *GatewayConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + in.Service.DeepCopyInto(&out.Service) + if in.Volumes != nil { + in, out := &in.Volumes, &out.Volumes + *out = make([]VolumeConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Runtime != nil { + in, out := &in.Runtime, &out.Runtime + *out = new(ComponentRuntimeConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayConfig. +func (in *GatewayConfig) DeepCopy() *GatewayConfig { + if in == nil { + return nil + } + out := new(GatewayConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayServiceConfig) DeepCopyInto(out *GatewayServiceConfig) { + *out = *in + in.ServiceSpec.DeepCopyInto(&out.ServiceSpec) + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = new(MetadataConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayServiceConfig. +func (in *GatewayServiceConfig) DeepCopy() *GatewayServiceConfig { + if in == nil { + return nil + } + out := new(GatewayServiceConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayVolume) DeepCopyInto(out *GatewayVolume) { + *out = *in + if in.ConfigMap != nil { + in, out := &in.ConfigMap, &out.ConfigMap + *out = new(v1.ConfigMapVolumeSource) + (*in).DeepCopyInto(*out) + } + if in.Secret != nil { + in, out := &in.Secret, &out.Secret + *out = new(v1.SecretVolumeSource) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayVolume. +func (in *GatewayVolume) DeepCopy() *GatewayVolume { + if in == nil { + return nil + } + out := new(GatewayVolume) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewaysConfig) DeepCopyInto(out *GatewaysConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.ClusterIngress != nil { + in, out := &in.ClusterIngress, &out.ClusterIngress + *out = new(ClusterIngressGatewayConfig) + (*in).DeepCopyInto(*out) + } + if in.ClusterEgress != nil { + in, out := &in.ClusterEgress, &out.ClusterEgress + *out = new(EgressGatewayConfig) + (*in).DeepCopyInto(*out) + } + if in.IngressGateways != nil { + in, out := &in.IngressGateways, &out.IngressGateways + *out = make(map[string]*IngressGatewayConfig, len(*in)) + for key, val := range *in { + var outVal *IngressGatewayConfig + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = new(IngressGatewayConfig) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } + if in.EgressGateways != nil { + in, out := &in.EgressGateways, &out.EgressGateways + *out = make(map[string]*EgressGatewayConfig, len(*in)) + for key, val := range *in { + var outVal *EgressGatewayConfig + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = new(EgressGatewayConfig) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } + if in.OpenShiftRoute != nil { + in, out := &in.OpenShiftRoute, &out.OpenShiftRoute + *out = new(OpenShiftRouteConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewaysConfig. +func (in *GatewaysConfig) DeepCopy() *GatewaysConfig { + if in == nil { + return nil + } + out := new(GatewaysConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GeneralConfig) DeepCopyInto(out *GeneralConfig) { + *out = *in + if in.Logging != nil { + in, out := &in.Logging, &out.Logging + *out = new(LoggingConfig) + (*in).DeepCopyInto(*out) + } + if in.ValidationMessages != nil { + in, out := &in.ValidationMessages, &out.ValidationMessages + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GeneralConfig. +func (in *GeneralConfig) DeepCopy() *GeneralConfig { + if in == nil { + return nil + } + out := new(GeneralConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaAddonConfig) DeepCopyInto(out *GrafanaAddonConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Install != nil { + in, out := &in.Install, &out.Install + *out = new(GrafanaInstallConfig) + (*in).DeepCopyInto(*out) + } + if in.Address != nil { + in, out := &in.Address, &out.Address + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaAddonConfig. +func (in *GrafanaAddonConfig) DeepCopy() *GrafanaAddonConfig { + if in == nil { + return nil + } + out := new(GrafanaAddonConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfig) DeepCopyInto(out *GrafanaConfig) { + *out = *in + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.EnvSecrets != nil { + in, out := &in.EnvSecrets, &out.EnvSecrets + *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 GrafanaConfig. +func (in *GrafanaConfig) DeepCopy() *GrafanaConfig { + if in == nil { + return nil + } + out := new(GrafanaConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaInstallConfig) DeepCopyInto(out *GrafanaInstallConfig) { + *out = *in + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = new(GrafanaConfig) + (*in).DeepCopyInto(*out) + } + if in.Service != nil { + in, out := &in.Service, &out.Service + *out = new(ComponentServiceConfig) + (*in).DeepCopyInto(*out) + } + if in.Persistence != nil { + in, out := &in.Persistence, &out.Persistence + *out = new(ComponentPersistenceConfig) + (*in).DeepCopyInto(*out) + } + if in.Security != nil { + in, out := &in.Security, &out.Security + *out = new(GrafanaSecurityConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaInstallConfig. +func (in *GrafanaInstallConfig) DeepCopy() *GrafanaInstallConfig { + if in == nil { + return nil + } + out := new(GrafanaInstallConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaSecurityConfig) DeepCopyInto(out *GrafanaSecurityConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaSecurityConfig. +func (in *GrafanaSecurityConfig) DeepCopy() *GrafanaSecurityConfig { + if in == nil { + return nil + } + out := new(GrafanaSecurityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IdentityConfig) DeepCopyInto(out *IdentityConfig) { + *out = *in + if in.ThirdParty != nil { + in, out := &in.ThirdParty, &out.ThirdParty + *out = new(ThirdPartyIdentityConfig) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IdentityConfig. +func (in *IdentityConfig) DeepCopy() *IdentityConfig { + if in == nil { + return nil + } + out := new(IdentityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IngressGatewayConfig) DeepCopyInto(out *IngressGatewayConfig) { + *out = *in + in.GatewayConfig.DeepCopyInto(&out.GatewayConfig) + if in.SDS != nil { + in, out := &in.SDS, &out.SDS + *out = new(SecretDiscoveryService) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressGatewayConfig. +func (in *IngressGatewayConfig) DeepCopy() *IngressGatewayConfig { + if in == nil { + return nil + } + out := new(IngressGatewayConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IstioPrivateKeyCertificateSignerConfig) DeepCopyInto(out *IstioPrivateKeyCertificateSignerConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IstioPrivateKeyCertificateSignerConfig. +func (in *IstioPrivateKeyCertificateSignerConfig) DeepCopy() *IstioPrivateKeyCertificateSignerConfig { + if in == nil { + return nil + } + out := new(IstioPrivateKeyCertificateSignerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IstioSelfSignedCertificateSignerConfig) DeepCopyInto(out *IstioSelfSignedCertificateSignerConfig) { + *out = *in + if in.EnableJitter != nil { + in, out := &in.EnableJitter, &out.EnableJitter + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IstioSelfSignedCertificateSignerConfig. +func (in *IstioSelfSignedCertificateSignerConfig) DeepCopy() *IstioSelfSignedCertificateSignerConfig { + if in == nil { + return nil + } + out := new(IstioSelfSignedCertificateSignerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IstiodCertificateAuthorityConfig) DeepCopyInto(out *IstiodCertificateAuthorityConfig) { + *out = *in + if in.SelfSigned != nil { + in, out := &in.SelfSigned, &out.SelfSigned + *out = new(IstioSelfSignedCertificateSignerConfig) + (*in).DeepCopyInto(*out) + } + if in.PrivateKey != nil { + in, out := &in.PrivateKey, &out.PrivateKey + *out = new(IstioPrivateKeyCertificateSignerConfig) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IstiodCertificateAuthorityConfig. +func (in *IstiodCertificateAuthorityConfig) DeepCopy() *IstiodCertificateAuthorityConfig { + if in == nil { + return nil + } + out := new(IstiodCertificateAuthorityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JaegerAddonConfig) DeepCopyInto(out *JaegerAddonConfig) { + *out = *in + if in.Install != nil { + in, out := &in.Install, &out.Install + *out = new(JaegerInstallConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JaegerAddonConfig. +func (in *JaegerAddonConfig) DeepCopy() *JaegerAddonConfig { + if in == nil { + return nil + } + out := new(JaegerAddonConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JaegerElasticsearchStorageConfig) DeepCopyInto(out *JaegerElasticsearchStorageConfig) { + *out = *in + if in.NodeCount != nil { + in, out := &in.NodeCount, &out.NodeCount + *out = new(int32) + **out = **in + } + if in.Storage != nil { + in, out := &in.Storage, &out.Storage + *out = (*in).DeepCopy() + } + if in.IndexCleaner != nil { + in, out := &in.IndexCleaner, &out.IndexCleaner + *out = (*in).DeepCopy() + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JaegerElasticsearchStorageConfig. +func (in *JaegerElasticsearchStorageConfig) DeepCopy() *JaegerElasticsearchStorageConfig { + if in == nil { + return nil + } + out := new(JaegerElasticsearchStorageConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JaegerIngressConfig) DeepCopyInto(out *JaegerIngressConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = new(MetadataConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JaegerIngressConfig. +func (in *JaegerIngressConfig) DeepCopy() *JaegerIngressConfig { + if in == nil { + return nil + } + out := new(JaegerIngressConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JaegerInstallConfig) DeepCopyInto(out *JaegerInstallConfig) { + *out = *in + if in.Storage != nil { + in, out := &in.Storage, &out.Storage + *out = new(JaegerStorageConfig) + (*in).DeepCopyInto(*out) + } + if in.Ingress != nil { + in, out := &in.Ingress, &out.Ingress + *out = new(JaegerIngressConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JaegerInstallConfig. +func (in *JaegerInstallConfig) DeepCopy() *JaegerInstallConfig { + if in == nil { + return nil + } + out := new(JaegerInstallConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JaegerMemoryStorageConfig) DeepCopyInto(out *JaegerMemoryStorageConfig) { + *out = *in + if in.MaxTraces != nil { + in, out := &in.MaxTraces, &out.MaxTraces + *out = new(int64) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JaegerMemoryStorageConfig. +func (in *JaegerMemoryStorageConfig) DeepCopy() *JaegerMemoryStorageConfig { + if in == nil { + return nil + } + out := new(JaegerMemoryStorageConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JaegerStorageConfig) DeepCopyInto(out *JaegerStorageConfig) { + *out = *in + if in.Memory != nil { + in, out := &in.Memory, &out.Memory + *out = new(JaegerMemoryStorageConfig) + (*in).DeepCopyInto(*out) + } + if in.Elasticsearch != nil { + in, out := &in.Elasticsearch, &out.Elasticsearch + *out = new(JaegerElasticsearchStorageConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JaegerStorageConfig. +func (in *JaegerStorageConfig) DeepCopy() *JaegerStorageConfig { + if in == nil { + return nil + } + out := new(JaegerStorageConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KialiAddonConfig) DeepCopyInto(out *KialiAddonConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Install != nil { + in, out := &in.Install, &out.Install + *out = new(KialiInstallConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KialiAddonConfig. +func (in *KialiAddonConfig) DeepCopy() *KialiAddonConfig { + if in == nil { + return nil + } + out := new(KialiAddonConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KialiDashboardConfig) DeepCopyInto(out *KialiDashboardConfig) { + *out = *in + if in.ViewOnly != nil { + in, out := &in.ViewOnly, &out.ViewOnly + *out = new(bool) + **out = **in + } + if in.EnableGrafana != nil { + in, out := &in.EnableGrafana, &out.EnableGrafana + *out = new(bool) + **out = **in + } + if in.EnablePrometheus != nil { + in, out := &in.EnablePrometheus, &out.EnablePrometheus + *out = new(bool) + **out = **in + } + if in.EnableTracing != nil { + in, out := &in.EnableTracing, &out.EnableTracing + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KialiDashboardConfig. +func (in *KialiDashboardConfig) DeepCopy() *KialiDashboardConfig { + if in == nil { + return nil + } + out := new(KialiDashboardConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KialiDeploymentConfig) DeepCopyInto(out *KialiDeploymentConfig) { + *out = *in + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(v1.Affinity) + (*in).DeepCopyInto(*out) + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]v1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KialiDeploymentConfig. +func (in *KialiDeploymentConfig) DeepCopy() *KialiDeploymentConfig { + if in == nil { + return nil + } + out := new(KialiDeploymentConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KialiInstallConfig) DeepCopyInto(out *KialiInstallConfig) { + *out = *in + if in.Dashboard != nil { + in, out := &in.Dashboard, &out.Dashboard + *out = new(KialiDashboardConfig) + (*in).DeepCopyInto(*out) + } + if in.Service != nil { + in, out := &in.Service, &out.Service + *out = new(ComponentServiceConfig) + (*in).DeepCopyInto(*out) + } + if in.Deployment != nil { + in, out := &in.Deployment, &out.Deployment + *out = new(KialiDeploymentConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KialiInstallConfig. +func (in *KialiInstallConfig) DeepCopy() *KialiInstallConfig { + if in == nil { + return nil + } + out := new(KialiInstallConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LightstepTracerConfig) DeepCopyInto(out *LightstepTracerConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LightstepTracerConfig. +func (in *LightstepTracerConfig) DeepCopy() *LightstepTracerConfig { + if in == nil { + return nil + } + out := new(LightstepTracerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LoggingConfig) DeepCopyInto(out *LoggingConfig) { + *out = *in + if in.ComponentLevels != nil { + in, out := &in.ComponentLevels, &out.ComponentLevels + *out = make(ComponentLogLevels, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.LogAsJSON != nil { + in, out := &in.LogAsJSON, &out.LogAsJSON + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoggingConfig. +func (in *LoggingConfig) DeepCopy() *LoggingConfig { + if in == nil { + return nil + } + out := new(LoggingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MeshEndpointConfig) DeepCopyInto(out *MeshEndpointConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshEndpointConfig. +func (in *MeshEndpointConfig) DeepCopy() *MeshEndpointConfig { + if in == nil { + return nil + } + out := new(MeshEndpointConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MeshExpansionConfig) DeepCopyInto(out *MeshExpansionConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.ILBGateway != nil { + in, out := &in.ILBGateway, &out.ILBGateway + *out = new(GatewayConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshExpansionConfig. +func (in *MeshExpansionConfig) DeepCopy() *MeshExpansionConfig { + if in == nil { + return nil + } + out := new(MeshExpansionConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MeshGatewayConfig) DeepCopyInto(out *MeshGatewayConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshGatewayConfig. +func (in *MeshGatewayConfig) DeepCopy() *MeshGatewayConfig { + if in == nil { + return nil + } + out := new(MeshGatewayConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MeshNetworkConfig) DeepCopyInto(out *MeshNetworkConfig) { + *out = *in + if in.Endpoints != nil { + in, out := &in.Endpoints, &out.Endpoints + *out = make([]MeshEndpointConfig, len(*in)) + copy(*out, *in) + } + if in.Gateways != nil { + in, out := &in.Gateways, &out.Gateways + *out = make([]MeshGatewayConfig, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshNetworkConfig. +func (in *MeshNetworkConfig) DeepCopy() *MeshNetworkConfig { + if in == nil { + return nil + } + out := new(MeshNetworkConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetadataConfig) DeepCopyInto(out *MetadataConfig) { + *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 MetadataConfig. +func (in *MetadataConfig) DeepCopy() *MetadataConfig { + if in == nil { + return nil + } + out := new(MetadataConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MixerPolicyAdaptersConfig) DeepCopyInto(out *MixerPolicyAdaptersConfig) { + *out = *in + if in.UseAdapterCRDs != nil { + in, out := &in.UseAdapterCRDs, &out.UseAdapterCRDs + *out = new(bool) + **out = **in + } + if in.KubernetesEnv != nil { + in, out := &in.KubernetesEnv, &out.KubernetesEnv + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MixerPolicyAdaptersConfig. +func (in *MixerPolicyAdaptersConfig) DeepCopy() *MixerPolicyAdaptersConfig { + if in == nil { + return nil + } + out := new(MixerPolicyAdaptersConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MixerPolicyConfig) DeepCopyInto(out *MixerPolicyConfig) { + *out = *in + if in.EnableChecks != nil { + in, out := &in.EnableChecks, &out.EnableChecks + *out = new(bool) + **out = **in + } + if in.FailOpen != nil { + in, out := &in.FailOpen, &out.FailOpen + *out = new(bool) + **out = **in + } + if in.SessionAffinity != nil { + in, out := &in.SessionAffinity, &out.SessionAffinity + *out = new(bool) + **out = **in + } + if in.Adapters != nil { + in, out := &in.Adapters, &out.Adapters + *out = new(MixerPolicyAdaptersConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MixerPolicyConfig. +func (in *MixerPolicyConfig) DeepCopy() *MixerPolicyConfig { + if in == nil { + return nil + } + out := new(MixerPolicyConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MixerTelemetryAdaptersConfig) DeepCopyInto(out *MixerTelemetryAdaptersConfig) { + *out = *in + if in.UseAdapterCRDs != nil { + in, out := &in.UseAdapterCRDs, &out.UseAdapterCRDs + *out = new(bool) + **out = **in + } + if in.KubernetesEnv != nil { + in, out := &in.KubernetesEnv, &out.KubernetesEnv + *out = new(bool) + **out = **in + } + if in.Stdio != nil { + in, out := &in.Stdio, &out.Stdio + *out = new(MixerTelemetryStdioConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MixerTelemetryAdaptersConfig. +func (in *MixerTelemetryAdaptersConfig) DeepCopy() *MixerTelemetryAdaptersConfig { + if in == nil { + return nil + } + out := new(MixerTelemetryAdaptersConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MixerTelemetryConfig) DeepCopyInto(out *MixerTelemetryConfig) { + *out = *in + if in.SessionAffinity != nil { + in, out := &in.SessionAffinity, &out.SessionAffinity + *out = new(bool) + **out = **in + } + if in.Loadshedding != nil { + in, out := &in.Loadshedding, &out.Loadshedding + *out = new(TelemetryLoadSheddingConfig) + **out = **in + } + if in.Batching != nil { + in, out := &in.Batching, &out.Batching + *out = new(TelemetryBatchingConfig) + (*in).DeepCopyInto(*out) + } + if in.Adapters != nil { + in, out := &in.Adapters, &out.Adapters + *out = new(MixerTelemetryAdaptersConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MixerTelemetryConfig. +func (in *MixerTelemetryConfig) DeepCopy() *MixerTelemetryConfig { + if in == nil { + return nil + } + out := new(MixerTelemetryConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MixerTelemetryStdioConfig) DeepCopyInto(out *MixerTelemetryStdioConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.OutputAsJSON != nil { + in, out := &in.OutputAsJSON, &out.OutputAsJSON + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MixerTelemetryStdioConfig. +func (in *MixerTelemetryStdioConfig) DeepCopy() *MixerTelemetryStdioConfig { + if in == nil { + return nil + } + out := new(MixerTelemetryStdioConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MultiClusterConfig) DeepCopyInto(out *MultiClusterConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.MeshNetworks != nil { + in, out := &in.MeshNetworks, &out.MeshNetworks + *out = make(map[string]MeshNetworkConfig, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MultiClusterConfig. +func (in *MultiClusterConfig) DeepCopy() *MultiClusterConfig { + if in == nil { + return nil + } + out := new(MultiClusterConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenShiftRouteConfig) DeepCopyInto(out *OpenShiftRouteConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenShiftRouteConfig. +func (in *OpenShiftRouteConfig) DeepCopy() *OpenShiftRouteConfig { + if in == nil { + return nil + } + out := new(OpenShiftRouteConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodAntiAffinity) DeepCopyInto(out *PodAntiAffinity) { + *out = *in + if in.PodAntiAffinity != nil { + in, out := &in.PodAntiAffinity, &out.PodAntiAffinity + *out = new(v1.PodAntiAffinity) + (*in).DeepCopyInto(*out) + } + if in.RequiredDuringScheduling != nil { + in, out := &in.RequiredDuringScheduling, &out.RequiredDuringScheduling + *out = make([]PodAntiAffinityTerm, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.PreferredDuringScheduling != nil { + in, out := &in.PreferredDuringScheduling, &out.PreferredDuringScheduling + *out = make([]PodAntiAffinityTerm, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodAntiAffinity. +func (in *PodAntiAffinity) DeepCopy() *PodAntiAffinity { + if in == nil { + return nil + } + out := new(PodAntiAffinity) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodAntiAffinityTerm) DeepCopyInto(out *PodAntiAffinityTerm) { + *out = *in + in.LabelSelectorRequirement.DeepCopyInto(&out.LabelSelectorRequirement) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodAntiAffinityTerm. +func (in *PodAntiAffinityTerm) DeepCopy() *PodAntiAffinityTerm { + if in == nil { + return nil + } + out := new(PodAntiAffinityTerm) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodDisruptionBudget) DeepCopyInto(out *PodDisruptionBudget) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.MinAvailable != nil { + in, out := &in.MinAvailable, &out.MinAvailable + *out = new(intstr.IntOrString) + **out = **in + } + if in.MaxUnavailable != nil { + in, out := &in.MaxUnavailable, &out.MaxUnavailable + *out = new(intstr.IntOrString) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodDisruptionBudget. +func (in *PodDisruptionBudget) DeepCopy() *PodDisruptionBudget { + if in == nil { + return nil + } + out := new(PodDisruptionBudget) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodRuntimeConfig) DeepCopyInto(out *PodRuntimeConfig) { + *out = *in + in.CommonPodRuntimeConfig.DeepCopyInto(&out.CommonPodRuntimeConfig) + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = new(MetadataConfig) + (*in).DeepCopyInto(*out) + } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(Affinity) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodRuntimeConfig. +func (in *PodRuntimeConfig) DeepCopy() *PodRuntimeConfig { + if in == nil { + return nil + } + out := new(PodRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyConfig) DeepCopyInto(out *PolicyConfig) { + *out = *in + if in.Mixer != nil { + in, out := &in.Mixer, &out.Mixer + *out = new(MixerPolicyConfig) + (*in).DeepCopyInto(*out) + } + if in.Remote != nil { + in, out := &in.Remote, &out.Remote + *out = new(RemotePolicyConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyConfig. +func (in *PolicyConfig) DeepCopy() *PolicyConfig { + if in == nil { + return nil + } + out := new(PolicyConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrometheusAddonConfig) DeepCopyInto(out *PrometheusAddonConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Scrape != nil { + in, out := &in.Scrape, &out.Scrape + *out = new(bool) + **out = **in + } + if in.Install != nil { + in, out := &in.Install, &out.Install + *out = new(PrometheusInstallConfig) + (*in).DeepCopyInto(*out) + } + if in.Address != nil { + in, out := &in.Address, &out.Address + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrometheusAddonConfig. +func (in *PrometheusAddonConfig) DeepCopy() *PrometheusAddonConfig { + if in == nil { + return nil + } + out := new(PrometheusAddonConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrometheusInstallConfig) DeepCopyInto(out *PrometheusInstallConfig) { + *out = *in + if in.Service != nil { + in, out := &in.Service, &out.Service + *out = new(ComponentServiceConfig) + (*in).DeepCopyInto(*out) + } + if in.UseTLS != nil { + in, out := &in.UseTLS, &out.UseTLS + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrometheusInstallConfig. +func (in *PrometheusInstallConfig) DeepCopy() *PrometheusInstallConfig { + if in == nil { + return nil + } + out := new(PrometheusInstallConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyAccessLoggingConfig) DeepCopyInto(out *ProxyAccessLoggingConfig) { + *out = *in + if in.File != nil { + in, out := &in.File, &out.File + *out = new(ProxyFileAccessLogConfig) + **out = **in + } + if in.EnvoyService != nil { + in, out := &in.EnvoyService, &out.EnvoyService + *out = new(ProxyEnvoyServiceConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyAccessLoggingConfig. +func (in *ProxyAccessLoggingConfig) DeepCopy() *ProxyAccessLoggingConfig { + if in == nil { + return nil + } + out := new(ProxyAccessLoggingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyConfig) DeepCopyInto(out *ProxyConfig) { + *out = *in + if in.Logging != nil { + in, out := &in.Logging, &out.Logging + *out = new(ProxyLoggingConfig) + (*in).DeepCopyInto(*out) + } + if in.Networking != nil { + in, out := &in.Networking, &out.Networking + *out = new(ProxyNetworkingConfig) + (*in).DeepCopyInto(*out) + } + if in.Runtime != nil { + in, out := &in.Runtime, &out.Runtime + *out = new(ProxyRuntimeConfig) + (*in).DeepCopyInto(*out) + } + if in.Injection != nil { + in, out := &in.Injection, &out.Injection + *out = new(ProxyInjectionConfig) + (*in).DeepCopyInto(*out) + } + if in.Concurrency != nil { + in, out := &in.Concurrency, &out.Concurrency + *out = new(int32) + **out = **in + } + if in.AccessLogging != nil { + in, out := &in.AccessLogging, &out.AccessLogging + *out = new(ProxyAccessLoggingConfig) + (*in).DeepCopyInto(*out) + } + if in.EnvoyMetricsService != nil { + in, out := &in.EnvoyMetricsService, &out.EnvoyMetricsService + *out = new(ProxyEnvoyServiceConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyConfig. +func (in *ProxyConfig) DeepCopy() *ProxyConfig { + if in == nil { + return nil + } + out := new(ProxyConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyDNSConfig) DeepCopyInto(out *ProxyDNSConfig) { + *out = *in + if in.SearchSuffixes != nil { + in, out := &in.SearchSuffixes, &out.SearchSuffixes + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyDNSConfig. +func (in *ProxyDNSConfig) DeepCopy() *ProxyDNSConfig { + if in == nil { + return nil + } + out := new(ProxyDNSConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyEnvoyServiceConfig) DeepCopyInto(out *ProxyEnvoyServiceConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.TCPKeepalive != nil { + in, out := &in.TCPKeepalive, &out.TCPKeepalive + *out = new(EnvoyServiceTCPKeepalive) + **out = **in + } + if in.TLSSettings != nil { + in, out := &in.TLSSettings, &out.TLSSettings + *out = new(EnvoyServiceClientTLSSettings) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyEnvoyServiceConfig. +func (in *ProxyEnvoyServiceConfig) DeepCopy() *ProxyEnvoyServiceConfig { + if in == nil { + return nil + } + out := new(ProxyEnvoyServiceConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyFileAccessLogConfig) DeepCopyInto(out *ProxyFileAccessLogConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyFileAccessLogConfig. +func (in *ProxyFileAccessLogConfig) DeepCopy() *ProxyFileAccessLogConfig { + if in == nil { + return nil + } + out := new(ProxyFileAccessLogConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyInboundTrafficControlConfig) DeepCopyInto(out *ProxyInboundTrafficControlConfig) { + *out = *in + if in.IncludedPorts != nil { + in, out := &in.IncludedPorts, &out.IncludedPorts + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ExcludedPorts != nil { + in, out := &in.ExcludedPorts, &out.ExcludedPorts + *out = make([]int32, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyInboundTrafficControlConfig. +func (in *ProxyInboundTrafficControlConfig) DeepCopy() *ProxyInboundTrafficControlConfig { + if in == nil { + return nil + } + out := new(ProxyInboundTrafficControlConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyInitContainerConfig) DeepCopyInto(out *ProxyInitContainerConfig) { + *out = *in + if in.Runtime != nil { + in, out := &in.Runtime, &out.Runtime + *out = new(ContainerConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyInitContainerConfig. +func (in *ProxyInitContainerConfig) DeepCopy() *ProxyInitContainerConfig { + if in == nil { + return nil + } + out := new(ProxyInitContainerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyInjectionConfig) DeepCopyInto(out *ProxyInjectionConfig) { + *out = *in + if in.AutoInject != nil { + in, out := &in.AutoInject, &out.AutoInject + *out = new(bool) + **out = **in + } + if in.AlwaysInjectSelector != nil { + in, out := &in.AlwaysInjectSelector, &out.AlwaysInjectSelector + *out = make([]metav1.LabelSelector, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.NeverInjectSelector != nil { + in, out := &in.NeverInjectSelector, &out.NeverInjectSelector + *out = make([]metav1.LabelSelector, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.InjectedAnnotations != nil { + in, out := &in.InjectedAnnotations, &out.InjectedAnnotations + *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 ProxyInjectionConfig. +func (in *ProxyInjectionConfig) DeepCopy() *ProxyInjectionConfig { + if in == nil { + return nil + } + out := new(ProxyInjectionConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyLoggingConfig) DeepCopyInto(out *ProxyLoggingConfig) { + *out = *in + if in.ComponentLevels != nil { + in, out := &in.ComponentLevels, &out.ComponentLevels + *out = make(ComponentLogLevels, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyLoggingConfig. +func (in *ProxyLoggingConfig) DeepCopy() *ProxyLoggingConfig { + if in == nil { + return nil + } + out := new(ProxyLoggingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyNetworkAutoProtocolDetectionConfig) DeepCopyInto(out *ProxyNetworkAutoProtocolDetectionConfig) { + *out = *in + if in.Inbound != nil { + in, out := &in.Inbound, &out.Inbound + *out = new(bool) + **out = **in + } + if in.Outbound != nil { + in, out := &in.Outbound, &out.Outbound + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyNetworkAutoProtocolDetectionConfig. +func (in *ProxyNetworkAutoProtocolDetectionConfig) DeepCopy() *ProxyNetworkAutoProtocolDetectionConfig { + if in == nil { + return nil + } + out := new(ProxyNetworkAutoProtocolDetectionConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyNetworkInitConfig) DeepCopyInto(out *ProxyNetworkInitConfig) { + *out = *in + if in.InitContainer != nil { + in, out := &in.InitContainer, &out.InitContainer + *out = new(ProxyInitContainerConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyNetworkInitConfig. +func (in *ProxyNetworkInitConfig) DeepCopy() *ProxyNetworkInitConfig { + if in == nil { + return nil + } + out := new(ProxyNetworkInitConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyNetworkProtocolConfig) DeepCopyInto(out *ProxyNetworkProtocolConfig) { + *out = *in + if in.AutoDetect != nil { + in, out := &in.AutoDetect, &out.AutoDetect + *out = new(ProxyNetworkAutoProtocolDetectionConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyNetworkProtocolConfig. +func (in *ProxyNetworkProtocolConfig) DeepCopy() *ProxyNetworkProtocolConfig { + if in == nil { + return nil + } + out := new(ProxyNetworkProtocolConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyNetworkingConfig) DeepCopyInto(out *ProxyNetworkingConfig) { + *out = *in + if in.Initialization != nil { + in, out := &in.Initialization, &out.Initialization + *out = new(ProxyNetworkInitConfig) + (*in).DeepCopyInto(*out) + } + if in.TrafficControl != nil { + in, out := &in.TrafficControl, &out.TrafficControl + *out = new(ProxyTrafficControlConfig) + (*in).DeepCopyInto(*out) + } + if in.Protocol != nil { + in, out := &in.Protocol, &out.Protocol + *out = new(ProxyNetworkProtocolConfig) + (*in).DeepCopyInto(*out) + } + if in.DNS != nil { + in, out := &in.DNS, &out.DNS + *out = new(ProxyDNSConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyNetworkingConfig. +func (in *ProxyNetworkingConfig) DeepCopy() *ProxyNetworkingConfig { + if in == nil { + return nil + } + out := new(ProxyNetworkingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyOutboundTrafficControlConfig) DeepCopyInto(out *ProxyOutboundTrafficControlConfig) { + *out = *in + if in.IncludedIPRanges != nil { + in, out := &in.IncludedIPRanges, &out.IncludedIPRanges + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ExcludedIPRanges != nil { + in, out := &in.ExcludedIPRanges, &out.ExcludedIPRanges + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ExcludedPorts != nil { + in, out := &in.ExcludedPorts, &out.ExcludedPorts + *out = make([]int32, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyOutboundTrafficControlConfig. +func (in *ProxyOutboundTrafficControlConfig) DeepCopy() *ProxyOutboundTrafficControlConfig { + if in == nil { + return nil + } + out := new(ProxyOutboundTrafficControlConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyReadinessConfig) DeepCopyInto(out *ProxyReadinessConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyReadinessConfig. +func (in *ProxyReadinessConfig) DeepCopy() *ProxyReadinessConfig { + if in == nil { + return nil + } + out := new(ProxyReadinessConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyRuntimeConfig) DeepCopyInto(out *ProxyRuntimeConfig) { + *out = *in + if in.Readiness != nil { + in, out := &in.Readiness, &out.Readiness + *out = new(ProxyReadinessConfig) + **out = **in + } + if in.Container != nil { + in, out := &in.Container, &out.Container + *out = new(ContainerConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyRuntimeConfig. +func (in *ProxyRuntimeConfig) DeepCopy() *ProxyRuntimeConfig { + if in == nil { + return nil + } + out := new(ProxyRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyTrafficControlConfig) DeepCopyInto(out *ProxyTrafficControlConfig) { + *out = *in + in.Inbound.DeepCopyInto(&out.Inbound) + in.Outbound.DeepCopyInto(&out.Outbound) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyTrafficControlConfig. +func (in *ProxyTrafficControlConfig) DeepCopy() *ProxyTrafficControlConfig { + if in == nil { + return nil + } + out := new(ProxyTrafficControlConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in ReadinessMap) DeepCopyInto(out *ReadinessMap) { + { + in := &in + *out = make(ReadinessMap, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + return + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReadinessMap. +func (in ReadinessMap) DeepCopy() ReadinessMap { + if in == nil { + return nil + } + out := new(ReadinessMap) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReadinessStatus) DeepCopyInto(out *ReadinessStatus) { + *out = *in + if in.Components != nil { + in, out := &in.Components, &out.Components + *out = make(ReadinessMap, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReadinessStatus. +func (in *ReadinessStatus) DeepCopy() *ReadinessStatus { + if in == nil { + return nil + } + out := new(ReadinessStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemotePolicyConfig) DeepCopyInto(out *RemotePolicyConfig) { + *out = *in + if in.CreateService != nil { + in, out := &in.CreateService, &out.CreateService + *out = new(bool) + **out = **in + } + if in.EnableChecks != nil { + in, out := &in.EnableChecks, &out.EnableChecks + *out = new(bool) + **out = **in + } + if in.FailOpen != nil { + in, out := &in.FailOpen, &out.FailOpen + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemotePolicyConfig. +func (in *RemotePolicyConfig) DeepCopy() *RemotePolicyConfig { + if in == nil { + return nil + } + out := new(RemotePolicyConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteTelemetryConfig) DeepCopyInto(out *RemoteTelemetryConfig) { + *out = *in + if in.CreateService != nil { + in, out := &in.CreateService, &out.CreateService + *out = new(bool) + **out = **in + } + if in.Batching != nil { + in, out := &in.Batching, &out.Batching + *out = new(TelemetryBatchingConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteTelemetryConfig. +func (in *RemoteTelemetryConfig) DeepCopy() *RemoteTelemetryConfig { + if in == nil { + return nil + } + out := new(RemoteTelemetryConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretDiscoveryService) DeepCopyInto(out *SecretDiscoveryService) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Runtime != nil { + in, out := &in.Runtime, &out.Runtime + *out = new(ContainerConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretDiscoveryService. +func (in *SecretDiscoveryService) DeepCopy() *SecretDiscoveryService { + if in == nil { + return nil + } + out := new(SecretDiscoveryService) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecurityConfig) DeepCopyInto(out *SecurityConfig) { + *out = *in + if in.Trust != nil { + in, out := &in.Trust, &out.Trust + *out = new(TrustConfig) + (*in).DeepCopyInto(*out) + } + if in.CertificateAuthority != nil { + in, out := &in.CertificateAuthority, &out.CertificateAuthority + *out = new(CertificateAuthorityConfig) + (*in).DeepCopyInto(*out) + } + if in.Identity != nil { + in, out := &in.Identity, &out.Identity + *out = new(IdentityConfig) + (*in).DeepCopyInto(*out) + } + if in.ControlPlane != nil { + in, out := &in.ControlPlane, &out.ControlPlane + *out = new(ControlPlaneSecurityConfig) + (*in).DeepCopyInto(*out) + } + if in.DataPlane != nil { + in, out := &in.DataPlane, &out.DataPlane + *out = new(DataPlaneSecurityConfig) + (*in).DeepCopyInto(*out) + } + if in.ManageNetworkPolicy != nil { + in, out := &in.ManageNetworkPolicy, &out.ManageNetworkPolicy + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityConfig. +func (in *SecurityConfig) DeepCopy() *SecurityConfig { + if in == nil { + return nil + } + out := new(SecurityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshControlPlane) DeepCopyInto(out *ServiceMeshControlPlane) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshControlPlane. +func (in *ServiceMeshControlPlane) DeepCopy() *ServiceMeshControlPlane { + if in == nil { + return nil + } + out := new(ServiceMeshControlPlane) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshControlPlane) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshControlPlaneList) DeepCopyInto(out *ServiceMeshControlPlaneList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServiceMeshControlPlane, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshControlPlaneList. +func (in *ServiceMeshControlPlaneList) DeepCopy() *ServiceMeshControlPlaneList { + if in == nil { + return nil + } + out := new(ServiceMeshControlPlaneList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshControlPlaneList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StackdriverAccessLogTelemetryConfig) DeepCopyInto(out *StackdriverAccessLogTelemetryConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StackdriverAccessLogTelemetryConfig. +func (in *StackdriverAccessLogTelemetryConfig) DeepCopy() *StackdriverAccessLogTelemetryConfig { + if in == nil { + return nil + } + out := new(StackdriverAccessLogTelemetryConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StackdriverAddonConfig) DeepCopyInto(out *StackdriverAddonConfig) { + *out = *in + if in.Tracer != nil { + in, out := &in.Tracer, &out.Tracer + *out = new(StackdriverTracerConfig) + (*in).DeepCopyInto(*out) + } + if in.Telemetry != nil { + in, out := &in.Telemetry, &out.Telemetry + *out = new(StackdriverTelemetryConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StackdriverAddonConfig. +func (in *StackdriverAddonConfig) DeepCopy() *StackdriverAddonConfig { + if in == nil { + return nil + } + out := new(StackdriverAddonConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StackdriverAuthConfig) DeepCopyInto(out *StackdriverAuthConfig) { + *out = *in + if in.AppCredentials != nil { + in, out := &in.AppCredentials, &out.AppCredentials + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StackdriverAuthConfig. +func (in *StackdriverAuthConfig) DeepCopy() *StackdriverAuthConfig { + if in == nil { + return nil + } + out := new(StackdriverAuthConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StackdriverTelemetryConfig) DeepCopyInto(out *StackdriverTelemetryConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Auth != nil { + in, out := &in.Auth, &out.Auth + *out = new(StackdriverAuthConfig) + (*in).DeepCopyInto(*out) + } + if in.EnableContextGraph != nil { + in, out := &in.EnableContextGraph, &out.EnableContextGraph + *out = new(bool) + **out = **in + } + if in.EnableLogging != nil { + in, out := &in.EnableLogging, &out.EnableLogging + *out = new(bool) + **out = **in + } + if in.EnableMetrics != nil { + in, out := &in.EnableMetrics, &out.EnableMetrics + *out = new(bool) + **out = **in + } + if in.AccessLogging != nil { + in, out := &in.AccessLogging, &out.AccessLogging + *out = new(StackdriverAccessLogTelemetryConfig) + (*in).DeepCopyInto(*out) + } + if in.ConfigOverride != nil { + in, out := &in.ConfigOverride, &out.ConfigOverride + *out = (*in).DeepCopy() + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StackdriverTelemetryConfig. +func (in *StackdriverTelemetryConfig) DeepCopy() *StackdriverTelemetryConfig { + if in == nil { + return nil + } + out := new(StackdriverTelemetryConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StackdriverTracerConfig) DeepCopyInto(out *StackdriverTracerConfig) { + *out = *in + if in.Debug != nil { + in, out := &in.Debug, &out.Debug + *out = new(bool) + **out = **in + } + if in.MaxNumberOfAttributes != nil { + in, out := &in.MaxNumberOfAttributes, &out.MaxNumberOfAttributes + *out = new(int64) + **out = **in + } + if in.MaxNumberOfAnnotations != nil { + in, out := &in.MaxNumberOfAnnotations, &out.MaxNumberOfAnnotations + *out = new(int64) + **out = **in + } + if in.MaxNumberOfMessageEvents != nil { + in, out := &in.MaxNumberOfMessageEvents, &out.MaxNumberOfMessageEvents + *out = new(int64) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StackdriverTracerConfig. +func (in *StackdriverTracerConfig) DeepCopy() *StackdriverTracerConfig { + if in == nil { + return nil + } + out := new(StackdriverTracerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TelemetryBatchingConfig) DeepCopyInto(out *TelemetryBatchingConfig) { + *out = *in + if in.MaxEntries != nil { + in, out := &in.MaxEntries, &out.MaxEntries + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TelemetryBatchingConfig. +func (in *TelemetryBatchingConfig) DeepCopy() *TelemetryBatchingConfig { + if in == nil { + return nil + } + out := new(TelemetryBatchingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TelemetryConfig) DeepCopyInto(out *TelemetryConfig) { + *out = *in + if in.Mixer != nil { + in, out := &in.Mixer, &out.Mixer + *out = new(MixerTelemetryConfig) + (*in).DeepCopyInto(*out) + } + if in.Remote != nil { + in, out := &in.Remote, &out.Remote + *out = new(RemoteTelemetryConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TelemetryConfig. +func (in *TelemetryConfig) DeepCopy() *TelemetryConfig { + if in == nil { + return nil + } + out := new(TelemetryConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TelemetryLoadSheddingConfig) DeepCopyInto(out *TelemetryLoadSheddingConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TelemetryLoadSheddingConfig. +func (in *TelemetryLoadSheddingConfig) DeepCopy() *TelemetryLoadSheddingConfig { + if in == nil { + return nil + } + out := new(TelemetryLoadSheddingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ThirdPartyIdentityConfig) DeepCopyInto(out *ThirdPartyIdentityConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThirdPartyIdentityConfig. +func (in *ThirdPartyIdentityConfig) DeepCopy() *ThirdPartyIdentityConfig { + if in == nil { + return nil + } + out := new(ThirdPartyIdentityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ThreeScaleAddonConfig) DeepCopyInto(out *ThreeScaleAddonConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.ListenAddr != nil { + in, out := &in.ListenAddr, &out.ListenAddr + *out = new(int32) + **out = **in + } + if in.LogGRPC != nil { + in, out := &in.LogGRPC, &out.LogGRPC + *out = new(bool) + **out = **in + } + if in.LogJSON != nil { + in, out := &in.LogJSON, &out.LogJSON + *out = new(bool) + **out = **in + } + if in.Metrics != nil { + in, out := &in.Metrics, &out.Metrics + *out = new(ThreeScaleMetricsConfig) + (*in).DeepCopyInto(*out) + } + if in.System != nil { + in, out := &in.System, &out.System + *out = new(ThreeScaleSystemConfig) + (*in).DeepCopyInto(*out) + } + if in.Client != nil { + in, out := &in.Client, &out.Client + *out = new(ThreeScaleClientConfig) + (*in).DeepCopyInto(*out) + } + if in.GRPC != nil { + in, out := &in.GRPC, &out.GRPC + *out = new(ThreeScaleGRPCConfig) + (*in).DeepCopyInto(*out) + } + if in.Backend != nil { + in, out := &in.Backend, &out.Backend + *out = new(ThreeScaleBackendConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThreeScaleAddonConfig. +func (in *ThreeScaleAddonConfig) DeepCopy() *ThreeScaleAddonConfig { + if in == nil { + return nil + } + out := new(ThreeScaleAddonConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ThreeScaleBackendConfig) DeepCopyInto(out *ThreeScaleBackendConfig) { + *out = *in + if in.EnableCache != nil { + in, out := &in.EnableCache, &out.EnableCache + *out = new(bool) + **out = **in + } + if in.CacheFlushInterval != nil { + in, out := &in.CacheFlushInterval, &out.CacheFlushInterval + *out = new(int32) + **out = **in + } + if in.PolicyFailClosed != nil { + in, out := &in.PolicyFailClosed, &out.PolicyFailClosed + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThreeScaleBackendConfig. +func (in *ThreeScaleBackendConfig) DeepCopy() *ThreeScaleBackendConfig { + if in == nil { + return nil + } + out := new(ThreeScaleBackendConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ThreeScaleClientConfig) DeepCopyInto(out *ThreeScaleClientConfig) { + *out = *in + if in.AllowInsecureConnections != nil { + in, out := &in.AllowInsecureConnections, &out.AllowInsecureConnections + *out = new(bool) + **out = **in + } + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThreeScaleClientConfig. +func (in *ThreeScaleClientConfig) DeepCopy() *ThreeScaleClientConfig { + if in == nil { + return nil + } + out := new(ThreeScaleClientConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ThreeScaleGRPCConfig) DeepCopyInto(out *ThreeScaleGRPCConfig) { + *out = *in + if in.MaxConnTimeout != nil { + in, out := &in.MaxConnTimeout, &out.MaxConnTimeout + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThreeScaleGRPCConfig. +func (in *ThreeScaleGRPCConfig) DeepCopy() *ThreeScaleGRPCConfig { + if in == nil { + return nil + } + out := new(ThreeScaleGRPCConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ThreeScaleMetricsConfig) DeepCopyInto(out *ThreeScaleMetricsConfig) { + *out = *in + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(int32) + **out = **in + } + if in.Report != nil { + in, out := &in.Report, &out.Report + *out = new(bool) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThreeScaleMetricsConfig. +func (in *ThreeScaleMetricsConfig) DeepCopy() *ThreeScaleMetricsConfig { + if in == nil { + return nil + } + out := new(ThreeScaleMetricsConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ThreeScaleSystemConfig) DeepCopyInto(out *ThreeScaleSystemConfig) { + *out = *in + if in.CacheMaxSize != nil { + in, out := &in.CacheMaxSize, &out.CacheMaxSize + *out = new(int64) + **out = **in + } + if in.CacheRefreshRetries != nil { + in, out := &in.CacheRefreshRetries, &out.CacheRefreshRetries + *out = new(int32) + **out = **in + } + if in.CacheRefreshInterval != nil { + in, out := &in.CacheRefreshInterval, &out.CacheRefreshInterval + *out = new(int32) + **out = **in + } + if in.CacheTTL != nil { + in, out := &in.CacheTTL, &out.CacheTTL + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThreeScaleSystemConfig. +func (in *ThreeScaleSystemConfig) DeepCopy() *ThreeScaleSystemConfig { + if in == nil { + return nil + } + out := new(ThreeScaleSystemConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TracingConfig) DeepCopyInto(out *TracingConfig) { + *out = *in + if in.Sampling != nil { + in, out := &in.Sampling, &out.Sampling + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TracingConfig. +func (in *TracingConfig) DeepCopy() *TracingConfig { + if in == nil { + return nil + } + out := new(TracingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrustConfig) DeepCopyInto(out *TrustConfig) { + *out = *in + if in.AdditionalDomains != nil { + in, out := &in.AdditionalDomains, &out.AdditionalDomains + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustConfig. +func (in *TrustConfig) DeepCopy() *TrustConfig { + if in == nil { + return nil + } + out := new(TrustConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeConfig) DeepCopyInto(out *VolumeConfig) { + *out = *in + in.Volume.DeepCopyInto(&out.Volume) + in.Mount.DeepCopyInto(&out.Mount) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeConfig. +func (in *VolumeConfig) DeepCopy() *VolumeConfig { + if in == nil { + return nil + } + out := new(VolumeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ZipkinTracerConfig) DeepCopyInto(out *ZipkinTracerConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZipkinTracerConfig. +func (in *ZipkinTracerConfig) DeepCopy() *ZipkinTracerConfig { + if in == nil { + return nil + } + out := new(ZipkinTracerConfig) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/maistra/istio-operator/pkg/version/version.go b/vendor/github.com/maistra/istio-operator/pkg/version/version.go new file mode 100644 index 0000000000..b55e3cf84c --- /dev/null +++ b/vendor/github.com/maistra/istio-operator/pkg/version/version.go @@ -0,0 +1,50 @@ +package version + +import ( + "fmt" + "runtime" + + sdkVersion "github.com/operator-framework/operator-sdk/version" +) + +var ( + buildVersion = "unknown" + buildGitRevision = "unknown" + buildStatus = "unknown" + buildTag = "unknown" + + // Minimum supported mesh version (nil (all), "v2_0", "v2_1" etc) + minimumSupportedVersion = "v2.0" + + // Info exports the build version information. + Info BuildInfo +) + +// BuildInfo describes version information about the binary build. +type BuildInfo struct { + Version string + GitRevision string + BuildStatus string + GitTag string + GoVersion string + GoArch string + OperatorSDK string + MinimumSupportedVersion string +} + +func (b BuildInfo) String() string { + return fmt.Sprintf("%#v", b) +} + +func init() { + Info = BuildInfo{ + Version: buildVersion, + GitRevision: buildGitRevision, + BuildStatus: buildStatus, + GitTag: buildTag, + GoVersion: runtime.Version(), + GoArch: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH), + OperatorSDK: sdkVersion.Version, + MinimumSupportedVersion: minimumSupportedVersion, + } +} diff --git a/vendor/github.com/mattn/go-colorable/.travis.yml b/vendor/github.com/mattn/go-colorable/.travis.yml index 98db8f060b..7942c565ce 100644 --- a/vendor/github.com/mattn/go-colorable/.travis.yml +++ b/vendor/github.com/mattn/go-colorable/.travis.yml @@ -1,9 +1,15 @@ language: go +sudo: false go: + - 1.13.x - tip before_install: - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover + - go get -t -v ./... + script: - - $HOME/gopath/bin/goveralls -repotoken xnXqRGwgW3SXIguzxf90ZSK1GPYZPaGrw + - ./go.test.sh + +after_success: + - bash <(curl -s https://codecov.io/bash) + diff --git a/vendor/github.com/mattn/go-colorable/README.md b/vendor/github.com/mattn/go-colorable/README.md index 56729a92ca..e055952b66 100644 --- a/vendor/github.com/mattn/go-colorable/README.md +++ b/vendor/github.com/mattn/go-colorable/README.md @@ -1,8 +1,8 @@ # go-colorable -[![Godoc Reference](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable) [![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable) -[![Coverage Status](https://coveralls.io/repos/github/mattn/go-colorable/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-colorable?branch=master) +[![Codecov](https://codecov.io/gh/mattn/go-colorable/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-colorable) +[![GoDoc](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable) [![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable) Colorable writer for windows. diff --git a/vendor/github.com/mattn/go-colorable/colorable_appengine.go b/vendor/github.com/mattn/go-colorable/colorable_appengine.go index 1f28d773d7..1f7806fe16 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_appengine.go +++ b/vendor/github.com/mattn/go-colorable/colorable_appengine.go @@ -9,7 +9,7 @@ import ( _ "github.com/mattn/go-isatty" ) -// NewColorable return new instance of Writer which handle escape sequence. +// NewColorable returns new instance of Writer which handles escape sequence. func NewColorable(file *os.File) io.Writer { if file == nil { panic("nil passed instead of *os.File to NewColorable()") @@ -18,12 +18,20 @@ func NewColorable(file *os.File) io.Writer { return file } -// NewColorableStdout return new instance of Writer which handle escape sequence for stdout. +// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout. func NewColorableStdout() io.Writer { return os.Stdout } -// NewColorableStderr return new instance of Writer which handle escape sequence for stderr. +// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr. func NewColorableStderr() io.Writer { return os.Stderr } + +// EnableColorsStdout enable colors if possible. +func EnableColorsStdout(enabled *bool) func() { + if enabled != nil { + *enabled = true + } + return func() {} +} diff --git a/vendor/github.com/mattn/go-colorable/colorable_others.go b/vendor/github.com/mattn/go-colorable/colorable_others.go index 887f203dc7..08cbd1e0fa 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_others.go +++ b/vendor/github.com/mattn/go-colorable/colorable_others.go @@ -10,7 +10,7 @@ import ( _ "github.com/mattn/go-isatty" ) -// NewColorable return new instance of Writer which handle escape sequence. +// NewColorable returns new instance of Writer which handles escape sequence. func NewColorable(file *os.File) io.Writer { if file == nil { panic("nil passed instead of *os.File to NewColorable()") @@ -19,12 +19,20 @@ func NewColorable(file *os.File) io.Writer { return file } -// NewColorableStdout return new instance of Writer which handle escape sequence for stdout. +// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout. func NewColorableStdout() io.Writer { return os.Stdout } -// NewColorableStderr return new instance of Writer which handle escape sequence for stderr. +// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr. func NewColorableStderr() io.Writer { return os.Stderr } + +// EnableColorsStdout enable colors if possible. +func EnableColorsStdout(enabled *bool) func() { + if enabled != nil { + *enabled = true + } + return func() {} +} diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go index 404e10ca02..41215d7fc4 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_windows.go +++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go @@ -10,6 +10,7 @@ import ( "os" "strconv" "strings" + "sync" "syscall" "unsafe" @@ -27,6 +28,9 @@ const ( backgroundRed = 0x40 backgroundIntensity = 0x80 backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity) + commonLvbUnderscore = 0x8000 + + cENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4 ) const ( @@ -78,10 +82,12 @@ var ( procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo") procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo") procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW") + procGetConsoleMode = kernel32.NewProc("GetConsoleMode") + procSetConsoleMode = kernel32.NewProc("SetConsoleMode") procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer") ) -// Writer provide colorable Writer to the console +// Writer provides colorable Writer to the console type Writer struct { out io.Writer handle syscall.Handle @@ -89,15 +95,20 @@ type Writer struct { oldattr word oldpos coord rest bytes.Buffer + mutex sync.Mutex } -// NewColorable return new instance of Writer which handle escape sequence from File. +// NewColorable returns new instance of Writer which handles escape sequence from File. func NewColorable(file *os.File) io.Writer { if file == nil { panic("nil passed instead of *os.File to NewColorable()") } if isatty.IsTerminal(file.Fd()) { + var mode uint32 + if r, _, _ := procGetConsoleMode.Call(file.Fd(), uintptr(unsafe.Pointer(&mode))); r != 0 && mode&cENABLE_VIRTUAL_TERMINAL_PROCESSING != 0 { + return file + } var csbi consoleScreenBufferInfo handle := syscall.Handle(file.Fd()) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) @@ -106,12 +117,12 @@ func NewColorable(file *os.File) io.Writer { return file } -// NewColorableStdout return new instance of Writer which handle escape sequence for stdout. +// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout. func NewColorableStdout() io.Writer { return NewColorable(os.Stdout) } -// NewColorableStderr return new instance of Writer which handle escape sequence for stderr. +// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr. func NewColorableStderr() io.Writer { return NewColorable(os.Stderr) } @@ -414,8 +425,18 @@ func doTitleSequence(er *bytes.Reader) error { return nil } -// Write write data on console +// returns Atoi(s) unless s == "" in which case it returns def +func atoiWithDefault(s string, def int) (int, error) { + if s == "" { + return def, nil + } + return strconv.Atoi(s) +} + +// Write writes data on console func (w *Writer) Write(data []byte) (n int, err error) { + w.mutex.Lock() + defer w.mutex.Unlock() var csbi consoleScreenBufferInfo procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) @@ -500,7 +521,7 @@ loop: switch m { case 'A': - n, err = strconv.Atoi(buf.String()) + n, err = atoiWithDefault(buf.String(), 1) if err != nil { continue } @@ -508,7 +529,7 @@ loop: csbi.cursorPosition.y -= short(n) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) case 'B': - n, err = strconv.Atoi(buf.String()) + n, err = atoiWithDefault(buf.String(), 1) if err != nil { continue } @@ -516,7 +537,7 @@ loop: csbi.cursorPosition.y += short(n) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) case 'C': - n, err = strconv.Atoi(buf.String()) + n, err = atoiWithDefault(buf.String(), 1) if err != nil { continue } @@ -524,7 +545,7 @@ loop: csbi.cursorPosition.x += short(n) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) case 'D': - n, err = strconv.Atoi(buf.String()) + n, err = atoiWithDefault(buf.String(), 1) if err != nil { continue } @@ -557,6 +578,9 @@ loop: if err != nil { continue } + if n < 1 { + n = 1 + } procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.x = short(n - 1) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) @@ -635,6 +659,20 @@ loop: } procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + case 'X': + n := 0 + if buf.Len() > 0 { + n, err = strconv.Atoi(buf.String()) + if err != nil { + continue + } + } + procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + var cursor coord + var written dword + cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} + procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) case 'm': procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) attr := csbi.attributes @@ -650,14 +688,19 @@ loop: switch { case n == 0 || n == 100: attr = w.oldattr - case 1 <= n && n <= 5: - attr |= foregroundIntensity - case n == 7: - attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4) - case n == 22 || n == 25: + case n == 4: + attr |= commonLvbUnderscore + case (1 <= n && n <= 3) || n == 5: attr |= foregroundIntensity - case n == 27: - attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4) + case n == 7 || n == 27: + attr = + (attr &^ (foregroundMask | backgroundMask)) | + ((attr & foregroundMask) << 4) | + ((attr & backgroundMask) >> 4) + case n == 22: + attr &^= foregroundIntensity + case n == 24: + attr &^= commonLvbUnderscore case 30 <= n && n <= 37: attr &= backgroundMask if (n-30)&1 != 0 { @@ -676,7 +719,7 @@ loop: n256setup() } attr &= backgroundMask - attr |= n256foreAttr[n256] + attr |= n256foreAttr[n256%len(n256foreAttr)] i += 2 } } else if len(token) == 5 && token[i+1] == "2" { @@ -718,7 +761,7 @@ loop: n256setup() } attr &= foregroundMask - attr |= n256backAttr[n256] + attr |= n256backAttr[n256%len(n256backAttr)] i += 2 } } else if len(token) == 5 && token[i+1] == "2" { @@ -978,3 +1021,23 @@ func n256setup() { n256backAttr[i] = c.backgroundAttr() } } + +// EnableColorsStdout enable colors if possible. +func EnableColorsStdout(enabled *bool) func() { + var mode uint32 + h := os.Stdout.Fd() + if r, _, _ := procGetConsoleMode.Call(h, uintptr(unsafe.Pointer(&mode))); r != 0 { + if r, _, _ = procSetConsoleMode.Call(h, uintptr(mode|cENABLE_VIRTUAL_TERMINAL_PROCESSING)); r != 0 { + if enabled != nil { + *enabled = true + } + return func() { + procSetConsoleMode.Call(h, uintptr(mode)) + } + } + } + if enabled != nil { + *enabled = true + } + return func() {} +} diff --git a/vendor/github.com/mattn/go-colorable/go.test.sh b/vendor/github.com/mattn/go-colorable/go.test.sh new file mode 100644 index 0000000000..012162b077 --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/go.test.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -e +echo "" > coverage.txt + +for d in $(go list ./... | grep -v vendor); do + go test -race -coverprofile=profile.out -covermode=atomic "$d" + if [ -f profile.out ]; then + cat profile.out >> coverage.txt + rm profile.out + fi +done diff --git a/vendor/github.com/mattn/go-colorable/noncolorable.go b/vendor/github.com/mattn/go-colorable/noncolorable.go index 9721e16f4b..95f2c6be25 100644 --- a/vendor/github.com/mattn/go-colorable/noncolorable.go +++ b/vendor/github.com/mattn/go-colorable/noncolorable.go @@ -5,17 +5,17 @@ import ( "io" ) -// NonColorable hold writer but remove escape sequence. +// NonColorable holds writer but removes escape sequence. type NonColorable struct { out io.Writer } -// NewNonColorable return new instance of Writer which remove escape sequence from Writer. +// NewNonColorable returns new instance of Writer which removes escape sequence from Writer. func NewNonColorable(w io.Writer) io.Writer { return &NonColorable{out: w} } -// Write write data on console +// Write writes data on console func (w *NonColorable) Write(data []byte) (n int, err error) { er := bytes.NewReader(data) var bw [1]byte diff --git a/vendor/github.com/mattn/go-isatty/.travis.yml b/vendor/github.com/mattn/go-isatty/.travis.yml index 5597e026dd..604314dd44 100644 --- a/vendor/github.com/mattn/go-isatty/.travis.yml +++ b/vendor/github.com/mattn/go-isatty/.travis.yml @@ -1,13 +1,14 @@ language: go +sudo: false go: + - 1.13.x - tip -os: - - linux - - osx - before_install: - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover + - go get -t -v ./... + script: - - $HOME/gopath/bin/goveralls -repotoken 3gHdORO5k5ziZcWMBxnd9LrMZaJs8m9x5 + - ./go.test.sh + +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/mattn/go-isatty/README.md b/vendor/github.com/mattn/go-isatty/README.md index 1e69004bb0..38418353e3 100644 --- a/vendor/github.com/mattn/go-isatty/README.md +++ b/vendor/github.com/mattn/go-isatty/README.md @@ -1,7 +1,7 @@ # go-isatty [![Godoc Reference](https://godoc.org/github.com/mattn/go-isatty?status.svg)](http://godoc.org/github.com/mattn/go-isatty) -[![Build Status](https://travis-ci.org/mattn/go-isatty.svg?branch=master)](https://travis-ci.org/mattn/go-isatty) +[![Codecov](https://codecov.io/gh/mattn/go-isatty/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-isatty) [![Coverage Status](https://coveralls.io/repos/github/mattn/go-isatty/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-isatty?branch=master) [![Go Report Card](https://goreportcard.com/badge/mattn/go-isatty)](https://goreportcard.com/report/mattn/go-isatty) diff --git a/vendor/github.com/mattn/go-isatty/go.test.sh b/vendor/github.com/mattn/go-isatty/go.test.sh new file mode 100644 index 0000000000..012162b077 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/go.test.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -e +echo "" > coverage.txt + +for d in $(go list ./... | grep -v vendor); do + go test -race -coverprofile=profile.out -covermode=atomic "$d" + if [ -f profile.out ]; then + cat profile.out >> coverage.txt + rm profile.out + fi +done diff --git a/vendor/github.com/mattn/go-isatty/isatty_android.go b/vendor/github.com/mattn/go-isatty/isatty_android.go deleted file mode 100644 index d3567cb5bf..0000000000 --- a/vendor/github.com/mattn/go-isatty/isatty_android.go +++ /dev/null @@ -1,23 +0,0 @@ -// +build android - -package isatty - -import ( - "syscall" - "unsafe" -) - -const ioctlReadTermios = syscall.TCGETS - -// IsTerminal return true if the file descriptor is terminal. -func IsTerminal(fd uintptr) bool { - var termios syscall.Termios - _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) - return err == 0 -} - -// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2 -// terminal. This is also always false on this environment. -func IsCygwinTerminal(fd uintptr) bool { - return false -} diff --git a/vendor/github.com/mattn/go-isatty/isatty_bsd.go b/vendor/github.com/mattn/go-isatty/isatty_bsd.go index 07e93039db..711f288085 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_bsd.go +++ b/vendor/github.com/mattn/go-isatty/isatty_bsd.go @@ -3,18 +3,12 @@ package isatty -import ( - "syscall" - "unsafe" -) - -const ioctlReadTermios = syscall.TIOCGETA +import "golang.org/x/sys/unix" // IsTerminal return true if the file descriptor is terminal. func IsTerminal(fd uintptr) bool { - var termios syscall.Termios - _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) - return err == 0 + _, err := unix.IoctlGetTermios(int(fd), unix.TIOCGETA) + return err == nil } // IsCygwinTerminal return true if the file descriptor is a cygwin or msys2 diff --git a/vendor/github.com/mattn/go-isatty/isatty_plan9.go b/vendor/github.com/mattn/go-isatty/isatty_plan9.go new file mode 100644 index 0000000000..c5b6e0c084 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/isatty_plan9.go @@ -0,0 +1,22 @@ +// +build plan9 + +package isatty + +import ( + "syscall" +) + +// IsTerminal returns true if the given file descriptor is a terminal. +func IsTerminal(fd uintptr) bool { + path, err := syscall.Fd2path(int(fd)) + if err != nil { + return false + } + return path == "/dev/cons" || path == "/mnt/term/dev/cons" +} + +// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2 +// terminal. This is also always false on this environment. +func IsCygwinTerminal(fd uintptr) bool { + return false +} diff --git a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go index 453b025d0d..31a1ca973c 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go +++ b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go @@ -1,6 +1,5 @@ // +build linux aix // +build !appengine -// +build !android package isatty diff --git a/vendor/github.com/mattn/go-isatty/isatty_windows.go b/vendor/github.com/mattn/go-isatty/isatty_windows.go index af51cbcaa4..1fa8691540 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_windows.go +++ b/vendor/github.com/mattn/go-isatty/isatty_windows.go @@ -4,6 +4,7 @@ package isatty import ( + "errors" "strings" "syscall" "unicode/utf16" @@ -11,15 +12,18 @@ import ( ) const ( - fileNameInfo uintptr = 2 - fileTypePipe = 3 + objectNameInfo uintptr = 1 + fileNameInfo = 2 + fileTypePipe = 3 ) var ( kernel32 = syscall.NewLazyDLL("kernel32.dll") + ntdll = syscall.NewLazyDLL("ntdll.dll") procGetConsoleMode = kernel32.NewProc("GetConsoleMode") procGetFileInformationByHandleEx = kernel32.NewProc("GetFileInformationByHandleEx") procGetFileType = kernel32.NewProc("GetFileType") + procNtQueryObject = ntdll.NewProc("NtQueryObject") ) func init() { @@ -45,7 +49,10 @@ func isCygwinPipeName(name string) bool { return false } - if token[0] != `\msys` && token[0] != `\cygwin` { + if token[0] != `\msys` && + token[0] != `\cygwin` && + token[0] != `\Device\NamedPipe\msys` && + token[0] != `\Device\NamedPipe\cygwin` { return false } @@ -68,11 +75,35 @@ func isCygwinPipeName(name string) bool { return true } +// getFileNameByHandle use the undocomented ntdll NtQueryObject to get file full name from file handler +// since GetFileInformationByHandleEx is not avilable under windows Vista and still some old fashion +// guys are using Windows XP, this is a workaround for those guys, it will also work on system from +// Windows vista to 10 +// see https://stackoverflow.com/a/18792477 for details +func getFileNameByHandle(fd uintptr) (string, error) { + if procNtQueryObject == nil { + return "", errors.New("ntdll.dll: NtQueryObject not supported") + } + + var buf [4 + syscall.MAX_PATH]uint16 + var result int + r, _, e := syscall.Syscall6(procNtQueryObject.Addr(), 5, + fd, objectNameInfo, uintptr(unsafe.Pointer(&buf)), uintptr(2*len(buf)), uintptr(unsafe.Pointer(&result)), 0) + if r != 0 { + return "", e + } + return string(utf16.Decode(buf[4 : 4+buf[0]/2])), nil +} + // IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2 // terminal. func IsCygwinTerminal(fd uintptr) bool { if procGetFileInformationByHandleEx == nil { - return false + name, err := getFileNameByHandle(fd) + if err != nil { + return false + } + return isCygwinPipeName(name) } // Cygwin/msys's pty is a pipe. diff --git a/vendor/github.com/mattn/go-isatty/renovate.json b/vendor/github.com/mattn/go-isatty/renovate.json new file mode 100644 index 0000000000..5ae9d96b74 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/renovate.json @@ -0,0 +1,8 @@ +{ + "extends": [ + "config:base" + ], + "postUpdateOptions": [ + "gomodTidy" + ] +} diff --git a/vendor/github.com/operator-framework/api/pkg/lib/version/version.go b/vendor/github.com/operator-framework/api/pkg/lib/version/version.go new file mode 100644 index 0000000000..713c5779bb --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/lib/version/version.go @@ -0,0 +1,67 @@ +package version + +import ( + "encoding/json" + + "github.com/blang/semver" +) + +// +k8s:openapi-gen=true +// OperatorVersion is a wrapper around semver.Version which supports correct +// marshaling to YAML and JSON. +// +kubebuilder:validation:Type=string +type OperatorVersion struct { + semver.Version `json:"-"` +} + +// DeepCopyInto creates a deep-copy of the Version value. +func (v *OperatorVersion) DeepCopyInto(out *OperatorVersion) { + out.Major = v.Major + out.Minor = v.Minor + out.Patch = v.Patch + + if v.Pre != nil { + pre := make([]semver.PRVersion, len(v.Pre)) + copy(pre, v.Pre) + out.Pre = pre + } + + if v.Build != nil { + build := make([]string, len(v.Build)) + copy(build, v.Build) + out.Build = build + } +} + +// MarshalJSON implements the encoding/json.Marshaler interface. +func (v OperatorVersion) MarshalJSON() ([]byte, error) { + return json.Marshal(v.String()) +} + +// UnmarshalJSON implements the encoding/json.Unmarshaler interface. +func (v *OperatorVersion) UnmarshalJSON(data []byte) (err error) { + var versionString string + + if err = json.Unmarshal(data, &versionString); err != nil { + return + } + + version := semver.Version{} + version, err = semver.ParseTolerant(versionString) + if err != nil { + return err + } + v.Version = version + return +} + +// OpenAPISchemaType is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +// +// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators +func (_ OperatorVersion) OpenAPISchemaType() []string { return []string{"string"} } + +// OpenAPISchemaFormat is used by the kube-openapi generator when constructing +// the OpenAPI spec of this type. +// "semver" is not a standard openapi format but tooling may use the value regardless +func (_ OperatorVersion) OpenAPISchemaFormat() string { return "semver" } diff --git a/vendor/github.com/operator-framework/api/pkg/operators/catalogsource_types.go b/vendor/github.com/operator-framework/api/pkg/operators/catalogsource_types.go new file mode 100644 index 0000000000..ff810f550a --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/catalogsource_types.go @@ -0,0 +1,142 @@ +package operators + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +// CatalogSourceKind is the PascalCase name of a CatalogSource's kind. +const CatalogSourceKind = "CatalogSource" + +// SourceType indicates the type of backing store for a CatalogSource +type SourceType string + +const ( + // SourceTypeInternal (deprecated) specifies a CatalogSource of type SourceTypeConfigmap + SourceTypeInternal SourceType = "internal" + + // SourceTypeConfigmap specifies a CatalogSource that generates a configmap-server registry + SourceTypeConfigmap SourceType = "configmap" + + // SourceTypeGrpc specifies a CatalogSource that can use an operator registry image to generate a + // registry-server or connect to a pre-existing registry at an address. + SourceTypeGrpc SourceType = "grpc" +) + +type CatalogSourceSpec struct { + // SourceType is the type of source + SourceType SourceType + + // ConfigMap is the name of the ConfigMap to be used to back a configmap-server registry. + // Only used when SourceType = SourceTypeConfigmap or SourceTypeInternal. + // +Optional + ConfigMap string + + // Address is a host that OLM can use to connect to a pre-existing registry. + // Format: : + // Only used when SourceType = SourceTypeGrpc. + // Ignored when the Image field is set. + // +Optional + Address string + + // Image is an operator-registry container image to instantiate a registry-server with. + // Only used when SourceType = SourceTypeGrpc. + // If present, the address field is ignored. + // +Optional + Image string + + // UpdateStrategy defines how updated catalog source images can be discovered + // Consists of an interval that defines polling duration and an embedded strategy type + // +Optional + UpdateStrategy *UpdateStrategy + + // Secrets represent set of secrets that can be used to access the contents of the catalog. + // It is best to keep this list small, since each will need to be tried for every catalog entry. + // +Optional + Secrets []string + + // Metadata + DisplayName string + Description string + Publisher string + Icon Icon +} + +// UpdateStrategy holds all the different types of catalog source update strategies +// Currently only registry polling strategy is implemented +type UpdateStrategy struct { + *RegistryPoll +} + +type RegistryPoll struct { + // Interval is used to determine the time interval between checks of the latest catalog source version. + // The catalog operator polls to see if a new version of the catalog source is available. + // If available, the latest image is pulled and gRPC traffic is directed to the latest catalog source. + Interval *metav1.Duration +} + +type RegistryServiceStatus struct { + Protocol string + ServiceName string + ServiceNamespace string + Port string + CreatedAt metav1.Time +} + +type GRPCConnectionState struct { + Address string + LastObservedState string + LastConnectTime metav1.Time +} + +func (s *RegistryServiceStatus) Address() string { + return fmt.Sprintf("%s.%s.svc:%s", s.ServiceName, s.ServiceNamespace, s.Port) +} + +type CatalogSourceStatus struct { + Message string `json:"message,omitempty"` + Reason ConditionReason `json:"reason,omitempty"` + ConfigMapResource *ConfigMapResourceReference + RegistryServiceStatus *RegistryServiceStatus + GRPCConnectionState *GRPCConnectionState + LatestImageRegistryPoll *metav1.Time +} + +type ConfigMapResourceReference struct { + Name string + Namespace string + UID types.UID + ResourceVersion string + LastUpdateTime metav1.Time +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient + +// CatalogSource is a repository of CSVs, CRDs, and operator packages. +type CatalogSource struct { + metav1.TypeMeta + metav1.ObjectMeta + + Spec CatalogSourceSpec + Status CatalogSourceStatus +} + +func (c *CatalogSource) Address() string { + if c.Spec.Address != "" { + return c.Spec.Address + } + return c.Status.RegistryServiceStatus.Address() +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// CatalogSourceList is a list of CatalogSource resources. +type CatalogSourceList struct { + metav1.TypeMeta + metav1.ListMeta + + Items []CatalogSource +} diff --git a/vendor/github.com/operator-framework/api/pkg/operators/clusterserviceversion_types.go b/vendor/github.com/operator-framework/api/pkg/operators/clusterserviceversion_types.go new file mode 100644 index 0000000000..fded5c3cb6 --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/clusterserviceversion_types.go @@ -0,0 +1,516 @@ +package operators + +import ( + "encoding/json" + "fmt" + "sort" + + appsv1 "k8s.io/api/apps/v1" + rbac "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/operator-framework/api/pkg/lib/version" +) + +// ClusterServiceVersionKind is the PascalCase name of a CSV's kind. +const ClusterServiceVersionKind = "ClusterServiceVersion" + +// InstallModeType is a supported type of install mode for CSV installation +type InstallModeType string + +const ( + // InstallModeTypeOwnNamespace indicates that the operator can be a member of an `OperatorGroup` that selects its own namespace. + InstallModeTypeOwnNamespace InstallModeType = "OwnNamespace" + // InstallModeTypeSingleNamespace indicates that the operator can be a member of an `OperatorGroup` that selects one namespace. + InstallModeTypeSingleNamespace InstallModeType = "SingleNamespace" + // InstallModeTypeMultiNamespace indicates that the operator can be a member of an `OperatorGroup` that selects more than one namespace. + InstallModeTypeMultiNamespace InstallModeType = "MultiNamespace" + // InstallModeTypeAllNamespaces indicates that the operator can be a member of an `OperatorGroup` that selects all namespaces (target namespace set is the empty string ""). + InstallModeTypeAllNamespaces InstallModeType = "AllNamespaces" + + InstallStrategyNameDeployment = "deployment" +) + +// InstallMode associates an InstallModeType with a flag representing if the CSV supports it +type InstallMode struct { + Type InstallModeType + Supported bool +} + +// InstallModeSet is a mapping of unique InstallModeTypes to whether they are supported. +type InstallModeSet map[InstallModeType]bool + +// NamedInstallStrategy represents the block of an ClusterServiceVersion resource +// where the install strategy is specified. +type NamedInstallStrategy struct { + StrategyName string + StrategySpec StrategyDetailsDeployment +} + +// StrategyDeploymentPermissions describe the rbac rules and service account needed by the install strategy +type StrategyDeploymentPermissions struct { + ServiceAccountName string + Rules []rbac.PolicyRule +} + +// StrategyDeploymentSpec contains the name and spec for the deployment ALM should create +type StrategyDeploymentSpec struct { + Name string + Spec appsv1.DeploymentSpec +} + +// StrategyDetailsDeployment represents the parsed details of a Deployment +// InstallStrategy. +type StrategyDetailsDeployment struct { + DeploymentSpecs []StrategyDeploymentSpec + Permissions []StrategyDeploymentPermissions + ClusterPermissions []StrategyDeploymentPermissions +} + +func (d *StrategyDetailsDeployment) GetStrategyName() string { + return InstallStrategyNameDeployment +} + +// StatusDescriptor describes a field in a status block of a CRD so that OLM can consume it +type StatusDescriptor struct { + Path string + DisplayName string + Description string + XDescriptors []string + Value json.RawMessage +} + +// SpecDescriptor describes a field in a spec block of a CRD so that OLM can consume it +type SpecDescriptor struct { + Path string + DisplayName string + Description string + XDescriptors []string + Value json.RawMessage +} + +// ActionDescriptor describes a declarative action that can be performed on a custom resource instance +type ActionDescriptor struct { + Path string + DisplayName string + Description string + XDescriptors []string + Value json.RawMessage +} + +// CRDDescription provides details to OLM about the CRDs +type CRDDescription struct { + Name string + Version string + Kind string + DisplayName string + Description string + Resources []APIResourceReference + StatusDescriptors []StatusDescriptor + SpecDescriptors []SpecDescriptor + ActionDescriptor []ActionDescriptor +} + +// APIServiceDescription provides details to OLM about apis provided via aggregation +type APIServiceDescription struct { + Name string + Group string + Version string + Kind string + DeploymentName string + ContainerPort int32 + DisplayName string + Description string + Resources []APIResourceReference + StatusDescriptors []StatusDescriptor + SpecDescriptors []SpecDescriptor + ActionDescriptor []ActionDescriptor +} + +// APIResourceReference is a Kubernetes resource type used by a custom resource +type APIResourceReference struct { + Name string + Kind string + Version string +} + +// GetName returns the name of an APIService as derived from its group and version. +func (d APIServiceDescription) GetName() string { + return fmt.Sprintf("%s.%s", d.Version, d.Group) +} + +// CustomResourceDefinitions declares all of the CRDs managed or required by +// an operator being ran by ClusterServiceVersion. +// +// If the CRD is present in the Owned list, it is implicitly required. +type CustomResourceDefinitions struct { + Owned []CRDDescription + Required []CRDDescription +} + +// APIServiceDefinitions declares all of the extension apis managed or required by +// an operator being ran by ClusterServiceVersion. +type APIServiceDefinitions struct { + Owned []APIServiceDescription + Required []APIServiceDescription +} + +// ClusterServiceVersionSpec declarations tell OLM how to install an operator +// that can manage apps for a given version. +type ClusterServiceVersionSpec struct { + InstallStrategy NamedInstallStrategy + Version version.OperatorVersion + Maturity string + CustomResourceDefinitions CustomResourceDefinitions + APIServiceDefinitions APIServiceDefinitions + NativeAPIs []metav1.GroupVersionKind + MinKubeVersion string + DisplayName string + Description string + Keywords []string + Maintainers []Maintainer + Provider AppLink + Links []AppLink + Icon []Icon + + // InstallModes specify supported installation types + // +optional + InstallModes []InstallMode + + // The name of a CSV this one replaces. Should match the `metadata.Name` field of the old CSV. + // +optional + Replaces string + + // Map of string keys and values that can be used to organize and categorize + // (scope and select) objects. + // +optional + Labels map[string]string + + // Annotations is an unstructured key value map stored with a resource that may be + // set by external tools to store and retrieve arbitrary metadata. + // +optional + Annotations map[string]string + + // Label selector for related resources. + // +optional + Selector *metav1.LabelSelector +} + +type Maintainer struct { + Name string + Email string +} + +type AppLink struct { + Name string + URL string +} + +type Icon struct { + Data string + MediaType string +} + +// ClusterServiceVersionPhase is a label for the condition of a ClusterServiceVersion at the current time. +type ClusterServiceVersionPhase string + +// These are the valid phases of ClusterServiceVersion +const ( + CSVPhaseNone = "" + // CSVPhasePending means the csv has been accepted by the system, but the install strategy has not been attempted. + // This is likely because there are unmet requirements. + CSVPhasePending ClusterServiceVersionPhase = "Pending" + // CSVPhaseInstallReady means that the requirements are met but the install strategy has not been run. + CSVPhaseInstallReady ClusterServiceVersionPhase = "InstallReady" + // CSVPhaseInstalling means that the install strategy has been initiated but not completed. + CSVPhaseInstalling ClusterServiceVersionPhase = "Installing" + // CSVPhaseSucceeded means that the resources in the CSV were created successfully. + CSVPhaseSucceeded ClusterServiceVersionPhase = "Succeeded" + // CSVPhaseFailed means that the install strategy could not be successfully completed. + CSVPhaseFailed ClusterServiceVersionPhase = "Failed" + // CSVPhaseUnknown means that for some reason the state of the csv could not be obtained. + CSVPhaseUnknown ClusterServiceVersionPhase = "Unknown" + // CSVPhaseReplacing means that a newer CSV has been created and the csv's resources will be transitioned to a new owner. + CSVPhaseReplacing ClusterServiceVersionPhase = "Replacing" + // CSVPhaseDeleting means that a CSV has been replaced by a new one and will be checked for safety before being deleted + CSVPhaseDeleting ClusterServiceVersionPhase = "Deleting" + // CSVPhaseAny matches all other phases in CSV queries + CSVPhaseAny ClusterServiceVersionPhase = "" +) + +// ConditionReason is a camelcased reason for the state transition +type ConditionReason string + +const ( + CSVReasonRequirementsUnknown ConditionReason = "RequirementsUnknown" + CSVReasonRequirementsNotMet ConditionReason = "RequirementsNotMet" + CSVReasonRequirementsMet ConditionReason = "AllRequirementsMet" + CSVReasonOwnerConflict ConditionReason = "OwnerConflict" + CSVReasonComponentFailed ConditionReason = "InstallComponentFailed" + CSVReasonInvalidStrategy ConditionReason = "InvalidInstallStrategy" + CSVReasonWaiting ConditionReason = "InstallWaiting" + CSVReasonInstallSuccessful ConditionReason = "InstallSucceeded" + CSVReasonInstallCheckFailed ConditionReason = "InstallCheckFailed" + CSVReasonComponentUnhealthy ConditionReason = "ComponentUnhealthy" + CSVReasonBeingReplaced ConditionReason = "BeingReplaced" + CSVReasonReplaced ConditionReason = "Replaced" + CSVReasonNeedsReinstall ConditionReason = "NeedsReinstall" + CSVReasonNeedsCertRotation ConditionReason = "NeedsCertRotation" + CSVReasonAPIServiceResourceIssue ConditionReason = "APIServiceResourceIssue" + CSVReasonAPIServiceResourcesNeedReinstall ConditionReason = "APIServiceResourcesNeedReinstall" + CSVReasonAPIServiceInstallFailed ConditionReason = "APIServiceInstallFailed" + CSVReasonCopied ConditionReason = "Copied" + CSVReasonInvalidInstallModes ConditionReason = "InvalidInstallModes" + CSVReasonNoTargetNamespaces ConditionReason = "NoTargetNamespaces" + CSVReasonUnsupportedOperatorGroup ConditionReason = "UnsupportedOperatorGroup" + CSVReasonNoOperatorGroup ConditionReason = "NoOperatorGroup" + CSVReasonTooManyOperatorGroups ConditionReason = "TooManyOperatorGroups" + CSVReasonInterOperatorGroupOwnerConflict ConditionReason = "InterOperatorGroupOwnerConflict" + CSVReasonCannotModifyStaticOperatorGroupProvidedAPIs ConditionReason = "CannotModifyStaticOperatorGroupProvidedAPIs" +) + +// Conditions appear in the status as a record of state transitions on the ClusterServiceVersion +type ClusterServiceVersionCondition struct { + // Condition of the ClusterServiceVersion + Phase ClusterServiceVersionPhase + // A human readable message indicating details about why the ClusterServiceVersion is in this condition. + // +optional + Message string + // A brief CamelCase message indicating details about why the ClusterServiceVersion is in this state. + // e.g. 'RequirementsNotMet' + // +optional + Reason ConditionReason + // Last time we updated the status + // +optional + LastUpdateTime *metav1.Time + // Last time the status transitioned from one status to another. + // +optional + LastTransitionTime *metav1.Time +} + +// OwnsCRD determines whether the current CSV owns a paritcular CRD. +func (csv ClusterServiceVersion) OwnsCRD(name string) bool { + for _, desc := range csv.Spec.CustomResourceDefinitions.Owned { + if desc.Name == name { + return true + } + } + + return false +} + +// OwnsAPIService determines whether the current CSV owns a paritcular APIService. +func (csv ClusterServiceVersion) OwnsAPIService(name string) bool { + for _, desc := range csv.Spec.APIServiceDefinitions.Owned { + apiServiceName := fmt.Sprintf("%s.%s", desc.Version, desc.Group) + if apiServiceName == name { + return true + } + } + + return false +} + +// StatusReason is a camelcased reason for the status of a RequirementStatus or DependentStatus +type StatusReason string + +const ( + RequirementStatusReasonPresent StatusReason = "Present" + RequirementStatusReasonNotPresent StatusReason = "NotPresent" + RequirementStatusReasonPresentNotSatisfied StatusReason = "PresentNotSatisfied" + // The CRD is present but the Established condition is False (not available) + RequirementStatusReasonNotAvailable StatusReason = "PresentNotAvailable" + DependentStatusReasonSatisfied StatusReason = "Satisfied" + DependentStatusReasonNotSatisfied StatusReason = "NotSatisfied" +) + +// DependentStatus is the status for a dependent requirement (to prevent infinite nesting) +type DependentStatus struct { + Group string + Version string + Kind string + Status StatusReason + UUID string + Message string +} + +type RequirementStatus struct { + Group string + Version string + Kind string + Name string + Status StatusReason + Message string + UUID string + Dependents []DependentStatus +} + +// ClusterServiceVersionStatus represents information about the status of a pod. Status may trail the actual +// state of a system. +type ClusterServiceVersionStatus struct { + // Current condition of the ClusterServiceVersion + Phase ClusterServiceVersionPhase + // A human readable message indicating details about why the ClusterServiceVersion is in this condition. + // +optional + Message string + // A brief CamelCase message indicating details about why the ClusterServiceVersion is in this state. + // e.g. 'RequirementsNotMet' + // +optional + Reason ConditionReason + // Last time we updated the status + // +optional + LastUpdateTime *metav1.Time + // Last time the status transitioned from one status to another. + // +optional + LastTransitionTime *metav1.Time + // List of conditions, a history of state transitions + Conditions []ClusterServiceVersionCondition + // The status of each requirement for this CSV + RequirementStatus []RequirementStatus + // Last time the owned APIService certs were updated + // +optional + CertsLastUpdated *metav1.Time + // Time the owned APIService certs will rotate next + // +optional + CertsRotateAt *metav1.Time +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient + +// ClusterServiceVersion is a Custom Resource of type `ClusterServiceVersionSpec`. +type ClusterServiceVersion struct { + metav1.TypeMeta + metav1.ObjectMeta + + Spec ClusterServiceVersionSpec + Status ClusterServiceVersionStatus +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ClusterServiceVersionList represents a list of ClusterServiceVersions. +type ClusterServiceVersionList struct { + metav1.TypeMeta + metav1.ListMeta + + Items []ClusterServiceVersion +} + +// GetAllCRDDescriptions returns a deduplicated set of CRDDescriptions that is +// the union of the owned and required CRDDescriptions. +// +// Descriptions with the same name prefer the value in Owned. +// Descriptions are returned in alphabetical order. +func (csv ClusterServiceVersion) GetAllCRDDescriptions() []CRDDescription { + set := make(map[string]CRDDescription) + for _, required := range csv.Spec.CustomResourceDefinitions.Required { + set[required.Name] = required + } + + for _, owned := range csv.Spec.CustomResourceDefinitions.Owned { + set[owned.Name] = owned + } + + keys := make([]string, 0) + for key := range set { + keys = append(keys, key) + } + sort.StringSlice(keys).Sort() + + descs := make([]CRDDescription, 0) + for _, key := range keys { + descs = append(descs, set[key]) + } + + return descs +} + +// GetAllAPIServiceDescriptions returns a deduplicated set of APIServiceDescriptions that is +// the union of the owned and required APIServiceDescriptions. +// +// Descriptions with the same name prefer the value in Owned. +// Descriptions are returned in alphabetical order. +func (csv ClusterServiceVersion) GetAllAPIServiceDescriptions() []APIServiceDescription { + set := make(map[string]APIServiceDescription) + for _, required := range csv.Spec.APIServiceDefinitions.Required { + name := fmt.Sprintf("%s.%s", required.Version, required.Group) + set[name] = required + } + + for _, owned := range csv.Spec.APIServiceDefinitions.Owned { + name := fmt.Sprintf("%s.%s", owned.Version, owned.Group) + set[name] = owned + } + + keys := make([]string, 0) + for key := range set { + keys = append(keys, key) + } + sort.StringSlice(keys).Sort() + + descs := make([]APIServiceDescription, 0) + for _, key := range keys { + descs = append(descs, set[key]) + } + + return descs +} + +// GetRequiredAPIServiceDescriptions returns a deduplicated set of required APIServiceDescriptions +// with the intersection of required and owned removed +// Equivalent to the set subtraction required - owned +// +// Descriptions are returned in alphabetical order. +func (csv ClusterServiceVersion) GetRequiredAPIServiceDescriptions() []APIServiceDescription { + set := make(map[string]APIServiceDescription) + for _, required := range csv.Spec.APIServiceDefinitions.Required { + name := fmt.Sprintf("%s.%s", required.Version, required.Group) + set[name] = required + } + + // Remove any shared owned from the set + for _, owned := range csv.Spec.APIServiceDefinitions.Owned { + name := fmt.Sprintf("%s.%s", owned.Version, owned.Group) + if _, ok := set[name]; ok { + delete(set, name) + } + } + + keys := make([]string, 0) + for key := range set { + keys = append(keys, key) + } + sort.StringSlice(keys).Sort() + + descs := make([]APIServiceDescription, 0) + for _, key := range keys { + descs = append(descs, set[key]) + } + + return descs +} + +// GetOwnedAPIServiceDescriptions returns a deduplicated set of owned APIServiceDescriptions +// +// Descriptions are returned in alphabetical order. +func (csv ClusterServiceVersion) GetOwnedAPIServiceDescriptions() []APIServiceDescription { + set := make(map[string]APIServiceDescription) + for _, owned := range csv.Spec.APIServiceDefinitions.Owned { + name := owned.GetName() + set[name] = owned + } + + keys := make([]string, 0) + for key := range set { + keys = append(keys, key) + } + sort.StringSlice(keys).Sort() + + descs := make([]APIServiceDescription, 0) + for _, key := range keys { + descs = append(descs, set[key]) + } + + return descs +} diff --git a/vendor/github.com/operator-framework/api/pkg/operators/doc.go b/vendor/github.com/operator-framework/api/pkg/operators/doc.go new file mode 100644 index 0000000000..ee6b62a7d2 --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/doc.go @@ -0,0 +1,5 @@ +// +k8s:deepcopy-gen=package +// +groupName=operators.coreos.com +// +kubebuilder:skip +// Package operators contains all resource types of the operators.coreos.com API group. +package operators diff --git a/vendor/github.com/operator-framework/api/pkg/operators/installplan_types.go b/vendor/github.com/operator-framework/api/pkg/operators/installplan_types.go new file mode 100644 index 0000000000..fcd7764e87 --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/installplan_types.go @@ -0,0 +1,392 @@ +package operators + +import ( + "errors" + "fmt" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// InstallPlanKind is the PascalCase name of an InstallPlan's kind. +const InstallPlanKind = "InstallPlan" + +// Approval is the user approval policy for an InstallPlan. +type Approval string + +const ( + ApprovalAutomatic Approval = "Automatic" + ApprovalManual Approval = "Manual" +) + +// InstallPlanSpec defines a set of Application resources to be installed +type InstallPlanSpec struct { + CatalogSource string + CatalogSourceNamespace string + ClusterServiceVersionNames []string + Approval Approval + Approved bool +} + +// InstallPlanPhase is the current status of a InstallPlan as a whole. +type InstallPlanPhase string + +const ( + InstallPlanPhaseNone InstallPlanPhase = "" + InstallPlanPhasePlanning InstallPlanPhase = "Planning" + InstallPlanPhaseRequiresApproval InstallPlanPhase = "RequiresApproval" + InstallPlanPhaseInstalling InstallPlanPhase = "Installing" + InstallPlanPhaseComplete InstallPlanPhase = "Complete" + InstallPlanPhaseFailed InstallPlanPhase = "Failed" +) + +// InstallPlanConditionType describes the state of an InstallPlan at a certain point as a whole. +type InstallPlanConditionType string + +const ( + InstallPlanResolved InstallPlanConditionType = "Resolved" + InstallPlanInstalled InstallPlanConditionType = "Installed" +) + +// ConditionReason is a camelcased reason for the state transition. +type InstallPlanConditionReason string + +const ( + InstallPlanReasonPlanUnknown InstallPlanConditionReason = "PlanUnknown" + InstallPlanReasonInstallCheckFailed InstallPlanConditionReason = "InstallCheckFailed" + InstallPlanReasonDependencyConflict InstallPlanConditionReason = "DependenciesConflict" + InstallPlanReasonComponentFailed InstallPlanConditionReason = "InstallComponentFailed" +) + +// StepStatus is the current status of a particular resource an in +// InstallPlan +type StepStatus string + +const ( + StepStatusUnknown StepStatus = "Unknown" + StepStatusNotPresent StepStatus = "NotPresent" + StepStatusPresent StepStatus = "Present" + StepStatusCreated StepStatus = "Created" + StepStatusWaitingForAPI StepStatus = "WaitingForApi" + StepStatusUnsupportedResource StepStatus = "UnsupportedResource" +) + +// ErrInvalidInstallPlan is the error returned by functions that operate on +// InstallPlans when the InstallPlan does not contain totally valid data. +var ErrInvalidInstallPlan = errors.New("the InstallPlan contains invalid data") + +// InstallPlanStatus represents the information about the status of +// steps required to complete installation. +// +// Status may trail the actual state of a system. +type InstallPlanStatus struct { + Phase InstallPlanPhase + Conditions []InstallPlanCondition + CatalogSources []string + Plan []*Step + // BundleLookups is the set of in-progress requests to pull and unpackage bundle content to the cluster. + // +optional + BundleLookups []BundleLookup + // AttenuatedServiceAccountRef references the service account that is used + // to do scoped operator install. + AttenuatedServiceAccountRef *corev1.ObjectReference +} + +// InstallPlanCondition represents the overall status of the execution of +// an InstallPlan. +type InstallPlanCondition struct { + Type InstallPlanConditionType + Status corev1.ConditionStatus // True, False, or Unknown + LastUpdateTime *metav1.Time + LastTransitionTime *metav1.Time + Reason InstallPlanConditionReason + Message string +} + +// allow overwriting `now` function for deterministic tests +var now = metav1.Now + +// GetCondition returns the InstallPlanCondition of the given type if it exists in the InstallPlanStatus' Conditions. +// Returns a condition of the given type with a ConditionStatus of "Unknown" if not found. +func (s InstallPlanStatus) GetCondition(conditionType InstallPlanConditionType) InstallPlanCondition { + for _, cond := range s.Conditions { + if cond.Type == conditionType { + return cond + } + } + + return InstallPlanCondition{ + Type: conditionType, + Status: corev1.ConditionUnknown, + } +} + +// SetCondition adds or updates a condition, using `Type` as merge key. +func (s *InstallPlanStatus) SetCondition(cond InstallPlanCondition) InstallPlanCondition { + for i, existing := range s.Conditions { + if existing.Type != cond.Type { + continue + } + if existing.Status == cond.Status { + cond.LastTransitionTime = existing.LastTransitionTime + } + s.Conditions[i] = cond + return cond + } + s.Conditions = append(s.Conditions, cond) + return cond +} + +func ConditionFailed(cond InstallPlanConditionType, reason InstallPlanConditionReason, message string, now *metav1.Time) InstallPlanCondition { + return InstallPlanCondition{ + Type: cond, + Status: corev1.ConditionFalse, + Reason: reason, + Message: message, + LastUpdateTime: now, + LastTransitionTime: now, + } +} + +func ConditionMet(cond InstallPlanConditionType, now *metav1.Time) InstallPlanCondition { + return InstallPlanCondition{ + Type: cond, + Status: corev1.ConditionTrue, + LastUpdateTime: now, + LastTransitionTime: now, + } +} + +// Step represents the status of an individual step in an InstallPlan. +type Step struct { + Resolving string + Resource StepResource + Status StepStatus +} + +// BundleLookupConditionType is a category of the overall state of a BundleLookup. +type BundleLookupConditionType string + +const ( + // BundleLookupPending describes BundleLookups that are not complete. + BundleLookupPending BundleLookupConditionType = "BundleLookupPending" + + crdKind = "CustomResourceDefinition" +) + +type BundleLookupCondition struct { + // Type of condition. + Type BundleLookupConditionType + // Status of the condition, one of True, False, Unknown. + Status corev1.ConditionStatus + // The reason for the condition's last transition. + // +optional + Reason string + // A human readable message indicating details about the transition. + // +optional + Message string + // Last time the condition was probed + // +optional + LastUpdateTime *metav1.Time + // Last time the condition transitioned from one status to another. + // +optional + LastTransitionTime *metav1.Time +} + +// BundleLookup is a request to pull and unpackage the content of a bundle to the cluster. +type BundleLookup struct { + // Path refers to the location of a bundle to pull. + // It's typically an image reference. + Path string + // Replaces is the name of the bundle to replace with the one found at Path. + Replaces string + // CatalogSourceRef is a reference to the CatalogSource the bundle path was resolved from. + CatalogSourceRef *corev1.ObjectReference + // Conditions represents the overall state of a BundleLookup. + // +optional + Conditions []BundleLookupCondition +} + +// GetCondition returns the BundleLookupCondition of the given type if it exists in the BundleLookup's Conditions. +// Returns a condition of the given type with a ConditionStatus of "Unknown" if not found. +func (b BundleLookup) GetCondition(conditionType BundleLookupConditionType) BundleLookupCondition { + for _, cond := range b.Conditions { + if cond.Type == conditionType { + return cond + } + } + + return BundleLookupCondition{ + Type: conditionType, + Status: corev1.ConditionUnknown, + } +} + +// RemoveCondition removes the BundleLookupCondition of the given type from the BundleLookup's Conditions if it exists. +func (b *BundleLookup) RemoveCondition(conditionType BundleLookupConditionType) { + for i, cond := range b.Conditions { + if cond.Type == conditionType { + b.Conditions = append(b.Conditions[:i], b.Conditions[i+1:]...) + if len(b.Conditions) == 0 { + b.Conditions = nil + } + return + } + } +} + +// SetCondition replaces the existing BundleLookupCondition of the same type, or adds it if it was not found. +func (b *BundleLookup) SetCondition(cond BundleLookupCondition) BundleLookupCondition { + for i, existing := range b.Conditions { + if existing.Type != cond.Type { + continue + } + if existing.Status == cond.Status { + cond.LastTransitionTime = existing.LastTransitionTime + } + b.Conditions[i] = cond + return cond + } + b.Conditions = append(b.Conditions, cond) + + return cond +} + +func OrderSteps(steps []*Step) []*Step { + // CSVs must be applied first + csvList := []*Step{} + + // CRDs must be applied second + crdList := []*Step{} + + // Other resources may be applied in any order + remainingResources := []*Step{} + for _, step := range steps { + switch step.Resource.Kind { + case crdKind: + crdList = append(crdList, step) + case ClusterServiceVersionKind: + csvList = append(csvList, step) + default: + remainingResources = append(remainingResources, step) + } + } + + result := make([]*Step, len(steps)) + i := 0 + + for j := range csvList { + result[i] = csvList[j] + i++ + } + + for j := range crdList { + result[i] = crdList[j] + i++ + } + + for j := range remainingResources { + result[i] = remainingResources[j] + i++ + } + + return result +} + +func (s InstallPlanStatus) NeedsRequeue() bool { + for _, step := range s.Plan { + switch step.Status { + case StepStatusWaitingForAPI: + return true + } + } + + return false +} + +// ManifestsMatch returns true if the CSV manifests in the StepResources of the given list of steps +// matches those in the InstallPlanStatus. +func (s *InstallPlanStatus) CSVManifestsMatch(steps []*Step) bool { + if s.Plan == nil && steps == nil { + return true + } + if s.Plan == nil || steps == nil { + return false + } + + manifests := make(map[string]struct{}) + for _, step := range s.Plan { + resource := step.Resource + if resource.Kind != ClusterServiceVersionKind { + continue + } + manifests[resource.Manifest] = struct{}{} + } + + for _, step := range steps { + resource := step.Resource + if resource.Kind != ClusterServiceVersionKind { + continue + } + if _, ok := manifests[resource.Manifest]; !ok { + return false + } + delete(manifests, resource.Manifest) + } + + return len(manifests) == 0 +} + +func (s *Step) String() string { + return fmt.Sprintf("%s: %s (%s)", s.Resolving, s.Resource, s.Status) +} + +// StepResource represents the status of a resource to be tracked by an +// InstallPlan. +type StepResource struct { + CatalogSource string + CatalogSourceNamespace string + Group string + Version string + Kind string + Name string + Manifest string +} + +func (r StepResource) String() string { + return fmt.Sprintf("%s[%s/%s/%s (%s/%s)]", r.Name, r.Group, r.Version, r.Kind, r.CatalogSource, r.CatalogSourceNamespace) +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient + +// InstallPlan defines the installation of a set of operators. +type InstallPlan struct { + metav1.TypeMeta + metav1.ObjectMeta + + Spec InstallPlanSpec + Status InstallPlanStatus +} + +// EnsureCatalogSource ensures that a CatalogSource is present in the Status +// block of an InstallPlan. +func (p *InstallPlan) EnsureCatalogSource(sourceName string) { + for _, srcName := range p.Status.CatalogSources { + if srcName == sourceName { + return + } + } + + p.Status.CatalogSources = append(p.Status.CatalogSources, sourceName) +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// InstallPlanList is a list of InstallPlan resources. +type InstallPlanList struct { + metav1.TypeMeta + metav1.ListMeta + + Items []InstallPlan +} diff --git a/vendor/github.com/operator-framework/api/pkg/operators/operatorgroup_types.go b/vendor/github.com/operator-framework/api/pkg/operators/operatorgroup_types.go new file mode 100644 index 0000000000..e94386c778 --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/operatorgroup_types.go @@ -0,0 +1,79 @@ +package operators + +import ( + "sort" + "strings" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// OperatorGroupKind is the PascalCase name of an OperatorGroup's kind. +const OperatorGroupKind = "OperatorGroup" + +const ( + OperatorGroupAnnotationKey = "olm.operatorGroup" + OperatorGroupNamespaceAnnotationKey = "olm.operatorNamespace" + OperatorGroupTargetsAnnotationKey = "olm.targetNamespaces" + OperatorGroupProvidedAPIsAnnotationKey = "olm.providedAPIs" +) + +// OperatorGroupSpec is the spec for an OperatorGroup resource. +type OperatorGroupSpec struct { + // Selector selects the OperatorGroup's target namespaces. + // +optional + Selector *metav1.LabelSelector + + // TargetNamespaces is an explicit set of namespaces to target. + // If it is set, Selector is ignored. + // +optional + TargetNamespaces []string + + // ServiceAccountName is the admin specified service account which will be + // used to deploy operator(s) in this operator group. + ServiceAccountName string + + // Static tells OLM not to update the OperatorGroup's providedAPIs annotation + // +optional + StaticProvidedAPIs bool +} + +// OperatorGroupStatus is the status for an OperatorGroupResource. +type OperatorGroupStatus struct { + // Namespaces is the set of target namespaces for the OperatorGroup. + Namespaces []string + + // ServiceAccountRef references the service account object specified. + ServiceAccountRef *corev1.ObjectReference + + // LastUpdated is a timestamp of the last time the OperatorGroup's status was Updated. + LastUpdated *metav1.Time +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient + +// OperatorGroup is the unit of multitenancy for OLM managed operators. +// It constrains the installation of operators in its namespace to a specified set of target namespaces. +type OperatorGroup struct { + metav1.TypeMeta + metav1.ObjectMeta + + Spec OperatorGroupSpec + Status OperatorGroupStatus +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// OperatorGroupList is a list of OperatorGroup resources. +type OperatorGroupList struct { + metav1.TypeMeta + metav1.ListMeta + + Items []OperatorGroup +} + +func (o *OperatorGroup) BuildTargetNamespaces() string { + sort.Strings(o.Status.Namespaces) + return strings.Join(o.Status.Namespaces, ",") +} diff --git a/vendor/github.com/operator-framework/api/pkg/operators/register.go b/vendor/github.com/operator-framework/api/pkg/operators/register.go new file mode 100644 index 0000000000..784b040264 --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/register.go @@ -0,0 +1,50 @@ +package operators + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +const ( + // GroupName is the group name used in this package. + GroupName = "operators.coreos.com" + // GroupVersion is the group version used in this package. + GroupVersion = runtime.APIVersionInternal +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // SchemeBuilder initializes a scheme builder + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // AddToScheme is a global function that registers this API group & version to a scheme + AddToScheme = SchemeBuilder.AddToScheme +) + +// addKnownTypes adds the list of known types to Scheme +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &CatalogSource{}, + &CatalogSourceList{}, + &InstallPlan{}, + &InstallPlanList{}, + &Subscription{}, + &SubscriptionList{}, + &ClusterServiceVersion{}, + &ClusterServiceVersionList{}, + &OperatorGroup{}, + &OperatorGroupList{}, + ) + return nil +} diff --git a/vendor/github.com/operator-framework/api/pkg/operators/subscription_types.go b/vendor/github.com/operator-framework/api/pkg/operators/subscription_types.go new file mode 100644 index 0000000000..931207681e --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/subscription_types.go @@ -0,0 +1,312 @@ +package operators + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +// SubscriptionKind is the PascalCase name of a Subscription's kind. +const SubscriptionKind = "Subscription" + +// SubscriptionState tracks when updates are available, installing, or service is up to date +type SubscriptionState string + +const ( + SubscriptionStateNone = "" + SubscriptionStateFailed = "UpgradeFailed" + SubscriptionStateUpgradeAvailable = "UpgradeAvailable" + SubscriptionStateUpgradePending = "UpgradePending" + SubscriptionStateAtLatest = "AtLatestKnown" +) + +const ( + SubscriptionReasonInvalidCatalog ConditionReason = "InvalidCatalog" + SubscriptionReasonUpgradeSucceeded ConditionReason = "UpgradeSucceeded" +) + +// SubscriptionSpec defines an Application that can be installed +type SubscriptionSpec struct { + CatalogSource string + CatalogSourceNamespace string + Package string + Channel string + StartingCSV string + InstallPlanApproval Approval + Config SubscriptionConfig +} + +// SubscriptionConfig contains configuration specified for a subscription. +type SubscriptionConfig struct { + // Label selector for pods. Existing ReplicaSets whose pods are + // selected by this will be the ones affected by this deployment. + // It must match the pod template's labels. + Selector *metav1.LabelSelector `json:"selector,omitempty"` + + // NodeSelector is a selector which must be true for the pod to fit on a node. + // Selector which must match a node's labels for the pod to be scheduled on that node. + // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + // +optional + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // If specified, the pod's tolerations. + // +optional + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + + // Compute Resources required by this container. + // Cannot be updated. + // More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + // +optional + Resources corev1.ResourceRequirements `json:"resources,omitempty"` + + // List of sources to populate environment variables in the container. + // The keys defined within a source must be a C_IDENTIFIER. All invalid keys + // will be reported as an event when the container is starting. When a key exists in multiple + // sources, the value associated with the last source will take precedence. + // Values defined by an Env with a duplicate key will take precedence. + // Cannot be updated. + // +optional + EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"` + // List of environment variables to set in the container. + // Cannot be updated. + // +optional + // +patchMergeKey=name + // +patchStrategy=merge + Env []corev1.EnvVar `json:"env,omitempty"` + + // List of Volumes to set in the podSpec. + // +optional + Volumes []corev1.Volume `json:"volumes,omitempty"` + + // List of VolumeMounts to set in the container. + // +optional + VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"` +} + +// SubscriptionConditionType indicates an explicit state condition about a Subscription in "abnormal-true" +// polarity form (see https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties). +type SubscriptionConditionType string + +const ( + // SubscriptionCatalogSourcesUnhealthy indicates that some or all of the CatalogSources to be used in resolution are unhealthy. + SubscriptionCatalogSourcesUnhealthy SubscriptionConditionType = "CatalogSourcesUnhealthy" + + // SubscriptionInstallPlanMissing indicates that a Subscription's InstallPlan is missing. + SubscriptionInstallPlanMissing SubscriptionConditionType = "InstallPlanMissing" + + // SubscriptionInstallPlanPending indicates that a Subscription's InstallPlan is pending installation. + SubscriptionInstallPlanPending SubscriptionConditionType = "InstallPlanPending" + + // SubscriptionInstallPlanFailed indicates that the installation of a Subscription's InstallPlan has failed. + SubscriptionInstallPlanFailed SubscriptionConditionType = "InstallPlanFailed" +) + +const ( + // NoCatalogSourcesFound is a reason string for Subscriptions with unhealthy CatalogSources due to none being available. + NoCatalogSourcesFound = "NoCatalogSourcesFound" + + // AllCatalogSourcesHealthy is a reason string for Subscriptions that transitioned due to all CatalogSources being healthy. + AllCatalogSourcesHealthy = "AllCatalogSourcesHealthy" + + // CatalogSourcesAdded is a reason string for Subscriptions that transitioned due to CatalogSources being added. + CatalogSourcesAdded = "CatalogSourcesAdded" + + // CatalogSourcesUpdated is a reason string for Subscriptions that transitioned due to CatalogSource being updated. + CatalogSourcesUpdated = "CatalogSourcesUpdated" + + // CatalogSourcesDeleted is a reason string for Subscriptions that transitioned due to CatalogSources being removed. + CatalogSourcesDeleted = "CatalogSourcesDeleted" + + // UnhealthyCatalogSourceFound is a reason string for Subscriptions that transitioned because an unhealthy CatalogSource was found. + UnhealthyCatalogSourceFound = "UnhealthyCatalogSourceFound" + + // ReferencedInstallPlanNotFound is a reason string for Subscriptions that transitioned due to a referenced InstallPlan not being found. + ReferencedInstallPlanNotFound = "ReferencedInstallPlanNotFound" + + // InstallPlanNotYetReconciled is a reason string for Subscriptions that transitioned due to a referenced InstallPlan not being reconciled yet. + InstallPlanNotYetReconciled = "InstallPlanNotYetReconciled" + + // InstallPlanFailed is a reason string for Subscriptions that transitioned due to a referenced InstallPlan failing without setting an explicit failure condition. + InstallPlanFailed = "InstallPlanFailed" +) + +// SubscriptionCondition represents the latest available observations of a Subscription's state. +type SubscriptionCondition struct { + // Type is the type of Subscription condition. + Type SubscriptionConditionType + + // Status is the status of the condition, one of True, False, Unknown. + Status corev1.ConditionStatus + + // Reason is a one-word CamelCase reason for the condition's last transition. + // +optional + Reason string + + // Message is a human-readable message indicating details about last transition. + // +optional + Message string + + // LastHeartbeatTime is the last time we got an update on a given condition + // +optional + LastHeartbeatTime *metav1.Time + + // LastTransitionTime is the last time the condition transit from one status to another + // +optional + LastTransitionTime *metav1.Time +} + +// Equals returns true if a SubscriptionCondition equals the one given, false otherwise. +// Equality is determined by the equality of the type, status, reason, and message fields ONLY. +func (s SubscriptionCondition) Equals(condition SubscriptionCondition) bool { + return s.Type == condition.Type && s.Status == condition.Status && s.Reason == condition.Reason && s.Message == condition.Message +} + +type SubscriptionStatus struct { + // CurrentCSV is the CSV the Subscription is progressing to. + // +optional + CurrentCSV string + + // InstalledCSV is the CSV currently installed by the Subscription. + // +optional + InstalledCSV string + + // Install is a reference to the latest InstallPlan generated for the Subscription. + // DEPRECATED: InstallPlanRef + // +optional + Install *InstallPlanReference + + // State represents the current state of the Subscription + // +optional + State SubscriptionState + + // Reason is the reason the Subscription was transitioned to its current state. + // +optional + Reason ConditionReason + + // InstallPlanRef is a reference to the latest InstallPlan that contains the Subscription's current CSV. + // +optional + InstallPlanRef *corev1.ObjectReference + + // CatalogHealth contains the Subscription's view of its relevant CatalogSources' status. + // It is used to determine SubscriptionStatusConditions related to CatalogSources. + // +optional + CatalogHealth []SubscriptionCatalogHealth + + // Conditions is a list of the latest available observations about a Subscription's current state. + // +optional + Conditions []SubscriptionCondition `hash:"set"` + + // LastUpdated represents the last time that the Subscription status was updated. + LastUpdated metav1.Time +} + +// GetCondition returns the SubscriptionCondition of the given type if it exists in the SubscriptionStatus' Conditions. +// Returns a condition of the given type with a ConditionStatus of "Unknown" if not found. +func (s SubscriptionStatus) GetCondition(conditionType SubscriptionConditionType) SubscriptionCondition { + for _, cond := range s.Conditions { + if cond.Type == conditionType { + return cond + } + } + + return SubscriptionCondition{ + Type: conditionType, + Status: corev1.ConditionUnknown, + } +} + +// SetCondition sets the given SubscriptionCondition in the SubscriptionStatus' Conditions. +func (s *SubscriptionStatus) SetCondition(condition SubscriptionCondition) { + for i, cond := range s.Conditions { + if cond.Type == condition.Type { + s.Conditions[i] = condition + return + } + } + + s.Conditions = append(s.Conditions, condition) +} + +// RemoveConditions removes any conditions of the given types from the SubscriptionStatus' Conditions. +func (s *SubscriptionStatus) RemoveConditions(remove ...SubscriptionConditionType) { + exclusions := map[SubscriptionConditionType]struct{}{} + for _, r := range remove { + exclusions[r] = struct{}{} + } + + var filtered []SubscriptionCondition + for _, cond := range s.Conditions { + if _, ok := exclusions[cond.Type]; ok { + // Skip excluded condition types + continue + } + filtered = append(filtered, cond) + } + + s.Conditions = filtered +} + +type InstallPlanReference struct { + APIVersion string + Kind string + Name string + UID types.UID +} + +// SubscriptionCatalogHealth describes the health of a CatalogSource the Subscription knows about. +type SubscriptionCatalogHealth struct { + // CatalogSourceRef is a reference to a CatalogSource. + CatalogSourceRef *corev1.ObjectReference + + // LastUpdated represents the last time that the CatalogSourceHealth changed + LastUpdated *metav1.Time + + // Healthy is true if the CatalogSource is healthy; false otherwise. + Healthy bool +} + +// Equals returns true if a SubscriptionCatalogHealth equals the one given, false otherwise. +// Equality is based SOLEY on health and UID. +func (s SubscriptionCatalogHealth) Equals(health SubscriptionCatalogHealth) bool { + return s.Healthy == health.Healthy && s.CatalogSourceRef.UID == health.CatalogSourceRef.UID +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient + +// Subscription keeps operators up to date by tracking changes to Catalogs. +type Subscription struct { + metav1.TypeMeta + metav1.ObjectMeta + + Spec *SubscriptionSpec + Status SubscriptionStatus +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// SubscriptionList is a list of Subscription resources. +type SubscriptionList struct { + metav1.TypeMeta + metav1.ListMeta + + Items []Subscription +} + +// GetInstallPlanApproval gets the configured install plan approval or the default +func (s *Subscription) GetInstallPlanApproval() Approval { + if s.Spec.InstallPlanApproval == ApprovalManual { + return ApprovalManual + } + return ApprovalAutomatic +} + +// NewInstallPlanReference returns an InstallPlanReference for the given ObjectReference. +func NewInstallPlanReference(ref *corev1.ObjectReference) *InstallPlanReference { + return &InstallPlanReference{ + APIVersion: ref.APIVersion, + Kind: ref.Kind, + Name: ref.Name, + UID: ref.UID, + } +} diff --git a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/catalogsource_types.go b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/catalogsource_types.go new file mode 100644 index 0000000000..e7d041fa7a --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/catalogsource_types.go @@ -0,0 +1,234 @@ +package v1alpha1 + +import ( + "fmt" + "time" + + "github.com/sirupsen/logrus" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +const ( + CatalogSourceCRDAPIVersion = GroupName + "/" + GroupVersion + CatalogSourceKind = "CatalogSource" +) + +// SourceType indicates the type of backing store for a CatalogSource +type SourceType string + +const ( + // SourceTypeInternal (deprecated) specifies a CatalogSource of type SourceTypeConfigmap + SourceTypeInternal SourceType = "internal" + + // SourceTypeConfigmap specifies a CatalogSource that generates a configmap-server registry + SourceTypeConfigmap SourceType = "configmap" + + // SourceTypeGrpc specifies a CatalogSource that can use an operator registry image to generate a + // registry-server or connect to a pre-existing registry at an address. + SourceTypeGrpc SourceType = "grpc" +) + +const ( + // CatalogSourceSpecInvalidError denotes when fields on the spec of the CatalogSource are not valid. + CatalogSourceSpecInvalidError ConditionReason = "SpecInvalidError" + // CatalogSourceConfigMapError denotes when there is an issue extracting manifests from the specified ConfigMap. + CatalogSourceConfigMapError ConditionReason = "ConfigMapError" + // CatalogSourceRegistryServerError denotes when there is an issue querying the specified registry server. + CatalogSourceRegistryServerError ConditionReason = "RegistryServerError" +) + +type CatalogSourceSpec struct { + // SourceType is the type of source + SourceType SourceType `json:"sourceType"` + + // ConfigMap is the name of the ConfigMap to be used to back a configmap-server registry. + // Only used when SourceType = SourceTypeConfigmap or SourceTypeInternal. + // +Optional + ConfigMap string `json:"configMap,omitempty"` + + // Address is a host that OLM can use to connect to a pre-existing registry. + // Format: : + // Only used when SourceType = SourceTypeGrpc. + // Ignored when the Image field is set. + // +Optional + Address string `json:"address,omitempty"` + + // Image is an operator-registry container image to instantiate a registry-server with. + // Only used when SourceType = SourceTypeGrpc. + // If present, the address field is ignored. + // +Optional + Image string `json:"image,omitempty"` + + // UpdateStrategy defines how updated catalog source images can be discovered + // Consists of an interval that defines polling duration and an embedded strategy type + // +Optional + UpdateStrategy *UpdateStrategy `json:"updateStrategy,omitempty"` + + // Secrets represent set of secrets that can be used to access the contents of the catalog. + // It is best to keep this list small, since each will need to be tried for every catalog entry. + // +Optional + Secrets []string `json:"secrets,omitempty"` + + // Metadata + DisplayName string `json:"displayName,omitempty"` + Description string `json:"description,omitempty"` + Publisher string `json:"publisher,omitempty"` + Icon Icon `json:"icon,omitempty"` +} + +// UpdateStrategy holds all the different types of catalog source update strategies +// Currently only registry polling strategy is implemented +type UpdateStrategy struct { + *RegistryPoll `json:"registryPoll,omitempty"` +} + +type RegistryPoll struct { + // Interval is used to determine the time interval between checks of the latest catalog source version. + // The catalog operator polls to see if a new version of the catalog source is available. + // If available, the latest image is pulled and gRPC traffic is directed to the latest catalog source. + Interval *metav1.Duration `json:"interval,omitempty"` +} + +type RegistryServiceStatus struct { + Protocol string `json:"protocol,omitempty"` + ServiceName string `json:"serviceName,omitempty"` + ServiceNamespace string `json:"serviceNamespace,omitempty"` + Port string `json:"port,omitempty"` + CreatedAt metav1.Time `json:"createdAt,omitempty"` +} + +func (s *RegistryServiceStatus) Address() string { + return fmt.Sprintf("%s.%s.svc:%s", s.ServiceName, s.ServiceNamespace, s.Port) +} + +type GRPCConnectionState struct { + Address string `json:"address,omitempty"` + LastObservedState string `json:"lastObservedState"` + LastConnectTime metav1.Time `json:"lastConnect,omitempty"` +} + +type CatalogSourceStatus struct { + // A human readable message indicating details about why the CatalogSource is in this condition. + // +optional + Message string `json:"message,omitempty"` + // Reason is the reason the CatalogSource was transitioned to its current state. + // +optional + Reason ConditionReason `json:"reason,omitempty"` + + // The last time the CatalogSource image registry has been polled to ensure the image is up-to-date + LatestImageRegistryPoll *metav1.Time `json:"latestImageRegistryPoll,omitempty"` + + ConfigMapResource *ConfigMapResourceReference `json:"configMapReference,omitempty"` + RegistryServiceStatus *RegistryServiceStatus `json:"registryService,omitempty"` + GRPCConnectionState *GRPCConnectionState `json:"connectionState,omitempty"` +} + +type ConfigMapResourceReference struct { + Name string `json:"name"` + Namespace string `json:"namespace"` + UID types.UID `json:"uid,omitempty"` + ResourceVersion string `json:"resourceVersion,omitempty"` + LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"` +} + +func (r *ConfigMapResourceReference) IsAMatch(object *metav1.ObjectMeta) bool { + return r.UID == object.GetUID() && r.ResourceVersion == object.GetResourceVersion() +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient +// +kubebuilder:resource:shortName=catsrc,categories=olm +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Display",type=string,JSONPath=`.spec.displayName`,description="The pretty name of the catalog" +// +kubebuilder:printcolumn:name="Type",type=string,JSONPath=`.spec.sourceType`,description="The type of the catalog" +// +kubebuilder:printcolumn:name="Publisher",type=string,JSONPath=`.spec.publisher`,description="The publisher of the catalog" +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` + +// CatalogSource is a repository of CSVs, CRDs, and operator packages. +type CatalogSource struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata"` + + Spec CatalogSourceSpec `json:"spec"` + // +optional + Status CatalogSourceStatus `json:"status"` +} + +func (c *CatalogSource) Address() string { + if c.Spec.Address != "" { + return c.Spec.Address + } + return c.Status.RegistryServiceStatus.Address() +} + +func (c *CatalogSource) SetError(reason ConditionReason, err error) { + c.Status.Reason = reason + c.Status.Message = "" + if err != nil { + c.Status.Message = err.Error() + } +} + +func (c *CatalogSource) SetLastUpdateTime() { + now := metav1.Now() + c.Status.LatestImageRegistryPoll = &now +} + +// Check if it is time to update based on polling setting +func (c *CatalogSource) Update() bool { + if !c.Poll() { + return false + } + interval := c.Spec.UpdateStrategy.Interval.Duration + latest := c.Status.LatestImageRegistryPoll + if latest == nil { + logrus.WithField("CatalogSource", c.Name).Debugf("latest poll %v", latest) + } else { + logrus.WithField("CatalogSource", c.Name).Debugf("latest poll %v", *c.Status.LatestImageRegistryPoll) + } + + if c.Status.LatestImageRegistryPoll.IsZero() { + logrus.WithField("CatalogSource", c.Name).Debugf("creation timestamp plus interval before now %t", c.CreationTimestamp.Add(interval).Before(time.Now())) + if c.CreationTimestamp.Add(interval).Before(time.Now()) { + return true + } + } else { + logrus.WithField("CatalogSource", c.Name).Debugf("latest poll plus interval before now %t", c.Status.LatestImageRegistryPoll.Add(interval).Before(time.Now())) + if c.Status.LatestImageRegistryPoll.Add(interval).Before(time.Now()) { + return true + } + } + + return false +} + +// Poll determines whether the polling feature is enabled on the particular catalog source +func (c *CatalogSource) Poll() bool { + if c.Spec.UpdateStrategy == nil { + return false + } + // if polling interval is zero polling will not be done + if c.Spec.UpdateStrategy.RegistryPoll == nil { + return false + } + // if catalog source is not backed by an image polling will not be done + if c.Spec.Image == "" { + return false + } + // if image is not type gRPC polling will not be done + if c.Spec.SourceType != SourceTypeGrpc { + return false + } + return true +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// CatalogSourceList is a repository of CSVs, CRDs, and operator packages. +type CatalogSourceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []CatalogSource `json:"items"` +} diff --git a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/clusterserviceversion.go b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/clusterserviceversion.go new file mode 100644 index 0000000000..ffc357b12b --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/clusterserviceversion.go @@ -0,0 +1,208 @@ +package v1alpha1 + +import ( + "fmt" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/record" +) + +const ( + CopiedLabelKey = "olm.copiedFrom" + + // ConditionsLengthLimit is the maximum length of Status.Conditions of a + // given ClusterServiceVersion object. The oldest condition(s) are removed + // from the list as it grows over time to keep it at limit. + ConditionsLengthLimit = 20 +) + +// obsoleteReasons are the set of reasons that mean a CSV should no longer be processed as active +var obsoleteReasons = map[ConditionReason]struct{}{ + CSVReasonReplaced: {}, + CSVReasonBeingReplaced: {}, +} + +// uncopiableReasons are the set of reasons that should prevent a CSV from being copied to target namespaces +var uncopiableReasons = map[ConditionReason]struct{}{ + CSVReasonCopied: {}, + CSVReasonInvalidInstallModes: {}, + CSVReasonNoTargetNamespaces: {}, + CSVReasonUnsupportedOperatorGroup: {}, + CSVReasonNoOperatorGroup: {}, + CSVReasonTooManyOperatorGroups: {}, + CSVReasonInterOperatorGroupOwnerConflict: {}, + CSVReasonCannotModifyStaticOperatorGroupProvidedAPIs: {}, +} + +// safeToAnnotateOperatorGroupReasons are the set of reasons that it's safe to attempt to update the operatorgroup +// annotations +var safeToAnnotateOperatorGroupReasons = map[ConditionReason]struct{}{ + CSVReasonOwnerConflict: {}, + CSVReasonInstallSuccessful: {}, + CSVReasonInvalidInstallModes: {}, + CSVReasonNoTargetNamespaces: {}, + CSVReasonUnsupportedOperatorGroup: {}, + CSVReasonNoOperatorGroup: {}, + CSVReasonTooManyOperatorGroups: {}, + CSVReasonInterOperatorGroupOwnerConflict: {}, + CSVReasonCannotModifyStaticOperatorGroupProvidedAPIs: {}, +} + +// SetPhaseWithEventIfChanged emits a Kubernetes event with details of a phase change and sets the current phase if phase, reason, or message would changed +func (c *ClusterServiceVersion) SetPhaseWithEventIfChanged(phase ClusterServiceVersionPhase, reason ConditionReason, message string, now *metav1.Time, recorder record.EventRecorder) { + if c.Status.Phase == phase && c.Status.Reason == reason && c.Status.Message == message { + return + } + + c.SetPhaseWithEvent(phase, reason, message, now, recorder) +} + +// SetPhaseWithEvent generates a Kubernetes event with details about the phase change and sets the current phase +func (c *ClusterServiceVersion) SetPhaseWithEvent(phase ClusterServiceVersionPhase, reason ConditionReason, message string, now *metav1.Time, recorder record.EventRecorder) { + var eventtype string + if phase == CSVPhaseFailed { + eventtype = v1.EventTypeWarning + } else { + eventtype = v1.EventTypeNormal + } + go recorder.Event(c, eventtype, string(reason), message) + c.SetPhase(phase, reason, message, now) +} + +// SetPhase sets the current phase and adds a condition if necessary +func (c *ClusterServiceVersion) SetPhase(phase ClusterServiceVersionPhase, reason ConditionReason, message string, now *metav1.Time) { + newCondition := func() ClusterServiceVersionCondition { + return ClusterServiceVersionCondition{ + Phase: c.Status.Phase, + LastTransitionTime: c.Status.LastTransitionTime, + LastUpdateTime: c.Status.LastUpdateTime, + Message: message, + Reason: reason, + } + } + + defer c.TrimConditionsIfLimitExceeded() + + c.Status.LastUpdateTime = now + if c.Status.Phase != phase { + c.Status.Phase = phase + c.Status.LastTransitionTime = now + } + c.Status.Message = message + c.Status.Reason = reason + if len(c.Status.Conditions) == 0 { + c.Status.Conditions = append(c.Status.Conditions, newCondition()) + return + } + + previousCondition := c.Status.Conditions[len(c.Status.Conditions)-1] + if previousCondition.Phase != c.Status.Phase || previousCondition.Reason != c.Status.Reason { + c.Status.Conditions = append(c.Status.Conditions, newCondition()) + } +} + +// SetRequirementStatus adds the status of all requirements to the CSV status +func (c *ClusterServiceVersion) SetRequirementStatus(statuses []RequirementStatus) { + c.Status.RequirementStatus = statuses +} + +// IsObsolete returns if this CSV is being replaced or is marked for deletion +func (c *ClusterServiceVersion) IsObsolete() bool { + for _, condition := range c.Status.Conditions { + _, ok := obsoleteReasons[condition.Reason] + if ok { + return true + } + } + return false +} + +// IsCopied returns true if the CSV has been copied and false otherwise. +func (c *ClusterServiceVersion) IsCopied() bool { + operatorNamespace, ok := c.GetAnnotations()[OperatorGroupNamespaceAnnotationKey] + if c.Status.Reason == CSVReasonCopied || ok && c.GetNamespace() != operatorNamespace { + return true + } + + if labels := c.GetLabels(); labels != nil { + if _, ok := labels[CopiedLabelKey]; ok { + return true + } + } + return false +} + +func (c *ClusterServiceVersion) IsUncopiable() bool { + if c.Status.Phase == CSVPhaseNone { + return true + } + _, ok := uncopiableReasons[c.Status.Reason] + return ok +} + +func (c *ClusterServiceVersion) IsSafeToUpdateOperatorGroupAnnotations() bool { + _, ok := safeToAnnotateOperatorGroupReasons[c.Status.Reason] + return ok +} + +// NewInstallModeSet returns an InstallModeSet instantiated from the given list of InstallModes. +// If the given list is not a set, an error is returned. +func NewInstallModeSet(modes []InstallMode) (InstallModeSet, error) { + set := InstallModeSet{} + for _, mode := range modes { + if _, exists := set[mode.Type]; exists { + return nil, fmt.Errorf("InstallMode list contains duplicates, cannot make set: %v", modes) + } + set[mode.Type] = mode.Supported + } + + return set, nil +} + +// Supports returns an error if the InstallModeSet does not support configuration for +// the given operatorNamespace and list of target namespaces. +func (set InstallModeSet) Supports(operatorNamespace string, namespaces []string) error { + numNamespaces := len(namespaces) + switch { + case numNamespaces == 0: + return fmt.Errorf("operatorgroup has invalid selected namespaces, cannot configure to watch zero namespaces") + case numNamespaces == 1: + switch namespaces[0] { + case operatorNamespace: + if !set[InstallModeTypeOwnNamespace] { + return fmt.Errorf("%s InstallModeType not supported, cannot configure to watch own namespace", InstallModeTypeOwnNamespace) + } + case v1.NamespaceAll: + if !set[InstallModeTypeAllNamespaces] { + return fmt.Errorf("%s InstallModeType not supported, cannot configure to watch all namespaces", InstallModeTypeAllNamespaces) + } + default: + if !set[InstallModeTypeSingleNamespace] { + return fmt.Errorf("%s InstallModeType not supported, cannot configure to watch one namespace", InstallModeTypeSingleNamespace) + } + } + case numNamespaces > 1 && !set[InstallModeTypeMultiNamespace]: + return fmt.Errorf("%s InstallModeType not supported, cannot configure to watch %d namespaces", InstallModeTypeMultiNamespace, numNamespaces) + case numNamespaces > 1: + for _, namespace := range namespaces { + if namespace == operatorNamespace && !set[InstallModeTypeOwnNamespace] { + return fmt.Errorf("%s InstallModeType not supported, cannot configure to watch own namespace", InstallModeTypeOwnNamespace) + } + if namespace == v1.NamespaceAll { + return fmt.Errorf("operatorgroup has invalid selected namespaces, NamespaceAll found when |selected namespaces| > 1") + } + } + } + + return nil +} + +func (c *ClusterServiceVersion) TrimConditionsIfLimitExceeded() { + if len(c.Status.Conditions) <= ConditionsLengthLimit { + return + } + + firstIndex := len(c.Status.Conditions) - ConditionsLengthLimit + c.Status.Conditions = c.Status.Conditions[firstIndex:len(c.Status.Conditions)] +} diff --git a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/clusterserviceversion_types.go b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/clusterserviceversion_types.go new file mode 100644 index 0000000000..4127bc9167 --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/clusterserviceversion_types.go @@ -0,0 +1,635 @@ +package v1alpha1 + +import ( + "encoding/json" + "fmt" + "sort" + "strings" + + admissionregistrationv1 "k8s.io/api/admissionregistration/v1" + + appsv1 "k8s.io/api/apps/v1" + rbac "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/operator-framework/api/pkg/lib/version" +) + +const ( + ClusterServiceVersionAPIVersion = GroupName + "/" + GroupVersion + ClusterServiceVersionKind = "ClusterServiceVersion" + OperatorGroupNamespaceAnnotationKey = "olm.operatorNamespace" + InstallStrategyNameDeployment = "deployment" +) + +// InstallModeType is a supported type of install mode for CSV installation +type InstallModeType string + +const ( + // InstallModeTypeOwnNamespace indicates that the operator can be a member of an `OperatorGroup` that selects its own namespace. + InstallModeTypeOwnNamespace InstallModeType = "OwnNamespace" + // InstallModeTypeSingleNamespace indicates that the operator can be a member of an `OperatorGroup` that selects one namespace. + InstallModeTypeSingleNamespace InstallModeType = "SingleNamespace" + // InstallModeTypeMultiNamespace indicates that the operator can be a member of an `OperatorGroup` that selects more than one namespace. + InstallModeTypeMultiNamespace InstallModeType = "MultiNamespace" + // InstallModeTypeAllNamespaces indicates that the operator can be a member of an `OperatorGroup` that selects all namespaces (target namespace set is the empty string ""). + InstallModeTypeAllNamespaces InstallModeType = "AllNamespaces" +) + +// InstallMode associates an InstallModeType with a flag representing if the CSV supports it +// +k8s:openapi-gen=true +type InstallMode struct { + Type InstallModeType `json:"type"` + Supported bool `json:"supported"` +} + +// InstallModeSet is a mapping of unique InstallModeTypes to whether they are supported. +type InstallModeSet map[InstallModeType]bool + +// NamedInstallStrategy represents the block of an ClusterServiceVersion resource +// where the install strategy is specified. +type NamedInstallStrategy struct { + StrategyName string `json:"strategy"` + StrategySpec StrategyDetailsDeployment `json:"spec,omitempty"` +} + +// StrategyDeploymentPermissions describe the rbac rules and service account needed by the install strategy +type StrategyDeploymentPermissions struct { + ServiceAccountName string `json:"serviceAccountName"` + Rules []rbac.PolicyRule `json:"rules"` +} + +// StrategyDeploymentSpec contains the name and spec for the deployment ALM should create +type StrategyDeploymentSpec struct { + Name string `json:"name"` + Spec appsv1.DeploymentSpec `json:"spec"` +} + +// StrategyDetailsDeployment represents the parsed details of a Deployment +// InstallStrategy. +type StrategyDetailsDeployment struct { + DeploymentSpecs []StrategyDeploymentSpec `json:"deployments"` + Permissions []StrategyDeploymentPermissions `json:"permissions,omitempty"` + ClusterPermissions []StrategyDeploymentPermissions `json:"clusterPermissions,omitempty"` +} + +func (d *StrategyDetailsDeployment) GetStrategyName() string { + return InstallStrategyNameDeployment +} + +// StatusDescriptor describes a field in a status block of a CRD so that OLM can consume it +// +k8s:openapi-gen=true +type StatusDescriptor struct { + Path string `json:"path"` + DisplayName string `json:"displayName,omitempty"` + Description string `json:"description,omitempty"` + XDescriptors []string `json:"x-descriptors,omitempty"` + Value json.RawMessage `json:"value,omitempty"` +} + +// SpecDescriptor describes a field in a spec block of a CRD so that OLM can consume it +// +k8s:openapi-gen=true +type SpecDescriptor struct { + Path string `json:"path"` + DisplayName string `json:"displayName,omitempty"` + Description string `json:"description,omitempty"` + XDescriptors []string `json:"x-descriptors,omitempty"` + Value json.RawMessage `json:"value,omitempty"` +} + +// ActionDescriptor describes a declarative action that can be performed on a custom resource instance +// +k8s:openapi-gen=true +type ActionDescriptor struct { + Path string `json:"path"` + DisplayName string `json:"displayName,omitempty"` + Description string `json:"description,omitempty"` + XDescriptors []string `json:"x-descriptors,omitempty"` + Value json.RawMessage `json:"value,omitempty"` +} + +// CRDDescription provides details to OLM about the CRDs +// +k8s:openapi-gen=true +type CRDDescription struct { + Name string `json:"name"` + Version string `json:"version"` + Kind string `json:"kind"` + DisplayName string `json:"displayName,omitempty"` + Description string `json:"description,omitempty"` + Resources []APIResourceReference `json:"resources,omitempty"` + StatusDescriptors []StatusDescriptor `json:"statusDescriptors,omitempty"` + SpecDescriptors []SpecDescriptor `json:"specDescriptors,omitempty"` + ActionDescriptor []ActionDescriptor `json:"actionDescriptors,omitempty"` +} + +// APIServiceDescription provides details to OLM about apis provided via aggregation +// +k8s:openapi-gen=true +type APIServiceDescription struct { + Name string `json:"name"` + Group string `json:"group"` + Version string `json:"version"` + Kind string `json:"kind"` + DeploymentName string `json:"deploymentName,omitempty"` + ContainerPort int32 `json:"containerPort,omitempty"` + DisplayName string `json:"displayName,omitempty"` + Description string `json:"description,omitempty"` + Resources []APIResourceReference `json:"resources,omitempty"` + StatusDescriptors []StatusDescriptor `json:"statusDescriptors,omitempty"` + SpecDescriptors []SpecDescriptor `json:"specDescriptors,omitempty"` + ActionDescriptor []ActionDescriptor `json:"actionDescriptors,omitempty"` +} + +// APIResourceReference is a Kubernetes resource type used by a custom resource +// +k8s:openapi-gen=true +type APIResourceReference struct { + Name string `json:"name"` + Kind string `json:"kind"` + Version string `json:"version"` +} + +// GetName returns the name of an APIService as derived from its group and version. +func (d APIServiceDescription) GetName() string { + return fmt.Sprintf("%s.%s", d.Version, d.Group) +} + +// WebhookAdmissionType is the type of admission webhooks supported by OLM +type WebhookAdmissionType string + +const ( + // ValidatingAdmissionWebhook is for validating admission webhooks + ValidatingAdmissionWebhook WebhookAdmissionType = "ValidatingAdmissionWebhook" + // MutatingAdmissionWebhook is for mutating admission webhooks + MutatingAdmissionWebhook WebhookAdmissionType = "MutatingAdmissionWebhook" +) + +// WebhookDescription provides details to OLM about required webhooks +// +k8s:openapi-gen=true +type WebhookDescription struct { + GenerateName string `json:"generateName"` + // +kubebuilder:validation:Enum=ValidatingAdmissionWebhook;MutatingAdmissionWebhook + Type WebhookAdmissionType `json:"type"` + DeploymentName string `json:"deploymentName,omitempty"` + ContainerPort int32 `json:"containerPort,omitempty"` + Rules []admissionregistrationv1.RuleWithOperations `json:"rules,omitempty"` + FailurePolicy *admissionregistrationv1.FailurePolicyType `json:"failurePolicy,omitempty"` + MatchPolicy *admissionregistrationv1.MatchPolicyType `json:"matchPolicy,omitempty"` + ObjectSelector *metav1.LabelSelector `json:"objectSelector,omitempty"` + SideEffects *admissionregistrationv1.SideEffectClass `json:"sideEffects"` + TimeoutSeconds *int32 `json:"timeoutSeconds,omitempty"` + AdmissionReviewVersions []string `json:"admissionReviewVersions"` + ReinvocationPolicy *admissionregistrationv1.ReinvocationPolicyType `json:"reinvocationPolicy,omitempty"` + WebhookPath *string `json:"webhookPath,omitempty"` +} + +// GetValidatingWebhook returns a ValidatingWebhook generated from the WebhookDescription +func (w *WebhookDescription) GetValidatingWebhook(namespace string, namespaceSelector *metav1.LabelSelector, caBundle []byte) admissionregistrationv1.ValidatingWebhook { + return admissionregistrationv1.ValidatingWebhook{ + Name: w.GenerateName, + Rules: w.Rules, + FailurePolicy: w.FailurePolicy, + MatchPolicy: w.MatchPolicy, + NamespaceSelector: namespaceSelector, + ObjectSelector: w.ObjectSelector, + SideEffects: w.SideEffects, + TimeoutSeconds: w.TimeoutSeconds, + AdmissionReviewVersions: w.AdmissionReviewVersions, + ClientConfig: admissionregistrationv1.WebhookClientConfig{ + Service: &admissionregistrationv1.ServiceReference{ + Name: w.DomainName() + "-service", + Namespace: namespace, + Path: w.WebhookPath, + Port: &w.ContainerPort, + }, + CABundle: caBundle, + }, + } +} + +// GetMutatingWebhook returns a MutatingWebhook generated from the WebhookDescription +func (w *WebhookDescription) GetMutatingWebhook(namespace string, namespaceSelector *metav1.LabelSelector, caBundle []byte) admissionregistrationv1.MutatingWebhook { + return admissionregistrationv1.MutatingWebhook{ + Name: w.GenerateName, + Rules: w.Rules, + FailurePolicy: w.FailurePolicy, + MatchPolicy: w.MatchPolicy, + NamespaceSelector: namespaceSelector, + ObjectSelector: w.ObjectSelector, + SideEffects: w.SideEffects, + TimeoutSeconds: w.TimeoutSeconds, + AdmissionReviewVersions: w.AdmissionReviewVersions, + ClientConfig: admissionregistrationv1.WebhookClientConfig{ + Service: &admissionregistrationv1.ServiceReference{ + Name: w.DomainName() + "-service", + Namespace: namespace, + Path: w.WebhookPath, + Port: &w.ContainerPort, + }, + CABundle: caBundle, + }, + ReinvocationPolicy: w.ReinvocationPolicy, + } +} + +// DomainName returns the result of replacing all periods in the given Webhook name with hyphens +func (w *WebhookDescription) DomainName() string { + // Replace all '.'s with "-"s to convert to a DNS-1035 label + return strings.Replace(w.DeploymentName, ".", "-", -1) +} + +// CustomResourceDefinitions declares all of the CRDs managed or required by +// an operator being ran by ClusterServiceVersion. +// +// If the CRD is present in the Owned list, it is implicitly required. +// +k8s:openapi-gen=true +type CustomResourceDefinitions struct { + Owned []CRDDescription `json:"owned,omitempty"` + Required []CRDDescription `json:"required,omitempty"` +} + +// APIServiceDefinitions declares all of the extension apis managed or required by +// an operator being ran by ClusterServiceVersion. +// +k8s:openapi-gen=true +type APIServiceDefinitions struct { + Owned []APIServiceDescription `json:"owned,omitempty"` + Required []APIServiceDescription `json:"required,omitempty"` +} + +// ClusterServiceVersionSpec declarations tell OLM how to install an operator +// that can manage apps for a given version. +type ClusterServiceVersionSpec struct { + InstallStrategy NamedInstallStrategy `json:"install"` + Version version.OperatorVersion `json:"version,omitempty"` + Maturity string `json:"maturity,omitempty"` + CustomResourceDefinitions CustomResourceDefinitions `json:"customresourcedefinitions,omitempty"` + APIServiceDefinitions APIServiceDefinitions `json:"apiservicedefinitions,omitempty"` + WebhookDefinitions []WebhookDescription `json:"webhookdefinitions,omitempty"` + NativeAPIs []metav1.GroupVersionKind `json:"nativeAPIs,omitempty"` + MinKubeVersion string `json:"minKubeVersion,omitempty"` + DisplayName string `json:"displayName"` + Description string `json:"description,omitempty"` + Keywords []string `json:"keywords,omitempty"` + Maintainers []Maintainer `json:"maintainers,omitempty"` + Provider AppLink `json:"provider,omitempty"` + Links []AppLink `json:"links,omitempty"` + Icon []Icon `json:"icon,omitempty"` + + // InstallModes specify supported installation types + // +optional + InstallModes []InstallMode `json:"installModes,omitempty"` + + // The name of a CSV this one replaces. Should match the `metadata.Name` field of the old CSV. + // +optional + Replaces string `json:"replaces,omitempty"` + + // Map of string keys and values that can be used to organize and categorize + // (scope and select) objects. + // +optional + Labels map[string]string `json:"labels,omitempty" protobuf:"bytes,11,rep,name=labels"` + + // Annotations is an unstructured key value map stored with a resource that may be + // set by external tools to store and retrieve arbitrary metadata. + // +optional + Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,12,rep,name=annotations"` + + // Label selector for related resources. + // +optional + Selector *metav1.LabelSelector `json:"selector,omitempty" protobuf:"bytes,2,opt,name=selector"` +} + +type Maintainer struct { + Name string `json:"name,omitempty"` + Email string `json:"email,omitempty"` +} + +type AppLink struct { + Name string `json:"name,omitempty"` + URL string `json:"url,omitempty"` +} + +type Icon struct { + Data string `json:"base64data"` + MediaType string `json:"mediatype"` +} + +// ClusterServiceVersionPhase is a label for the condition of a ClusterServiceVersion at the current time. +type ClusterServiceVersionPhase string + +// These are the valid phases of ClusterServiceVersion +const ( + CSVPhaseNone = "" + // CSVPhasePending means the csv has been accepted by the system, but the install strategy has not been attempted. + // This is likely because there are unmet requirements. + CSVPhasePending ClusterServiceVersionPhase = "Pending" + // CSVPhaseInstallReady means that the requirements are met but the install strategy has not been run. + CSVPhaseInstallReady ClusterServiceVersionPhase = "InstallReady" + // CSVPhaseInstalling means that the install strategy has been initiated but not completed. + CSVPhaseInstalling ClusterServiceVersionPhase = "Installing" + // CSVPhaseSucceeded means that the resources in the CSV were created successfully. + CSVPhaseSucceeded ClusterServiceVersionPhase = "Succeeded" + // CSVPhaseFailed means that the install strategy could not be successfully completed. + CSVPhaseFailed ClusterServiceVersionPhase = "Failed" + // CSVPhaseUnknown means that for some reason the state of the csv could not be obtained. + CSVPhaseUnknown ClusterServiceVersionPhase = "Unknown" + // CSVPhaseReplacing means that a newer CSV has been created and the csv's resources will be transitioned to a new owner. + CSVPhaseReplacing ClusterServiceVersionPhase = "Replacing" + // CSVPhaseDeleting means that a CSV has been replaced by a new one and will be checked for safety before being deleted + CSVPhaseDeleting ClusterServiceVersionPhase = "Deleting" + // CSVPhaseAny matches all other phases in CSV queries + CSVPhaseAny ClusterServiceVersionPhase = "" +) + +// ConditionReason is a camelcased reason for the state transition +type ConditionReason string + +const ( + CSVReasonRequirementsUnknown ConditionReason = "RequirementsUnknown" + CSVReasonRequirementsNotMet ConditionReason = "RequirementsNotMet" + CSVReasonRequirementsMet ConditionReason = "AllRequirementsMet" + CSVReasonOwnerConflict ConditionReason = "OwnerConflict" + CSVReasonComponentFailed ConditionReason = "InstallComponentFailed" + CSVReasonComponentFailedNoRetry ConditionReason = "InstallComponentFailedNoRetry" + CSVReasonInvalidStrategy ConditionReason = "InvalidInstallStrategy" + CSVReasonWaiting ConditionReason = "InstallWaiting" + CSVReasonInstallSuccessful ConditionReason = "InstallSucceeded" + CSVReasonInstallCheckFailed ConditionReason = "InstallCheckFailed" + CSVReasonComponentUnhealthy ConditionReason = "ComponentUnhealthy" + CSVReasonBeingReplaced ConditionReason = "BeingReplaced" + CSVReasonReplaced ConditionReason = "Replaced" + CSVReasonNeedsReinstall ConditionReason = "NeedsReinstall" + CSVReasonNeedsCertRotation ConditionReason = "NeedsCertRotation" + CSVReasonAPIServiceResourceIssue ConditionReason = "APIServiceResourceIssue" + CSVReasonAPIServiceResourcesNeedReinstall ConditionReason = "APIServiceResourcesNeedReinstall" + CSVReasonAPIServiceInstallFailed ConditionReason = "APIServiceInstallFailed" + CSVReasonCopied ConditionReason = "Copied" + CSVReasonInvalidInstallModes ConditionReason = "InvalidInstallModes" + CSVReasonNoTargetNamespaces ConditionReason = "NoTargetNamespaces" + CSVReasonUnsupportedOperatorGroup ConditionReason = "UnsupportedOperatorGroup" + CSVReasonNoOperatorGroup ConditionReason = "NoOperatorGroup" + CSVReasonTooManyOperatorGroups ConditionReason = "TooManyOperatorGroups" + CSVReasonInterOperatorGroupOwnerConflict ConditionReason = "InterOperatorGroupOwnerConflict" + CSVReasonCannotModifyStaticOperatorGroupProvidedAPIs ConditionReason = "CannotModifyStaticOperatorGroupProvidedAPIs" + CSVReasonDetectedClusterChange ConditionReason = "DetectedClusterChange" + CSVReasonInvalidWebhookDescription ConditionReason = "InvalidWebhookDescription" +) + +// HasCaResources returns true if the CSV has owned APIServices or Webhooks. +func (c *ClusterServiceVersion) HasCAResources() bool { + // Return early if there are no owned APIServices + if len(c.Spec.APIServiceDefinitions.Owned)+len(c.Spec.WebhookDefinitions) == 0 { + return false + } + return true +} + +// Conditions appear in the status as a record of state transitions on the ClusterServiceVersion +type ClusterServiceVersionCondition struct { + // Condition of the ClusterServiceVersion + Phase ClusterServiceVersionPhase `json:"phase,omitempty"` + // A human readable message indicating details about why the ClusterServiceVersion is in this condition. + // +optional + Message string `json:"message,omitempty"` + // A brief CamelCase message indicating details about why the ClusterServiceVersion is in this state. + // e.g. 'RequirementsNotMet' + // +optional + Reason ConditionReason `json:"reason,omitempty"` + // Last time we updated the status + // +optional + LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"` + // Last time the status transitioned from one status to another. + // +optional + LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty"` +} + +// OwnsCRD determines whether the current CSV owns a particular CRD. +func (csv ClusterServiceVersion) OwnsCRD(name string) bool { + for _, desc := range csv.Spec.CustomResourceDefinitions.Owned { + if desc.Name == name { + return true + } + } + + return false +} + +// OwnsAPIService determines whether the current CSV owns a particular APIService. +func (csv ClusterServiceVersion) OwnsAPIService(name string) bool { + for _, desc := range csv.Spec.APIServiceDefinitions.Owned { + apiServiceName := fmt.Sprintf("%s.%s", desc.Version, desc.Group) + if apiServiceName == name { + return true + } + } + + return false +} + +// StatusReason is a camelcased reason for the status of a RequirementStatus or DependentStatus +type StatusReason string + +const ( + RequirementStatusReasonPresent StatusReason = "Present" + RequirementStatusReasonNotPresent StatusReason = "NotPresent" + RequirementStatusReasonPresentNotSatisfied StatusReason = "PresentNotSatisfied" + // The CRD is present but the Established condition is False (not available) + RequirementStatusReasonNotAvailable StatusReason = "PresentNotAvailable" + DependentStatusReasonSatisfied StatusReason = "Satisfied" + DependentStatusReasonNotSatisfied StatusReason = "NotSatisfied" +) + +// DependentStatus is the status for a dependent requirement (to prevent infinite nesting) +type DependentStatus struct { + Group string `json:"group"` + Version string `json:"version"` + Kind string `json:"kind"` + Status StatusReason `json:"status"` + UUID string `json:"uuid,omitempty"` + Message string `json:"message,omitempty"` +} + +type RequirementStatus struct { + Group string `json:"group"` + Version string `json:"version"` + Kind string `json:"kind"` + Name string `json:"name"` + Status StatusReason `json:"status"` + Message string `json:"message"` + UUID string `json:"uuid,omitempty"` + Dependents []DependentStatus `json:"dependents,omitempty"` +} + +// ClusterServiceVersionStatus represents information about the status of a pod. Status may trail the actual +// state of a system. +type ClusterServiceVersionStatus struct { + // Current condition of the ClusterServiceVersion + Phase ClusterServiceVersionPhase `json:"phase,omitempty"` + // A human readable message indicating details about why the ClusterServiceVersion is in this condition. + // +optional + Message string `json:"message,omitempty"` + // A brief CamelCase message indicating details about why the ClusterServiceVersion is in this state. + // e.g. 'RequirementsNotMet' + // +optional + Reason ConditionReason `json:"reason,omitempty"` + // Last time we updated the status + // +optional + LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"` + // Last time the status transitioned from one status to another. + // +optional + LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty"` + // List of conditions, a history of state transitions + Conditions []ClusterServiceVersionCondition `json:"conditions,omitempty"` + // The status of each requirement for this CSV + RequirementStatus []RequirementStatus `json:"requirementStatus,omitempty"` + // Last time the owned APIService certs were updated + // +optional + CertsLastUpdated *metav1.Time `json:"certsLastUpdated,omitempty"` + // Time the owned APIService certs will rotate next + // +optional + CertsRotateAt *metav1.Time `json:"certsRotateAt,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient +// +kubebuilder:storageversion +// +kubebuilder:resource:shortName={csv, csvs},categories=olm +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Display",type=string,JSONPath=`.spec.displayName`,description="The name of the CSV" +// +kubebuilder:printcolumn:name="Version",type=string,JSONPath=`.spec.version`,description="The version of the CSV" +// +kubebuilder:printcolumn:name="Replaces",type=string,JSONPath=`.spec.replaces`,description="The name of a CSV that this one replaces" +// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase` + +// ClusterServiceVersion is a Custom Resource of type `ClusterServiceVersionSpec`. +type ClusterServiceVersion struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata"` + + Spec ClusterServiceVersionSpec `json:"spec"` + // +optional + Status ClusterServiceVersionStatus `json:"status"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ClusterServiceVersionList represents a list of ClusterServiceVersions. +type ClusterServiceVersionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []ClusterServiceVersion `json:"items"` +} + +// GetAllCRDDescriptions returns a deduplicated set of CRDDescriptions that is +// the union of the owned and required CRDDescriptions. +// +// Descriptions with the same name prefer the value in Owned. +// Descriptions are returned in alphabetical order. +func (csv ClusterServiceVersion) GetAllCRDDescriptions() []CRDDescription { + set := make(map[string]CRDDescription) + for _, required := range csv.Spec.CustomResourceDefinitions.Required { + set[required.Name] = required + } + + for _, owned := range csv.Spec.CustomResourceDefinitions.Owned { + set[owned.Name] = owned + } + + keys := make([]string, 0) + for key := range set { + keys = append(keys, key) + } + sort.StringSlice(keys).Sort() + + descs := make([]CRDDescription, 0) + for _, key := range keys { + descs = append(descs, set[key]) + } + + return descs +} + +// GetAllAPIServiceDescriptions returns a deduplicated set of APIServiceDescriptions that is +// the union of the owned and required APIServiceDescriptions. +// +// Descriptions with the same name prefer the value in Owned. +// Descriptions are returned in alphabetical order. +func (csv ClusterServiceVersion) GetAllAPIServiceDescriptions() []APIServiceDescription { + set := make(map[string]APIServiceDescription) + for _, required := range csv.Spec.APIServiceDefinitions.Required { + name := fmt.Sprintf("%s.%s", required.Version, required.Group) + set[name] = required + } + + for _, owned := range csv.Spec.APIServiceDefinitions.Owned { + name := fmt.Sprintf("%s.%s", owned.Version, owned.Group) + set[name] = owned + } + + keys := make([]string, 0) + for key := range set { + keys = append(keys, key) + } + sort.StringSlice(keys).Sort() + + descs := make([]APIServiceDescription, 0) + for _, key := range keys { + descs = append(descs, set[key]) + } + + return descs +} + +// GetRequiredAPIServiceDescriptions returns a deduplicated set of required APIServiceDescriptions +// with the intersection of required and owned removed +// Equivalent to the set subtraction required - owned +// +// Descriptions are returned in alphabetical order. +func (csv ClusterServiceVersion) GetRequiredAPIServiceDescriptions() []APIServiceDescription { + set := make(map[string]APIServiceDescription) + for _, required := range csv.Spec.APIServiceDefinitions.Required { + name := fmt.Sprintf("%s.%s", required.Version, required.Group) + set[name] = required + } + + // Remove any shared owned from the set + for _, owned := range csv.Spec.APIServiceDefinitions.Owned { + name := fmt.Sprintf("%s.%s", owned.Version, owned.Group) + if _, ok := set[name]; ok { + delete(set, name) + } + } + + keys := make([]string, 0) + for key := range set { + keys = append(keys, key) + } + sort.StringSlice(keys).Sort() + + descs := make([]APIServiceDescription, 0) + for _, key := range keys { + descs = append(descs, set[key]) + } + + return descs +} + +// GetOwnedAPIServiceDescriptions returns a deduplicated set of owned APIServiceDescriptions +// +// Descriptions are returned in alphabetical order. +func (csv ClusterServiceVersion) GetOwnedAPIServiceDescriptions() []APIServiceDescription { + set := make(map[string]APIServiceDescription) + for _, owned := range csv.Spec.APIServiceDefinitions.Owned { + name := owned.GetName() + set[name] = owned + } + + keys := make([]string, 0) + for key := range set { + keys = append(keys, key) + } + sort.StringSlice(keys).Sort() + + descs := make([]APIServiceDescription, 0) + for _, key := range keys { + descs = append(descs, set[key]) + } + + return descs +} diff --git a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/doc.go b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/doc.go new file mode 100644 index 0000000000..3938a475ee --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/doc.go @@ -0,0 +1,6 @@ +// +k8s:deepcopy-gen=package +// +k8s:conversion-gen=github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators +// +groupName=operators.coreos.com + +// Package v1alpha1 contains resources types for version v1alpha1 of the operators.coreos.com API group. +package v1alpha1 diff --git a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/installplan_types.go b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/installplan_types.go new file mode 100644 index 0000000000..41bbd429f7 --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/installplan_types.go @@ -0,0 +1,369 @@ +package v1alpha1 + +import ( + "errors" + "fmt" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + InstallPlanKind = "InstallPlan" + InstallPlanAPIVersion = GroupName + "/" + GroupVersion +) + +// Approval is the user approval policy for an InstallPlan. +type Approval string + +const ( + ApprovalAutomatic Approval = "Automatic" + ApprovalManual Approval = "Manual" +) + +// InstallPlanSpec defines a set of Application resources to be installed +type InstallPlanSpec struct { + CatalogSource string `json:"source,omitempty"` + CatalogSourceNamespace string `json:"sourceNamespace,omitempty"` + ClusterServiceVersionNames []string `json:"clusterServiceVersionNames"` + Approval Approval `json:"approval"` + Approved bool `json:"approved"` + Generation int `json:"generation,omitempty"` +} + +// InstallPlanPhase is the current status of a InstallPlan as a whole. +type InstallPlanPhase string + +const ( + InstallPlanPhaseNone InstallPlanPhase = "" + InstallPlanPhasePlanning InstallPlanPhase = "Planning" + InstallPlanPhaseRequiresApproval InstallPlanPhase = "RequiresApproval" + InstallPlanPhaseInstalling InstallPlanPhase = "Installing" + InstallPlanPhaseComplete InstallPlanPhase = "Complete" + InstallPlanPhaseFailed InstallPlanPhase = "Failed" +) + +// InstallPlanConditionType describes the state of an InstallPlan at a certain point as a whole. +type InstallPlanConditionType string + +const ( + InstallPlanResolved InstallPlanConditionType = "Resolved" + InstallPlanInstalled InstallPlanConditionType = "Installed" +) + +// ConditionReason is a camelcased reason for the state transition. +type InstallPlanConditionReason string + +const ( + InstallPlanReasonPlanUnknown InstallPlanConditionReason = "PlanUnknown" + InstallPlanReasonInstallCheckFailed InstallPlanConditionReason = "InstallCheckFailed" + InstallPlanReasonDependencyConflict InstallPlanConditionReason = "DependenciesConflict" + InstallPlanReasonComponentFailed InstallPlanConditionReason = "InstallComponentFailed" +) + +// StepStatus is the current status of a particular resource an in +// InstallPlan +type StepStatus string + +const ( + StepStatusUnknown StepStatus = "Unknown" + StepStatusNotPresent StepStatus = "NotPresent" + StepStatusPresent StepStatus = "Present" + StepStatusCreated StepStatus = "Created" + StepStatusWaitingForAPI StepStatus = "WaitingForApi" + StepStatusUnsupportedResource StepStatus = "UnsupportedResource" +) + +// ErrInvalidInstallPlan is the error returned by functions that operate on +// InstallPlans when the InstallPlan does not contain totally valid data. +var ErrInvalidInstallPlan = errors.New("the InstallPlan contains invalid data") + +// InstallPlanStatus represents the information about the status of +// steps required to complete installation. +// +// Status may trail the actual state of a system. +type InstallPlanStatus struct { + Phase InstallPlanPhase `json:"phase"` + Conditions []InstallPlanCondition `json:"conditions,omitempty"` + CatalogSources []string `json:"catalogSources"` + Plan []*Step `json:"plan,omitempty"` + // BundleLookups is the set of in-progress requests to pull and unpackage bundle content to the cluster. + // +optional + BundleLookups []BundleLookup `json:"bundleLookups,omitempty"` + // AttenuatedServiceAccountRef references the service account that is used + // to do scoped operator install. + AttenuatedServiceAccountRef *corev1.ObjectReference `json:"attenuatedServiceAccountRef,omitempty"` +} + +// InstallPlanCondition represents the overall status of the execution of +// an InstallPlan. +type InstallPlanCondition struct { + Type InstallPlanConditionType `json:"type,omitempty"` + Status corev1.ConditionStatus `json:"status,omitempty"` // True, False, or Unknown + LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"` + LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty"` + Reason InstallPlanConditionReason `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +// allow overwriting `now` function for deterministic tests +var now = metav1.Now + +// GetCondition returns the InstallPlanCondition of the given type if it exists in the InstallPlanStatus' Conditions. +// Returns a condition of the given type with a ConditionStatus of "Unknown" if not found. +func (s InstallPlanStatus) GetCondition(conditionType InstallPlanConditionType) InstallPlanCondition { + for _, cond := range s.Conditions { + if cond.Type == conditionType { + return cond + } + } + + return InstallPlanCondition{ + Type: conditionType, + Status: corev1.ConditionUnknown, + } +} + +// SetCondition adds or updates a condition, using `Type` as merge key. +func (s *InstallPlanStatus) SetCondition(cond InstallPlanCondition) InstallPlanCondition { + for i, existing := range s.Conditions { + if existing.Type != cond.Type { + continue + } + if existing.Status == cond.Status { + cond.LastTransitionTime = existing.LastTransitionTime + } + s.Conditions[i] = cond + return cond + } + s.Conditions = append(s.Conditions, cond) + return cond +} + +func OrderSteps(steps []*Step) []*Step { + // CSVs must be applied first + csvList := []*Step{} + + // CRDs must be applied second + crdList := []*Step{} + + // Other resources may be applied in any order + remainingResources := []*Step{} + for _, step := range steps { + switch step.Resource.Kind { + case crdKind: + crdList = append(crdList, step) + case ClusterServiceVersionKind: + csvList = append(csvList, step) + default: + remainingResources = append(remainingResources, step) + } + } + + result := make([]*Step, len(steps)) + i := 0 + + for j := range csvList { + result[i] = csvList[j] + i++ + } + + for j := range crdList { + result[i] = crdList[j] + i++ + } + + for j := range remainingResources { + result[i] = remainingResources[j] + i++ + } + + return result +} + +func (s InstallPlanStatus) NeedsRequeue() bool { + for _, step := range s.Plan { + switch step.Status { + case StepStatusWaitingForAPI: + return true + } + } + + return false +} +func ConditionFailed(cond InstallPlanConditionType, reason InstallPlanConditionReason, message string, now *metav1.Time) InstallPlanCondition { + return InstallPlanCondition{ + Type: cond, + Status: corev1.ConditionFalse, + Reason: reason, + Message: message, + LastUpdateTime: now, + LastTransitionTime: now, + } +} + +func ConditionMet(cond InstallPlanConditionType, now *metav1.Time) InstallPlanCondition { + return InstallPlanCondition{ + Type: cond, + Status: corev1.ConditionTrue, + LastUpdateTime: now, + LastTransitionTime: now, + } +} + +// Step represents the status of an individual step in an InstallPlan. +type Step struct { + Resolving string `json:"resolving"` + Resource StepResource `json:"resource"` + Status StepStatus `json:"status"` +} + +// BundleLookupConditionType is a category of the overall state of a BundleLookup. +type BundleLookupConditionType string + +const ( + // BundleLookupPending describes BundleLookups that are not complete. + BundleLookupPending BundleLookupConditionType = "BundleLookupPending" + + crdKind = "CustomResourceDefinition" +) + +type BundleLookupCondition struct { + // Type of condition. + Type BundleLookupConditionType `json:"type"` + // Status of the condition, one of True, False, Unknown. + Status corev1.ConditionStatus `json:"status"` + // The reason for the condition's last transition. + // +optional + Reason string `json:"reason,omitempty"` + // A human readable message indicating details about the transition. + // +optional + Message string `json:"message,omitempty"` + // Last time the condition was probed. + // +optional + LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"` + // Last time the condition transitioned from one status to another. + // +optional + LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty"` +} + +// BundleLookup is a request to pull and unpackage the content of a bundle to the cluster. +type BundleLookup struct { + // Path refers to the location of a bundle to pull. + // It's typically an image reference. + Path string `json:"path"` + // Identifier is the catalog-unique name of the operator (the name of the CSV for bundles that contain CSVs) + Identifier string `json:"identifier"` + // Replaces is the name of the bundle to replace with the one found at Path. + Replaces string `json:"replaces"` + // CatalogSourceRef is a reference to the CatalogSource the bundle path was resolved from. + CatalogSourceRef *corev1.ObjectReference `json:"catalogSourceRef"` + // Conditions represents the overall state of a BundleLookup. + // +optional + Conditions []BundleLookupCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` +} + +// GetCondition returns the BundleLookupCondition of the given type if it exists in the BundleLookup's Conditions. +// Returns a condition of the given type with a ConditionStatus of "Unknown" if not found. +func (b BundleLookup) GetCondition(conditionType BundleLookupConditionType) BundleLookupCondition { + for _, cond := range b.Conditions { + if cond.Type == conditionType { + return cond + } + } + + return BundleLookupCondition{ + Type: conditionType, + Status: corev1.ConditionUnknown, + } +} + +// RemoveCondition removes the BundleLookupCondition of the given type from the BundleLookup's Conditions if it exists. +func (b *BundleLookup) RemoveCondition(conditionType BundleLookupConditionType) { + for i, cond := range b.Conditions { + if cond.Type == conditionType { + b.Conditions = append(b.Conditions[:i], b.Conditions[i+1:]...) + if len(b.Conditions) == 0 { + b.Conditions = nil + } + return + } + } +} + +// SetCondition replaces the existing BundleLookupCondition of the same type, or adds it if it was not found. +func (b *BundleLookup) SetCondition(cond BundleLookupCondition) BundleLookupCondition { + for i, existing := range b.Conditions { + if existing.Type != cond.Type { + continue + } + if existing.Status == cond.Status { + cond.LastTransitionTime = existing.LastTransitionTime + } + b.Conditions[i] = cond + return cond + } + b.Conditions = append(b.Conditions, cond) + + return cond +} + +func (s *Step) String() string { + return fmt.Sprintf("%s: %s (%s)", s.Resolving, s.Resource, s.Status) +} + +// StepResource represents the status of a resource to be tracked by an +// InstallPlan. +type StepResource struct { + CatalogSource string `json:"sourceName"` + CatalogSourceNamespace string `json:"sourceNamespace"` + Group string `json:"group"` + Version string `json:"version"` + Kind string `json:"kind"` + Name string `json:"name"` + Manifest string `json:"manifest,omitempty"` +} + +func (r StepResource) String() string { + return fmt.Sprintf("%s[%s/%s/%s (%s/%s)]", r.Name, r.Group, r.Version, r.Kind, r.CatalogSource, r.CatalogSourceNamespace) +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient +// +kubebuilder:resource:shortName=ip,categories=olm +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="CSV",type=string,JSONPath=`.spec.clusterServiceVersionNames[0]`,description="The first CSV in the list of clusterServiceVersionNames" +// +kubebuilder:printcolumn:name="Approval",type=string,JSONPath=`.spec.approval`,description="The approval mode" +// +kubebuilder:printcolumn:name="Approved",type=boolean,JSONPath=`.spec.approved` + +// InstallPlan defines the installation of a set of operators. +type InstallPlan struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata"` + + Spec InstallPlanSpec `json:"spec"` + // +optional + Status InstallPlanStatus `json:"status"` +} + +// EnsureCatalogSource ensures that a CatalogSource is present in the Status +// block of an InstallPlan. +func (p *InstallPlan) EnsureCatalogSource(sourceName string) { + for _, srcName := range p.Status.CatalogSources { + if srcName == sourceName { + return + } + } + + p.Status.CatalogSources = append(p.Status.CatalogSources, sourceName) +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// InstallPlanList is a list of InstallPlan resources. +type InstallPlanList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []InstallPlan `json:"items"` +} diff --git a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/register.go b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/register.go new file mode 100644 index 0000000000..f1cd86f1a3 --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/register.go @@ -0,0 +1,55 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/operator-framework/api/pkg/operators" +) + +const ( + // GroupName is the group name used in this package. + GroupName = operators.GroupName + // GroupVersion is the group version used in this package. + GroupVersion = "v1alpha1" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: GroupVersion} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // SchemeBuilder initializes a scheme builder + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // AddToScheme is a global function that registers this API group & version to a scheme + AddToScheme = SchemeBuilder.AddToScheme + + // localSchemeBuilder is expected by generated conversion functions + localSchemeBuilder = &SchemeBuilder +) + +// addKnownTypes adds the list of known types to Scheme +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &CatalogSource{}, + &CatalogSourceList{}, + &InstallPlan{}, + &InstallPlanList{}, + &Subscription{}, + &SubscriptionList{}, + &ClusterServiceVersion{}, + &ClusterServiceVersionList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/subscription_types.go b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/subscription_types.go new file mode 100644 index 0000000000..4664d14723 --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/subscription_types.go @@ -0,0 +1,325 @@ +package v1alpha1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +const ( + SubscriptionKind = "Subscription" + SubscriptionCRDAPIVersion = GroupName + "/" + GroupVersion +) + +// SubscriptionState tracks when updates are available, installing, or service is up to date +type SubscriptionState string + +const ( + SubscriptionStateNone = "" + SubscriptionStateFailed = "UpgradeFailed" + SubscriptionStateUpgradeAvailable = "UpgradeAvailable" + SubscriptionStateUpgradePending = "UpgradePending" + SubscriptionStateAtLatest = "AtLatestKnown" +) + +const ( + SubscriptionReasonInvalidCatalog ConditionReason = "InvalidCatalog" + SubscriptionReasonUpgradeSucceeded ConditionReason = "UpgradeSucceeded" +) + +// SubscriptionSpec defines an Application that can be installed +type SubscriptionSpec struct { + CatalogSource string `json:"source"` + CatalogSourceNamespace string `json:"sourceNamespace"` + Package string `json:"name"` + Channel string `json:"channel,omitempty"` + StartingCSV string `json:"startingCSV,omitempty"` + InstallPlanApproval Approval `json:"installPlanApproval,omitempty"` + Config SubscriptionConfig `json:"config,omitempty"` +} + +// SubscriptionConfig contains configuration specified for a subscription. +type SubscriptionConfig struct { + // Selector is the label selector for pods to be configured. + // Existing ReplicaSets whose pods are + // selected by this will be the ones affected by this deployment. + // It must match the pod template's labels. + Selector *metav1.LabelSelector `json:"selector,omitempty"` + + // NodeSelector is a selector which must be true for the pod to fit on a node. + // Selector which must match a node's labels for the pod to be scheduled on that node. + // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + // +optional + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // Tolerations are the pod's tolerations. + // +optional + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + + // Resources represents compute resources required by this container. + // Immutable. + // More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ + // +optional + Resources corev1.ResourceRequirements `json:"resources,omitempty"` + + // EnvFrom is a list of sources to populate environment variables in the container. + // The keys defined within a source must be a C_IDENTIFIER. All invalid keys + // will be reported as an event when the container is starting. When a key exists in multiple + // sources, the value associated with the last source will take precedence. + // Values defined by an Env with a duplicate key will take precedence. + // Immutable. + // +optional + EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"` + // Env is a list of environment variables to set in the container. + // Cannot be updated. + // +patchMergeKey=name + // +patchStrategy=merge + // +optional + Env []corev1.EnvVar `json:"env,omitempty" patchMergeKey:"name" patchStrategy:"merge"` + + // List of Volumes to set in the podSpec. + // +optional + Volumes []corev1.Volume `json:"volumes,omitempty"` + + // List of VolumeMounts to set in the container. + // +optional + VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"` +} + +// SubscriptionConditionType indicates an explicit state condition about a Subscription in "abnormal-true" +// polarity form (see https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties). +type SubscriptionConditionType string + +const ( + // SubscriptionCatalogSourcesUnhealthy indicates that some or all of the CatalogSources to be used in resolution are unhealthy. + SubscriptionCatalogSourcesUnhealthy SubscriptionConditionType = "CatalogSourcesUnhealthy" + + // SubscriptionInstallPlanMissing indicates that a Subscription's InstallPlan is missing. + SubscriptionInstallPlanMissing SubscriptionConditionType = "InstallPlanMissing" + + // SubscriptionInstallPlanPending indicates that a Subscription's InstallPlan is pending installation. + SubscriptionInstallPlanPending SubscriptionConditionType = "InstallPlanPending" + + // SubscriptionInstallPlanFailed indicates that the installation of a Subscription's InstallPlan has failed. + SubscriptionInstallPlanFailed SubscriptionConditionType = "InstallPlanFailed" +) + +const ( + // NoCatalogSourcesFound is a reason string for Subscriptions with unhealthy CatalogSources due to none being available. + NoCatalogSourcesFound = "NoCatalogSourcesFound" + + // AllCatalogSourcesHealthy is a reason string for Subscriptions that transitioned due to all CatalogSources being healthy. + AllCatalogSourcesHealthy = "AllCatalogSourcesHealthy" + + // CatalogSourcesAdded is a reason string for Subscriptions that transitioned due to CatalogSources being added. + CatalogSourcesAdded = "CatalogSourcesAdded" + + // CatalogSourcesUpdated is a reason string for Subscriptions that transitioned due to CatalogSource being updated. + CatalogSourcesUpdated = "CatalogSourcesUpdated" + + // CatalogSourcesDeleted is a reason string for Subscriptions that transitioned due to CatalogSources being removed. + CatalogSourcesDeleted = "CatalogSourcesDeleted" + + // UnhealthyCatalogSourceFound is a reason string for Subscriptions that transitioned because an unhealthy CatalogSource was found. + UnhealthyCatalogSourceFound = "UnhealthyCatalogSourceFound" + + // ReferencedInstallPlanNotFound is a reason string for Subscriptions that transitioned due to a referenced InstallPlan not being found. + ReferencedInstallPlanNotFound = "ReferencedInstallPlanNotFound" + + // InstallPlanNotYetReconciled is a reason string for Subscriptions that transitioned due to a referenced InstallPlan not being reconciled yet. + InstallPlanNotYetReconciled = "InstallPlanNotYetReconciled" + + // InstallPlanFailed is a reason string for Subscriptions that transitioned due to a referenced InstallPlan failing without setting an explicit failure condition. + InstallPlanFailed = "InstallPlanFailed" +) + +// SubscriptionCondition represents the latest available observations of a Subscription's state. +type SubscriptionCondition struct { + // Type is the type of Subscription condition. + Type SubscriptionConditionType `json:"type" description:"type of Subscription condition"` + + // Status is the status of the condition, one of True, False, Unknown. + Status corev1.ConditionStatus `json:"status" description:"status of the condition, one of True, False, Unknown"` + + // Reason is a one-word CamelCase reason for the condition's last transition. + // +optional + Reason string `json:"reason,omitempty" description:"one-word CamelCase reason for the condition's last transition"` + + // Message is a human-readable message indicating details about last transition. + // +optional + Message string `json:"message,omitempty" description:"human-readable message indicating details about last transition"` + + // LastHeartbeatTime is the last time we got an update on a given condition + // +optional + LastHeartbeatTime *metav1.Time `json:"lastHeartbeatTime,omitempty" description:"last time we got an update on a given condition"` + + // LastTransitionTime is the last time the condition transit from one status to another + // +optional + LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty" description:"last time the condition transit from one status to another" hash:"ignore"` +} + +// Equals returns true if a SubscriptionCondition equals the one given, false otherwise. +// Equality is determined by the equality of the type, status, reason, and message fields ONLY. +func (s SubscriptionCondition) Equals(condition SubscriptionCondition) bool { + return s.Type == condition.Type && s.Status == condition.Status && s.Reason == condition.Reason && s.Message == condition.Message +} + +type SubscriptionStatus struct { + // CurrentCSV is the CSV the Subscription is progressing to. + // +optional + CurrentCSV string `json:"currentCSV,omitempty"` + + // InstalledCSV is the CSV currently installed by the Subscription. + // +optional + InstalledCSV string `json:"installedCSV,omitempty"` + + // Install is a reference to the latest InstallPlan generated for the Subscription. + // DEPRECATED: InstallPlanRef + // +optional + Install *InstallPlanReference `json:"installplan,omitempty"` + + // State represents the current state of the Subscription + // +optional + State SubscriptionState `json:"state,omitempty"` + + // Reason is the reason the Subscription was transitioned to its current state. + // +optional + Reason ConditionReason `json:"reason,omitempty"` + + // InstallPlanGeneration is the current generation of the installplan + // +optional + InstallPlanGeneration int `json:"installPlanGeneration,omitempty"` + + // InstallPlanRef is a reference to the latest InstallPlan that contains the Subscription's current CSV. + // +optional + InstallPlanRef *corev1.ObjectReference `json:"installPlanRef,omitempty"` + + // CatalogHealth contains the Subscription's view of its relevant CatalogSources' status. + // It is used to determine SubscriptionStatusConditions related to CatalogSources. + // +optional + CatalogHealth []SubscriptionCatalogHealth `json:"catalogHealth,omitempty"` + + // Conditions is a list of the latest available observations about a Subscription's current state. + // +optional + Conditions []SubscriptionCondition `json:"conditions,omitempty" hash:"set"` + + // LastUpdated represents the last time that the Subscription status was updated. + LastUpdated metav1.Time `json:"lastUpdated"` +} + +// GetCondition returns the SubscriptionCondition of the given type if it exists in the SubscriptionStatus' Conditions. +// Returns a condition of the given type with a ConditionStatus of "Unknown" if not found. +func (s SubscriptionStatus) GetCondition(conditionType SubscriptionConditionType) SubscriptionCondition { + for _, cond := range s.Conditions { + if cond.Type == conditionType { + return cond + } + } + + return SubscriptionCondition{ + Type: conditionType, + Status: corev1.ConditionUnknown, + } +} + +// SetCondition sets the given SubscriptionCondition in the SubscriptionStatus' Conditions. +func (s *SubscriptionStatus) SetCondition(condition SubscriptionCondition) { + for i, cond := range s.Conditions { + if cond.Type == condition.Type { + s.Conditions[i] = condition + return + } + } + + s.Conditions = append(s.Conditions, condition) +} + +// RemoveConditions removes any conditions of the given types from the SubscriptionStatus' Conditions. +func (s *SubscriptionStatus) RemoveConditions(remove ...SubscriptionConditionType) { + exclusions := map[SubscriptionConditionType]struct{}{} + for _, r := range remove { + exclusions[r] = struct{}{} + } + + var filtered []SubscriptionCondition + for _, cond := range s.Conditions { + if _, ok := exclusions[cond.Type]; ok { + // Skip excluded condition types + continue + } + filtered = append(filtered, cond) + } + + s.Conditions = filtered +} + +type InstallPlanReference struct { + APIVersion string `json:"apiVersion"` + Kind string `json:"kind"` + Name string `json:"name"` + UID types.UID `json:"uuid"` +} + +// SubscriptionCatalogHealth describes the health of a CatalogSource the Subscription knows about. +type SubscriptionCatalogHealth struct { + // CatalogSourceRef is a reference to a CatalogSource. + CatalogSourceRef *corev1.ObjectReference `json:"catalogSourceRef"` + + // LastUpdated represents the last time that the CatalogSourceHealth changed + LastUpdated *metav1.Time `json:"lastUpdated"` + + // Healthy is true if the CatalogSource is healthy; false otherwise. + Healthy bool `json:"healthy"` +} + +// Equals returns true if a SubscriptionCatalogHealth equals the one given, false otherwise. +// Equality is based SOLEY on health and UID. +func (s SubscriptionCatalogHealth) Equals(health SubscriptionCatalogHealth) bool { + return s.Healthy == health.Healthy && s.CatalogSourceRef.UID == health.CatalogSourceRef.UID +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +genclient +// +kubebuilder:resource:shortName={sub, subs},categories=olm +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Package",type=string,JSONPath=`.spec.name`,description="The package subscribed to" +// +kubebuilder:printcolumn:name="Source",type=string,JSONPath=`.spec.source`,description="The catalog source for the specified package" +// +kubebuilder:printcolumn:name="Channel",type=string,JSONPath=`.spec.channel`,description="The channel of updates to subscribe to" + +// Subscription keeps operators up to date by tracking changes to Catalogs. +type Subscription struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata"` + + Spec *SubscriptionSpec `json:"spec"` + // +optional + Status SubscriptionStatus `json:"status"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// SubscriptionList is a list of Subscription resources. +type SubscriptionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []Subscription `json:"items"` +} + +// GetInstallPlanApproval gets the configured install plan approval or the default +func (s *Subscription) GetInstallPlanApproval() Approval { + if s.Spec.InstallPlanApproval == ApprovalManual { + return ApprovalManual + } + return ApprovalAutomatic +} + +// NewInstallPlanReference returns an InstallPlanReference for the given ObjectReference. +func NewInstallPlanReference(ref *corev1.ObjectReference) *InstallPlanReference { + return &InstallPlanReference{ + APIVersion: ref.APIVersion, + Kind: ref.Kind, + Name: ref.Name, + UID: ref.UID, + } +} diff --git a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/zz_generated.deepcopy.go b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..a3d8a11ec1 --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,1414 @@ +// +build !ignore_autogenerated + +/* + +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "encoding/json" + admissionregistrationv1 "k8s.io/api/admissionregistration/v1" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIResourceReference) DeepCopyInto(out *APIResourceReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIResourceReference. +func (in *APIResourceReference) DeepCopy() *APIResourceReference { + if in == nil { + return nil + } + out := new(APIResourceReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIServiceDefinitions) DeepCopyInto(out *APIServiceDefinitions) { + *out = *in + if in.Owned != nil { + in, out := &in.Owned, &out.Owned + *out = make([]APIServiceDescription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Required != nil { + in, out := &in.Required, &out.Required + *out = make([]APIServiceDescription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIServiceDefinitions. +func (in *APIServiceDefinitions) DeepCopy() *APIServiceDefinitions { + if in == nil { + return nil + } + out := new(APIServiceDefinitions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIServiceDescription) DeepCopyInto(out *APIServiceDescription) { + *out = *in + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]APIResourceReference, len(*in)) + copy(*out, *in) + } + if in.StatusDescriptors != nil { + in, out := &in.StatusDescriptors, &out.StatusDescriptors + *out = make([]StatusDescriptor, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.SpecDescriptors != nil { + in, out := &in.SpecDescriptors, &out.SpecDescriptors + *out = make([]SpecDescriptor, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ActionDescriptor != nil { + in, out := &in.ActionDescriptor, &out.ActionDescriptor + *out = make([]ActionDescriptor, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIServiceDescription. +func (in *APIServiceDescription) DeepCopy() *APIServiceDescription { + if in == nil { + return nil + } + out := new(APIServiceDescription) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActionDescriptor) DeepCopyInto(out *ActionDescriptor) { + *out = *in + if in.XDescriptors != nil { + in, out := &in.XDescriptors, &out.XDescriptors + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = make(json.RawMessage, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActionDescriptor. +func (in *ActionDescriptor) DeepCopy() *ActionDescriptor { + if in == nil { + return nil + } + out := new(ActionDescriptor) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AppLink) DeepCopyInto(out *AppLink) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppLink. +func (in *AppLink) DeepCopy() *AppLink { + if in == nil { + return nil + } + out := new(AppLink) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BundleLookup) DeepCopyInto(out *BundleLookup) { + *out = *in + if in.CatalogSourceRef != nil { + in, out := &in.CatalogSourceRef, &out.CatalogSourceRef + *out = new(corev1.ObjectReference) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]BundleLookupCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BundleLookup. +func (in *BundleLookup) DeepCopy() *BundleLookup { + if in == nil { + return nil + } + out := new(BundleLookup) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BundleLookupCondition) DeepCopyInto(out *BundleLookupCondition) { + *out = *in + if in.LastUpdateTime != nil { + in, out := &in.LastUpdateTime, &out.LastUpdateTime + *out = (*in).DeepCopy() + } + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BundleLookupCondition. +func (in *BundleLookupCondition) DeepCopy() *BundleLookupCondition { + if in == nil { + return nil + } + out := new(BundleLookupCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CRDDescription) DeepCopyInto(out *CRDDescription) { + *out = *in + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]APIResourceReference, len(*in)) + copy(*out, *in) + } + if in.StatusDescriptors != nil { + in, out := &in.StatusDescriptors, &out.StatusDescriptors + *out = make([]StatusDescriptor, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.SpecDescriptors != nil { + in, out := &in.SpecDescriptors, &out.SpecDescriptors + *out = make([]SpecDescriptor, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ActionDescriptor != nil { + in, out := &in.ActionDescriptor, &out.ActionDescriptor + *out = make([]ActionDescriptor, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CRDDescription. +func (in *CRDDescription) DeepCopy() *CRDDescription { + if in == nil { + return nil + } + out := new(CRDDescription) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CatalogSource) DeepCopyInto(out *CatalogSource) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CatalogSource. +func (in *CatalogSource) DeepCopy() *CatalogSource { + if in == nil { + return nil + } + out := new(CatalogSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CatalogSource) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CatalogSourceList) DeepCopyInto(out *CatalogSourceList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]CatalogSource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CatalogSourceList. +func (in *CatalogSourceList) DeepCopy() *CatalogSourceList { + if in == nil { + return nil + } + out := new(CatalogSourceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CatalogSourceList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CatalogSourceSpec) DeepCopyInto(out *CatalogSourceSpec) { + *out = *in + if in.UpdateStrategy != nil { + in, out := &in.UpdateStrategy, &out.UpdateStrategy + *out = new(UpdateStrategy) + (*in).DeepCopyInto(*out) + } + if in.Secrets != nil { + in, out := &in.Secrets, &out.Secrets + *out = make([]string, len(*in)) + copy(*out, *in) + } + out.Icon = in.Icon +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CatalogSourceSpec. +func (in *CatalogSourceSpec) DeepCopy() *CatalogSourceSpec { + if in == nil { + return nil + } + out := new(CatalogSourceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CatalogSourceStatus) DeepCopyInto(out *CatalogSourceStatus) { + *out = *in + if in.LatestImageRegistryPoll != nil { + in, out := &in.LatestImageRegistryPoll, &out.LatestImageRegistryPoll + *out = (*in).DeepCopy() + } + if in.ConfigMapResource != nil { + in, out := &in.ConfigMapResource, &out.ConfigMapResource + *out = new(ConfigMapResourceReference) + (*in).DeepCopyInto(*out) + } + if in.RegistryServiceStatus != nil { + in, out := &in.RegistryServiceStatus, &out.RegistryServiceStatus + *out = new(RegistryServiceStatus) + (*in).DeepCopyInto(*out) + } + if in.GRPCConnectionState != nil { + in, out := &in.GRPCConnectionState, &out.GRPCConnectionState + *out = new(GRPCConnectionState) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CatalogSourceStatus. +func (in *CatalogSourceStatus) DeepCopy() *CatalogSourceStatus { + if in == nil { + return nil + } + out := new(CatalogSourceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterServiceVersion) DeepCopyInto(out *ClusterServiceVersion) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterServiceVersion. +func (in *ClusterServiceVersion) DeepCopy() *ClusterServiceVersion { + if in == nil { + return nil + } + out := new(ClusterServiceVersion) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterServiceVersion) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterServiceVersionCondition) DeepCopyInto(out *ClusterServiceVersionCondition) { + *out = *in + if in.LastUpdateTime != nil { + in, out := &in.LastUpdateTime, &out.LastUpdateTime + *out = (*in).DeepCopy() + } + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterServiceVersionCondition. +func (in *ClusterServiceVersionCondition) DeepCopy() *ClusterServiceVersionCondition { + if in == nil { + return nil + } + out := new(ClusterServiceVersionCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterServiceVersionList) DeepCopyInto(out *ClusterServiceVersionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterServiceVersion, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterServiceVersionList. +func (in *ClusterServiceVersionList) DeepCopy() *ClusterServiceVersionList { + if in == nil { + return nil + } + out := new(ClusterServiceVersionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterServiceVersionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterServiceVersionSpec) DeepCopyInto(out *ClusterServiceVersionSpec) { + *out = *in + in.InstallStrategy.DeepCopyInto(&out.InstallStrategy) + in.Version.DeepCopyInto(&out.Version) + in.CustomResourceDefinitions.DeepCopyInto(&out.CustomResourceDefinitions) + in.APIServiceDefinitions.DeepCopyInto(&out.APIServiceDefinitions) + if in.WebhookDefinitions != nil { + in, out := &in.WebhookDefinitions, &out.WebhookDefinitions + *out = make([]WebhookDescription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.NativeAPIs != nil { + in, out := &in.NativeAPIs, &out.NativeAPIs + *out = make([]v1.GroupVersionKind, len(*in)) + copy(*out, *in) + } + if in.Keywords != nil { + in, out := &in.Keywords, &out.Keywords + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Maintainers != nil { + in, out := &in.Maintainers, &out.Maintainers + *out = make([]Maintainer, len(*in)) + copy(*out, *in) + } + out.Provider = in.Provider + if in.Links != nil { + in, out := &in.Links, &out.Links + *out = make([]AppLink, len(*in)) + copy(*out, *in) + } + if in.Icon != nil { + in, out := &in.Icon, &out.Icon + *out = make([]Icon, len(*in)) + copy(*out, *in) + } + if in.InstallModes != nil { + in, out := &in.InstallModes, &out.InstallModes + *out = make([]InstallMode, len(*in)) + copy(*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 + } + } + if in.Selector != nil { + in, out := &in.Selector, &out.Selector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterServiceVersionSpec. +func (in *ClusterServiceVersionSpec) DeepCopy() *ClusterServiceVersionSpec { + if in == nil { + return nil + } + out := new(ClusterServiceVersionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterServiceVersionStatus) DeepCopyInto(out *ClusterServiceVersionStatus) { + *out = *in + if in.LastUpdateTime != nil { + in, out := &in.LastUpdateTime, &out.LastUpdateTime + *out = (*in).DeepCopy() + } + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]ClusterServiceVersionCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.RequirementStatus != nil { + in, out := &in.RequirementStatus, &out.RequirementStatus + *out = make([]RequirementStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.CertsLastUpdated != nil { + in, out := &in.CertsLastUpdated, &out.CertsLastUpdated + *out = (*in).DeepCopy() + } + if in.CertsRotateAt != nil { + in, out := &in.CertsRotateAt, &out.CertsRotateAt + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterServiceVersionStatus. +func (in *ClusterServiceVersionStatus) DeepCopy() *ClusterServiceVersionStatus { + if in == nil { + return nil + } + out := new(ClusterServiceVersionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigMapResourceReference) DeepCopyInto(out *ConfigMapResourceReference) { + *out = *in + in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapResourceReference. +func (in *ConfigMapResourceReference) DeepCopy() *ConfigMapResourceReference { + if in == nil { + return nil + } + out := new(ConfigMapResourceReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomResourceDefinitions) DeepCopyInto(out *CustomResourceDefinitions) { + *out = *in + if in.Owned != nil { + in, out := &in.Owned, &out.Owned + *out = make([]CRDDescription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Required != nil { + in, out := &in.Required, &out.Required + *out = make([]CRDDescription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitions. +func (in *CustomResourceDefinitions) DeepCopy() *CustomResourceDefinitions { + if in == nil { + return nil + } + out := new(CustomResourceDefinitions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DependentStatus) DeepCopyInto(out *DependentStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DependentStatus. +func (in *DependentStatus) DeepCopy() *DependentStatus { + if in == nil { + return nil + } + out := new(DependentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCConnectionState) DeepCopyInto(out *GRPCConnectionState) { + *out = *in + in.LastConnectTime.DeepCopyInto(&out.LastConnectTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCConnectionState. +func (in *GRPCConnectionState) DeepCopy() *GRPCConnectionState { + if in == nil { + return nil + } + out := new(GRPCConnectionState) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Icon) DeepCopyInto(out *Icon) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Icon. +func (in *Icon) DeepCopy() *Icon { + if in == nil { + return nil + } + out := new(Icon) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallMode) DeepCopyInto(out *InstallMode) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallMode. +func (in *InstallMode) DeepCopy() *InstallMode { + if in == nil { + return nil + } + out := new(InstallMode) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in InstallModeSet) DeepCopyInto(out *InstallModeSet) { + { + in := &in + *out = make(InstallModeSet, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallModeSet. +func (in InstallModeSet) DeepCopy() InstallModeSet { + if in == nil { + return nil + } + out := new(InstallModeSet) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallPlan) DeepCopyInto(out *InstallPlan) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallPlan. +func (in *InstallPlan) DeepCopy() *InstallPlan { + if in == nil { + return nil + } + out := new(InstallPlan) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *InstallPlan) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallPlanCondition) DeepCopyInto(out *InstallPlanCondition) { + *out = *in + if in.LastUpdateTime != nil { + in, out := &in.LastUpdateTime, &out.LastUpdateTime + *out = (*in).DeepCopy() + } + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallPlanCondition. +func (in *InstallPlanCondition) DeepCopy() *InstallPlanCondition { + if in == nil { + return nil + } + out := new(InstallPlanCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallPlanList) DeepCopyInto(out *InstallPlanList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]InstallPlan, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallPlanList. +func (in *InstallPlanList) DeepCopy() *InstallPlanList { + if in == nil { + return nil + } + out := new(InstallPlanList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *InstallPlanList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallPlanReference) DeepCopyInto(out *InstallPlanReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallPlanReference. +func (in *InstallPlanReference) DeepCopy() *InstallPlanReference { + if in == nil { + return nil + } + out := new(InstallPlanReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallPlanSpec) DeepCopyInto(out *InstallPlanSpec) { + *out = *in + if in.ClusterServiceVersionNames != nil { + in, out := &in.ClusterServiceVersionNames, &out.ClusterServiceVersionNames + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallPlanSpec. +func (in *InstallPlanSpec) DeepCopy() *InstallPlanSpec { + if in == nil { + return nil + } + out := new(InstallPlanSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallPlanStatus) DeepCopyInto(out *InstallPlanStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]InstallPlanCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.CatalogSources != nil { + in, out := &in.CatalogSources, &out.CatalogSources + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Plan != nil { + in, out := &in.Plan, &out.Plan + *out = make([]*Step, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Step) + **out = **in + } + } + } + if in.BundleLookups != nil { + in, out := &in.BundleLookups, &out.BundleLookups + *out = make([]BundleLookup, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.AttenuatedServiceAccountRef != nil { + in, out := &in.AttenuatedServiceAccountRef, &out.AttenuatedServiceAccountRef + *out = new(corev1.ObjectReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallPlanStatus. +func (in *InstallPlanStatus) DeepCopy() *InstallPlanStatus { + if in == nil { + return nil + } + out := new(InstallPlanStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Maintainer) DeepCopyInto(out *Maintainer) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Maintainer. +func (in *Maintainer) DeepCopy() *Maintainer { + if in == nil { + return nil + } + out := new(Maintainer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamedInstallStrategy) DeepCopyInto(out *NamedInstallStrategy) { + *out = *in + in.StrategySpec.DeepCopyInto(&out.StrategySpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamedInstallStrategy. +func (in *NamedInstallStrategy) DeepCopy() *NamedInstallStrategy { + if in == nil { + return nil + } + out := new(NamedInstallStrategy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RegistryPoll) DeepCopyInto(out *RegistryPoll) { + *out = *in + if in.Interval != nil { + in, out := &in.Interval, &out.Interval + *out = new(v1.Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistryPoll. +func (in *RegistryPoll) DeepCopy() *RegistryPoll { + if in == nil { + return nil + } + out := new(RegistryPoll) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RegistryServiceStatus) DeepCopyInto(out *RegistryServiceStatus) { + *out = *in + in.CreatedAt.DeepCopyInto(&out.CreatedAt) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistryServiceStatus. +func (in *RegistryServiceStatus) DeepCopy() *RegistryServiceStatus { + if in == nil { + return nil + } + out := new(RegistryServiceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RequirementStatus) DeepCopyInto(out *RequirementStatus) { + *out = *in + if in.Dependents != nil { + in, out := &in.Dependents, &out.Dependents + *out = make([]DependentStatus, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequirementStatus. +func (in *RequirementStatus) DeepCopy() *RequirementStatus { + if in == nil { + return nil + } + out := new(RequirementStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SpecDescriptor) DeepCopyInto(out *SpecDescriptor) { + *out = *in + if in.XDescriptors != nil { + in, out := &in.XDescriptors, &out.XDescriptors + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = make(json.RawMessage, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SpecDescriptor. +func (in *SpecDescriptor) DeepCopy() *SpecDescriptor { + if in == nil { + return nil + } + out := new(SpecDescriptor) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StatusDescriptor) DeepCopyInto(out *StatusDescriptor) { + *out = *in + if in.XDescriptors != nil { + in, out := &in.XDescriptors, &out.XDescriptors + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = make(json.RawMessage, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatusDescriptor. +func (in *StatusDescriptor) DeepCopy() *StatusDescriptor { + if in == nil { + return nil + } + out := new(StatusDescriptor) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Step) DeepCopyInto(out *Step) { + *out = *in + out.Resource = in.Resource +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Step. +func (in *Step) DeepCopy() *Step { + if in == nil { + return nil + } + out := new(Step) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StepResource) DeepCopyInto(out *StepResource) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StepResource. +func (in *StepResource) DeepCopy() *StepResource { + if in == nil { + return nil + } + out := new(StepResource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StrategyDeploymentPermissions) DeepCopyInto(out *StrategyDeploymentPermissions) { + *out = *in + if in.Rules != nil { + in, out := &in.Rules, &out.Rules + *out = make([]rbacv1.PolicyRule, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategyDeploymentPermissions. +func (in *StrategyDeploymentPermissions) DeepCopy() *StrategyDeploymentPermissions { + if in == nil { + return nil + } + out := new(StrategyDeploymentPermissions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StrategyDeploymentSpec) DeepCopyInto(out *StrategyDeploymentSpec) { + *out = *in + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategyDeploymentSpec. +func (in *StrategyDeploymentSpec) DeepCopy() *StrategyDeploymentSpec { + if in == nil { + return nil + } + out := new(StrategyDeploymentSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StrategyDetailsDeployment) DeepCopyInto(out *StrategyDetailsDeployment) { + *out = *in + if in.DeploymentSpecs != nil { + in, out := &in.DeploymentSpecs, &out.DeploymentSpecs + *out = make([]StrategyDeploymentSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Permissions != nil { + in, out := &in.Permissions, &out.Permissions + *out = make([]StrategyDeploymentPermissions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ClusterPermissions != nil { + in, out := &in.ClusterPermissions, &out.ClusterPermissions + *out = make([]StrategyDeploymentPermissions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategyDetailsDeployment. +func (in *StrategyDetailsDeployment) DeepCopy() *StrategyDetailsDeployment { + if in == nil { + return nil + } + out := new(StrategyDetailsDeployment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Subscription) DeepCopyInto(out *Subscription) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(SubscriptionSpec) + (*in).DeepCopyInto(*out) + } + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subscription. +func (in *Subscription) DeepCopy() *Subscription { + if in == nil { + return nil + } + out := new(Subscription) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Subscription) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionCatalogHealth) DeepCopyInto(out *SubscriptionCatalogHealth) { + *out = *in + if in.CatalogSourceRef != nil { + in, out := &in.CatalogSourceRef, &out.CatalogSourceRef + *out = new(corev1.ObjectReference) + **out = **in + } + if in.LastUpdated != nil { + in, out := &in.LastUpdated, &out.LastUpdated + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionCatalogHealth. +func (in *SubscriptionCatalogHealth) DeepCopy() *SubscriptionCatalogHealth { + if in == nil { + return nil + } + out := new(SubscriptionCatalogHealth) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionCondition) DeepCopyInto(out *SubscriptionCondition) { + *out = *in + if in.LastHeartbeatTime != nil { + in, out := &in.LastHeartbeatTime, &out.LastHeartbeatTime + *out = (*in).DeepCopy() + } + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionCondition. +func (in *SubscriptionCondition) DeepCopy() *SubscriptionCondition { + if in == nil { + return nil + } + out := new(SubscriptionCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionConfig) DeepCopyInto(out *SubscriptionConfig) { + *out = *in + if in.Selector != nil { + in, out := &in.Selector, &out.Selector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]corev1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.Resources.DeepCopyInto(&out.Resources) + if in.EnvFrom != nil { + in, out := &in.EnvFrom, &out.EnvFrom + *out = make([]corev1.EnvFromSource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]corev1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Volumes != nil { + in, out := &in.Volumes, &out.Volumes + *out = make([]corev1.Volume, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.VolumeMounts != nil { + in, out := &in.VolumeMounts, &out.VolumeMounts + *out = make([]corev1.VolumeMount, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionConfig. +func (in *SubscriptionConfig) DeepCopy() *SubscriptionConfig { + if in == nil { + return nil + } + out := new(SubscriptionConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionList) DeepCopyInto(out *SubscriptionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Subscription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionList. +func (in *SubscriptionList) DeepCopy() *SubscriptionList { + if in == nil { + return nil + } + out := new(SubscriptionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *SubscriptionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionSpec) DeepCopyInto(out *SubscriptionSpec) { + *out = *in + in.Config.DeepCopyInto(&out.Config) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionSpec. +func (in *SubscriptionSpec) DeepCopy() *SubscriptionSpec { + if in == nil { + return nil + } + out := new(SubscriptionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionStatus) DeepCopyInto(out *SubscriptionStatus) { + *out = *in + if in.Install != nil { + in, out := &in.Install, &out.Install + *out = new(InstallPlanReference) + **out = **in + } + if in.InstallPlanRef != nil { + in, out := &in.InstallPlanRef, &out.InstallPlanRef + *out = new(corev1.ObjectReference) + **out = **in + } + if in.CatalogHealth != nil { + in, out := &in.CatalogHealth, &out.CatalogHealth + *out = make([]SubscriptionCatalogHealth, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]SubscriptionCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.LastUpdated.DeepCopyInto(&out.LastUpdated) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionStatus. +func (in *SubscriptionStatus) DeepCopy() *SubscriptionStatus { + if in == nil { + return nil + } + out := new(SubscriptionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UpdateStrategy) DeepCopyInto(out *UpdateStrategy) { + *out = *in + if in.RegistryPoll != nil { + in, out := &in.RegistryPoll, &out.RegistryPoll + *out = new(RegistryPoll) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateStrategy. +func (in *UpdateStrategy) DeepCopy() *UpdateStrategy { + if in == nil { + return nil + } + out := new(UpdateStrategy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebhookDescription) DeepCopyInto(out *WebhookDescription) { + *out = *in + if in.Rules != nil { + in, out := &in.Rules, &out.Rules + *out = make([]admissionregistrationv1.RuleWithOperations, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.FailurePolicy != nil { + in, out := &in.FailurePolicy, &out.FailurePolicy + *out = new(admissionregistrationv1.FailurePolicyType) + **out = **in + } + if in.MatchPolicy != nil { + in, out := &in.MatchPolicy, &out.MatchPolicy + *out = new(admissionregistrationv1.MatchPolicyType) + **out = **in + } + if in.ObjectSelector != nil { + in, out := &in.ObjectSelector, &out.ObjectSelector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.SideEffects != nil { + in, out := &in.SideEffects, &out.SideEffects + *out = new(admissionregistrationv1.SideEffectClass) + **out = **in + } + if in.TimeoutSeconds != nil { + in, out := &in.TimeoutSeconds, &out.TimeoutSeconds + *out = new(int32) + **out = **in + } + if in.AdmissionReviewVersions != nil { + in, out := &in.AdmissionReviewVersions, &out.AdmissionReviewVersions + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ReinvocationPolicy != nil { + in, out := &in.ReinvocationPolicy, &out.ReinvocationPolicy + *out = new(admissionregistrationv1.ReinvocationPolicyType) + **out = **in + } + if in.WebhookPath != nil { + in, out := &in.WebhookPath, &out.WebhookPath + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookDescription. +func (in *WebhookDescription) DeepCopy() *WebhookDescription { + if in == nil { + return nil + } + out := new(WebhookDescription) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/operator-framework/api/pkg/operators/zz_generated.deepcopy.go b/vendor/github.com/operator-framework/api/pkg/operators/zz_generated.deepcopy.go new file mode 100644 index 0000000000..8b8760842f --- /dev/null +++ b/vendor/github.com/operator-framework/api/pkg/operators/zz_generated.deepcopy.go @@ -0,0 +1,1457 @@ +// +build !ignore_autogenerated + +/* + +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package operators + +import ( + "encoding/json" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIResourceReference) DeepCopyInto(out *APIResourceReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIResourceReference. +func (in *APIResourceReference) DeepCopy() *APIResourceReference { + if in == nil { + return nil + } + out := new(APIResourceReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIServiceDefinitions) DeepCopyInto(out *APIServiceDefinitions) { + *out = *in + if in.Owned != nil { + in, out := &in.Owned, &out.Owned + *out = make([]APIServiceDescription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Required != nil { + in, out := &in.Required, &out.Required + *out = make([]APIServiceDescription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIServiceDefinitions. +func (in *APIServiceDefinitions) DeepCopy() *APIServiceDefinitions { + if in == nil { + return nil + } + out := new(APIServiceDefinitions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIServiceDescription) DeepCopyInto(out *APIServiceDescription) { + *out = *in + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]APIResourceReference, len(*in)) + copy(*out, *in) + } + if in.StatusDescriptors != nil { + in, out := &in.StatusDescriptors, &out.StatusDescriptors + *out = make([]StatusDescriptor, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.SpecDescriptors != nil { + in, out := &in.SpecDescriptors, &out.SpecDescriptors + *out = make([]SpecDescriptor, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ActionDescriptor != nil { + in, out := &in.ActionDescriptor, &out.ActionDescriptor + *out = make([]ActionDescriptor, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIServiceDescription. +func (in *APIServiceDescription) DeepCopy() *APIServiceDescription { + if in == nil { + return nil + } + out := new(APIServiceDescription) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActionDescriptor) DeepCopyInto(out *ActionDescriptor) { + *out = *in + if in.XDescriptors != nil { + in, out := &in.XDescriptors, &out.XDescriptors + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = make(json.RawMessage, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActionDescriptor. +func (in *ActionDescriptor) DeepCopy() *ActionDescriptor { + if in == nil { + return nil + } + out := new(ActionDescriptor) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AppLink) DeepCopyInto(out *AppLink) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppLink. +func (in *AppLink) DeepCopy() *AppLink { + if in == nil { + return nil + } + out := new(AppLink) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BundleLookup) DeepCopyInto(out *BundleLookup) { + *out = *in + if in.CatalogSourceRef != nil { + in, out := &in.CatalogSourceRef, &out.CatalogSourceRef + *out = new(corev1.ObjectReference) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]BundleLookupCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BundleLookup. +func (in *BundleLookup) DeepCopy() *BundleLookup { + if in == nil { + return nil + } + out := new(BundleLookup) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BundleLookupCondition) DeepCopyInto(out *BundleLookupCondition) { + *out = *in + if in.LastUpdateTime != nil { + in, out := &in.LastUpdateTime, &out.LastUpdateTime + *out = (*in).DeepCopy() + } + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BundleLookupCondition. +func (in *BundleLookupCondition) DeepCopy() *BundleLookupCondition { + if in == nil { + return nil + } + out := new(BundleLookupCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CRDDescription) DeepCopyInto(out *CRDDescription) { + *out = *in + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]APIResourceReference, len(*in)) + copy(*out, *in) + } + if in.StatusDescriptors != nil { + in, out := &in.StatusDescriptors, &out.StatusDescriptors + *out = make([]StatusDescriptor, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.SpecDescriptors != nil { + in, out := &in.SpecDescriptors, &out.SpecDescriptors + *out = make([]SpecDescriptor, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ActionDescriptor != nil { + in, out := &in.ActionDescriptor, &out.ActionDescriptor + *out = make([]ActionDescriptor, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CRDDescription. +func (in *CRDDescription) DeepCopy() *CRDDescription { + if in == nil { + return nil + } + out := new(CRDDescription) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CatalogSource) DeepCopyInto(out *CatalogSource) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CatalogSource. +func (in *CatalogSource) DeepCopy() *CatalogSource { + if in == nil { + return nil + } + out := new(CatalogSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CatalogSource) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CatalogSourceList) DeepCopyInto(out *CatalogSourceList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]CatalogSource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CatalogSourceList. +func (in *CatalogSourceList) DeepCopy() *CatalogSourceList { + if in == nil { + return nil + } + out := new(CatalogSourceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CatalogSourceList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CatalogSourceSpec) DeepCopyInto(out *CatalogSourceSpec) { + *out = *in + if in.UpdateStrategy != nil { + in, out := &in.UpdateStrategy, &out.UpdateStrategy + *out = new(UpdateStrategy) + (*in).DeepCopyInto(*out) + } + if in.Secrets != nil { + in, out := &in.Secrets, &out.Secrets + *out = make([]string, len(*in)) + copy(*out, *in) + } + out.Icon = in.Icon +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CatalogSourceSpec. +func (in *CatalogSourceSpec) DeepCopy() *CatalogSourceSpec { + if in == nil { + return nil + } + out := new(CatalogSourceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CatalogSourceStatus) DeepCopyInto(out *CatalogSourceStatus) { + *out = *in + if in.ConfigMapResource != nil { + in, out := &in.ConfigMapResource, &out.ConfigMapResource + *out = new(ConfigMapResourceReference) + (*in).DeepCopyInto(*out) + } + if in.RegistryServiceStatus != nil { + in, out := &in.RegistryServiceStatus, &out.RegistryServiceStatus + *out = new(RegistryServiceStatus) + (*in).DeepCopyInto(*out) + } + if in.GRPCConnectionState != nil { + in, out := &in.GRPCConnectionState, &out.GRPCConnectionState + *out = new(GRPCConnectionState) + (*in).DeepCopyInto(*out) + } + if in.LatestImageRegistryPoll != nil { + in, out := &in.LatestImageRegistryPoll, &out.LatestImageRegistryPoll + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CatalogSourceStatus. +func (in *CatalogSourceStatus) DeepCopy() *CatalogSourceStatus { + if in == nil { + return nil + } + out := new(CatalogSourceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterServiceVersion) DeepCopyInto(out *ClusterServiceVersion) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterServiceVersion. +func (in *ClusterServiceVersion) DeepCopy() *ClusterServiceVersion { + if in == nil { + return nil + } + out := new(ClusterServiceVersion) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterServiceVersion) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterServiceVersionCondition) DeepCopyInto(out *ClusterServiceVersionCondition) { + *out = *in + if in.LastUpdateTime != nil { + in, out := &in.LastUpdateTime, &out.LastUpdateTime + *out = (*in).DeepCopy() + } + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterServiceVersionCondition. +func (in *ClusterServiceVersionCondition) DeepCopy() *ClusterServiceVersionCondition { + if in == nil { + return nil + } + out := new(ClusterServiceVersionCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterServiceVersionList) DeepCopyInto(out *ClusterServiceVersionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterServiceVersion, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterServiceVersionList. +func (in *ClusterServiceVersionList) DeepCopy() *ClusterServiceVersionList { + if in == nil { + return nil + } + out := new(ClusterServiceVersionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterServiceVersionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterServiceVersionSpec) DeepCopyInto(out *ClusterServiceVersionSpec) { + *out = *in + in.InstallStrategy.DeepCopyInto(&out.InstallStrategy) + in.Version.DeepCopyInto(&out.Version) + in.CustomResourceDefinitions.DeepCopyInto(&out.CustomResourceDefinitions) + in.APIServiceDefinitions.DeepCopyInto(&out.APIServiceDefinitions) + if in.NativeAPIs != nil { + in, out := &in.NativeAPIs, &out.NativeAPIs + *out = make([]v1.GroupVersionKind, len(*in)) + copy(*out, *in) + } + if in.Keywords != nil { + in, out := &in.Keywords, &out.Keywords + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Maintainers != nil { + in, out := &in.Maintainers, &out.Maintainers + *out = make([]Maintainer, len(*in)) + copy(*out, *in) + } + out.Provider = in.Provider + if in.Links != nil { + in, out := &in.Links, &out.Links + *out = make([]AppLink, len(*in)) + copy(*out, *in) + } + if in.Icon != nil { + in, out := &in.Icon, &out.Icon + *out = make([]Icon, len(*in)) + copy(*out, *in) + } + if in.InstallModes != nil { + in, out := &in.InstallModes, &out.InstallModes + *out = make([]InstallMode, len(*in)) + copy(*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 + } + } + if in.Selector != nil { + in, out := &in.Selector, &out.Selector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterServiceVersionSpec. +func (in *ClusterServiceVersionSpec) DeepCopy() *ClusterServiceVersionSpec { + if in == nil { + return nil + } + out := new(ClusterServiceVersionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterServiceVersionStatus) DeepCopyInto(out *ClusterServiceVersionStatus) { + *out = *in + if in.LastUpdateTime != nil { + in, out := &in.LastUpdateTime, &out.LastUpdateTime + *out = (*in).DeepCopy() + } + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]ClusterServiceVersionCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.RequirementStatus != nil { + in, out := &in.RequirementStatus, &out.RequirementStatus + *out = make([]RequirementStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.CertsLastUpdated != nil { + in, out := &in.CertsLastUpdated, &out.CertsLastUpdated + *out = (*in).DeepCopy() + } + if in.CertsRotateAt != nil { + in, out := &in.CertsRotateAt, &out.CertsRotateAt + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterServiceVersionStatus. +func (in *ClusterServiceVersionStatus) DeepCopy() *ClusterServiceVersionStatus { + if in == nil { + return nil + } + out := new(ClusterServiceVersionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigMapResourceReference) DeepCopyInto(out *ConfigMapResourceReference) { + *out = *in + in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapResourceReference. +func (in *ConfigMapResourceReference) DeepCopy() *ConfigMapResourceReference { + if in == nil { + return nil + } + out := new(ConfigMapResourceReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomResourceDefinitions) DeepCopyInto(out *CustomResourceDefinitions) { + *out = *in + if in.Owned != nil { + in, out := &in.Owned, &out.Owned + *out = make([]CRDDescription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Required != nil { + in, out := &in.Required, &out.Required + *out = make([]CRDDescription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitions. +func (in *CustomResourceDefinitions) DeepCopy() *CustomResourceDefinitions { + if in == nil { + return nil + } + out := new(CustomResourceDefinitions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DependentStatus) DeepCopyInto(out *DependentStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DependentStatus. +func (in *DependentStatus) DeepCopy() *DependentStatus { + if in == nil { + return nil + } + out := new(DependentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GRPCConnectionState) DeepCopyInto(out *GRPCConnectionState) { + *out = *in + in.LastConnectTime.DeepCopyInto(&out.LastConnectTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GRPCConnectionState. +func (in *GRPCConnectionState) DeepCopy() *GRPCConnectionState { + if in == nil { + return nil + } + out := new(GRPCConnectionState) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Icon) DeepCopyInto(out *Icon) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Icon. +func (in *Icon) DeepCopy() *Icon { + if in == nil { + return nil + } + out := new(Icon) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallMode) DeepCopyInto(out *InstallMode) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallMode. +func (in *InstallMode) DeepCopy() *InstallMode { + if in == nil { + return nil + } + out := new(InstallMode) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in InstallModeSet) DeepCopyInto(out *InstallModeSet) { + { + in := &in + *out = make(InstallModeSet, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallModeSet. +func (in InstallModeSet) DeepCopy() InstallModeSet { + if in == nil { + return nil + } + out := new(InstallModeSet) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallPlan) DeepCopyInto(out *InstallPlan) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallPlan. +func (in *InstallPlan) DeepCopy() *InstallPlan { + if in == nil { + return nil + } + out := new(InstallPlan) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *InstallPlan) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallPlanCondition) DeepCopyInto(out *InstallPlanCondition) { + *out = *in + if in.LastUpdateTime != nil { + in, out := &in.LastUpdateTime, &out.LastUpdateTime + *out = (*in).DeepCopy() + } + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallPlanCondition. +func (in *InstallPlanCondition) DeepCopy() *InstallPlanCondition { + if in == nil { + return nil + } + out := new(InstallPlanCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallPlanList) DeepCopyInto(out *InstallPlanList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]InstallPlan, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallPlanList. +func (in *InstallPlanList) DeepCopy() *InstallPlanList { + if in == nil { + return nil + } + out := new(InstallPlanList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *InstallPlanList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallPlanReference) DeepCopyInto(out *InstallPlanReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallPlanReference. +func (in *InstallPlanReference) DeepCopy() *InstallPlanReference { + if in == nil { + return nil + } + out := new(InstallPlanReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallPlanSpec) DeepCopyInto(out *InstallPlanSpec) { + *out = *in + if in.ClusterServiceVersionNames != nil { + in, out := &in.ClusterServiceVersionNames, &out.ClusterServiceVersionNames + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallPlanSpec. +func (in *InstallPlanSpec) DeepCopy() *InstallPlanSpec { + if in == nil { + return nil + } + out := new(InstallPlanSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallPlanStatus) DeepCopyInto(out *InstallPlanStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]InstallPlanCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.CatalogSources != nil { + in, out := &in.CatalogSources, &out.CatalogSources + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Plan != nil { + in, out := &in.Plan, &out.Plan + *out = make([]*Step, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Step) + **out = **in + } + } + } + if in.BundleLookups != nil { + in, out := &in.BundleLookups, &out.BundleLookups + *out = make([]BundleLookup, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.AttenuatedServiceAccountRef != nil { + in, out := &in.AttenuatedServiceAccountRef, &out.AttenuatedServiceAccountRef + *out = new(corev1.ObjectReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallPlanStatus. +func (in *InstallPlanStatus) DeepCopy() *InstallPlanStatus { + if in == nil { + return nil + } + out := new(InstallPlanStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Maintainer) DeepCopyInto(out *Maintainer) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Maintainer. +func (in *Maintainer) DeepCopy() *Maintainer { + if in == nil { + return nil + } + out := new(Maintainer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamedInstallStrategy) DeepCopyInto(out *NamedInstallStrategy) { + *out = *in + in.StrategySpec.DeepCopyInto(&out.StrategySpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamedInstallStrategy. +func (in *NamedInstallStrategy) DeepCopy() *NamedInstallStrategy { + if in == nil { + return nil + } + out := new(NamedInstallStrategy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OperatorGroup) DeepCopyInto(out *OperatorGroup) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OperatorGroup. +func (in *OperatorGroup) DeepCopy() *OperatorGroup { + if in == nil { + return nil + } + out := new(OperatorGroup) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *OperatorGroup) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OperatorGroupList) DeepCopyInto(out *OperatorGroupList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]OperatorGroup, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OperatorGroupList. +func (in *OperatorGroupList) DeepCopy() *OperatorGroupList { + if in == nil { + return nil + } + out := new(OperatorGroupList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *OperatorGroupList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OperatorGroupSpec) DeepCopyInto(out *OperatorGroupSpec) { + *out = *in + if in.Selector != nil { + in, out := &in.Selector, &out.Selector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.TargetNamespaces != nil { + in, out := &in.TargetNamespaces, &out.TargetNamespaces + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OperatorGroupSpec. +func (in *OperatorGroupSpec) DeepCopy() *OperatorGroupSpec { + if in == nil { + return nil + } + out := new(OperatorGroupSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OperatorGroupStatus) DeepCopyInto(out *OperatorGroupStatus) { + *out = *in + if in.Namespaces != nil { + in, out := &in.Namespaces, &out.Namespaces + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ServiceAccountRef != nil { + in, out := &in.ServiceAccountRef, &out.ServiceAccountRef + *out = new(corev1.ObjectReference) + **out = **in + } + if in.LastUpdated != nil { + in, out := &in.LastUpdated, &out.LastUpdated + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OperatorGroupStatus. +func (in *OperatorGroupStatus) DeepCopy() *OperatorGroupStatus { + if in == nil { + return nil + } + out := new(OperatorGroupStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RegistryPoll) DeepCopyInto(out *RegistryPoll) { + *out = *in + if in.Interval != nil { + in, out := &in.Interval, &out.Interval + *out = new(v1.Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistryPoll. +func (in *RegistryPoll) DeepCopy() *RegistryPoll { + if in == nil { + return nil + } + out := new(RegistryPoll) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RegistryServiceStatus) DeepCopyInto(out *RegistryServiceStatus) { + *out = *in + in.CreatedAt.DeepCopyInto(&out.CreatedAt) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistryServiceStatus. +func (in *RegistryServiceStatus) DeepCopy() *RegistryServiceStatus { + if in == nil { + return nil + } + out := new(RegistryServiceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RequirementStatus) DeepCopyInto(out *RequirementStatus) { + *out = *in + if in.Dependents != nil { + in, out := &in.Dependents, &out.Dependents + *out = make([]DependentStatus, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RequirementStatus. +func (in *RequirementStatus) DeepCopy() *RequirementStatus { + if in == nil { + return nil + } + out := new(RequirementStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SpecDescriptor) DeepCopyInto(out *SpecDescriptor) { + *out = *in + if in.XDescriptors != nil { + in, out := &in.XDescriptors, &out.XDescriptors + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = make(json.RawMessage, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SpecDescriptor. +func (in *SpecDescriptor) DeepCopy() *SpecDescriptor { + if in == nil { + return nil + } + out := new(SpecDescriptor) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StatusDescriptor) DeepCopyInto(out *StatusDescriptor) { + *out = *in + if in.XDescriptors != nil { + in, out := &in.XDescriptors, &out.XDescriptors + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = make(json.RawMessage, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatusDescriptor. +func (in *StatusDescriptor) DeepCopy() *StatusDescriptor { + if in == nil { + return nil + } + out := new(StatusDescriptor) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Step) DeepCopyInto(out *Step) { + *out = *in + out.Resource = in.Resource +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Step. +func (in *Step) DeepCopy() *Step { + if in == nil { + return nil + } + out := new(Step) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StepResource) DeepCopyInto(out *StepResource) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StepResource. +func (in *StepResource) DeepCopy() *StepResource { + if in == nil { + return nil + } + out := new(StepResource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StrategyDeploymentPermissions) DeepCopyInto(out *StrategyDeploymentPermissions) { + *out = *in + if in.Rules != nil { + in, out := &in.Rules, &out.Rules + *out = make([]rbacv1.PolicyRule, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategyDeploymentPermissions. +func (in *StrategyDeploymentPermissions) DeepCopy() *StrategyDeploymentPermissions { + if in == nil { + return nil + } + out := new(StrategyDeploymentPermissions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StrategyDeploymentSpec) DeepCopyInto(out *StrategyDeploymentSpec) { + *out = *in + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategyDeploymentSpec. +func (in *StrategyDeploymentSpec) DeepCopy() *StrategyDeploymentSpec { + if in == nil { + return nil + } + out := new(StrategyDeploymentSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StrategyDetailsDeployment) DeepCopyInto(out *StrategyDetailsDeployment) { + *out = *in + if in.DeploymentSpecs != nil { + in, out := &in.DeploymentSpecs, &out.DeploymentSpecs + *out = make([]StrategyDeploymentSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Permissions != nil { + in, out := &in.Permissions, &out.Permissions + *out = make([]StrategyDeploymentPermissions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.ClusterPermissions != nil { + in, out := &in.ClusterPermissions, &out.ClusterPermissions + *out = make([]StrategyDeploymentPermissions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategyDetailsDeployment. +func (in *StrategyDetailsDeployment) DeepCopy() *StrategyDetailsDeployment { + if in == nil { + return nil + } + out := new(StrategyDetailsDeployment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Subscription) DeepCopyInto(out *Subscription) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(SubscriptionSpec) + (*in).DeepCopyInto(*out) + } + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subscription. +func (in *Subscription) DeepCopy() *Subscription { + if in == nil { + return nil + } + out := new(Subscription) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Subscription) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionCatalogHealth) DeepCopyInto(out *SubscriptionCatalogHealth) { + *out = *in + if in.CatalogSourceRef != nil { + in, out := &in.CatalogSourceRef, &out.CatalogSourceRef + *out = new(corev1.ObjectReference) + **out = **in + } + if in.LastUpdated != nil { + in, out := &in.LastUpdated, &out.LastUpdated + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionCatalogHealth. +func (in *SubscriptionCatalogHealth) DeepCopy() *SubscriptionCatalogHealth { + if in == nil { + return nil + } + out := new(SubscriptionCatalogHealth) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionCondition) DeepCopyInto(out *SubscriptionCondition) { + *out = *in + if in.LastHeartbeatTime != nil { + in, out := &in.LastHeartbeatTime, &out.LastHeartbeatTime + *out = (*in).DeepCopy() + } + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionCondition. +func (in *SubscriptionCondition) DeepCopy() *SubscriptionCondition { + if in == nil { + return nil + } + out := new(SubscriptionCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionConfig) DeepCopyInto(out *SubscriptionConfig) { + *out = *in + if in.Selector != nil { + in, out := &in.Selector, &out.Selector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]corev1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.Resources.DeepCopyInto(&out.Resources) + if in.EnvFrom != nil { + in, out := &in.EnvFrom, &out.EnvFrom + *out = make([]corev1.EnvFromSource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]corev1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Volumes != nil { + in, out := &in.Volumes, &out.Volumes + *out = make([]corev1.Volume, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.VolumeMounts != nil { + in, out := &in.VolumeMounts, &out.VolumeMounts + *out = make([]corev1.VolumeMount, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionConfig. +func (in *SubscriptionConfig) DeepCopy() *SubscriptionConfig { + if in == nil { + return nil + } + out := new(SubscriptionConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionList) DeepCopyInto(out *SubscriptionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Subscription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionList. +func (in *SubscriptionList) DeepCopy() *SubscriptionList { + if in == nil { + return nil + } + out := new(SubscriptionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *SubscriptionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionSpec) DeepCopyInto(out *SubscriptionSpec) { + *out = *in + in.Config.DeepCopyInto(&out.Config) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionSpec. +func (in *SubscriptionSpec) DeepCopy() *SubscriptionSpec { + if in == nil { + return nil + } + out := new(SubscriptionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionStatus) DeepCopyInto(out *SubscriptionStatus) { + *out = *in + if in.Install != nil { + in, out := &in.Install, &out.Install + *out = new(InstallPlanReference) + **out = **in + } + if in.InstallPlanRef != nil { + in, out := &in.InstallPlanRef, &out.InstallPlanRef + *out = new(corev1.ObjectReference) + **out = **in + } + if in.CatalogHealth != nil { + in, out := &in.CatalogHealth, &out.CatalogHealth + *out = make([]SubscriptionCatalogHealth, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]SubscriptionCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.LastUpdated.DeepCopyInto(&out.LastUpdated) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionStatus. +func (in *SubscriptionStatus) DeepCopy() *SubscriptionStatus { + if in == nil { + return nil + } + out := new(SubscriptionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UpdateStrategy) DeepCopyInto(out *UpdateStrategy) { + *out = *in + if in.RegistryPoll != nil { + in, out := &in.RegistryPoll, &out.RegistryPoll + *out = new(RegistryPoll) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateStrategy. +func (in *UpdateStrategy) DeepCopy() *UpdateStrategy { + if in == nil { + return nil + } + out := new(UpdateStrategy) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/operator-framework/operator-sdk/LICENSE b/vendor/github.com/operator-framework/operator-sdk/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/vendor/github.com/operator-framework/operator-sdk/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/operator-framework/operator-sdk/version/version.go b/vendor/github.com/operator-framework/operator-sdk/version/version.go new file mode 100644 index 0000000000..520d51b533 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-sdk/version/version.go @@ -0,0 +1,29 @@ +// Copyright 2018 The Operator-SDK 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 version + +import ( + "fmt" + "runtime" +) + +//var needs to be used instead of const for ldflags +var ( + Version = "v0.18.0" + GitVersion = "unknown" + GitCommit = "unknown" + KubernetesVersion = "unknown" + GoVersion = fmt.Sprintf("%s %s/%s", runtime.Version(), runtime.GOOS, runtime.GOARCH) +) diff --git a/vendor/github.com/sirupsen/logrus/.gitignore b/vendor/github.com/sirupsen/logrus/.gitignore new file mode 100644 index 0000000000..1fb13abebe --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/.gitignore @@ -0,0 +1,4 @@ +logrus +vendor + +.idea/ diff --git a/vendor/github.com/sirupsen/logrus/.golangci.yml b/vendor/github.com/sirupsen/logrus/.golangci.yml new file mode 100644 index 0000000000..65dc285037 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/.golangci.yml @@ -0,0 +1,40 @@ +run: + # do not run on test files yet + tests: false + +# all available settings of specific linters +linters-settings: + errcheck: + # report about not checking of errors in type assetions: `a := b.(MyStruct)`; + # default is false: such cases aren't reported by default. + check-type-assertions: false + + # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`; + # default is false: such cases aren't reported by default. + check-blank: false + + lll: + line-length: 100 + tab-width: 4 + + prealloc: + simple: false + range-loops: false + for-loops: false + + whitespace: + multi-if: false # Enforces newlines (or comments) after every multi-line if statement + multi-func: false # Enforces newlines (or comments) after every multi-line function signature + +linters: + enable: + - megacheck + - govet + disable: + - maligned + - prealloc + disable-all: false + presets: + - bugs + - unused + fast: false diff --git a/vendor/github.com/sirupsen/logrus/.travis.yml b/vendor/github.com/sirupsen/logrus/.travis.yml new file mode 100644 index 0000000000..c1dbd5a3a3 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/.travis.yml @@ -0,0 +1,15 @@ +language: go +go_import_path: github.com/sirupsen/logrus +git: + depth: 1 +env: + - GO111MODULE=on +go: 1.15.x +os: linux +install: + - ./travis/install.sh +script: + - cd ci + - go run mage.go -v -w ../ crossBuild + - go run mage.go -v -w ../ lint + - go run mage.go -v -w ../ test diff --git a/vendor/github.com/sirupsen/logrus/CHANGELOG.md b/vendor/github.com/sirupsen/logrus/CHANGELOG.md new file mode 100644 index 0000000000..7567f61289 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/CHANGELOG.md @@ -0,0 +1,259 @@ +# 1.8.1 +Code quality: + * move magefile in its own subdir/submodule to remove magefile dependency on logrus consumer + * improve timestamp format documentation + +Fixes: + * fix race condition on logger hooks + + +# 1.8.0 + +Correct versioning number replacing v1.7.1. + +# 1.7.1 + +Beware this release has introduced a new public API and its semver is therefore incorrect. + +Code quality: + * use go 1.15 in travis + * use magefile as task runner + +Fixes: + * small fixes about new go 1.13 error formatting system + * Fix for long time race condiction with mutating data hooks + +Features: + * build support for zos + +# 1.7.0 +Fixes: + * the dependency toward a windows terminal library has been removed + +Features: + * a new buffer pool management API has been added + * a set of `Fn()` functions have been added + +# 1.6.0 +Fixes: + * end of line cleanup + * revert the entry concurrency bug fix whic leads to deadlock under some circumstances + * update dependency on go-windows-terminal-sequences to fix a crash with go 1.14 + +Features: + * add an option to the `TextFormatter` to completely disable fields quoting + +# 1.5.0 +Code quality: + * add golangci linter run on travis + +Fixes: + * add mutex for hooks concurrent access on `Entry` data + * caller function field for go1.14 + * fix build issue for gopherjs target + +Feature: + * add an hooks/writer sub-package whose goal is to split output on different stream depending on the trace level + * add a `DisableHTMLEscape` option in the `JSONFormatter` + * add `ForceQuote` and `PadLevelText` options in the `TextFormatter` + +# 1.4.2 + * Fixes build break for plan9, nacl, solaris +# 1.4.1 +This new release introduces: + * Enhance TextFormatter to not print caller information when they are empty (#944) + * Remove dependency on golang.org/x/crypto (#932, #943) + +Fixes: + * Fix Entry.WithContext method to return a copy of the initial entry (#941) + +# 1.4.0 +This new release introduces: + * Add `DeferExitHandler`, similar to `RegisterExitHandler` but prepending the handler to the list of handlers (semantically like `defer`) (#848). + * Add `CallerPrettyfier` to `JSONFormatter` and `TextFormatter` (#909, #911) + * Add `Entry.WithContext()` and `Entry.Context`, to set a context on entries to be used e.g. in hooks (#919). + +Fixes: + * Fix wrong method calls `Logger.Print` and `Logger.Warningln` (#893). + * Update `Entry.Logf` to not do string formatting unless the log level is enabled (#903) + * Fix infinite recursion on unknown `Level.String()` (#907) + * Fix race condition in `getCaller` (#916). + + +# 1.3.0 +This new release introduces: + * Log, Logf, Logln functions for Logger and Entry that take a Level + +Fixes: + * Building prometheus node_exporter on AIX (#840) + * Race condition in TextFormatter (#468) + * Travis CI import path (#868) + * Remove coloured output on Windows (#862) + * Pointer to func as field in JSONFormatter (#870) + * Properly marshal Levels (#873) + +# 1.2.0 +This new release introduces: + * A new method `SetReportCaller` in the `Logger` to enable the file, line and calling function from which the trace has been issued + * A new trace level named `Trace` whose level is below `Debug` + * A configurable exit function to be called upon a Fatal trace + * The `Level` object now implements `encoding.TextUnmarshaler` interface + +# 1.1.1 +This is a bug fix release. + * fix the build break on Solaris + * don't drop a whole trace in JSONFormatter when a field param is a function pointer which can not be serialized + +# 1.1.0 +This new release introduces: + * several fixes: + * a fix for a race condition on entry formatting + * proper cleanup of previously used entries before putting them back in the pool + * the extra new line at the end of message in text formatter has been removed + * a new global public API to check if a level is activated: IsLevelEnabled + * the following methods have been added to the Logger object + * IsLevelEnabled + * SetFormatter + * SetOutput + * ReplaceHooks + * introduction of go module + * an indent configuration for the json formatter + * output colour support for windows + * the field sort function is now configurable for text formatter + * the CLICOLOR and CLICOLOR\_FORCE environment variable support in text formater + +# 1.0.6 + +This new release introduces: + * a new api WithTime which allows to easily force the time of the log entry + which is mostly useful for logger wrapper + * a fix reverting the immutability of the entry given as parameter to the hooks + a new configuration field of the json formatter in order to put all the fields + in a nested dictionnary + * a new SetOutput method in the Logger + * a new configuration of the textformatter to configure the name of the default keys + * a new configuration of the text formatter to disable the level truncation + +# 1.0.5 + +* Fix hooks race (#707) +* Fix panic deadlock (#695) + +# 1.0.4 + +* Fix race when adding hooks (#612) +* Fix terminal check in AppEngine (#635) + +# 1.0.3 + +* Replace example files with testable examples + +# 1.0.2 + +* bug: quote non-string values in text formatter (#583) +* Make (*Logger) SetLevel a public method + +# 1.0.1 + +* bug: fix escaping in text formatter (#575) + +# 1.0.0 + +* Officially changed name to lower-case +* bug: colors on Windows 10 (#541) +* bug: fix race in accessing level (#512) + +# 0.11.5 + +* feature: add writer and writerlevel to entry (#372) + +# 0.11.4 + +* bug: fix undefined variable on solaris (#493) + +# 0.11.3 + +* formatter: configure quoting of empty values (#484) +* formatter: configure quoting character (default is `"`) (#484) +* bug: fix not importing io correctly in non-linux environments (#481) + +# 0.11.2 + +* bug: fix windows terminal detection (#476) + +# 0.11.1 + +* bug: fix tty detection with custom out (#471) + +# 0.11.0 + +* performance: Use bufferpool to allocate (#370) +* terminal: terminal detection for app-engine (#343) +* feature: exit handler (#375) + +# 0.10.0 + +* feature: Add a test hook (#180) +* feature: `ParseLevel` is now case-insensitive (#326) +* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308) +* performance: avoid re-allocations on `WithFields` (#335) + +# 0.9.0 + +* logrus/text_formatter: don't emit empty msg +* logrus/hooks/airbrake: move out of main repository +* logrus/hooks/sentry: move out of main repository +* logrus/hooks/papertrail: move out of main repository +* logrus/hooks/bugsnag: move out of main repository +* logrus/core: run tests with `-race` +* logrus/core: detect TTY based on `stderr` +* logrus/core: support `WithError` on logger +* logrus/core: Solaris support + +# 0.8.7 + +* logrus/core: fix possible race (#216) +* logrus/doc: small typo fixes and doc improvements + + +# 0.8.6 + +* hooks/raven: allow passing an initialized client + +# 0.8.5 + +* logrus/core: revert #208 + +# 0.8.4 + +* formatter/text: fix data race (#218) + +# 0.8.3 + +* logrus/core: fix entry log level (#208) +* logrus/core: improve performance of text formatter by 40% +* logrus/core: expose `LevelHooks` type +* logrus/core: add support for DragonflyBSD and NetBSD +* formatter/text: print structs more verbosely + +# 0.8.2 + +* logrus: fix more Fatal family functions + +# 0.8.1 + +* logrus: fix not exiting on `Fatalf` and `Fatalln` + +# 0.8.0 + +* logrus: defaults to stderr instead of stdout +* hooks/sentry: add special field for `*http.Request` +* formatter/text: ignore Windows for colors + +# 0.7.3 + +* formatter/\*: allow configuration of timestamp layout + +# 0.7.2 + +* formatter/text: Add configuration option for time format (#158) diff --git a/vendor/github.com/sirupsen/logrus/LICENSE b/vendor/github.com/sirupsen/logrus/LICENSE new file mode 100644 index 0000000000..f090cb42f3 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Simon Eskildsen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/sirupsen/logrus/README.md b/vendor/github.com/sirupsen/logrus/README.md new file mode 100644 index 0000000000..5152b6aa40 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/README.md @@ -0,0 +1,513 @@ +# Logrus :walrus: [![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](https://godoc.org/github.com/sirupsen/logrus) + +Logrus is a structured logger for Go (golang), completely API compatible with +the standard library logger. + +**Logrus is in maintenance-mode.** We will not be introducing new features. It's +simply too hard to do in a way that won't break many people's projects, which is +the last thing you want from your Logging library (again...). + +This does not mean Logrus is dead. Logrus will continue to be maintained for +security, (backwards compatible) bug fixes, and performance (where we are +limited by the interface). + +I believe Logrus' biggest contribution is to have played a part in today's +widespread use of structured logging in Golang. There doesn't seem to be a +reason to do a major, breaking iteration into Logrus V2, since the fantastic Go +community has built those independently. Many fantastic alternatives have sprung +up. Logrus would look like those, had it been re-designed with what we know +about structured logging in Go today. Check out, for example, +[Zerolog][zerolog], [Zap][zap], and [Apex][apex]. + +[zerolog]: https://github.com/rs/zerolog +[zap]: https://github.com/uber-go/zap +[apex]: https://github.com/apex/log + +**Seeing weird case-sensitive problems?** It's in the past been possible to +import Logrus as both upper- and lower-case. Due to the Go package environment, +this caused issues in the community and we needed a standard. Some environments +experienced problems with the upper-case variant, so the lower-case was decided. +Everything using `logrus` will need to use the lower-case: +`github.com/sirupsen/logrus`. Any package that isn't, should be changed. + +To fix Glide, see [these +comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437). +For an in-depth explanation of the casing issue, see [this +comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276). + +Nicely color-coded in development (when a TTY is attached, otherwise just +plain text): + +![Colored](http://i.imgur.com/PY7qMwd.png) + +With `log.SetFormatter(&log.JSONFormatter{})`, for easy parsing by logstash +or Splunk: + +```json +{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the +ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"} + +{"level":"warning","msg":"The group's number increased tremendously!", +"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"} + +{"animal":"walrus","level":"info","msg":"A giant walrus appears!", +"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"} + +{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.", +"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"} + +{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true, +"time":"2014-03-10 19:57:38.562543128 -0400 EDT"} +``` + +With the default `log.SetFormatter(&log.TextFormatter{})` when a TTY is not +attached, the output is compatible with the +[logfmt](http://godoc.org/github.com/kr/logfmt) format: + +```text +time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8 +time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10 +time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true +time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4 +time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009 +time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true +``` +To ensure this behaviour even if a TTY is attached, set your formatter as follows: + +```go + log.SetFormatter(&log.TextFormatter{ + DisableColors: true, + FullTimestamp: true, + }) +``` + +#### Logging Method Name + +If you wish to add the calling method as a field, instruct the logger via: +```go +log.SetReportCaller(true) +``` +This adds the caller as 'method' like so: + +```json +{"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by", +"time":"2014-03-10 19:57:38.562543129 -0400 EDT"} +``` + +```text +time="2015-03-26T01:27:38-04:00" level=fatal method=github.com/sirupsen/arcticcreatures.migrate msg="a penguin swims by" animal=penguin +``` +Note that this does add measurable overhead - the cost will depend on the version of Go, but is +between 20 and 40% in recent tests with 1.6 and 1.7. You can validate this in your +environment via benchmarks: +``` +go test -bench=.*CallerTracing +``` + + +#### Case-sensitivity + +The organization's name was changed to lower-case--and this will not be changed +back. If you are getting import conflicts due to case sensitivity, please use +the lower-case import: `github.com/sirupsen/logrus`. + +#### Example + +The simplest way to use Logrus is simply the package-level exported logger: + +```go +package main + +import ( + log "github.com/sirupsen/logrus" +) + +func main() { + log.WithFields(log.Fields{ + "animal": "walrus", + }).Info("A walrus appears") +} +``` + +Note that it's completely api-compatible with the stdlib logger, so you can +replace your `log` imports everywhere with `log "github.com/sirupsen/logrus"` +and you'll now have the flexibility of Logrus. You can customize it all you +want: + +```go +package main + +import ( + "os" + log "github.com/sirupsen/logrus" +) + +func init() { + // Log as JSON instead of the default ASCII formatter. + log.SetFormatter(&log.JSONFormatter{}) + + // Output to stdout instead of the default stderr + // Can be any io.Writer, see below for File example + log.SetOutput(os.Stdout) + + // Only log the warning severity or above. + log.SetLevel(log.WarnLevel) +} + +func main() { + log.WithFields(log.Fields{ + "animal": "walrus", + "size": 10, + }).Info("A group of walrus emerges from the ocean") + + log.WithFields(log.Fields{ + "omg": true, + "number": 122, + }).Warn("The group's number increased tremendously!") + + log.WithFields(log.Fields{ + "omg": true, + "number": 100, + }).Fatal("The ice breaks!") + + // A common pattern is to re-use fields between logging statements by re-using + // the logrus.Entry returned from WithFields() + contextLogger := log.WithFields(log.Fields{ + "common": "this is a common field", + "other": "I also should be logged always", + }) + + contextLogger.Info("I'll be logged with common and other field") + contextLogger.Info("Me too") +} +``` + +For more advanced usage such as logging to multiple locations from the same +application, you can also create an instance of the `logrus` Logger: + +```go +package main + +import ( + "os" + "github.com/sirupsen/logrus" +) + +// Create a new instance of the logger. You can have any number of instances. +var log = logrus.New() + +func main() { + // The API for setting attributes is a little different than the package level + // exported logger. See Godoc. + log.Out = os.Stdout + + // You could set this to any `io.Writer` such as a file + // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) + // if err == nil { + // log.Out = file + // } else { + // log.Info("Failed to log to file, using default stderr") + // } + + log.WithFields(logrus.Fields{ + "animal": "walrus", + "size": 10, + }).Info("A group of walrus emerges from the ocean") +} +``` + +#### Fields + +Logrus encourages careful, structured logging through logging fields instead of +long, unparseable error messages. For example, instead of: `log.Fatalf("Failed +to send event %s to topic %s with key %d")`, you should log the much more +discoverable: + +```go +log.WithFields(log.Fields{ + "event": event, + "topic": topic, + "key": key, +}).Fatal("Failed to send event") +``` + +We've found this API forces you to think about logging in a way that produces +much more useful logging messages. We've been in countless situations where just +a single added field to a log statement that was already there would've saved us +hours. The `WithFields` call is optional. + +In general, with Logrus using any of the `printf`-family functions should be +seen as a hint you should add a field, however, you can still use the +`printf`-family functions with Logrus. + +#### Default Fields + +Often it's helpful to have fields _always_ attached to log statements in an +application or parts of one. For example, you may want to always log the +`request_id` and `user_ip` in the context of a request. Instead of writing +`log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})` on +every line, you can create a `logrus.Entry` to pass around instead: + +```go +requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip}) +requestLogger.Info("something happened on that request") # will log request_id and user_ip +requestLogger.Warn("something not great happened") +``` + +#### Hooks + +You can add hooks for logging levels. For example to send errors to an exception +tracking service on `Error`, `Fatal` and `Panic`, info to StatsD or log to +multiple places simultaneously, e.g. syslog. + +Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in +`init`: + +```go +import ( + log "github.com/sirupsen/logrus" + "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake" + logrus_syslog "github.com/sirupsen/logrus/hooks/syslog" + "log/syslog" +) + +func init() { + + // Use the Airbrake hook to report errors that have Error severity or above to + // an exception tracker. You can create custom hooks, see the Hooks section. + log.AddHook(airbrake.NewHook(123, "xyz", "production")) + + hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") + if err != nil { + log.Error("Unable to connect to local syslog daemon") + } else { + log.AddHook(hook) + } +} +``` +Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md). + +A list of currently known service hooks can be found in this wiki [page](https://github.com/sirupsen/logrus/wiki/Hooks) + + +#### Level logging + +Logrus has seven logging levels: Trace, Debug, Info, Warning, Error, Fatal and Panic. + +```go +log.Trace("Something very low level.") +log.Debug("Useful debugging information.") +log.Info("Something noteworthy happened!") +log.Warn("You should probably take a look at this.") +log.Error("Something failed but I'm not quitting.") +// Calls os.Exit(1) after logging +log.Fatal("Bye.") +// Calls panic() after logging +log.Panic("I'm bailing.") +``` + +You can set the logging level on a `Logger`, then it will only log entries with +that severity or anything above it: + +```go +// Will log anything that is info or above (warn, error, fatal, panic). Default. +log.SetLevel(log.InfoLevel) +``` + +It may be useful to set `log.Level = logrus.DebugLevel` in a debug or verbose +environment if your application has that. + +#### Entries + +Besides the fields added with `WithField` or `WithFields` some fields are +automatically added to all logging events: + +1. `time`. The timestamp when the entry was created. +2. `msg`. The logging message passed to `{Info,Warn,Error,Fatal,Panic}` after + the `AddFields` call. E.g. `Failed to send event.` +3. `level`. The logging level. E.g. `info`. + +#### Environments + +Logrus has no notion of environment. + +If you wish for hooks and formatters to only be used in specific environments, +you should handle that yourself. For example, if your application has a global +variable `Environment`, which is a string representation of the environment you +could do: + +```go +import ( + log "github.com/sirupsen/logrus" +) + +init() { + // do something here to set environment depending on an environment variable + // or command-line flag + if Environment == "production" { + log.SetFormatter(&log.JSONFormatter{}) + } else { + // The TextFormatter is default, you don't actually have to do this. + log.SetFormatter(&log.TextFormatter{}) + } +} +``` + +This configuration is how `logrus` was intended to be used, but JSON in +production is mostly only useful if you do log aggregation with tools like +Splunk or Logstash. + +#### Formatters + +The built-in logging formatters are: + +* `logrus.TextFormatter`. Logs the event in colors if stdout is a tty, otherwise + without colors. + * *Note:* to force colored output when there is no TTY, set the `ForceColors` + field to `true`. To force no colored output even if there is a TTY set the + `DisableColors` field to `true`. For Windows, see + [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable). + * When colors are enabled, levels are truncated to 4 characters by default. To disable + truncation set the `DisableLevelTruncation` field to `true`. + * When outputting to a TTY, it's often helpful to visually scan down a column where all the levels are the same width. Setting the `PadLevelText` field to `true` enables this behavior, by adding padding to the level text. + * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter). +* `logrus.JSONFormatter`. Logs fields as JSON. + * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter). + +Third party logging formatters: + +* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can be parsed by Kubernetes and Google Container Engine. +* [`GELF`](https://github.com/fabienm/go-logrus-formatters). Formats entries so they comply to Graylog's [GELF 1.1 specification](http://docs.graylog.org/en/2.4/pages/gelf.html). +* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events. +* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout. +* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the Power of Zalgo. +* [`nested-logrus-formatter`](https://github.com/antonfisher/nested-logrus-formatter). Converts logrus fields to a nested structure. +* [`powerful-logrus-formatter`](https://github.com/zput/zxcTool). get fileName, log's line number and the latest function's name when print log; Sava log to files. +* [`caption-json-formatter`](https://github.com/nolleh/caption_json_formatter). logrus's message json formatter with human-readable caption added. + +You can define your formatter by implementing the `Formatter` interface, +requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a +`Fields` type (`map[string]interface{}`) with all your fields as well as the +default ones (see Entries section above): + +```go +type MyJSONFormatter struct { +} + +log.SetFormatter(new(MyJSONFormatter)) + +func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) { + // Note this doesn't include Time, Level and Message which are available on + // the Entry. Consult `godoc` on information about those fields or read the + // source of the official loggers. + serialized, err := json.Marshal(entry.Data) + if err != nil { + return nil, fmt.Errorf("Failed to marshal fields to JSON, %w", err) + } + return append(serialized, '\n'), nil +} +``` + +#### Logger as an `io.Writer` + +Logrus can be transformed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsibility to close it. + +```go +w := logger.Writer() +defer w.Close() + +srv := http.Server{ + // create a stdlib log.Logger that writes to + // logrus.Logger. + ErrorLog: log.New(w, "", 0), +} +``` + +Each line written to that writer will be printed the usual way, using formatters +and hooks. The level for those entries is `info`. + +This means that we can override the standard library logger easily: + +```go +logger := logrus.New() +logger.Formatter = &logrus.JSONFormatter{} + +// Use logrus for standard log output +// Note that `log` here references stdlib's log +// Not logrus imported under the name `log`. +log.SetOutput(logger.Writer()) +``` + +#### Rotation + +Log rotation is not provided with Logrus. Log rotation should be done by an +external program (like `logrotate(8)`) that can compress and delete old log +entries. It should not be a feature of the application-level logger. + +#### Tools + +| Tool | Description | +| ---- | ----------- | +|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will be generated with different configs in different environments.| +|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) | + +#### Testing + +Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides: + +* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just adds the `test` hook +* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any): + +```go +import( + "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus/hooks/test" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestSomething(t*testing.T){ + logger, hook := test.NewNullLogger() + logger.Error("Helloerror") + + assert.Equal(t, 1, len(hook.Entries)) + assert.Equal(t, logrus.ErrorLevel, hook.LastEntry().Level) + assert.Equal(t, "Helloerror", hook.LastEntry().Message) + + hook.Reset() + assert.Nil(t, hook.LastEntry()) +} +``` + +#### Fatal handlers + +Logrus can register one or more functions that will be called when any `fatal` +level message is logged. The registered handlers will be executed before +logrus performs an `os.Exit(1)`. This behavior may be helpful if callers need +to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted. + +``` +... +handler := func() { + // gracefully shutdown something... +} +logrus.RegisterExitHandler(handler) +... +``` + +#### Thread safety + +By default, Logger is protected by a mutex for concurrent writes. The mutex is held when calling hooks and writing logs. +If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking. + +Situation when locking is not needed includes: + +* You have no hooks registered, or hooks calling is already thread-safe. + +* Writing to logger.Out is already thread-safe, for example: + + 1) logger.Out is protected by locks. + + 2) logger.Out is an os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allows multi-thread/multi-process writing) + + (Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/) diff --git a/vendor/github.com/sirupsen/logrus/alt_exit.go b/vendor/github.com/sirupsen/logrus/alt_exit.go new file mode 100644 index 0000000000..8fd189e1cc --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/alt_exit.go @@ -0,0 +1,76 @@ +package logrus + +// The following code was sourced and modified from the +// https://github.com/tebeka/atexit package governed by the following license: +// +// Copyright (c) 2012 Miki Tebeka . +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import ( + "fmt" + "os" +) + +var handlers = []func(){} + +func runHandler(handler func()) { + defer func() { + if err := recover(); err != nil { + fmt.Fprintln(os.Stderr, "Error: Logrus exit handler error:", err) + } + }() + + handler() +} + +func runHandlers() { + for _, handler := range handlers { + runHandler(handler) + } +} + +// Exit runs all the Logrus atexit handlers and then terminates the program using os.Exit(code) +func Exit(code int) { + runHandlers() + os.Exit(code) +} + +// RegisterExitHandler appends a Logrus Exit handler to the list of handlers, +// call logrus.Exit to invoke all handlers. The handlers will also be invoked when +// any Fatal log entry is made. +// +// This method is useful when a caller wishes to use logrus to log a fatal +// message but also needs to gracefully shutdown. An example usecase could be +// closing database connections, or sending a alert that the application is +// closing. +func RegisterExitHandler(handler func()) { + handlers = append(handlers, handler) +} + +// DeferExitHandler prepends a Logrus Exit handler to the list of handlers, +// call logrus.Exit to invoke all handlers. The handlers will also be invoked when +// any Fatal log entry is made. +// +// This method is useful when a caller wishes to use logrus to log a fatal +// message but also needs to gracefully shutdown. An example usecase could be +// closing database connections, or sending a alert that the application is +// closing. +func DeferExitHandler(handler func()) { + handlers = append([]func(){handler}, handlers...) +} diff --git a/vendor/github.com/sirupsen/logrus/appveyor.yml b/vendor/github.com/sirupsen/logrus/appveyor.yml new file mode 100644 index 0000000000..df9d65c3a5 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/appveyor.yml @@ -0,0 +1,14 @@ +version: "{build}" +platform: x64 +clone_folder: c:\gopath\src\github.com\sirupsen\logrus +environment: + GOPATH: c:\gopath +branches: + only: + - master +install: + - set PATH=%GOPATH%\bin;c:\go\bin;%PATH% + - go version +build_script: + - go get -t + - go test diff --git a/vendor/github.com/sirupsen/logrus/buffer_pool.go b/vendor/github.com/sirupsen/logrus/buffer_pool.go new file mode 100644 index 0000000000..4545dec07d --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/buffer_pool.go @@ -0,0 +1,52 @@ +package logrus + +import ( + "bytes" + "sync" +) + +var ( + bufferPool BufferPool +) + +type BufferPool interface { + Put(*bytes.Buffer) + Get() *bytes.Buffer +} + +type defaultPool struct { + pool *sync.Pool +} + +func (p *defaultPool) Put(buf *bytes.Buffer) { + p.pool.Put(buf) +} + +func (p *defaultPool) Get() *bytes.Buffer { + return p.pool.Get().(*bytes.Buffer) +} + +func getBuffer() *bytes.Buffer { + return bufferPool.Get() +} + +func putBuffer(buf *bytes.Buffer) { + buf.Reset() + bufferPool.Put(buf) +} + +// SetBufferPool allows to replace the default logrus buffer pool +// to better meets the specific needs of an application. +func SetBufferPool(bp BufferPool) { + bufferPool = bp +} + +func init() { + SetBufferPool(&defaultPool{ + pool: &sync.Pool{ + New: func() interface{} { + return new(bytes.Buffer) + }, + }, + }) +} diff --git a/vendor/github.com/sirupsen/logrus/doc.go b/vendor/github.com/sirupsen/logrus/doc.go new file mode 100644 index 0000000000..da67aba06d --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/doc.go @@ -0,0 +1,26 @@ +/* +Package logrus is a structured logger for Go, completely API compatible with the standard library logger. + + +The simplest way to use Logrus is simply the package-level exported logger: + + package main + + import ( + log "github.com/sirupsen/logrus" + ) + + func main() { + log.WithFields(log.Fields{ + "animal": "walrus", + "number": 1, + "size": 10, + }).Info("A walrus appears") + } + +Output: + time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10 + +For a full guide visit https://github.com/sirupsen/logrus +*/ +package logrus diff --git a/vendor/github.com/sirupsen/logrus/entry.go b/vendor/github.com/sirupsen/logrus/entry.go new file mode 100644 index 0000000000..07a1e5fa72 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/entry.go @@ -0,0 +1,431 @@ +package logrus + +import ( + "bytes" + "context" + "fmt" + "os" + "reflect" + "runtime" + "strings" + "sync" + "time" +) + +var ( + + // qualified package name, cached at first use + logrusPackage string + + // Positions in the call stack when tracing to report the calling method + minimumCallerDepth int + + // Used for caller information initialisation + callerInitOnce sync.Once +) + +const ( + maximumCallerDepth int = 25 + knownLogrusFrames int = 4 +) + +func init() { + // start at the bottom of the stack before the package-name cache is primed + minimumCallerDepth = 1 +} + +// Defines the key when adding errors using WithError. +var ErrorKey = "error" + +// An entry is the final or intermediate Logrus logging entry. It contains all +// the fields passed with WithField{,s}. It's finally logged when Trace, Debug, +// Info, Warn, Error, Fatal or Panic is called on it. These objects can be +// reused and passed around as much as you wish to avoid field duplication. +type Entry struct { + Logger *Logger + + // Contains all the fields set by the user. + Data Fields + + // Time at which the log entry was created + Time time.Time + + // Level the log entry was logged at: Trace, Debug, Info, Warn, Error, Fatal or Panic + // This field will be set on entry firing and the value will be equal to the one in Logger struct field. + Level Level + + // Calling method, with package name + Caller *runtime.Frame + + // Message passed to Trace, Debug, Info, Warn, Error, Fatal or Panic + Message string + + // When formatter is called in entry.log(), a Buffer may be set to entry + Buffer *bytes.Buffer + + // Contains the context set by the user. Useful for hook processing etc. + Context context.Context + + // err may contain a field formatting error + err string +} + +func NewEntry(logger *Logger) *Entry { + return &Entry{ + Logger: logger, + // Default is three fields, plus one optional. Give a little extra room. + Data: make(Fields, 6), + } +} + +func (entry *Entry) Dup() *Entry { + data := make(Fields, len(entry.Data)) + for k, v := range entry.Data { + data[k] = v + } + return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, Context: entry.Context, err: entry.err} +} + +// Returns the bytes representation of this entry from the formatter. +func (entry *Entry) Bytes() ([]byte, error) { + return entry.Logger.Formatter.Format(entry) +} + +// Returns the string representation from the reader and ultimately the +// formatter. +func (entry *Entry) String() (string, error) { + serialized, err := entry.Bytes() + if err != nil { + return "", err + } + str := string(serialized) + return str, nil +} + +// Add an error as single field (using the key defined in ErrorKey) to the Entry. +func (entry *Entry) WithError(err error) *Entry { + return entry.WithField(ErrorKey, err) +} + +// Add a context to the Entry. +func (entry *Entry) WithContext(ctx context.Context) *Entry { + dataCopy := make(Fields, len(entry.Data)) + for k, v := range entry.Data { + dataCopy[k] = v + } + return &Entry{Logger: entry.Logger, Data: dataCopy, Time: entry.Time, err: entry.err, Context: ctx} +} + +// Add a single field to the Entry. +func (entry *Entry) WithField(key string, value interface{}) *Entry { + return entry.WithFields(Fields{key: value}) +} + +// Add a map of fields to the Entry. +func (entry *Entry) WithFields(fields Fields) *Entry { + data := make(Fields, len(entry.Data)+len(fields)) + for k, v := range entry.Data { + data[k] = v + } + fieldErr := entry.err + for k, v := range fields { + isErrField := false + if t := reflect.TypeOf(v); t != nil { + switch { + case t.Kind() == reflect.Func, t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Func: + isErrField = true + } + } + if isErrField { + tmp := fmt.Sprintf("can not add field %q", k) + if fieldErr != "" { + fieldErr = entry.err + ", " + tmp + } else { + fieldErr = tmp + } + } else { + data[k] = v + } + } + return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr, Context: entry.Context} +} + +// Overrides the time of the Entry. +func (entry *Entry) WithTime(t time.Time) *Entry { + dataCopy := make(Fields, len(entry.Data)) + for k, v := range entry.Data { + dataCopy[k] = v + } + return &Entry{Logger: entry.Logger, Data: dataCopy, Time: t, err: entry.err, Context: entry.Context} +} + +// getPackageName reduces a fully qualified function name to the package name +// There really ought to be to be a better way... +func getPackageName(f string) string { + for { + lastPeriod := strings.LastIndex(f, ".") + lastSlash := strings.LastIndex(f, "/") + if lastPeriod > lastSlash { + f = f[:lastPeriod] + } else { + break + } + } + + return f +} + +// getCaller retrieves the name of the first non-logrus calling function +func getCaller() *runtime.Frame { + // cache this package's fully-qualified name + callerInitOnce.Do(func() { + pcs := make([]uintptr, maximumCallerDepth) + _ = runtime.Callers(0, pcs) + + // dynamic get the package name and the minimum caller depth + for i := 0; i < maximumCallerDepth; i++ { + funcName := runtime.FuncForPC(pcs[i]).Name() + if strings.Contains(funcName, "getCaller") { + logrusPackage = getPackageName(funcName) + break + } + } + + minimumCallerDepth = knownLogrusFrames + }) + + // Restrict the lookback frames to avoid runaway lookups + pcs := make([]uintptr, maximumCallerDepth) + depth := runtime.Callers(minimumCallerDepth, pcs) + frames := runtime.CallersFrames(pcs[:depth]) + + for f, again := frames.Next(); again; f, again = frames.Next() { + pkg := getPackageName(f.Function) + + // If the caller isn't part of this package, we're done + if pkg != logrusPackage { + return &f //nolint:scopelint + } + } + + // if we got here, we failed to find the caller's context + return nil +} + +func (entry Entry) HasCaller() (has bool) { + return entry.Logger != nil && + entry.Logger.ReportCaller && + entry.Caller != nil +} + +func (entry *Entry) log(level Level, msg string) { + var buffer *bytes.Buffer + + newEntry := entry.Dup() + + if newEntry.Time.IsZero() { + newEntry.Time = time.Now() + } + + newEntry.Level = level + newEntry.Message = msg + + newEntry.Logger.mu.Lock() + reportCaller := newEntry.Logger.ReportCaller + newEntry.Logger.mu.Unlock() + + if reportCaller { + newEntry.Caller = getCaller() + } + + newEntry.fireHooks() + + buffer = getBuffer() + defer func() { + newEntry.Buffer = nil + putBuffer(buffer) + }() + buffer.Reset() + newEntry.Buffer = buffer + + newEntry.write() + + newEntry.Buffer = nil + + // To avoid Entry#log() returning a value that only would make sense for + // panic() to use in Entry#Panic(), we avoid the allocation by checking + // directly here. + if level <= PanicLevel { + panic(newEntry) + } +} + +func (entry *Entry) fireHooks() { + var tmpHooks LevelHooks + entry.Logger.mu.Lock() + tmpHooks = make(LevelHooks, len(entry.Logger.Hooks)) + for k, v := range entry.Logger.Hooks { + tmpHooks[k] = v + } + entry.Logger.mu.Unlock() + + err := tmpHooks.Fire(entry.Level, entry) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) + } +} + +func (entry *Entry) write() { + serialized, err := entry.Logger.Formatter.Format(entry) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) + return + } + entry.Logger.mu.Lock() + defer entry.Logger.mu.Unlock() + if _, err := entry.Logger.Out.Write(serialized); err != nil { + fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) + } +} + +func (entry *Entry) Log(level Level, args ...interface{}) { + if entry.Logger.IsLevelEnabled(level) { + entry.log(level, fmt.Sprint(args...)) + } +} + +func (entry *Entry) Trace(args ...interface{}) { + entry.Log(TraceLevel, args...) +} + +func (entry *Entry) Debug(args ...interface{}) { + entry.Log(DebugLevel, args...) +} + +func (entry *Entry) Print(args ...interface{}) { + entry.Info(args...) +} + +func (entry *Entry) Info(args ...interface{}) { + entry.Log(InfoLevel, args...) +} + +func (entry *Entry) Warn(args ...interface{}) { + entry.Log(WarnLevel, args...) +} + +func (entry *Entry) Warning(args ...interface{}) { + entry.Warn(args...) +} + +func (entry *Entry) Error(args ...interface{}) { + entry.Log(ErrorLevel, args...) +} + +func (entry *Entry) Fatal(args ...interface{}) { + entry.Log(FatalLevel, args...) + entry.Logger.Exit(1) +} + +func (entry *Entry) Panic(args ...interface{}) { + entry.Log(PanicLevel, args...) +} + +// Entry Printf family functions + +func (entry *Entry) Logf(level Level, format string, args ...interface{}) { + if entry.Logger.IsLevelEnabled(level) { + entry.Log(level, fmt.Sprintf(format, args...)) + } +} + +func (entry *Entry) Tracef(format string, args ...interface{}) { + entry.Logf(TraceLevel, format, args...) +} + +func (entry *Entry) Debugf(format string, args ...interface{}) { + entry.Logf(DebugLevel, format, args...) +} + +func (entry *Entry) Infof(format string, args ...interface{}) { + entry.Logf(InfoLevel, format, args...) +} + +func (entry *Entry) Printf(format string, args ...interface{}) { + entry.Infof(format, args...) +} + +func (entry *Entry) Warnf(format string, args ...interface{}) { + entry.Logf(WarnLevel, format, args...) +} + +func (entry *Entry) Warningf(format string, args ...interface{}) { + entry.Warnf(format, args...) +} + +func (entry *Entry) Errorf(format string, args ...interface{}) { + entry.Logf(ErrorLevel, format, args...) +} + +func (entry *Entry) Fatalf(format string, args ...interface{}) { + entry.Logf(FatalLevel, format, args...) + entry.Logger.Exit(1) +} + +func (entry *Entry) Panicf(format string, args ...interface{}) { + entry.Logf(PanicLevel, format, args...) +} + +// Entry Println family functions + +func (entry *Entry) Logln(level Level, args ...interface{}) { + if entry.Logger.IsLevelEnabled(level) { + entry.Log(level, entry.sprintlnn(args...)) + } +} + +func (entry *Entry) Traceln(args ...interface{}) { + entry.Logln(TraceLevel, args...) +} + +func (entry *Entry) Debugln(args ...interface{}) { + entry.Logln(DebugLevel, args...) +} + +func (entry *Entry) Infoln(args ...interface{}) { + entry.Logln(InfoLevel, args...) +} + +func (entry *Entry) Println(args ...interface{}) { + entry.Infoln(args...) +} + +func (entry *Entry) Warnln(args ...interface{}) { + entry.Logln(WarnLevel, args...) +} + +func (entry *Entry) Warningln(args ...interface{}) { + entry.Warnln(args...) +} + +func (entry *Entry) Errorln(args ...interface{}) { + entry.Logln(ErrorLevel, args...) +} + +func (entry *Entry) Fatalln(args ...interface{}) { + entry.Logln(FatalLevel, args...) + entry.Logger.Exit(1) +} + +func (entry *Entry) Panicln(args ...interface{}) { + entry.Logln(PanicLevel, args...) +} + +// Sprintlnn => Sprint no newline. This is to get the behavior of how +// fmt.Sprintln where spaces are always added between operands, regardless of +// their type. Instead of vendoring the Sprintln implementation to spare a +// string allocation, we do the simplest thing. +func (entry *Entry) sprintlnn(args ...interface{}) string { + msg := fmt.Sprintln(args...) + return msg[:len(msg)-1] +} diff --git a/vendor/github.com/sirupsen/logrus/exported.go b/vendor/github.com/sirupsen/logrus/exported.go new file mode 100644 index 0000000000..017c30ce67 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/exported.go @@ -0,0 +1,270 @@ +package logrus + +import ( + "context" + "io" + "time" +) + +var ( + // std is the name of the standard logger in stdlib `log` + std = New() +) + +func StandardLogger() *Logger { + return std +} + +// SetOutput sets the standard logger output. +func SetOutput(out io.Writer) { + std.SetOutput(out) +} + +// SetFormatter sets the standard logger formatter. +func SetFormatter(formatter Formatter) { + std.SetFormatter(formatter) +} + +// SetReportCaller sets whether the standard logger will include the calling +// method as a field. +func SetReportCaller(include bool) { + std.SetReportCaller(include) +} + +// SetLevel sets the standard logger level. +func SetLevel(level Level) { + std.SetLevel(level) +} + +// GetLevel returns the standard logger level. +func GetLevel() Level { + return std.GetLevel() +} + +// IsLevelEnabled checks if the log level of the standard logger is greater than the level param +func IsLevelEnabled(level Level) bool { + return std.IsLevelEnabled(level) +} + +// AddHook adds a hook to the standard logger hooks. +func AddHook(hook Hook) { + std.AddHook(hook) +} + +// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key. +func WithError(err error) *Entry { + return std.WithField(ErrorKey, err) +} + +// WithContext creates an entry from the standard logger and adds a context to it. +func WithContext(ctx context.Context) *Entry { + return std.WithContext(ctx) +} + +// WithField creates an entry from the standard logger and adds a field to +// it. If you want multiple fields, use `WithFields`. +// +// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal +// or Panic on the Entry it returns. +func WithField(key string, value interface{}) *Entry { + return std.WithField(key, value) +} + +// WithFields creates an entry from the standard logger and adds multiple +// fields to it. This is simply a helper for `WithField`, invoking it +// once for each field. +// +// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal +// or Panic on the Entry it returns. +func WithFields(fields Fields) *Entry { + return std.WithFields(fields) +} + +// WithTime creates an entry from the standard logger and overrides the time of +// logs generated with it. +// +// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal +// or Panic on the Entry it returns. +func WithTime(t time.Time) *Entry { + return std.WithTime(t) +} + +// Trace logs a message at level Trace on the standard logger. +func Trace(args ...interface{}) { + std.Trace(args...) +} + +// Debug logs a message at level Debug on the standard logger. +func Debug(args ...interface{}) { + std.Debug(args...) +} + +// Print logs a message at level Info on the standard logger. +func Print(args ...interface{}) { + std.Print(args...) +} + +// Info logs a message at level Info on the standard logger. +func Info(args ...interface{}) { + std.Info(args...) +} + +// Warn logs a message at level Warn on the standard logger. +func Warn(args ...interface{}) { + std.Warn(args...) +} + +// Warning logs a message at level Warn on the standard logger. +func Warning(args ...interface{}) { + std.Warning(args...) +} + +// Error logs a message at level Error on the standard logger. +func Error(args ...interface{}) { + std.Error(args...) +} + +// Panic logs a message at level Panic on the standard logger. +func Panic(args ...interface{}) { + std.Panic(args...) +} + +// Fatal logs a message at level Fatal on the standard logger then the process will exit with status set to 1. +func Fatal(args ...interface{}) { + std.Fatal(args...) +} + +// TraceFn logs a message from a func at level Trace on the standard logger. +func TraceFn(fn LogFunction) { + std.TraceFn(fn) +} + +// DebugFn logs a message from a func at level Debug on the standard logger. +func DebugFn(fn LogFunction) { + std.DebugFn(fn) +} + +// PrintFn logs a message from a func at level Info on the standard logger. +func PrintFn(fn LogFunction) { + std.PrintFn(fn) +} + +// InfoFn logs a message from a func at level Info on the standard logger. +func InfoFn(fn LogFunction) { + std.InfoFn(fn) +} + +// WarnFn logs a message from a func at level Warn on the standard logger. +func WarnFn(fn LogFunction) { + std.WarnFn(fn) +} + +// WarningFn logs a message from a func at level Warn on the standard logger. +func WarningFn(fn LogFunction) { + std.WarningFn(fn) +} + +// ErrorFn logs a message from a func at level Error on the standard logger. +func ErrorFn(fn LogFunction) { + std.ErrorFn(fn) +} + +// PanicFn logs a message from a func at level Panic on the standard logger. +func PanicFn(fn LogFunction) { + std.PanicFn(fn) +} + +// FatalFn logs a message from a func at level Fatal on the standard logger then the process will exit with status set to 1. +func FatalFn(fn LogFunction) { + std.FatalFn(fn) +} + +// Tracef logs a message at level Trace on the standard logger. +func Tracef(format string, args ...interface{}) { + std.Tracef(format, args...) +} + +// Debugf logs a message at level Debug on the standard logger. +func Debugf(format string, args ...interface{}) { + std.Debugf(format, args...) +} + +// Printf logs a message at level Info on the standard logger. +func Printf(format string, args ...interface{}) { + std.Printf(format, args...) +} + +// Infof logs a message at level Info on the standard logger. +func Infof(format string, args ...interface{}) { + std.Infof(format, args...) +} + +// Warnf logs a message at level Warn on the standard logger. +func Warnf(format string, args ...interface{}) { + std.Warnf(format, args...) +} + +// Warningf logs a message at level Warn on the standard logger. +func Warningf(format string, args ...interface{}) { + std.Warningf(format, args...) +} + +// Errorf logs a message at level Error on the standard logger. +func Errorf(format string, args ...interface{}) { + std.Errorf(format, args...) +} + +// Panicf logs a message at level Panic on the standard logger. +func Panicf(format string, args ...interface{}) { + std.Panicf(format, args...) +} + +// Fatalf logs a message at level Fatal on the standard logger then the process will exit with status set to 1. +func Fatalf(format string, args ...interface{}) { + std.Fatalf(format, args...) +} + +// Traceln logs a message at level Trace on the standard logger. +func Traceln(args ...interface{}) { + std.Traceln(args...) +} + +// Debugln logs a message at level Debug on the standard logger. +func Debugln(args ...interface{}) { + std.Debugln(args...) +} + +// Println logs a message at level Info on the standard logger. +func Println(args ...interface{}) { + std.Println(args...) +} + +// Infoln logs a message at level Info on the standard logger. +func Infoln(args ...interface{}) { + std.Infoln(args...) +} + +// Warnln logs a message at level Warn on the standard logger. +func Warnln(args ...interface{}) { + std.Warnln(args...) +} + +// Warningln logs a message at level Warn on the standard logger. +func Warningln(args ...interface{}) { + std.Warningln(args...) +} + +// Errorln logs a message at level Error on the standard logger. +func Errorln(args ...interface{}) { + std.Errorln(args...) +} + +// Panicln logs a message at level Panic on the standard logger. +func Panicln(args ...interface{}) { + std.Panicln(args...) +} + +// Fatalln logs a message at level Fatal on the standard logger then the process will exit with status set to 1. +func Fatalln(args ...interface{}) { + std.Fatalln(args...) +} diff --git a/vendor/github.com/sirupsen/logrus/formatter.go b/vendor/github.com/sirupsen/logrus/formatter.go new file mode 100644 index 0000000000..408883773e --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/formatter.go @@ -0,0 +1,78 @@ +package logrus + +import "time" + +// Default key names for the default fields +const ( + defaultTimestampFormat = time.RFC3339 + FieldKeyMsg = "msg" + FieldKeyLevel = "level" + FieldKeyTime = "time" + FieldKeyLogrusError = "logrus_error" + FieldKeyFunc = "func" + FieldKeyFile = "file" +) + +// The Formatter interface is used to implement a custom Formatter. It takes an +// `Entry`. It exposes all the fields, including the default ones: +// +// * `entry.Data["msg"]`. The message passed from Info, Warn, Error .. +// * `entry.Data["time"]`. The timestamp. +// * `entry.Data["level"]. The level the entry was logged at. +// +// Any additional fields added with `WithField` or `WithFields` are also in +// `entry.Data`. Format is expected to return an array of bytes which are then +// logged to `logger.Out`. +type Formatter interface { + Format(*Entry) ([]byte, error) +} + +// This is to not silently overwrite `time`, `msg`, `func` and `level` fields when +// dumping it. If this code wasn't there doing: +// +// logrus.WithField("level", 1).Info("hello") +// +// Would just silently drop the user provided level. Instead with this code +// it'll logged as: +// +// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."} +// +// It's not exported because it's still using Data in an opinionated way. It's to +// avoid code duplication between the two default formatters. +func prefixFieldClashes(data Fields, fieldMap FieldMap, reportCaller bool) { + timeKey := fieldMap.resolve(FieldKeyTime) + if t, ok := data[timeKey]; ok { + data["fields."+timeKey] = t + delete(data, timeKey) + } + + msgKey := fieldMap.resolve(FieldKeyMsg) + if m, ok := data[msgKey]; ok { + data["fields."+msgKey] = m + delete(data, msgKey) + } + + levelKey := fieldMap.resolve(FieldKeyLevel) + if l, ok := data[levelKey]; ok { + data["fields."+levelKey] = l + delete(data, levelKey) + } + + logrusErrKey := fieldMap.resolve(FieldKeyLogrusError) + if l, ok := data[logrusErrKey]; ok { + data["fields."+logrusErrKey] = l + delete(data, logrusErrKey) + } + + // If reportCaller is not set, 'func' will not conflict. + if reportCaller { + funcKey := fieldMap.resolve(FieldKeyFunc) + if l, ok := data[funcKey]; ok { + data["fields."+funcKey] = l + } + fileKey := fieldMap.resolve(FieldKeyFile) + if l, ok := data[fileKey]; ok { + data["fields."+fileKey] = l + } + } +} diff --git a/vendor/github.com/sirupsen/logrus/hooks.go b/vendor/github.com/sirupsen/logrus/hooks.go new file mode 100644 index 0000000000..3f151cdc39 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/hooks.go @@ -0,0 +1,34 @@ +package logrus + +// A hook to be fired when logging on the logging levels returned from +// `Levels()` on your implementation of the interface. Note that this is not +// fired in a goroutine or a channel with workers, you should handle such +// functionality yourself if your call is non-blocking and you don't wish for +// the logging calls for levels returned from `Levels()` to block. +type Hook interface { + Levels() []Level + Fire(*Entry) error +} + +// Internal type for storing the hooks on a logger instance. +type LevelHooks map[Level][]Hook + +// Add a hook to an instance of logger. This is called with +// `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface. +func (hooks LevelHooks) Add(hook Hook) { + for _, level := range hook.Levels() { + hooks[level] = append(hooks[level], hook) + } +} + +// Fire all the hooks for the passed level. Used by `entry.log` to fire +// appropriate hooks for a log entry. +func (hooks LevelHooks) Fire(level Level, entry *Entry) error { + for _, hook := range hooks[level] { + if err := hook.Fire(entry); err != nil { + return err + } + } + + return nil +} diff --git a/vendor/github.com/sirupsen/logrus/json_formatter.go b/vendor/github.com/sirupsen/logrus/json_formatter.go new file mode 100644 index 0000000000..c96dc5636b --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/json_formatter.go @@ -0,0 +1,128 @@ +package logrus + +import ( + "bytes" + "encoding/json" + "fmt" + "runtime" +) + +type fieldKey string + +// FieldMap allows customization of the key names for default fields. +type FieldMap map[fieldKey]string + +func (f FieldMap) resolve(key fieldKey) string { + if k, ok := f[key]; ok { + return k + } + + return string(key) +} + +// JSONFormatter formats logs into parsable json +type JSONFormatter struct { + // TimestampFormat sets the format used for marshaling timestamps. + // The format to use is the same than for time.Format or time.Parse from the standard + // library. + // The standard Library already provides a set of predefined format. + TimestampFormat string + + // DisableTimestamp allows disabling automatic timestamps in output + DisableTimestamp bool + + // DisableHTMLEscape allows disabling html escaping in output + DisableHTMLEscape bool + + // DataKey allows users to put all the log entry parameters into a nested dictionary at a given key. + DataKey string + + // FieldMap allows users to customize the names of keys for default fields. + // As an example: + // formatter := &JSONFormatter{ + // FieldMap: FieldMap{ + // FieldKeyTime: "@timestamp", + // FieldKeyLevel: "@level", + // FieldKeyMsg: "@message", + // FieldKeyFunc: "@caller", + // }, + // } + FieldMap FieldMap + + // CallerPrettyfier can be set by the user to modify the content + // of the function and file keys in the json data when ReportCaller is + // activated. If any of the returned value is the empty string the + // corresponding key will be removed from json fields. + CallerPrettyfier func(*runtime.Frame) (function string, file string) + + // PrettyPrint will indent all json logs + PrettyPrint bool +} + +// Format renders a single log entry +func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { + data := make(Fields, len(entry.Data)+4) + for k, v := range entry.Data { + switch v := v.(type) { + case error: + // Otherwise errors are ignored by `encoding/json` + // https://github.com/sirupsen/logrus/issues/137 + data[k] = v.Error() + default: + data[k] = v + } + } + + if f.DataKey != "" { + newData := make(Fields, 4) + newData[f.DataKey] = data + data = newData + } + + prefixFieldClashes(data, f.FieldMap, entry.HasCaller()) + + timestampFormat := f.TimestampFormat + if timestampFormat == "" { + timestampFormat = defaultTimestampFormat + } + + if entry.err != "" { + data[f.FieldMap.resolve(FieldKeyLogrusError)] = entry.err + } + if !f.DisableTimestamp { + data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat) + } + data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message + data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String() + if entry.HasCaller() { + funcVal := entry.Caller.Function + fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + if f.CallerPrettyfier != nil { + funcVal, fileVal = f.CallerPrettyfier(entry.Caller) + } + if funcVal != "" { + data[f.FieldMap.resolve(FieldKeyFunc)] = funcVal + } + if fileVal != "" { + data[f.FieldMap.resolve(FieldKeyFile)] = fileVal + } + } + + var b *bytes.Buffer + if entry.Buffer != nil { + b = entry.Buffer + } else { + b = &bytes.Buffer{} + } + + encoder := json.NewEncoder(b) + encoder.SetEscapeHTML(!f.DisableHTMLEscape) + if f.PrettyPrint { + encoder.SetIndent("", " ") + } + if err := encoder.Encode(data); err != nil { + return nil, fmt.Errorf("failed to marshal fields to JSON, %w", err) + } + + return b.Bytes(), nil +} diff --git a/vendor/github.com/sirupsen/logrus/logger.go b/vendor/github.com/sirupsen/logrus/logger.go new file mode 100644 index 0000000000..337704457a --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/logger.go @@ -0,0 +1,404 @@ +package logrus + +import ( + "context" + "io" + "os" + "sync" + "sync/atomic" + "time" +) + +// LogFunction For big messages, it can be more efficient to pass a function +// and only call it if the log level is actually enables rather than +// generating the log message and then checking if the level is enabled +type LogFunction func() []interface{} + +type Logger struct { + // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a + // file, or leave it default which is `os.Stderr`. You can also set this to + // something more adventurous, such as logging to Kafka. + Out io.Writer + // Hooks for the logger instance. These allow firing events based on logging + // levels and log entries. For example, to send errors to an error tracking + // service, log to StatsD or dump the core on fatal errors. + Hooks LevelHooks + // All log entries pass through the formatter before logged to Out. The + // included formatters are `TextFormatter` and `JSONFormatter` for which + // TextFormatter is the default. In development (when a TTY is attached) it + // logs with colors, but to a file it wouldn't. You can easily implement your + // own that implements the `Formatter` interface, see the `README` or included + // formatters for examples. + Formatter Formatter + + // Flag for whether to log caller info (off by default) + ReportCaller bool + + // The logging level the logger should log at. This is typically (and defaults + // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be + // logged. + Level Level + // Used to sync writing to the log. Locking is enabled by Default + mu MutexWrap + // Reusable empty entry + entryPool sync.Pool + // Function to exit the application, defaults to `os.Exit()` + ExitFunc exitFunc +} + +type exitFunc func(int) + +type MutexWrap struct { + lock sync.Mutex + disabled bool +} + +func (mw *MutexWrap) Lock() { + if !mw.disabled { + mw.lock.Lock() + } +} + +func (mw *MutexWrap) Unlock() { + if !mw.disabled { + mw.lock.Unlock() + } +} + +func (mw *MutexWrap) Disable() { + mw.disabled = true +} + +// Creates a new logger. Configuration should be set by changing `Formatter`, +// `Out` and `Hooks` directly on the default logger instance. You can also just +// instantiate your own: +// +// var log = &logrus.Logger{ +// Out: os.Stderr, +// Formatter: new(logrus.TextFormatter), +// Hooks: make(logrus.LevelHooks), +// Level: logrus.DebugLevel, +// } +// +// It's recommended to make this a global instance called `log`. +func New() *Logger { + return &Logger{ + Out: os.Stderr, + Formatter: new(TextFormatter), + Hooks: make(LevelHooks), + Level: InfoLevel, + ExitFunc: os.Exit, + ReportCaller: false, + } +} + +func (logger *Logger) newEntry() *Entry { + entry, ok := logger.entryPool.Get().(*Entry) + if ok { + return entry + } + return NewEntry(logger) +} + +func (logger *Logger) releaseEntry(entry *Entry) { + entry.Data = map[string]interface{}{} + logger.entryPool.Put(entry) +} + +// WithField allocates a new entry and adds a field to it. +// Debug, Print, Info, Warn, Error, Fatal or Panic must be then applied to +// this new returned entry. +// If you want multiple fields, use `WithFields`. +func (logger *Logger) WithField(key string, value interface{}) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithField(key, value) +} + +// Adds a struct of fields to the log entry. All it does is call `WithField` for +// each `Field`. +func (logger *Logger) WithFields(fields Fields) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithFields(fields) +} + +// Add an error as single field to the log entry. All it does is call +// `WithError` for the given `error`. +func (logger *Logger) WithError(err error) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithError(err) +} + +// Add a context to the log entry. +func (logger *Logger) WithContext(ctx context.Context) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithContext(ctx) +} + +// Overrides the time of the log entry. +func (logger *Logger) WithTime(t time.Time) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithTime(t) +} + +func (logger *Logger) Logf(level Level, format string, args ...interface{}) { + if logger.IsLevelEnabled(level) { + entry := logger.newEntry() + entry.Logf(level, format, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Tracef(format string, args ...interface{}) { + logger.Logf(TraceLevel, format, args...) +} + +func (logger *Logger) Debugf(format string, args ...interface{}) { + logger.Logf(DebugLevel, format, args...) +} + +func (logger *Logger) Infof(format string, args ...interface{}) { + logger.Logf(InfoLevel, format, args...) +} + +func (logger *Logger) Printf(format string, args ...interface{}) { + entry := logger.newEntry() + entry.Printf(format, args...) + logger.releaseEntry(entry) +} + +func (logger *Logger) Warnf(format string, args ...interface{}) { + logger.Logf(WarnLevel, format, args...) +} + +func (logger *Logger) Warningf(format string, args ...interface{}) { + logger.Warnf(format, args...) +} + +func (logger *Logger) Errorf(format string, args ...interface{}) { + logger.Logf(ErrorLevel, format, args...) +} + +func (logger *Logger) Fatalf(format string, args ...interface{}) { + logger.Logf(FatalLevel, format, args...) + logger.Exit(1) +} + +func (logger *Logger) Panicf(format string, args ...interface{}) { + logger.Logf(PanicLevel, format, args...) +} + +func (logger *Logger) Log(level Level, args ...interface{}) { + if logger.IsLevelEnabled(level) { + entry := logger.newEntry() + entry.Log(level, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) LogFn(level Level, fn LogFunction) { + if logger.IsLevelEnabled(level) { + entry := logger.newEntry() + entry.Log(level, fn()...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Trace(args ...interface{}) { + logger.Log(TraceLevel, args...) +} + +func (logger *Logger) Debug(args ...interface{}) { + logger.Log(DebugLevel, args...) +} + +func (logger *Logger) Info(args ...interface{}) { + logger.Log(InfoLevel, args...) +} + +func (logger *Logger) Print(args ...interface{}) { + entry := logger.newEntry() + entry.Print(args...) + logger.releaseEntry(entry) +} + +func (logger *Logger) Warn(args ...interface{}) { + logger.Log(WarnLevel, args...) +} + +func (logger *Logger) Warning(args ...interface{}) { + logger.Warn(args...) +} + +func (logger *Logger) Error(args ...interface{}) { + logger.Log(ErrorLevel, args...) +} + +func (logger *Logger) Fatal(args ...interface{}) { + logger.Log(FatalLevel, args...) + logger.Exit(1) +} + +func (logger *Logger) Panic(args ...interface{}) { + logger.Log(PanicLevel, args...) +} + +func (logger *Logger) TraceFn(fn LogFunction) { + logger.LogFn(TraceLevel, fn) +} + +func (logger *Logger) DebugFn(fn LogFunction) { + logger.LogFn(DebugLevel, fn) +} + +func (logger *Logger) InfoFn(fn LogFunction) { + logger.LogFn(InfoLevel, fn) +} + +func (logger *Logger) PrintFn(fn LogFunction) { + entry := logger.newEntry() + entry.Print(fn()...) + logger.releaseEntry(entry) +} + +func (logger *Logger) WarnFn(fn LogFunction) { + logger.LogFn(WarnLevel, fn) +} + +func (logger *Logger) WarningFn(fn LogFunction) { + logger.WarnFn(fn) +} + +func (logger *Logger) ErrorFn(fn LogFunction) { + logger.LogFn(ErrorLevel, fn) +} + +func (logger *Logger) FatalFn(fn LogFunction) { + logger.LogFn(FatalLevel, fn) + logger.Exit(1) +} + +func (logger *Logger) PanicFn(fn LogFunction) { + logger.LogFn(PanicLevel, fn) +} + +func (logger *Logger) Logln(level Level, args ...interface{}) { + if logger.IsLevelEnabled(level) { + entry := logger.newEntry() + entry.Logln(level, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Traceln(args ...interface{}) { + logger.Logln(TraceLevel, args...) +} + +func (logger *Logger) Debugln(args ...interface{}) { + logger.Logln(DebugLevel, args...) +} + +func (logger *Logger) Infoln(args ...interface{}) { + logger.Logln(InfoLevel, args...) +} + +func (logger *Logger) Println(args ...interface{}) { + entry := logger.newEntry() + entry.Println(args...) + logger.releaseEntry(entry) +} + +func (logger *Logger) Warnln(args ...interface{}) { + logger.Logln(WarnLevel, args...) +} + +func (logger *Logger) Warningln(args ...interface{}) { + logger.Warnln(args...) +} + +func (logger *Logger) Errorln(args ...interface{}) { + logger.Logln(ErrorLevel, args...) +} + +func (logger *Logger) Fatalln(args ...interface{}) { + logger.Logln(FatalLevel, args...) + logger.Exit(1) +} + +func (logger *Logger) Panicln(args ...interface{}) { + logger.Logln(PanicLevel, args...) +} + +func (logger *Logger) Exit(code int) { + runHandlers() + if logger.ExitFunc == nil { + logger.ExitFunc = os.Exit + } + logger.ExitFunc(code) +} + +//When file is opened with appending mode, it's safe to +//write concurrently to a file (within 4k message on Linux). +//In these cases user can choose to disable the lock. +func (logger *Logger) SetNoLock() { + logger.mu.Disable() +} + +func (logger *Logger) level() Level { + return Level(atomic.LoadUint32((*uint32)(&logger.Level))) +} + +// SetLevel sets the logger level. +func (logger *Logger) SetLevel(level Level) { + atomic.StoreUint32((*uint32)(&logger.Level), uint32(level)) +} + +// GetLevel returns the logger level. +func (logger *Logger) GetLevel() Level { + return logger.level() +} + +// AddHook adds a hook to the logger hooks. +func (logger *Logger) AddHook(hook Hook) { + logger.mu.Lock() + defer logger.mu.Unlock() + logger.Hooks.Add(hook) +} + +// IsLevelEnabled checks if the log level of the logger is greater than the level param +func (logger *Logger) IsLevelEnabled(level Level) bool { + return logger.level() >= level +} + +// SetFormatter sets the logger formatter. +func (logger *Logger) SetFormatter(formatter Formatter) { + logger.mu.Lock() + defer logger.mu.Unlock() + logger.Formatter = formatter +} + +// SetOutput sets the logger output. +func (logger *Logger) SetOutput(output io.Writer) { + logger.mu.Lock() + defer logger.mu.Unlock() + logger.Out = output +} + +func (logger *Logger) SetReportCaller(reportCaller bool) { + logger.mu.Lock() + defer logger.mu.Unlock() + logger.ReportCaller = reportCaller +} + +// ReplaceHooks replaces the logger hooks and returns the old ones +func (logger *Logger) ReplaceHooks(hooks LevelHooks) LevelHooks { + logger.mu.Lock() + oldHooks := logger.Hooks + logger.Hooks = hooks + logger.mu.Unlock() + return oldHooks +} diff --git a/vendor/github.com/sirupsen/logrus/logrus.go b/vendor/github.com/sirupsen/logrus/logrus.go new file mode 100644 index 0000000000..2f16224cb9 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/logrus.go @@ -0,0 +1,186 @@ +package logrus + +import ( + "fmt" + "log" + "strings" +) + +// Fields type, used to pass to `WithFields`. +type Fields map[string]interface{} + +// Level type +type Level uint32 + +// Convert the Level to a string. E.g. PanicLevel becomes "panic". +func (level Level) String() string { + if b, err := level.MarshalText(); err == nil { + return string(b) + } else { + return "unknown" + } +} + +// ParseLevel takes a string level and returns the Logrus log level constant. +func ParseLevel(lvl string) (Level, error) { + switch strings.ToLower(lvl) { + case "panic": + return PanicLevel, nil + case "fatal": + return FatalLevel, nil + case "error": + return ErrorLevel, nil + case "warn", "warning": + return WarnLevel, nil + case "info": + return InfoLevel, nil + case "debug": + return DebugLevel, nil + case "trace": + return TraceLevel, nil + } + + var l Level + return l, fmt.Errorf("not a valid logrus Level: %q", lvl) +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (level *Level) UnmarshalText(text []byte) error { + l, err := ParseLevel(string(text)) + if err != nil { + return err + } + + *level = l + + return nil +} + +func (level Level) MarshalText() ([]byte, error) { + switch level { + case TraceLevel: + return []byte("trace"), nil + case DebugLevel: + return []byte("debug"), nil + case InfoLevel: + return []byte("info"), nil + case WarnLevel: + return []byte("warning"), nil + case ErrorLevel: + return []byte("error"), nil + case FatalLevel: + return []byte("fatal"), nil + case PanicLevel: + return []byte("panic"), nil + } + + return nil, fmt.Errorf("not a valid logrus level %d", level) +} + +// A constant exposing all logging levels +var AllLevels = []Level{ + PanicLevel, + FatalLevel, + ErrorLevel, + WarnLevel, + InfoLevel, + DebugLevel, + TraceLevel, +} + +// These are the different logging levels. You can set the logging level to log +// on your instance of logger, obtained with `logrus.New()`. +const ( + // PanicLevel level, highest level of severity. Logs and then calls panic with the + // message passed to Debug, Info, ... + PanicLevel Level = iota + // FatalLevel level. Logs and then calls `logger.Exit(1)`. It will exit even if the + // logging level is set to Panic. + FatalLevel + // ErrorLevel level. Logs. Used for errors that should definitely be noted. + // Commonly used for hooks to send errors to an error tracking service. + ErrorLevel + // WarnLevel level. Non-critical entries that deserve eyes. + WarnLevel + // InfoLevel level. General operational entries about what's going on inside the + // application. + InfoLevel + // DebugLevel level. Usually only enabled when debugging. Very verbose logging. + DebugLevel + // TraceLevel level. Designates finer-grained informational events than the Debug. + TraceLevel +) + +// Won't compile if StdLogger can't be realized by a log.Logger +var ( + _ StdLogger = &log.Logger{} + _ StdLogger = &Entry{} + _ StdLogger = &Logger{} +) + +// StdLogger is what your logrus-enabled library should take, that way +// it'll accept a stdlib logger and a logrus logger. There's no standard +// interface, this is the closest we get, unfortunately. +type StdLogger interface { + Print(...interface{}) + Printf(string, ...interface{}) + Println(...interface{}) + + Fatal(...interface{}) + Fatalf(string, ...interface{}) + Fatalln(...interface{}) + + Panic(...interface{}) + Panicf(string, ...interface{}) + Panicln(...interface{}) +} + +// The FieldLogger interface generalizes the Entry and Logger types +type FieldLogger interface { + WithField(key string, value interface{}) *Entry + WithFields(fields Fields) *Entry + WithError(err error) *Entry + + Debugf(format string, args ...interface{}) + Infof(format string, args ...interface{}) + Printf(format string, args ...interface{}) + Warnf(format string, args ...interface{}) + Warningf(format string, args ...interface{}) + Errorf(format string, args ...interface{}) + Fatalf(format string, args ...interface{}) + Panicf(format string, args ...interface{}) + + Debug(args ...interface{}) + Info(args ...interface{}) + Print(args ...interface{}) + Warn(args ...interface{}) + Warning(args ...interface{}) + Error(args ...interface{}) + Fatal(args ...interface{}) + Panic(args ...interface{}) + + Debugln(args ...interface{}) + Infoln(args ...interface{}) + Println(args ...interface{}) + Warnln(args ...interface{}) + Warningln(args ...interface{}) + Errorln(args ...interface{}) + Fatalln(args ...interface{}) + Panicln(args ...interface{}) + + // IsDebugEnabled() bool + // IsInfoEnabled() bool + // IsWarnEnabled() bool + // IsErrorEnabled() bool + // IsFatalEnabled() bool + // IsPanicEnabled() bool +} + +// Ext1FieldLogger (the first extension to FieldLogger) is superfluous, it is +// here for consistancy. Do not use. Use Logger or Entry instead. +type Ext1FieldLogger interface { + FieldLogger + Tracef(format string, args ...interface{}) + Trace(args ...interface{}) + Traceln(args ...interface{}) +} diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go b/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go new file mode 100644 index 0000000000..2403de9819 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_appengine.go @@ -0,0 +1,11 @@ +// +build appengine + +package logrus + +import ( + "io" +) + +func checkIfTerminal(w io.Writer) bool { + return true +} diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go b/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go new file mode 100644 index 0000000000..499789984d --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go @@ -0,0 +1,13 @@ +// +build darwin dragonfly freebsd netbsd openbsd +// +build !js + +package logrus + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TIOCGETA + +func isTerminal(fd int) bool { + _, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + return err == nil +} diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_js.go b/vendor/github.com/sirupsen/logrus/terminal_check_js.go new file mode 100644 index 0000000000..ebdae3ec62 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_js.go @@ -0,0 +1,7 @@ +// +build js + +package logrus + +func isTerminal(fd int) bool { + return false +} diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go b/vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go new file mode 100644 index 0000000000..97af92c68e --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_no_terminal.go @@ -0,0 +1,11 @@ +// +build js nacl plan9 + +package logrus + +import ( + "io" +) + +func checkIfTerminal(w io.Writer) bool { + return false +} diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go b/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go new file mode 100644 index 0000000000..3293fb3caa --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go @@ -0,0 +1,17 @@ +// +build !appengine,!js,!windows,!nacl,!plan9 + +package logrus + +import ( + "io" + "os" +) + +func checkIfTerminal(w io.Writer) bool { + switch v := w.(type) { + case *os.File: + return isTerminal(int(v.Fd())) + default: + return false + } +} diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_solaris.go b/vendor/github.com/sirupsen/logrus/terminal_check_solaris.go new file mode 100644 index 0000000000..f6710b3bd0 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_solaris.go @@ -0,0 +1,11 @@ +package logrus + +import ( + "golang.org/x/sys/unix" +) + +// IsTerminal returns true if the given file descriptor is a terminal. +func isTerminal(fd int) bool { + _, err := unix.IoctlGetTermio(fd, unix.TCGETA) + return err == nil +} diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_unix.go b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go new file mode 100644 index 0000000000..04748b8515 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go @@ -0,0 +1,13 @@ +// +build linux aix zos +// +build !js + +package logrus + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TCGETS + +func isTerminal(fd int) bool { + _, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + return err == nil +} diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_windows.go b/vendor/github.com/sirupsen/logrus/terminal_check_windows.go new file mode 100644 index 0000000000..2879eb50ea --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_windows.go @@ -0,0 +1,27 @@ +// +build !appengine,!js,windows + +package logrus + +import ( + "io" + "os" + + "golang.org/x/sys/windows" +) + +func checkIfTerminal(w io.Writer) bool { + switch v := w.(type) { + case *os.File: + handle := windows.Handle(v.Fd()) + var mode uint32 + if err := windows.GetConsoleMode(handle, &mode); err != nil { + return false + } + mode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING + if err := windows.SetConsoleMode(handle, mode); err != nil { + return false + } + return true + } + return false +} diff --git a/vendor/github.com/sirupsen/logrus/text_formatter.go b/vendor/github.com/sirupsen/logrus/text_formatter.go new file mode 100644 index 0000000000..be2c6efe5e --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/text_formatter.go @@ -0,0 +1,339 @@ +package logrus + +import ( + "bytes" + "fmt" + "os" + "runtime" + "sort" + "strconv" + "strings" + "sync" + "time" + "unicode/utf8" +) + +const ( + red = 31 + yellow = 33 + blue = 36 + gray = 37 +) + +var baseTimestamp time.Time + +func init() { + baseTimestamp = time.Now() +} + +// TextFormatter formats logs into text +type TextFormatter struct { + // Set to true to bypass checking for a TTY before outputting colors. + ForceColors bool + + // Force disabling colors. + DisableColors bool + + // Force quoting of all values + ForceQuote bool + + // DisableQuote disables quoting for all values. + // DisableQuote will have a lower priority than ForceQuote. + // If both of them are set to true, quote will be forced on all values. + DisableQuote bool + + // Override coloring based on CLICOLOR and CLICOLOR_FORCE. - https://bixense.com/clicolors/ + EnvironmentOverrideColors bool + + // Disable timestamp logging. useful when output is redirected to logging + // system that already adds timestamps. + DisableTimestamp bool + + // Enable logging the full timestamp when a TTY is attached instead of just + // the time passed since beginning of execution. + FullTimestamp bool + + // TimestampFormat to use for display when a full timestamp is printed. + // The format to use is the same than for time.Format or time.Parse from the standard + // library. + // The standard Library already provides a set of predefined format. + TimestampFormat string + + // The fields are sorted by default for a consistent output. For applications + // that log extremely frequently and don't use the JSON formatter this may not + // be desired. + DisableSorting bool + + // The keys sorting function, when uninitialized it uses sort.Strings. + SortingFunc func([]string) + + // Disables the truncation of the level text to 4 characters. + DisableLevelTruncation bool + + // PadLevelText Adds padding the level text so that all the levels output at the same length + // PadLevelText is a superset of the DisableLevelTruncation option + PadLevelText bool + + // QuoteEmptyFields will wrap empty fields in quotes if true + QuoteEmptyFields bool + + // Whether the logger's out is to a terminal + isTerminal bool + + // FieldMap allows users to customize the names of keys for default fields. + // As an example: + // formatter := &TextFormatter{ + // FieldMap: FieldMap{ + // FieldKeyTime: "@timestamp", + // FieldKeyLevel: "@level", + // FieldKeyMsg: "@message"}} + FieldMap FieldMap + + // CallerPrettyfier can be set by the user to modify the content + // of the function and file keys in the data when ReportCaller is + // activated. If any of the returned value is the empty string the + // corresponding key will be removed from fields. + CallerPrettyfier func(*runtime.Frame) (function string, file string) + + terminalInitOnce sync.Once + + // The max length of the level text, generated dynamically on init + levelTextMaxLength int +} + +func (f *TextFormatter) init(entry *Entry) { + if entry.Logger != nil { + f.isTerminal = checkIfTerminal(entry.Logger.Out) + } + // Get the max length of the level text + for _, level := range AllLevels { + levelTextLength := utf8.RuneCount([]byte(level.String())) + if levelTextLength > f.levelTextMaxLength { + f.levelTextMaxLength = levelTextLength + } + } +} + +func (f *TextFormatter) isColored() bool { + isColored := f.ForceColors || (f.isTerminal && (runtime.GOOS != "windows")) + + if f.EnvironmentOverrideColors { + switch force, ok := os.LookupEnv("CLICOLOR_FORCE"); { + case ok && force != "0": + isColored = true + case ok && force == "0", os.Getenv("CLICOLOR") == "0": + isColored = false + } + } + + return isColored && !f.DisableColors +} + +// Format renders a single log entry +func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { + data := make(Fields) + for k, v := range entry.Data { + data[k] = v + } + prefixFieldClashes(data, f.FieldMap, entry.HasCaller()) + keys := make([]string, 0, len(data)) + for k := range data { + keys = append(keys, k) + } + + var funcVal, fileVal string + + fixedKeys := make([]string, 0, 4+len(data)) + if !f.DisableTimestamp { + fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyTime)) + } + fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLevel)) + if entry.Message != "" { + fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyMsg)) + } + if entry.err != "" { + fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLogrusError)) + } + if entry.HasCaller() { + if f.CallerPrettyfier != nil { + funcVal, fileVal = f.CallerPrettyfier(entry.Caller) + } else { + funcVal = entry.Caller.Function + fileVal = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + } + + if funcVal != "" { + fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyFunc)) + } + if fileVal != "" { + fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyFile)) + } + } + + if !f.DisableSorting { + if f.SortingFunc == nil { + sort.Strings(keys) + fixedKeys = append(fixedKeys, keys...) + } else { + if !f.isColored() { + fixedKeys = append(fixedKeys, keys...) + f.SortingFunc(fixedKeys) + } else { + f.SortingFunc(keys) + } + } + } else { + fixedKeys = append(fixedKeys, keys...) + } + + var b *bytes.Buffer + if entry.Buffer != nil { + b = entry.Buffer + } else { + b = &bytes.Buffer{} + } + + f.terminalInitOnce.Do(func() { f.init(entry) }) + + timestampFormat := f.TimestampFormat + if timestampFormat == "" { + timestampFormat = defaultTimestampFormat + } + if f.isColored() { + f.printColored(b, entry, keys, data, timestampFormat) + } else { + + for _, key := range fixedKeys { + var value interface{} + switch { + case key == f.FieldMap.resolve(FieldKeyTime): + value = entry.Time.Format(timestampFormat) + case key == f.FieldMap.resolve(FieldKeyLevel): + value = entry.Level.String() + case key == f.FieldMap.resolve(FieldKeyMsg): + value = entry.Message + case key == f.FieldMap.resolve(FieldKeyLogrusError): + value = entry.err + case key == f.FieldMap.resolve(FieldKeyFunc) && entry.HasCaller(): + value = funcVal + case key == f.FieldMap.resolve(FieldKeyFile) && entry.HasCaller(): + value = fileVal + default: + value = data[key] + } + f.appendKeyValue(b, key, value) + } + } + + b.WriteByte('\n') + return b.Bytes(), nil +} + +func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, data Fields, timestampFormat string) { + var levelColor int + switch entry.Level { + case DebugLevel, TraceLevel: + levelColor = gray + case WarnLevel: + levelColor = yellow + case ErrorLevel, FatalLevel, PanicLevel: + levelColor = red + case InfoLevel: + levelColor = blue + default: + levelColor = blue + } + + levelText := strings.ToUpper(entry.Level.String()) + if !f.DisableLevelTruncation && !f.PadLevelText { + levelText = levelText[0:4] + } + if f.PadLevelText { + // Generates the format string used in the next line, for example "%-6s" or "%-7s". + // Based on the max level text length. + formatString := "%-" + strconv.Itoa(f.levelTextMaxLength) + "s" + // Formats the level text by appending spaces up to the max length, for example: + // - "INFO " + // - "WARNING" + levelText = fmt.Sprintf(formatString, levelText) + } + + // Remove a single newline if it already exists in the message to keep + // the behavior of logrus text_formatter the same as the stdlib log package + entry.Message = strings.TrimSuffix(entry.Message, "\n") + + caller := "" + if entry.HasCaller() { + funcVal := fmt.Sprintf("%s()", entry.Caller.Function) + fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + + if f.CallerPrettyfier != nil { + funcVal, fileVal = f.CallerPrettyfier(entry.Caller) + } + + if fileVal == "" { + caller = funcVal + } else if funcVal == "" { + caller = fileVal + } else { + caller = fileVal + " " + funcVal + } + } + + switch { + case f.DisableTimestamp: + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m%s %-44s ", levelColor, levelText, caller, entry.Message) + case !f.FullTimestamp: + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d]%s %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), caller, entry.Message) + default: + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s]%s %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), caller, entry.Message) + } + for _, k := range keys { + v := data[k] + fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k) + f.appendValue(b, v) + } +} + +func (f *TextFormatter) needsQuoting(text string) bool { + if f.ForceQuote { + return true + } + if f.QuoteEmptyFields && len(text) == 0 { + return true + } + if f.DisableQuote { + return false + } + for _, ch := range text { + if !((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || + ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '@' || ch == '^' || ch == '+') { + return true + } + } + return false +} + +func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) { + if b.Len() > 0 { + b.WriteByte(' ') + } + b.WriteString(key) + b.WriteByte('=') + f.appendValue(b, value) +} + +func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) { + stringVal, ok := value.(string) + if !ok { + stringVal = fmt.Sprint(value) + } + + if !f.needsQuoting(stringVal) { + b.WriteString(stringVal) + } else { + b.WriteString(fmt.Sprintf("%q", stringVal)) + } +} diff --git a/vendor/github.com/sirupsen/logrus/writer.go b/vendor/github.com/sirupsen/logrus/writer.go new file mode 100644 index 0000000000..72e8e3a1b6 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/writer.go @@ -0,0 +1,70 @@ +package logrus + +import ( + "bufio" + "io" + "runtime" +) + +// Writer at INFO level. See WriterLevel for details. +func (logger *Logger) Writer() *io.PipeWriter { + return logger.WriterLevel(InfoLevel) +} + +// WriterLevel returns an io.Writer that can be used to write arbitrary text to +// the logger at the given log level. Each line written to the writer will be +// printed in the usual way using formatters and hooks. The writer is part of an +// io.Pipe and it is the callers responsibility to close the writer when done. +// This can be used to override the standard library logger easily. +func (logger *Logger) WriterLevel(level Level) *io.PipeWriter { + return NewEntry(logger).WriterLevel(level) +} + +func (entry *Entry) Writer() *io.PipeWriter { + return entry.WriterLevel(InfoLevel) +} + +func (entry *Entry) WriterLevel(level Level) *io.PipeWriter { + reader, writer := io.Pipe() + + var printFunc func(args ...interface{}) + + switch level { + case TraceLevel: + printFunc = entry.Trace + case DebugLevel: + printFunc = entry.Debug + case InfoLevel: + printFunc = entry.Info + case WarnLevel: + printFunc = entry.Warn + case ErrorLevel: + printFunc = entry.Error + case FatalLevel: + printFunc = entry.Fatal + case PanicLevel: + printFunc = entry.Panic + default: + printFunc = entry.Print + } + + go entry.writerScanner(reader, printFunc) + runtime.SetFinalizer(writer, writerFinalizer) + + return writer +} + +func (entry *Entry) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) { + scanner := bufio.NewScanner(reader) + for scanner.Scan() { + printFunc(scanner.Text()) + } + if err := scanner.Err(); err != nil { + entry.Errorf("Error while reading from Writer: %s", err) + } + reader.Close() +} + +func writerFinalizer(writer *io.PipeWriter) { + writer.Close() +} diff --git a/vendor/modules.txt b/vendor/modules.txt index c7080623a6..d8bc2b9499 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,7 +1,7 @@ # cloud.google.com/go v0.97.0 ## explicit; go 1.11 cloud.google.com/go/compute/metadata -# github.com/Azure/azure-sdk-for-go v30.0.0+incompatible +# github.com/Azure/azure-sdk-for-go v36.1.0+incompatible ## explicit github.com/Azure/azure-sdk-for-go/profiles/2018-03-01/dns/mgmt/dns github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2016-04-01/dns @@ -20,10 +20,10 @@ github.com/Azure/go-autorest/autorest/adal # github.com/Azure/go-autorest/autorest/date v0.3.0 ## explicit; go 1.12 github.com/Azure/go-autorest/autorest/date -# github.com/Azure/go-autorest/autorest/to v0.2.0 +# github.com/Azure/go-autorest/autorest/to v0.3.1-0.20191028180845-3492b2aff503 ## explicit; go 1.12 github.com/Azure/go-autorest/autorest/to -# github.com/Azure/go-autorest/autorest/validation v0.1.0 +# github.com/Azure/go-autorest/autorest/validation v0.2.1-0.20191028180845-3492b2aff503 ## explicit; go 1.12 github.com/Azure/go-autorest/autorest/validation # github.com/Azure/go-autorest/logger v0.2.1 @@ -108,6 +108,9 @@ github.com/aws/aws-sdk-go/service/sts/stsiface # github.com/beorn7/perks v1.0.1 ## explicit; go 1.11 github.com/beorn7/perks/quantile +# github.com/blang/semver v3.5.1+incompatible +## explicit +github.com/blang/semver # github.com/blang/semver/v4 v4.0.0 ## explicit; go 1.14 github.com/blang/semver/v4 @@ -127,13 +130,13 @@ github.com/evanphx/json-patch # github.com/evanphx/json-patch/v5 v5.6.0 ## explicit; go 1.12 github.com/evanphx/json-patch/v5 -# github.com/fatih/color v1.7.0 -## explicit +# github.com/fatih/color v1.12.0 +## explicit; go 1.13 github.com/fatih/color # github.com/fsnotify/fsnotify v1.6.0 ## explicit; go 1.16 github.com/fsnotify/fsnotify -# github.com/ghodss/yaml v1.0.0 +# github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 ## explicit github.com/ghodss/yaml # github.com/go-logr/logr v1.2.3 @@ -246,11 +249,17 @@ github.com/leodido/go-urn github.com/mailru/easyjson/buffer github.com/mailru/easyjson/jlexer github.com/mailru/easyjson/jwriter -# github.com/mattn/go-colorable v0.1.2 -## explicit +# github.com/maistra/istio-operator v0.0.0-20230213165116-3138f8d64e59 +## explicit; go 1.15 +github.com/maistra/istio-operator/pkg/apis/maistra/status +github.com/maistra/istio-operator/pkg/apis/maistra/v1 +github.com/maistra/istio-operator/pkg/apis/maistra/v2 +github.com/maistra/istio-operator/pkg/version +# github.com/mattn/go-colorable v0.1.8 +## explicit; go 1.13 github.com/mattn/go-colorable -# github.com/mattn/go-isatty v0.0.8 -## explicit +# github.com/mattn/go-isatty v0.0.12 +## explicit; go 1.12 github.com/mattn/go-isatty # github.com/matttproud/golang_protobuf_extensions v1.0.2 ## explicit; go 1.9 @@ -274,7 +283,7 @@ github.com/munnerz/goautoneg # github.com/oklog/ulid v1.3.1 ## explicit github.com/oklog/ulid -# github.com/openshift/api v0.0.0-20230213202419-42edf4f1d905 +# github.com/openshift/api v3.9.1-0.20190924102528-32369d4db2ad+incompatible => github.com/openshift/api v0.0.0-20230213202419-42edf4f1d905 ## explicit; go 1.19 github.com/openshift/api github.com/openshift/api/apiserver @@ -353,7 +362,7 @@ github.com/openshift/client-go/route/applyconfigurations/route/v1 github.com/openshift/client-go/route/clientset/versioned github.com/openshift/client-go/route/clientset/versioned/scheme github.com/openshift/client-go/route/clientset/versioned/typed/route/v1 -# github.com/openshift/library-go v0.0.0-20230120214501-9bc305884fcb +# github.com/openshift/library-go v0.0.0-20230209193239-2e9167362f31 ## explicit; go 1.19 github.com/openshift/library-go/pkg/controller/factory github.com/openshift/library-go/pkg/crypto @@ -366,6 +375,14 @@ github.com/openshift/library-go/pkg/operator/resource/resourcemerge github.com/openshift/library-go/pkg/operator/resource/resourceread github.com/openshift/library-go/pkg/operator/v1helpers github.com/openshift/library-go/test/library/metrics +# github.com/operator-framework/api v0.3.7-0.20200528122852-759ca0d84007 +## explicit; go 1.13 +github.com/operator-framework/api/pkg/lib/version +github.com/operator-framework/api/pkg/operators +github.com/operator-framework/api/pkg/operators/v1alpha1 +# github.com/operator-framework/operator-sdk v0.18.0 +## explicit; go 1.13 +github.com/operator-framework/operator-sdk/version # github.com/pkg/errors v0.9.1 ## explicit github.com/pkg/errors @@ -398,13 +415,16 @@ github.com/prometheus/procfs/internal/util # github.com/robfig/cron v1.2.0 ## explicit github.com/robfig/cron +# github.com/sirupsen/logrus v1.8.1 +## explicit; go 1.13 +github.com/sirupsen/logrus # github.com/spf13/cobra v1.6.0 ## explicit; go 1.15 github.com/spf13/cobra # github.com/spf13/pflag v1.0.5 ## explicit; go 1.12 github.com/spf13/pflag -# github.com/stretchr/testify v1.8.0 +# github.com/stretchr/testify v1.8.1 ## explicit; go 1.13 github.com/stretchr/testify/assert # github.com/summerwind/h2spec v0.0.0-20200804131034-70ac22940108 @@ -768,7 +788,7 @@ k8s.io/apimachinery/third_party/forked/golang/reflect ## explicit; go 1.19 k8s.io/apiserver/pkg/authentication/user k8s.io/apiserver/pkg/storage/names -# k8s.io/client-go v0.26.1 +# k8s.io/client-go v12.0.0+incompatible => k8s.io/client-go v0.26.1 ## explicit; go 1.19 k8s.io/client-go/applyconfigurations/admissionregistration/v1 k8s.io/client-go/applyconfigurations/admissionregistration/v1alpha1 @@ -1066,7 +1086,7 @@ k8s.io/kube-openapi/pkg/schemamutation k8s.io/kube-openapi/pkg/spec3 k8s.io/kube-openapi/pkg/util/proto k8s.io/kube-openapi/pkg/validation/spec -# k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 +# k8s.io/utils v0.0.0-20230209194617-a36077c30491 ## explicit; go 1.18 k8s.io/utils/buffer k8s.io/utils/clock @@ -1080,6 +1100,7 @@ k8s.io/utils/trace # sigs.k8s.io/controller-runtime v0.14.4 ## explicit; go 1.19 sigs.k8s.io/controller-runtime/pkg/cache +sigs.k8s.io/controller-runtime/pkg/cache/informertest sigs.k8s.io/controller-runtime/pkg/cache/internal sigs.k8s.io/controller-runtime/pkg/certwatcher sigs.k8s.io/controller-runtime/pkg/certwatcher/metrics @@ -1091,6 +1112,8 @@ sigs.k8s.io/controller-runtime/pkg/cluster sigs.k8s.io/controller-runtime/pkg/config sigs.k8s.io/controller-runtime/pkg/config/v1alpha1 sigs.k8s.io/controller-runtime/pkg/controller +sigs.k8s.io/controller-runtime/pkg/controller/controllertest +sigs.k8s.io/controller-runtime/pkg/conversion sigs.k8s.io/controller-runtime/pkg/event sigs.k8s.io/controller-runtime/pkg/handler sigs.k8s.io/controller-runtime/pkg/healthz @@ -1117,6 +1140,9 @@ sigs.k8s.io/controller-runtime/pkg/source/internal sigs.k8s.io/controller-runtime/pkg/webhook sigs.k8s.io/controller-runtime/pkg/webhook/admission sigs.k8s.io/controller-runtime/pkg/webhook/internal/metrics +# sigs.k8s.io/gateway-api v0.5.1-0.20220921185115-ee7a83814203 +## explicit; go 1.18 +sigs.k8s.io/gateway-api/apis/v1beta1 # sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 ## explicit; go 1.18 sigs.k8s.io/json @@ -1136,3 +1162,6 @@ sigs.k8s.io/structured-merge-diff/v4/value # sigs.k8s.io/yaml v1.3.0 ## explicit; go 1.12 sigs.k8s.io/yaml +# bitbucket.org/ww/goautoneg => github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d +# github.com/openshift/api => github.com/openshift/api v0.0.0-20230213202419-42edf4f1d905 +# k8s.io/client-go => k8s.io/client-go v0.26.1 diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/cache/informertest/fake_cache.go b/vendor/sigs.k8s.io/controller-runtime/pkg/cache/informertest/fake_cache.go new file mode 100644 index 0000000000..da3bf8e0d4 --- /dev/null +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/cache/informertest/fake_cache.go @@ -0,0 +1,141 @@ +/* +Copyright 2018 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 informertest + +import ( + "context" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/kubernetes/scheme" + toolscache "k8s.io/client-go/tools/cache" + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllertest" +) + +var _ cache.Cache = &FakeInformers{} + +// FakeInformers is a fake implementation of Informers. +type FakeInformers struct { + InformersByGVK map[schema.GroupVersionKind]toolscache.SharedIndexInformer + Scheme *runtime.Scheme + Error error + Synced *bool +} + +// GetInformerForKind implements Informers. +func (c *FakeInformers) GetInformerForKind(ctx context.Context, gvk schema.GroupVersionKind) (cache.Informer, error) { + if c.Scheme == nil { + c.Scheme = scheme.Scheme + } + obj, err := c.Scheme.New(gvk) + if err != nil { + return nil, err + } + return c.informerFor(gvk, obj) +} + +// FakeInformerForKind implements Informers. +func (c *FakeInformers) FakeInformerForKind(ctx context.Context, gvk schema.GroupVersionKind) (*controllertest.FakeInformer, error) { + if c.Scheme == nil { + c.Scheme = scheme.Scheme + } + obj, err := c.Scheme.New(gvk) + if err != nil { + return nil, err + } + i, err := c.informerFor(gvk, obj) + if err != nil { + return nil, err + } + return i.(*controllertest.FakeInformer), nil +} + +// GetInformer implements Informers. +func (c *FakeInformers) GetInformer(ctx context.Context, obj client.Object) (cache.Informer, error) { + if c.Scheme == nil { + c.Scheme = scheme.Scheme + } + gvks, _, err := c.Scheme.ObjectKinds(obj) + if err != nil { + return nil, err + } + gvk := gvks[0] + return c.informerFor(gvk, obj) +} + +// WaitForCacheSync implements Informers. +func (c *FakeInformers) WaitForCacheSync(ctx context.Context) bool { + if c.Synced == nil { + return true + } + return *c.Synced +} + +// FakeInformerFor implements Informers. +func (c *FakeInformers) FakeInformerFor(obj runtime.Object) (*controllertest.FakeInformer, error) { + if c.Scheme == nil { + c.Scheme = scheme.Scheme + } + gvks, _, err := c.Scheme.ObjectKinds(obj) + if err != nil { + return nil, err + } + gvk := gvks[0] + i, err := c.informerFor(gvk, obj) + if err != nil { + return nil, err + } + return i.(*controllertest.FakeInformer), nil +} + +func (c *FakeInformers) informerFor(gvk schema.GroupVersionKind, _ runtime.Object) (toolscache.SharedIndexInformer, error) { + if c.Error != nil { + return nil, c.Error + } + if c.InformersByGVK == nil { + c.InformersByGVK = map[schema.GroupVersionKind]toolscache.SharedIndexInformer{} + } + informer, ok := c.InformersByGVK[gvk] + if ok { + return informer, nil + } + + c.InformersByGVK[gvk] = &controllertest.FakeInformer{} + return c.InformersByGVK[gvk], nil +} + +// Start implements Informers. +func (c *FakeInformers) Start(ctx context.Context) error { + return c.Error +} + +// IndexField implements Cache. +func (c *FakeInformers) IndexField(ctx context.Context, obj client.Object, field string, extractValue client.IndexerFunc) error { + return nil +} + +// Get implements Cache. +func (c *FakeInformers) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error { + return nil +} + +// List implements Cache. +func (c *FakeInformers) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { + return nil +} diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/controller/controllertest/doc.go b/vendor/sigs.k8s.io/controller-runtime/pkg/controller/controllertest/doc.go new file mode 100644 index 0000000000..91c5a3e35e --- /dev/null +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/controller/controllertest/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2017 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 controllertest contains fake informers for testing controllers +// When in doubt, it's almost always better to test against a real API server +// using envtest.Environment. +package controllertest diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/controller/controllertest/testing.go b/vendor/sigs.k8s.io/controller-runtime/pkg/controller/controllertest/testing.go new file mode 100644 index 0000000000..b9f97d5289 --- /dev/null +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/controller/controllertest/testing.go @@ -0,0 +1,62 @@ +/* +Copyright 2018 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 controllertest + +import ( + "time" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/util/workqueue" +) + +var _ runtime.Object = &ErrorType{} + +// ErrorType implements runtime.Object but isn't registered in any scheme and should cause errors in tests as a result. +type ErrorType struct{} + +// GetObjectKind implements runtime.Object. +func (ErrorType) GetObjectKind() schema.ObjectKind { return nil } + +// DeepCopyObject implements runtime.Object. +func (ErrorType) DeepCopyObject() runtime.Object { return nil } + +var _ workqueue.RateLimitingInterface = Queue{} + +// Queue implements a RateLimiting queue as a non-ratelimited queue for testing. +// This helps testing by having functions that use a RateLimiting queue synchronously add items to the queue. +type Queue struct { + workqueue.Interface +} + +// AddAfter implements RateLimitingInterface. +func (q Queue) AddAfter(item interface{}, duration time.Duration) { + q.Add(item) +} + +// AddRateLimited implements RateLimitingInterface. TODO(community): Implement this. +func (q Queue) AddRateLimited(item interface{}) { + q.Add(item) +} + +// Forget implements RateLimitingInterface. TODO(community): Implement this. +func (q Queue) Forget(item interface{}) {} + +// NumRequeues implements RateLimitingInterface. TODO(community): Implement this. +func (q Queue) NumRequeues(item interface{}) int { + return 0 +} diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/controller/controllertest/unconventionallisttypecrd.go b/vendor/sigs.k8s.io/controller-runtime/pkg/controller/controllertest/unconventionallisttypecrd.go new file mode 100644 index 0000000000..d0f5017154 --- /dev/null +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/controller/controllertest/unconventionallisttypecrd.go @@ -0,0 +1,76 @@ +/* +Copyright 2021 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 controllertest + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +var _ runtime.Object = &UnconventionalListType{} +var _ runtime.Object = &UnconventionalListTypeList{} + +// UnconventionalListType is used to test CRDs with List types that +// have a slice of pointers rather than a slice of literals. +type UnconventionalListType struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec string `json:"spec,omitempty"` +} + +// DeepCopyObject implements runtime.Object +// Handwritten for simplicity. +func (u *UnconventionalListType) DeepCopyObject() runtime.Object { + return u.DeepCopy() +} + +// DeepCopy implements *UnconventionalListType +// Handwritten for simplicity. +func (u *UnconventionalListType) DeepCopy() *UnconventionalListType { + return &UnconventionalListType{ + TypeMeta: u.TypeMeta, + ObjectMeta: *u.ObjectMeta.DeepCopy(), + Spec: u.Spec, + } +} + +// UnconventionalListTypeList is used to test CRDs with List types that +// have a slice of pointers rather than a slice of literals. +type UnconventionalListTypeList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []*UnconventionalListType `json:"items"` +} + +// DeepCopyObject implements runtime.Object +// Handwritten for simplicity. +func (u *UnconventionalListTypeList) DeepCopyObject() runtime.Object { + return u.DeepCopy() +} + +// DeepCopy implements *UnconventionalListTypeListt +// Handwritten for simplicity. +func (u *UnconventionalListTypeList) DeepCopy() *UnconventionalListTypeList { + out := &UnconventionalListTypeList{ + TypeMeta: u.TypeMeta, + ListMeta: *u.ListMeta.DeepCopy(), + } + for _, item := range u.Items { + out.Items = append(out.Items, item.DeepCopy()) + } + return out +} diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/controller/controllertest/util.go b/vendor/sigs.k8s.io/controller-runtime/pkg/controller/controllertest/util.go new file mode 100644 index 0000000000..17641e9c02 --- /dev/null +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/controller/controllertest/util.go @@ -0,0 +1,129 @@ +/* +Copyright 2017 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 controllertest + +import ( + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/cache" +) + +var _ cache.SharedIndexInformer = &FakeInformer{} + +// FakeInformer provides fake Informer functionality for testing. +type FakeInformer struct { + // Synced is returned by the HasSynced functions to implement the Informer interface + Synced bool + + // RunCount is incremented each time RunInformersAndControllers is called + RunCount int + + handlers []cache.ResourceEventHandler +} + +// AddIndexers does nothing. TODO(community): Implement this. +func (f *FakeInformer) AddIndexers(indexers cache.Indexers) error { + return nil +} + +// GetIndexer does nothing. TODO(community): Implement this. +func (f *FakeInformer) GetIndexer() cache.Indexer { + return nil +} + +// Informer returns the fake Informer. +func (f *FakeInformer) Informer() cache.SharedIndexInformer { + return f +} + +// HasSynced implements the Informer interface. Returns f.Synced. +func (f *FakeInformer) HasSynced() bool { + return f.Synced +} + +// AddEventHandler implements the Informer interface. Adds an EventHandler to the fake Informers. TODO(community): Implement Registration. +func (f *FakeInformer) AddEventHandler(handler cache.ResourceEventHandler) (cache.ResourceEventHandlerRegistration, error) { + f.handlers = append(f.handlers, handler) + return nil, nil +} + +// Run implements the Informer interface. Increments f.RunCount. +func (f *FakeInformer) Run(<-chan struct{}) { + f.RunCount++ +} + +// Add fakes an Add event for obj. +func (f *FakeInformer) Add(obj metav1.Object) { + for _, h := range f.handlers { + h.OnAdd(obj) + } +} + +// Update fakes an Update event for obj. +func (f *FakeInformer) Update(oldObj, newObj metav1.Object) { + for _, h := range f.handlers { + h.OnUpdate(oldObj, newObj) + } +} + +// Delete fakes an Delete event for obj. +func (f *FakeInformer) Delete(obj metav1.Object) { + for _, h := range f.handlers { + h.OnDelete(obj) + } +} + +// AddEventHandlerWithResyncPeriod does nothing. TODO(community): Implement this. +func (f *FakeInformer) AddEventHandlerWithResyncPeriod(handler cache.ResourceEventHandler, resyncPeriod time.Duration) (cache.ResourceEventHandlerRegistration, error) { + return nil, nil +} + +// RemoveEventHandler does nothing. TODO(community): Implement this. +func (f *FakeInformer) RemoveEventHandler(handle cache.ResourceEventHandlerRegistration) error { + return nil +} + +// GetStore does nothing. TODO(community): Implement this. +func (f *FakeInformer) GetStore() cache.Store { + return nil +} + +// GetController does nothing. TODO(community): Implement this. +func (f *FakeInformer) GetController() cache.Controller { + return nil +} + +// LastSyncResourceVersion does nothing. TODO(community): Implement this. +func (f *FakeInformer) LastSyncResourceVersion() string { + return "" +} + +// SetWatchErrorHandler does nothing. TODO(community): Implement this. +func (f *FakeInformer) SetWatchErrorHandler(cache.WatchErrorHandler) error { + return nil +} + +// SetTransform does nothing. TODO(community): Implement this. +func (f *FakeInformer) SetTransform(t cache.TransformFunc) error { + return nil +} + +// IsStopped does nothing. TODO(community): Implement this. +func (f *FakeInformer) IsStopped() bool { + return false +} diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/conversion/conversion.go b/vendor/sigs.k8s.io/controller-runtime/pkg/conversion/conversion.go new file mode 100644 index 0000000000..da32ab48e4 --- /dev/null +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/conversion/conversion.go @@ -0,0 +1,40 @@ +/* +Copyright 2019 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 conversion provides interface definitions that an API Type needs to +implement for it to be supported by the generic conversion webhook handler +defined under pkg/webhook/conversion. +*/ +package conversion + +import "k8s.io/apimachinery/pkg/runtime" + +// Convertible defines capability of a type to convertible i.e. it can be converted to/from a hub type. +type Convertible interface { + runtime.Object + ConvertTo(dst Hub) error + ConvertFrom(src Hub) error +} + +// Hub marks that a given type is the hub type for conversion. This means that +// all conversions will first convert to the hub type, then convert from the hub +// type to the destination type. All types besides the hub type should implement +// Convertible. +type Hub interface { + runtime.Object + Hub() +} diff --git a/vendor/sigs.k8s.io/gateway-api/LICENSE b/vendor/sigs.k8s.io/gateway-api/LICENSE new file mode 100644 index 0000000000..a5949bd7a2 --- /dev/null +++ b/vendor/sigs.k8s.io/gateway-api/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 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. diff --git a/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/doc.go b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/doc.go new file mode 100644 index 0000000000..d29a3c14a2 --- /dev/null +++ b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2020 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 v1beta1 contains API Schema definitions for the +// gateway.networking.k8s.io API group. +// +kubebuilder:object:generate=true +// +groupName=gateway.networking.k8s.io +package v1beta1 diff --git a/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/gateway_types.go b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/gateway_types.go new file mode 100644 index 0000000000..3ff65f0f70 --- /dev/null +++ b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/gateway_types.go @@ -0,0 +1,794 @@ +/* +Copyright 2020 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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories=gateway-api,shortName=gtw +// +kubebuilder:storageversion +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Class",type=string,JSONPath=`.spec.gatewayClassName` +// +kubebuilder:printcolumn:name="Address",type=string,JSONPath=`.status.addresses[*].value` +// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` + +// Gateway represents an instance of a service-traffic handling infrastructure +// by binding Listeners to a set of IP addresses. +type Gateway struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of Gateway. + Spec GatewaySpec `json:"spec"` + + // Status defines the current state of Gateway. + // + // +kubebuilder:default={conditions: {{type: "Scheduled", status: "Unknown", reason:"NotReconciled", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}} + Status GatewayStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// GatewayList contains a list of Gateways. +type GatewayList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Gateway `json:"items"` +} + +// GatewaySpec defines the desired state of Gateway. +// +// Not all possible combinations of options specified in the Spec are +// valid. Some invalid configurations can be caught synchronously via a +// webhook, but there are many cases that will require asynchronous +// signaling via the GatewayStatus block. +type GatewaySpec struct { + // GatewayClassName used for this Gateway. This is the name of a + // GatewayClass resource. + GatewayClassName ObjectName `json:"gatewayClassName"` + + // Listeners associated with this Gateway. Listeners define + // logical endpoints that are bound on this Gateway's addresses. + // At least one Listener MUST be specified. + // + // Each listener in a Gateway must have a unique combination of Hostname, + // Port, and Protocol. + // + // An implementation MAY group Listeners by Port and then collapse each + // group of Listeners into a single Listener if the implementation + // determines that the Listeners in the group are "compatible". An + // implementation MAY also group together and collapse compatible + // Listeners belonging to different Gateways. + // + // For example, an implementation might consider Listeners to be + // compatible with each other if all of the following conditions are + // met: + // + // 1. Either each Listener within the group specifies the "HTTP" + // Protocol or each Listener within the group specifies either + // the "HTTPS" or "TLS" Protocol. + // + // 2. Each Listener within the group specifies a Hostname that is unique + // within the group. + // + // 3. As a special case, one Listener within a group may omit Hostname, + // in which case this Listener matches when no other Listener + // matches. + // + // If the implementation does collapse compatible Listeners, the + // hostname provided in the incoming client request MUST be + // matched to a Listener to find the correct set of Routes. + // The incoming hostname MUST be matched using the Hostname + // field for each Listener in order of most to least specific. + // That is, exact matches must be processed before wildcard + // matches. + // + // If this field specifies multiple Listeners that have the same + // Port value but are not compatible, the implementation must raise + // a "Conflicted" condition in the Listener status. + // + // Support: Core + // + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=64 + Listeners []Listener `json:"listeners"` + + // Addresses requested for this Gateway. This is optional and behavior can + // depend on the implementation. If a value is set in the spec and the + // requested address is invalid or unavailable, the implementation MUST + // indicate this in the associated entry in GatewayStatus.Addresses. + // + // The Addresses field represents a request for the address(es) on the + // "outside of the Gateway", that traffic bound for this Gateway will use. + // This could be the IP address or hostname of an external load balancer or + // other networking infrastructure, or some other address that traffic will + // be sent to. + // + // The .listener.hostname field is used to route traffic that has already + // arrived at the Gateway to the correct in-cluster destination. + // + // If no Addresses are specified, the implementation MAY schedule the + // Gateway in an implementation-specific manner, assigning an appropriate + // set of Addresses. + // + // The implementation MUST bind all Listeners to every GatewayAddress that + // it assigns to the Gateway and add a corresponding entry in + // GatewayStatus.Addresses. + // + // Support: Extended + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Addresses []GatewayAddress `json:"addresses,omitempty"` +} + +// Listener embodies the concept of a logical endpoint where a Gateway accepts +// network connections. +type Listener struct { + // Name is the name of the Listener. This name MUST be unique within a + // Gateway. + // + // Support: Core + Name SectionName `json:"name"` + + // Hostname specifies the virtual hostname to match for protocol types that + // define this concept. When unspecified, all hostnames are matched. This + // field is ignored for protocols that don't require hostname based + // matching. + // + // Implementations MUST apply Hostname matching appropriately for each of + // the following protocols: + // + // * TLS: The Listener Hostname MUST match the SNI. + // * HTTP: The Listener Hostname MUST match the Host header of the request. + // * HTTPS: The Listener Hostname SHOULD match at both the TLS and HTTP + // protocol layers as described above. If an implementation does not + // ensure that both the SNI and Host header match the Listener hostname, + // it MUST clearly document that. + // + // For HTTPRoute and TLSRoute resources, there is an interaction with the + // `spec.hostnames` array. When both listener and route specify hostnames, + // there MUST be an intersection between the values for a Route to be + // accepted. For more information, refer to the Route specific Hostnames + // documentation. + // + // Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + // as a suffix match. That means that a match for `*.example.com` would match + // both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + // + // Support: Core + // + // +optional + Hostname *Hostname `json:"hostname,omitempty"` + + // Port is the network port. Multiple listeners may use the + // same port, subject to the Listener compatibility rules. + // + // Support: Core + Port PortNumber `json:"port"` + + // Protocol specifies the network protocol this listener expects to receive. + // + // Support: Core + Protocol ProtocolType `json:"protocol"` + + // TLS is the TLS configuration for the Listener. This field is required if + // the Protocol field is "HTTPS" or "TLS". It is invalid to set this field + // if the Protocol field is "HTTP", "TCP", or "UDP". + // + // The association of SNIs to Certificate defined in GatewayTLSConfig is + // defined based on the Hostname field for this listener. + // + // The GatewayClass MUST use the longest matching SNI out of all + // available certificates for any TLS handshake. + // + // Support: Core + // + // +optional + TLS *GatewayTLSConfig `json:"tls,omitempty"` + + // AllowedRoutes defines the types of routes that MAY be attached to a + // Listener and the trusted namespaces where those Route resources MAY be + // present. + // + // Although a client request may match multiple route rules, only one rule + // may ultimately receive the request. Matching precedence MUST be + // determined in order of the following criteria: + // + // * The most specific match as defined by the Route type. + // * The oldest Route based on creation timestamp. For example, a Route with + // a creation timestamp of "2020-09-08 01:02:03" is given precedence over + // a Route with a creation timestamp of "2020-09-08 01:02:04". + // * If everything else is equivalent, the Route appearing first in + // alphabetical order (namespace/name) should be given precedence. For + // example, foo/bar is given precedence over foo/baz. + // + // All valid rules within a Route attached to this Listener should be + // implemented. Invalid Route rules can be ignored (sometimes that will mean + // the full Route). If a Route rule transitions from valid to invalid, + // support for that Route rule should be dropped to ensure consistency. For + // example, even if a filter specified by a Route rule is invalid, the rest + // of the rules within that Route should still be supported. + // + // Support: Core + // +kubebuilder:default={namespaces:{from: Same}} + // +optional + AllowedRoutes *AllowedRoutes `json:"allowedRoutes,omitempty"` +} + +// ProtocolType defines the application protocol accepted by a Listener. +// Implementations are not required to accept all the defined protocols. +// If an implementation does not support a specified protocol, it +// should raise a "Detached" condition for the affected Listener with +// a reason of "UnsupportedProtocol". +// +// Core ProtocolType values are listed in the table below. +// +// Implementations can define their own protocols if a core ProtocolType does not +// exist. Such definitions must use prefixed name, such as +// `mycompany.com/my-custom-protocol`. Un-prefixed names are reserved for core +// protocols. Any protocol defined by implementations will fall under custom +// conformance. +// +// Valid values include: +// +// * "HTTP" - Core support +// * "example.com/bar" - Implementation-specific support +// +// Invalid values include: +// +// * "example.com" - must include path if domain is used +// * "foo.example.com" - must include path if domain is used +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=255 +// +kubebuilder:validation:Pattern=`^[a-zA-Z0-9]([-a-zSA-Z0-9]*[a-zA-Z0-9])?$|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9]+$` +type ProtocolType string + +const ( + // Accepts cleartext HTTP/1.1 sessions over TCP. Implementations MAY also + // support HTTP/2 over cleartext. If implementations support HTTP/2 over + // cleartext on "HTTP" listeners, that MUST be clearly documented by the + // implementation. + HTTPProtocolType ProtocolType = "HTTP" + + // Accepts HTTP/1.1 or HTTP/2 sessions over TLS. + HTTPSProtocolType ProtocolType = "HTTPS" + + // Accepts TLS sessions over TCP. + TLSProtocolType ProtocolType = "TLS" + + // Accepts TCP sessions. + TCPProtocolType ProtocolType = "TCP" + + // Accepts UDP packets. + UDPProtocolType ProtocolType = "UDP" +) + +// GatewayTLSConfig describes a TLS configuration. +type GatewayTLSConfig struct { + // Mode defines the TLS behavior for the TLS session initiated by the client. + // There are two possible modes: + // + // - Terminate: The TLS session between the downstream client + // and the Gateway is terminated at the Gateway. This mode requires + // certificateRefs to be set and contain at least one element. + // - Passthrough: The TLS session is NOT terminated by the Gateway. This + // implies that the Gateway can't decipher the TLS stream except for + // the ClientHello message of the TLS protocol. + // CertificateRefs field is ignored in this mode. + // + // Support: Core + // + // +optional + // +kubebuilder:default=Terminate + Mode *TLSModeType `json:"mode,omitempty"` + + // CertificateRefs contains a series of references to Kubernetes objects that + // contains TLS certificates and private keys. These certificates are used to + // establish a TLS handshake for requests that match the hostname of the + // associated listener. + // + // A single CertificateRef to a Kubernetes Secret has "Core" support. + // Implementations MAY choose to support attaching multiple certificates to + // a Listener, but this behavior is implementation-specific. + // + // References to a resource in different namespace are invalid UNLESS there + // is a ReferenceGrant in the target namespace that allows the certificate + // to be attached. If a ReferenceGrant does not allow this reference, the + // "ResolvedRefs" condition MUST be set to False for this listener with the + // "InvalidCertificateRef" reason. + // + // This field is required to have at least one element when the mode is set + // to "Terminate" (default) and is optional otherwise. + // + // CertificateRefs can reference to standard Kubernetes resources, i.e. + // Secret, or implementation-specific custom resources. + // + // Support: Core - A single reference to a Kubernetes Secret of type kubernetes.io/tls + // + // Support: Implementation-specific (More than one reference or other resource types) + // + // +optional + // +kubebuilder:validation:MaxItems=64 + CertificateRefs []SecretObjectReference `json:"certificateRefs,omitempty"` + + // Options are a list of key/value pairs to enable extended TLS + // configuration for each implementation. For example, configuring the + // minimum TLS version or supported cipher suites. + // + // A set of common keys MAY be defined by the API in the future. To avoid + // any ambiguity, implementation-specific definitions MUST use + // domain-prefixed names, such as `example.com/my-custom-option`. + // Un-prefixed names are reserved for key names defined by Gateway API. + // + // Support: Implementation-specific + // + // +optional + // +kubebuilder:validation:MaxProperties=16 + Options map[AnnotationKey]AnnotationValue `json:"options,omitempty"` +} + +// TLSModeType type defines how a Gateway handles TLS sessions. +// +// +kubebuilder:validation:Enum=Terminate;Passthrough +type TLSModeType string + +const ( + // In this mode, TLS session between the downstream client + // and the Gateway is terminated at the Gateway. + TLSModeTerminate TLSModeType = "Terminate" + + // In this mode, the TLS session is NOT terminated by the Gateway. This + // implies that the Gateway can't decipher the TLS stream except for + // the ClientHello message of the TLS protocol. + // + // Note that SSL passthrough is only supported by TLSRoute. + TLSModePassthrough TLSModeType = "Passthrough" +) + +// AllowedRoutes defines which Routes may be attached to this Listener. +type AllowedRoutes struct { + // Namespaces indicates namespaces from which Routes may be attached to this + // Listener. This is restricted to the namespace of this Gateway by default. + // + // Support: Core + // + // +optional + // +kubebuilder:default={from: Same} + Namespaces *RouteNamespaces `json:"namespaces,omitempty"` + + // Kinds specifies the groups and kinds of Routes that are allowed to bind + // to this Gateway Listener. When unspecified or empty, the kinds of Routes + // selected are determined using the Listener protocol. + // + // A RouteGroupKind MUST correspond to kinds of Routes that are compatible + // with the application protocol specified in the Listener's Protocol field. + // If an implementation does not support or recognize this resource type, it + // MUST set the "ResolvedRefs" condition to False for this Listener with the + // "InvalidRouteKinds" reason. + // + // Support: Core + // + // +optional + // +kubebuilder:validation:MaxItems=8 + Kinds []RouteGroupKind `json:"kinds,omitempty"` +} + +// FromNamespaces specifies namespace from which Routes may be attached to a +// Gateway. +// +// +kubebuilder:validation:Enum=All;Selector;Same +type FromNamespaces string + +const ( + // Routes in all namespaces may be attached to this Gateway. + NamespacesFromAll FromNamespaces = "All" + // Only Routes in namespaces selected by the selector may be attached to + // this Gateway. + NamespacesFromSelector FromNamespaces = "Selector" + // Only Routes in the same namespace as the Gateway may be attached to this + // Gateway. + NamespacesFromSame FromNamespaces = "Same" +) + +// RouteNamespaces indicate which namespaces Routes should be selected from. +type RouteNamespaces struct { + // From indicates where Routes will be selected for this Gateway. Possible + // values are: + // * All: Routes in all namespaces may be used by this Gateway. + // * Selector: Routes in namespaces selected by the selector may be used by + // this Gateway. + // * Same: Only Routes in the same namespace may be used by this Gateway. + // + // Support: Core + // + // +optional + // +kubebuilder:default=Same + From *FromNamespaces `json:"from,omitempty"` + + // Selector must be specified when From is set to "Selector". In that case, + // only Routes in Namespaces matching this Selector will be selected by this + // Gateway. This field is ignored for other values of "From". + // + // Support: Core + // + // +optional + Selector *metav1.LabelSelector `json:"selector,omitempty"` +} + +// RouteGroupKind indicates the group and kind of a Route resource. +type RouteGroupKind struct { + // Group is the group of the Route. + // + // +optional + // +kubebuilder:default=gateway.networking.k8s.io + Group *Group `json:"group,omitempty"` + + // Kind is the kind of the Route. + Kind Kind `json:"kind"` +} + +// GatewayAddress describes an address that can be bound to a Gateway. +type GatewayAddress struct { + // Type of the address. + // + // +optional + // +kubebuilder:default=IPAddress + Type *AddressType `json:"type,omitempty"` + + // Value of the address. The validity of the values will depend + // on the type and support by the controller. + // + // Examples: `1.2.3.4`, `128::1`, `my-ip-address`. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Value string `json:"value"` +} + +// GatewayStatus defines the observed state of Gateway. +type GatewayStatus struct { + // Addresses lists the IP addresses that have actually been + // bound to the Gateway. These addresses may differ from the + // addresses in the Spec, e.g. if the Gateway automatically + // assigns an address from a reserved pool. + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Addresses []GatewayAddress `json:"addresses,omitempty"` + + // Conditions describe the current conditions of the Gateway. + // + // Implementations should prefer to express Gateway conditions + // using the `GatewayConditionType` and `GatewayConditionReason` + // constants so that operators and tools can converge on a common + // vocabulary to describe Gateway state. + // + // Known condition types are: + // + // * "Scheduled" + // * "Ready" + // + // +optional + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:default={{type: "Scheduled", status: "Unknown", reason:"NotReconciled", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}} + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // Listeners provide status for each unique listener port defined in the Spec. + // + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=64 + Listeners []ListenerStatus `json:"listeners,omitempty"` +} + +// GatewayConditionType is a type of condition associated with a +// Gateway. This type should be used with the GatewayStatus.Conditions +// field. +type GatewayConditionType string + +// GatewayConditionReason defines the set of reasons that explain why a +// particular Gateway condition type has been raised. +type GatewayConditionReason string + +const ( + // This condition is true when the controller managing the + // Gateway has scheduled the Gateway to the underlying network + // infrastructure. + // + // Possible reasons for this condition to be true are: + // + // * "Scheduled" + // + // Possible reasons for this condition to be False are: + // + // * "NotReconciled" + // * "NoResources" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + GatewayConditionScheduled GatewayConditionType = "Scheduled" + + // This reason is used with the "Scheduled" condition when the condition is + // true. + GatewayReasonScheduled GatewayConditionReason = "Scheduled" + + // This reason is used with the "Scheduled" condition when no controller has + // reconciled the Gateway. + GatewayReasonNotReconciled GatewayConditionReason = "NotReconciled" + + // This reason is used with the "Scheduled" condition when the + // Gateway is not scheduled because insufficient infrastructure + // resources are available. + GatewayReasonNoResources GatewayConditionReason = "NoResources" +) + +const ( + // This condition is true when the Gateway is expected to be able + // to serve traffic. Note that this does not indicate that the + // Gateway configuration is current or even complete (e.g. the + // controller may still not have reconciled the latest version, + // or some parts of the configuration could be missing). + // + // If both the "ListenersNotValid" and "ListenersNotReady" + // reasons are true, the Gateway controller should prefer the + // "ListenersNotValid" reason. + // + // Possible reasons for this condition to be true are: + // + // * "Ready" + // + // Possible reasons for this condition to be False are: + // + // * "ListenersNotValid" + // * "ListenersNotReady" + // * "AddressNotAssigned" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + GatewayConditionReady GatewayConditionType = "Ready" + + // This reason is used with the "Ready" condition when the condition is + // true. + GatewayReasonReady GatewayConditionReason = "Ready" + + // This reason is used with the "Ready" condition when one or + // more Listeners have an invalid or unsupported configuration + // and cannot be configured on the Gateway. + GatewayReasonListenersNotValid GatewayConditionReason = "ListenersNotValid" + + // This reason is used with the "Ready" condition when one or + // more Listeners are not ready to serve traffic. + GatewayReasonListenersNotReady GatewayConditionReason = "ListenersNotReady" + + // This reason is used with the "Ready" condition when none of the requested + // addresses have been assigned to the Gateway. This reason can be used to + // express a range of circumstances, including (but not limited to) IPAM + // address exhaustion, invalid or unsupported address requests, or a named + // address not being found. + GatewayReasonAddressNotAssigned GatewayConditionReason = "AddressNotAssigned" +) + +// ListenerStatus is the status associated with a Listener. +type ListenerStatus struct { + // Name is the name of the Listener that this status corresponds to. + Name SectionName `json:"name"` + + // SupportedKinds is the list indicating the Kinds supported by this + // listener. This MUST represent the kinds an implementation supports for + // that Listener configuration. + // + // If kinds are specified in Spec that are not supported, they MUST NOT + // appear in this list and an implementation MUST set the "ResolvedRefs" + // condition to "False" with the "InvalidRouteKinds" reason. If both valid + // and invalid Route kinds are specified, the implementation MUST + // reference the valid Route kinds that have been specified. + // + // +kubebuilder:validation:MaxItems=8 + SupportedKinds []RouteGroupKind `json:"supportedKinds"` + + // AttachedRoutes represents the total number of Routes that have been + // successfully attached to this Listener. + AttachedRoutes int32 `json:"attachedRoutes"` + + // Conditions describe the current condition of this listener. + // + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions"` +} + +// ListenerConditionType is a type of condition associated with the +// listener. This type should be used with the ListenerStatus.Conditions +// field. +type ListenerConditionType string + +// ListenerConditionReason defines the set of reasons that explain +// why a particular Listener condition type has been raised. +type ListenerConditionReason string + +const ( + // This condition indicates that the controller was unable to resolve + // conflicting specification requirements for this Listener. If a + // Listener is conflicted, its network port should not be configured + // on any network elements. + // + // Possible reasons for this condition to be true are: + // + // * "HostnameConflict" + // * "ProtocolConflict" + // + // Possible reasons for this condition to be False are: + // + // * "NoConflicts" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + ListenerConditionConflicted ListenerConditionType = "Conflicted" + + // This reason is used with the "Conflicted" condition when + // the Listener conflicts with hostnames in other Listeners. For + // example, this reason would be used when multiple Listeners on + // the same port use `example.com` in the hostname field. + ListenerReasonHostnameConflict ListenerConditionReason = "HostnameConflict" + + // This reason is used with the "Conflicted" condition when + // multiple Listeners are specified with the same Listener port + // number, but have conflicting protocol specifications. + ListenerReasonProtocolConflict ListenerConditionReason = "ProtocolConflict" + + // This reason is used with the "Conflicted" condition when the condition + // is False. + ListenerReasonNoConflicts ListenerConditionReason = "NoConflicts" +) + +const ( + // This condition indicates that, even though the listener is + // syntactically and semantically valid, the controller is not able + // to configure it on the underlying Gateway infrastructure. + // + // A Listener is specified as a logical requirement, but needs to be + // configured on a network endpoint (i.e. address and port) by a + // controller. The controller may be unable to attach the Listener + // if it specifies an unsupported requirement, or prerequisite + // resources are not available. + // + // Possible reasons for this condition to be true are: + // + // * "PortUnavailable" + // * "UnsupportedProtocol" + // * "UnsupportedAddress" + // + // Possible reasons for this condition to be False are: + // + // * "Attached" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + ListenerConditionDetached ListenerConditionType = "Detached" + + // This reason is used with the "Detached" condition when the Listener + // requests a port that cannot be used on the Gateway. This reason could be + // used in a number of instances, including: + // + // * The port is already in use. + // * The port is not supported by the implementation. + ListenerReasonPortUnavailable ListenerConditionReason = "PortUnavailable" + + // This reason is used with the "Detached" condition when the + // Listener could not be attached to be Gateway because its + // protocol type is not supported. + ListenerReasonUnsupportedProtocol ListenerConditionReason = "UnsupportedProtocol" + + // This reason is used with the "Detached" condition when the Listener could + // not be attached to the Gateway because the requested address is not + // supported. This reason could be used in a number of instances, including: + // + // * The address is already in use. + // * The type of address is not supported by the implementation. + ListenerReasonUnsupportedAddress ListenerConditionReason = "UnsupportedAddress" + + // This reason is used with the "Detached" condition when the condition is + // False. + ListenerReasonAttached ListenerConditionReason = "Attached" +) + +const ( + // This condition indicates whether the controller was able to + // resolve all the object references for the Listener. + // + // Possible reasons for this condition to be true are: + // + // * "ResolvedRefs" + // + // Possible reasons for this condition to be False are: + // + // * "InvalidCertificateRef" + // * "InvalidRouteKinds" + // * "RefNotPermitted" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + ListenerConditionResolvedRefs ListenerConditionType = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when the condition + // is true. + ListenerReasonResolvedRefs ListenerConditionReason = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when the + // Listener has a TLS configuration with at least one TLS CertificateRef + // that is invalid or cannot be resolved. + ListenerReasonInvalidCertificateRef ListenerConditionReason = "InvalidCertificateRef" + + // This reason is used with the "ResolvedRefs" condition when an invalid or + // unsupported Route kind is specified by the Listener. + ListenerReasonInvalidRouteKinds ListenerConditionReason = "InvalidRouteKinds" + + // This reason is used with the "ResolvedRefs" condition when + // one of the Listener's Routes has a BackendRef to an object in + // another namespace, where the object in the other namespace does + // not have a ReferenceGrant explicitly allowing the reference. + ListenerReasonRefNotPermitted ListenerConditionReason = "RefNotPermitted" +) + +const ( + // This condition indicates whether the Listener has been + // configured on the Gateway. + // + // Possible reasons for this condition to be true are: + // + // * "Ready" + // + // Possible reasons for this condition to be False are: + // + // * "Invalid" + // * "Pending" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + ListenerConditionReady ListenerConditionType = "Ready" + + // This reason is used with the "Ready" condition when the condition is + // true. + ListenerReasonReady ListenerConditionReason = "Ready" + + // This reason is used with the "Ready" condition when the + // Listener is syntactically or semantically invalid. + ListenerReasonInvalid ListenerConditionReason = "Invalid" + + // This reason is used with the "Ready" condition when the + // Listener is not yet not online and ready to accept client + // traffic. + ListenerReasonPending ListenerConditionReason = "Pending" +) diff --git a/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/gatewayclass_types.go b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/gatewayclass_types.go new file mode 100644 index 0000000000..2cc57e6fdc --- /dev/null +++ b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/gatewayclass_types.go @@ -0,0 +1,201 @@ +/* +Copyright 2020 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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories=gateway-api,scope=Cluster,shortName=gc +// +kubebuilder:storageversion +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Controller",type=string,JSONPath=`.spec.controllerName` +// +kubebuilder:printcolumn:name="Accepted",type=string,JSONPath=`.status.conditions[?(@.type=="Accepted")].status` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +kubebuilder:printcolumn:name="Description",type=string,JSONPath=`.spec.description`,priority=1 + +// GatewayClass describes a class of Gateways available to the user for creating +// Gateway resources. +// +// It is recommended that this resource be used as a template for Gateways. This +// means that a Gateway is based on the state of the GatewayClass at the time it +// was created and changes to the GatewayClass or associated parameters are not +// propagated down to existing Gateways. This recommendation is intended to +// limit the blast radius of changes to GatewayClass or associated parameters. +// If implementations choose to propagate GatewayClass changes to existing +// Gateways, that MUST be clearly documented by the implementation. +// +// Whenever one or more Gateways are using a GatewayClass, implementations MUST +// add the `gateway-exists-finalizer.gateway.networking.k8s.io` finalizer on the +// associated GatewayClass. This ensures that a GatewayClass associated with a +// Gateway is not deleted while in use. +// +// GatewayClass is a Cluster level resource. +type GatewayClass struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of GatewayClass. + Spec GatewayClassSpec `json:"spec"` + + // Status defines the current state of GatewayClass. + // + // +kubebuilder:default={conditions: {{type: "Accepted", status: "Unknown", message: "Waiting for controller", reason: "Waiting", lastTransitionTime: "1970-01-01T00:00:00Z"}}} + Status GatewayClassStatus `json:"status,omitempty"` +} + +const ( + // GatewayClassFinalizerGatewaysExist should be added as a finalizer to the + // GatewayClass whenever there are provisioned Gateways using a + // GatewayClass. + GatewayClassFinalizerGatewaysExist = "gateway-exists-finalizer.gateway.networking.k8s.io" +) + +// GatewayClassSpec reflects the configuration of a class of Gateways. +type GatewayClassSpec struct { + // ControllerName is the name of the controller that is managing Gateways of + // this class. The value of this field MUST be a domain prefixed path. + // + // Example: "example.net/gateway-controller". + // + // This field is not mutable and cannot be empty. + // + // Support: Core + ControllerName GatewayController `json:"controllerName"` + + // ParametersRef is a reference to a resource that contains the configuration + // parameters corresponding to the GatewayClass. This is optional if the + // controller does not require any additional configuration. + // + // ParametersRef can reference a standard Kubernetes resource, i.e. ConfigMap, + // or an implementation-specific custom resource. The resource can be + // cluster-scoped or namespace-scoped. + // + // If the referent cannot be found, the GatewayClass's "InvalidParameters" + // status condition will be true. + // + // Support: Custom + // + // +optional + ParametersRef *ParametersReference `json:"parametersRef,omitempty"` + + // Description helps describe a GatewayClass with more details. + // + // +kubebuilder:validation:MaxLength=64 + // +optional + Description *string `json:"description,omitempty"` +} + +// ParametersReference identifies an API object containing controller-specific +// configuration resource within the cluster. +type ParametersReference struct { + // Group is the group of the referent. + Group Group `json:"group"` + + // Kind is kind of the referent. + Kind Kind `json:"kind"` + + // Name is the name of the referent. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Name string `json:"name"` + + // Namespace is the namespace of the referent. + // This field is required when referring to a Namespace-scoped resource and + // MUST be unset when referring to a Cluster-scoped resource. + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` +} + +// GatewayClassConditionType is the type for status conditions on +// Gateway resources. This type should be used with the +// GatewayClassStatus.Conditions field. +type GatewayClassConditionType string + +// GatewayClassConditionReason defines the set of reasons that explain why a +// particular GatewayClass condition type has been raised. +type GatewayClassConditionReason string + +const ( + // This condition indicates whether the GatewayClass has been accepted by + // the controller requested in the `spec.controller` field. + // + // This condition defaults to Unknown, and MUST be set by a controller when + // it sees a GatewayClass using its controller string. The status of this + // condition MUST be set to True if the controller will support provisioning + // Gateways using this class. Otherwise, this status MUST be set to False. + // If the status is set to False, the controller SHOULD set a Message and + // Reason as an explanation. + // + // Possible reasons for this condition to be true are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "InvalidParameters" + // * "Waiting" + // + // Controllers should prefer to use the values of GatewayClassConditionReason + // for the corresponding Reason, where appropriate. + GatewayClassConditionStatusAccepted GatewayClassConditionType = "Accepted" + + // This reason is used with the "Accepted" condition when the condition is + // true. + GatewayClassReasonAccepted GatewayClassConditionReason = "Accepted" + + // This reason is used with the "Accepted" condition when the + // GatewayClass was not accepted because the parametersRef field + // was invalid, with more detail in the message. + GatewayClassReasonInvalidParameters GatewayClassConditionReason = "InvalidParameters" + + // This reason is used with the "Accepted" condition when the + // requested controller has not yet made a decision about whether + // to admit the GatewayClass. It is the default Reason on a new + // GatewayClass. + GatewayClassReasonWaiting GatewayClassConditionReason = "Waiting" +) + +// GatewayClassStatus is the current status for the GatewayClass. +type GatewayClassStatus struct { + // Conditions is the current status from the controller for + // this GatewayClass. + // + // Controllers should prefer to publish conditions using values + // of GatewayClassConditionType for the type of each Condition. + // + // +optional + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:default={{type: "Accepted", status: "Unknown", message: "Waiting for controller", reason: "Waiting", lastTransitionTime: "1970-01-01T00:00:00Z"}} + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true + +// GatewayClassList contains a list of GatewayClass +type GatewayClassList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []GatewayClass `json:"items"` +} diff --git a/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/httproute_types.go b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/httproute_types.go new file mode 100644 index 0000000000..ff1d0dec09 --- /dev/null +++ b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/httproute_types.go @@ -0,0 +1,989 @@ +/* +Copyright 2020 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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:resource:categories=gateway-api +// +kubebuilder:storageversion +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Hostnames",type=string,JSONPath=`.spec.hostnames` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` + +// HTTPRoute provides a way to route HTTP requests. This includes the capability +// to match requests by hostname, path, header, or query param. Filters can be +// used to specify additional processing steps. Backends specify where matching +// requests should be routed. +type HTTPRoute struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of HTTPRoute. + Spec HTTPRouteSpec `json:"spec"` + + // Status defines the current state of HTTPRoute. + Status HTTPRouteStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// HTTPRouteList contains a list of HTTPRoute. +type HTTPRouteList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []HTTPRoute `json:"items"` +} + +// HTTPRouteSpec defines the desired state of HTTPRoute +type HTTPRouteSpec struct { + CommonRouteSpec `json:",inline"` + + // Hostnames defines a set of hostname that should match against the HTTP + // Host header to select a HTTPRoute to process the request. This matches + // the RFC 1123 definition of a hostname with 2 notable exceptions: + // + // 1. IPs are not allowed. + // 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard + // label must appear by itself as the first label. + // + // If a hostname is specified by both the Listener and HTTPRoute, there + // must be at least one intersecting hostname for the HTTPRoute to be + // attached to the Listener. For example: + // + // * A Listener with `test.example.com` as the hostname matches HTTPRoutes + // that have either not specified any hostnames, or have specified at + // least one of `test.example.com` or `*.example.com`. + // * A Listener with `*.example.com` as the hostname matches HTTPRoutes + // that have either not specified any hostnames or have specified at least + // one hostname that matches the Listener hostname. For example, + // `*.example.com`, `test.example.com`, and `foo.test.example.com` would + // all match. On the other hand, `example.com` and `test.example.net` would + // not match. + // + // Hostnames that are prefixed with a wildcard label (`*.`) are interpreted + // as a suffix match. That means that a match for `*.example.com` would match + // both `test.example.com`, and `foo.test.example.com`, but not `example.com`. + // + // If both the Listener and HTTPRoute have specified hostnames, any + // HTTPRoute hostnames that do not match the Listener hostname MUST be + // ignored. For example, if a Listener specified `*.example.com`, and the + // HTTPRoute specified `test.example.com` and `test.example.net`, + // `test.example.net` must not be considered for a match. + // + // If both the Listener and HTTPRoute have specified hostnames, and none + // match with the criteria above, then the HTTPRoute is not accepted. The + // implementation must raise an 'Accepted' Condition with a status of + // `False` in the corresponding RouteParentStatus. + // + // Support: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Hostnames []Hostname `json:"hostnames,omitempty"` + + // Rules are a list of HTTP matchers, filters and actions. + // + // +optional + // +kubebuilder:validation:MaxItems=16 + // +kubebuilder:default={{matches: {{path: {type: "PathPrefix", value: "/"}}}}} + Rules []HTTPRouteRule `json:"rules,omitempty"` +} + +// HTTPRouteRule defines semantics for matching an HTTP request based on +// conditions (matches), processing it (filters), and forwarding the request to +// an API object (backendRefs). +type HTTPRouteRule struct { + // Matches define conditions used for matching the rule against incoming + // HTTP requests. Each match is independent, i.e. this rule will be matched + // if **any** one of the matches is satisfied. + // + // For example, take the following matches configuration: + // + // ``` + // matches: + // - path: + // value: "/foo" + // headers: + // - name: "version" + // value: "v2" + // - path: + // value: "/v2/foo" + // ``` + // + // For a request to match against this rule, a request must satisfy + // EITHER of the two conditions: + // + // - path prefixed with `/foo` AND contains the header `version: v2` + // - path prefix of `/v2/foo` + // + // See the documentation for HTTPRouteMatch on how to specify multiple + // match conditions that should be ANDed together. + // + // If no matches are specified, the default is a prefix + // path match on "/", which has the effect of matching every + // HTTP request. + // + // Proxy or Load Balancer routing configuration generated from HTTPRoutes + // MUST prioritize rules based on the following criteria, continuing on + // ties. Precedence must be given to the Rule with the largest number + // of: + // + // * Characters in a matching non-wildcard hostname. + // * Characters in a matching hostname. + // * Characters in a matching path. + // * Header matches. + // * Query param matches. + // + // If ties still exist across multiple Routes, matching precedence MUST be + // determined in order of the following criteria, continuing on ties: + // + // * The oldest Route based on creation timestamp. + // * The Route appearing first in alphabetical order by + // "{namespace}/{name}". + // + // If ties still exist within the Route that has been given precedence, + // matching precedence MUST be granted to the FIRST matching rule (in list + // order) meeting the above criteria. + // + // When no rules matching a request have been successfully attached to the + // parent a request is coming from, a HTTP 404 status code MUST be returned. + // + // +optional + // +kubebuilder:validation:MaxItems=8 + // +kubebuilder:default={{path:{ type: "PathPrefix", value: "/"}}} + Matches []HTTPRouteMatch `json:"matches,omitempty"` + + // Filters define the filters that are applied to requests that match + // this rule. + // + // The effects of ordering of multiple behaviors are currently unspecified. + // This can change in the future based on feedback during the alpha stage. + // + // Conformance-levels at this level are defined based on the type of filter: + // + // - ALL core filters MUST be supported by all implementations. + // - Implementers are encouraged to support extended filters. + // - Implementation-specific custom filters have no API guarantees across + // implementations. + // + // Specifying a core filter multiple times has unspecified or custom + // conformance. + // + // All filters are expected to be compatible with each other except for the + // URLRewrite and RequestRedirect filters, which may not be combined. If an + // implementation can not support other combinations of filters, they must clearly + // document that limitation. In all cases where incompatible or unsupported + // filters are specified, implementations MUST add a warning condition to status. + // + // Support: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Filters []HTTPRouteFilter `json:"filters,omitempty"` + + // BackendRefs defines the backend(s) where matching requests should be + // sent. + // + // Failure behavior here depends on how many BackendRefs are specified and + // how many are invalid. + // + // If *all* entries in BackendRefs are invalid, and there are also no filters + // specified in this route rule, *all* traffic which matches this rule MUST + // receive a 500 status code. + // + // See the HTTPBackendRef definition for the rules about what makes a single + // HTTPBackendRef invalid. + // + // When a HTTPBackendRef is invalid, 500 status codes MUST be returned for + // requests that would have otherwise been routed to an invalid backend. If + // multiple backends are specified, and some are invalid, the proportion of + // requests that would otherwise have been routed to an invalid backend + // MUST receive a 500 status code. + // + // For example, if two backends are specified with equal weights, and one is + // invalid, 50 percent of traffic must receive a 500. Implementations may + // choose how that 50 percent is determined. + // + // Support: Core for Kubernetes Service + // + // Support: Custom for any other resource + // + // Support for weight: Core + // + // +optional + // +kubebuilder:validation:MaxItems=16 + BackendRefs []HTTPBackendRef `json:"backendRefs,omitempty"` +} + +// PathMatchType specifies the semantics of how HTTP paths should be compared. +// Valid PathMatchType values are: +// +// * "Exact" +// * "PathPrefix" +// * "RegularExpression" +// +// PathPrefix and Exact paths must be syntactically valid: +// +// - Must begin with the `/` character +// - Must not contain consecutive `/` characters (e.g. `/foo///`, `//`). +// +// Note that values may be added to this enum, implementations +// must ensure that unknown values will not cause a crash. +// +// Unknown values here must result in the implementation setting the +// Attached Condition for the Route to `status: False`, with a +// Reason of `UnsupportedValue`. +// +// +kubebuilder:validation:Enum=Exact;PathPrefix;RegularExpression +type PathMatchType string + +const ( + // Matches the URL path exactly and with case sensitivity. + PathMatchExact PathMatchType = "Exact" + + // Matches based on a URL path prefix split by `/`. Matching is + // case sensitive and done on a path element by element basis. A + // path element refers to the list of labels in the path split by + // the `/` separator. When specified, a trailing `/` is ignored. + // + // For example, the paths `/abc`, `/abc/`, and `/abc/def` would all match + // the prefix `/abc`, but the path `/abcd` would not. + // + // "PathPrefix" is semantically equivalent to the "Prefix" path type in the + // Kubernetes Ingress API. + PathMatchPathPrefix PathMatchType = "PathPrefix" + + // Matches if the URL path matches the given regular expression with + // case sensitivity. + // + // Since `"RegularExpression"` has custom conformance, implementations + // can support POSIX, PCRE, RE2 or any other regular expression dialect. + // Please read the implementation's documentation to determine the supported + // dialect. + PathMatchRegularExpression PathMatchType = "RegularExpression" +) + +// HTTPPathMatch describes how to select a HTTP route by matching the HTTP request path. +type HTTPPathMatch struct { + // Type specifies how to match against the path Value. + // + // Support: Core (Exact, PathPrefix) + // + // Support: Custom (RegularExpression) + // + // +optional + // +kubebuilder:default=PathPrefix + Type *PathMatchType `json:"type,omitempty"` + + // Value of the HTTP path to match against. + // + // +optional + // +kubebuilder:default="/" + // +kubebuilder:validation:MaxLength=1024 + Value *string `json:"value,omitempty"` +} + +// HeaderMatchType specifies the semantics of how HTTP header values should be +// compared. Valid HeaderMatchType values are: +// +// * "Exact" +// * "RegularExpression" +// +// Note that values may be added to this enum, implementations +// must ensure that unknown values will not cause a crash. +// +// Unknown values here must result in the implementation setting the +// Attached Condition for the Route to `status: False`, with a +// Reason of `UnsupportedValue`. +// +// +kubebuilder:validation:Enum=Exact;RegularExpression +type HeaderMatchType string + +// HeaderMatchType constants. +const ( + HeaderMatchExact HeaderMatchType = "Exact" + HeaderMatchRegularExpression HeaderMatchType = "RegularExpression" +) + +// HTTPHeaderName is the name of an HTTP header. +// +// Valid values include: +// +// * "Authorization" +// * "Set-Cookie" +// +// Invalid values include: +// +// * ":method" - ":" is an invalid character. This means that HTTP/2 pseudo +// headers are not currently supported by this type. +// * "/invalid" - "/" is an invalid character +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=256 +// +kubebuilder:validation:Pattern=`^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$` +type HTTPHeaderName string + +// HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request +// headers. +type HTTPHeaderMatch struct { + // Type specifies how to match against the value of the header. + // + // Support: Core (Exact) + // + // Support: Custom (RegularExpression) + // + // Since RegularExpression HeaderMatchType has custom conformance, + // implementations can support POSIX, PCRE or any other dialects of regular + // expressions. Please read the implementation's documentation to determine + // the supported dialect. + // + // +optional + // +kubebuilder:default=Exact + Type *HeaderMatchType `json:"type,omitempty"` + + // Name is the name of the HTTP Header to be matched. Name matching MUST be + // case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + // + // If multiple entries specify equivalent header names, only the first + // entry with an equivalent name MUST be considered for a match. Subsequent + // entries with an equivalent header name MUST be ignored. Due to the + // case-insensitivity of header names, "foo" and "Foo" are considered + // equivalent. + // + // When a header is repeated in an HTTP request, it is + // implementation-specific behavior as to how this is represented. + // Generally, proxies should follow the guidance from the RFC: + // https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding + // processing a repeated header, with special handling for "Set-Cookie". + Name HTTPHeaderName `json:"name"` + + // Value is the value of HTTP Header to be matched. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=4096 + Value string `json:"value"` +} + +// QueryParamMatchType specifies the semantics of how HTTP query parameter +// values should be compared. Valid QueryParamMatchType values are: +// +// * "Exact" +// * "RegularExpression" +// +// Note that values may be added to this enum, implementations +// must ensure that unknown values will not cause a crash. +// +// Unknown values here must result in the implementation setting the +// Attached Condition for the Route to `status: False`, with a +// Reason of `UnsupportedValue`. +// +// +kubebuilder:validation:Enum=Exact;RegularExpression +type QueryParamMatchType string + +// QueryParamMatchType constants. +const ( + QueryParamMatchExact QueryParamMatchType = "Exact" + QueryParamMatchRegularExpression QueryParamMatchType = "RegularExpression" +) + +// HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP +// query parameters. +type HTTPQueryParamMatch struct { + // Type specifies how to match against the value of the query parameter. + // + // Support: Extended (Exact) + // + // Support: Custom (RegularExpression) + // + // Since RegularExpression QueryParamMatchType has custom conformance, + // implementations can support POSIX, PCRE or any other dialects of regular + // expressions. Please read the implementation's documentation to determine + // the supported dialect. + // + // +optional + // +kubebuilder:default=Exact + Type *QueryParamMatchType `json:"type,omitempty"` + + // Name is the name of the HTTP query param to be matched. This must be an + // exact string match. (See + // https://tools.ietf.org/html/rfc7230#section-2.7.3). + // + // If multiple entries specify equivalent query param names, only the first + // entry with an equivalent name MUST be considered for a match. Subsequent + // entries with an equivalent query param name MUST be ignored. + // + // If a query param is repeated in an HTTP request, the behavior + // is purposely left undefined, since different data planes have different + // capabilities. However, it's *recommended* that implementations should + // match against the first value of the param if the data plane supports it, + // as this behavior is expected in other load balancing contexts outside of + // the Gateway API. + // Users should not route traffic based on repeated query params to guard + // themselves against potential differences in the implementations. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=256 + Name string `json:"name"` + + // Value is the value of HTTP query param to be matched. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=1024 + Value string `json:"value"` +} + +// HTTPMethod describes how to select a HTTP route by matching the HTTP +// method as defined by +// [RFC 7231](https://datatracker.ietf.org/doc/html/rfc7231#section-4) and +// [RFC 5789](https://datatracker.ietf.org/doc/html/rfc5789#section-2). +// The value is expected in upper case. +// +// Note that values may be added to this enum, implementations +// must ensure that unknown values will not cause a crash. +// +// Unknown values here must result in the implementation setting the +// Attached Condition for the Route to `status: False`, with a +// Reason of `UnsupportedValue`. +// +// +kubebuilder:validation:Enum=GET;HEAD;POST;PUT;DELETE;CONNECT;OPTIONS;TRACE;PATCH +type HTTPMethod string + +const ( + HTTPMethodGet HTTPMethod = "GET" + HTTPMethodHead HTTPMethod = "HEAD" + HTTPMethodPost HTTPMethod = "POST" + HTTPMethodPut HTTPMethod = "PUT" + HTTPMethodDelete HTTPMethod = "DELETE" + HTTPMethodConnect HTTPMethod = "CONNECT" + HTTPMethodOptions HTTPMethod = "OPTIONS" + HTTPMethodTrace HTTPMethod = "TRACE" + HTTPMethodPatch HTTPMethod = "PATCH" +) + +// HTTPRouteMatch defines the predicate used to match requests to a given +// action. Multiple match types are ANDed together, i.e. the match will +// evaluate to true only if all conditions are satisfied. +// +// For example, the match below will match a HTTP request only if its path +// starts with `/foo` AND it contains the `version: v1` header: +// +// ``` +// match: +// path: +// value: "/foo" +// headers: +// - name: "version" +// value "v1" +// ``` +type HTTPRouteMatch struct { + // Path specifies a HTTP request path matcher. If this field is not + // specified, a default prefix match on the "/" path is provided. + // + // +optional + // +kubebuilder:default={type: "PathPrefix", value: "/"} + Path *HTTPPathMatch `json:"path,omitempty"` + + // Headers specifies HTTP request header matchers. Multiple match values are + // ANDed together, meaning, a request must match all the specified headers + // to select the route. + // + // +listType=map + // +listMapKey=name + // +optional + // +kubebuilder:validation:MaxItems=16 + Headers []HTTPHeaderMatch `json:"headers,omitempty"` + + // QueryParams specifies HTTP query parameter matchers. Multiple match + // values are ANDed together, meaning, a request must match all the + // specified query parameters to select the route. + // + // +listType=map + // +listMapKey=name + // +optional + // +kubebuilder:validation:MaxItems=16 + QueryParams []HTTPQueryParamMatch `json:"queryParams,omitempty"` + + // Method specifies HTTP method matcher. + // When specified, this route will be matched only if the request has the + // specified method. + // + // Support: Extended + // + // +optional + Method *HTTPMethod `json:"method,omitempty"` +} + +// HTTPRouteFilter defines processing steps that must be completed during the +// request or response lifecycle. HTTPRouteFilters are meant as an extension +// point to express processing that may be done in Gateway implementations. Some +// examples include request or response modification, implementing +// authentication strategies, rate-limiting, and traffic shaping. API +// guarantee/conformance is defined based on the type of the filter. +type HTTPRouteFilter struct { + // Type identifies the type of filter to apply. As with other API fields, + // types are classified into three conformance levels: + // + // - Core: Filter types and their corresponding configuration defined by + // "Support: Core" in this package, e.g. "RequestHeaderModifier". All + // implementations must support core filters. + // + // - Extended: Filter types and their corresponding configuration defined by + // "Support: Extended" in this package, e.g. "RequestMirror". Implementers + // are encouraged to support extended filters. + // + // - Custom: Filters that are defined and supported by specific vendors. + // In the future, filters showing convergence in behavior across multiple + // implementations will be considered for inclusion in extended or core + // conformance levels. Filter-specific configuration for such filters + // is specified using the ExtensionRef field. `Type` should be set to + // "ExtensionRef" for custom filters. + // + // Implementers are encouraged to define custom implementation types to + // extend the core API with implementation-specific behavior. + // + // If a reference to a custom filter type cannot be resolved, the filter + // MUST NOT be skipped. Instead, requests that would have been processed by + // that filter MUST receive a HTTP error response. + // + // Note that values may be added to this enum, implementations + // must ensure that unknown values will not cause a crash. + // + // Unknown values here must result in the implementation setting the + // Attached Condition for the Route to `status: False`, with a + // Reason of `UnsupportedValue`. + // + // +unionDiscriminator + // +kubebuilder:validation:Enum=RequestHeaderModifier;RequestMirror;RequestRedirect;ExtensionRef + // + Type HTTPRouteFilterType `json:"type"` + + // RequestHeaderModifier defines a schema for a filter that modifies request + // headers. + // + // Support: Core + // + // +optional + RequestHeaderModifier *HTTPRequestHeaderFilter `json:"requestHeaderModifier,omitempty"` + + // RequestMirror defines a schema for a filter that mirrors requests. + // Requests are sent to the specified destination, but responses from + // that destination are ignored. + // + // Support: Extended + // + // +optional + RequestMirror *HTTPRequestMirrorFilter `json:"requestMirror,omitempty"` + + // RequestRedirect defines a schema for a filter that responds to the + // request with an HTTP redirection. + // + // Support: Core + // + // +optional + RequestRedirect *HTTPRequestRedirectFilter `json:"requestRedirect,omitempty"` + + // URLRewrite defines a schema for a filter that modifies a request during forwarding. + // + // Support: Extended + // + // + // +optional + URLRewrite *HTTPURLRewriteFilter `json:"urlRewrite,omitempty"` + + // ExtensionRef is an optional, implementation-specific extension to the + // "filter" behavior. For example, resource "myroutefilter" in group + // "networking.example.net"). ExtensionRef MUST NOT be used for core and + // extended filters. + // + // Support: Implementation-specific + // + // +optional + ExtensionRef *LocalObjectReference `json:"extensionRef,omitempty"` +} + +// HTTPRouteFilterType identifies a type of HTTPRoute filter. +type HTTPRouteFilterType string + +const ( + // HTTPRouteFilterRequestHeaderModifier can be used to add or remove an HTTP + // header from an HTTP request before it is sent to the upstream target. + // + // Support in HTTPRouteRule: Core + // + // Support in HTTPBackendRef: Extended + HTTPRouteFilterRequestHeaderModifier HTTPRouteFilterType = "RequestHeaderModifier" + + // HTTPRouteFilterRequestRedirect can be used to redirect a request to + // another location. This filter can also be used for HTTP to HTTPS + // redirects. This may not be used on the same Route rule or BackendRef as a + // URLRewrite filter. + // + // Support in HTTPRouteRule: Core + // + // Support in HTTPBackendRef: Extended + HTTPRouteFilterRequestRedirect HTTPRouteFilterType = "RequestRedirect" + + // HTTPRouteFilterURLRewrite can be used to modify a request during + // forwarding. At most one of these filters may be used on a Route rule. + // This may not be used on the same Route rule or BackendRef as a + // RequestRedirect filter. + // + // Support in HTTPRouteRule: Extended + // + // Support in HTTPBackendRef: Extended + // + // + HTTPRouteFilterURLRewrite HTTPRouteFilterType = "URLRewrite" + + // HTTPRouteFilterRequestMirror can be used to mirror HTTP requests to a + // different backend. The responses from this backend MUST be ignored by + // the Gateway. + // + // Support in HTTPRouteRule: Extended + // + // Support in HTTPBackendRef: Extended + HTTPRouteFilterRequestMirror HTTPRouteFilterType = "RequestMirror" + + // HTTPRouteFilterExtensionRef should be used for configuring custom + // HTTP filters. + // + // Support in HTTPRouteRule: Custom + // + // Support in HTTPBackendRef: Custom + HTTPRouteFilterExtensionRef HTTPRouteFilterType = "ExtensionRef" +) + +// HTTPHeader represents an HTTP Header name and value as defined by RFC 7230. +type HTTPHeader struct { + // Name is the name of the HTTP Header to be matched. Name matching MUST be + // case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + // + // If multiple entries specify equivalent header names, the first entry with + // an equivalent name MUST be considered for a match. Subsequent entries + // with an equivalent header name MUST be ignored. Due to the + // case-insensitivity of header names, "foo" and "Foo" are considered + // equivalent. + Name HTTPHeaderName `json:"name"` + + // Value is the value of HTTP Header to be matched. + // + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=4096 + Value string `json:"value"` +} + +// HTTPRequestHeaderFilter defines configuration for the RequestHeaderModifier +// filter. +type HTTPRequestHeaderFilter struct { + // Set overwrites the request with the given header (name, value) + // before the action. + // + // Input: + // GET /foo HTTP/1.1 + // my-header: foo + // + // Config: + // set: + // - name: "my-header" + // value: "bar" + // + // Output: + // GET /foo HTTP/1.1 + // my-header: bar + // + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=16 + Set []HTTPHeader `json:"set,omitempty"` + + // Add adds the given header(s) (name, value) to the request + // before the action. It appends to any existing values associated + // with the header name. + // + // Input: + // GET /foo HTTP/1.1 + // my-header: foo + // + // Config: + // add: + // - name: "my-header" + // value: "bar" + // + // Output: + // GET /foo HTTP/1.1 + // my-header: foo + // my-header: bar + // + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=16 + Add []HTTPHeader `json:"add,omitempty"` + + // Remove the given header(s) from the HTTP request before the action. The + // value of Remove is a list of HTTP header names. Note that the header + // names are case-insensitive (see + // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + // + // Input: + // GET /foo HTTP/1.1 + // my-header1: foo + // my-header2: bar + // my-header3: baz + // + // Config: + // remove: ["my-header1", "my-header3"] + // + // Output: + // GET /foo HTTP/1.1 + // my-header2: bar + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Remove []string `json:"remove,omitempty"` +} + +// HTTPPathModifierType defines the type of path redirect or rewrite. +type HTTPPathModifierType string + +const ( + // This type of modifier indicates that the full path will be replaced + // by the specified value. + FullPathHTTPPathModifier HTTPPathModifierType = "ReplaceFullPath" + + // This type of modifier indicates that any prefix path matches will be + // replaced by the substitution value. For example, a path with a prefix + // match of "/foo" and a ReplacePrefixMatch substitution of "/bar" will have + // the "/foo" prefix replaced with "/bar" in matching requests. + // + // Note that this matches the behavior of the PathPrefix match type. This + // matches full path elements. A path element refers to the list of labels + // in the path split by the `/` separator. When specified, a trailing `/` is + // ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + // match the prefix `/abc`, but the path `/abcd` would not. + PrefixMatchHTTPPathModifier HTTPPathModifierType = "ReplacePrefixMatch" +) + +// HTTPPathModifier defines configuration for path modifiers. +// +type HTTPPathModifier struct { + // Type defines the type of path modifier. Additional types may be + // added in a future release of the API. + // + // Note that values may be added to this enum, implementations + // must ensure that unknown values will not cause a crash. + // + // Unknown values here must result in the implementation setting the + // Attached Condition for the Route to `status: False`, with a + // Reason of `UnsupportedValue`. + // + // + // +kubebuilder:validation:Enum=ReplaceFullPath;ReplacePrefixMatch + Type HTTPPathModifierType `json:"type"` + + // ReplaceFullPath specifies the value with which to replace the full path + // of a request during a rewrite or redirect. + // + // + // +kubebuilder:validation:MaxLength=1024 + // +optional + ReplaceFullPath *string `json:"replaceFullPath,omitempty"` + + // ReplacePrefixMatch specifies the value with which to replace the prefix + // match of a request during a rewrite or redirect. For example, a request + // to "/foo/bar" with a prefix match of "/foo" would be modified to "/bar". + // + // Note that this matches the behavior of the PathPrefix match type. This + // matches full path elements. A path element refers to the list of labels + // in the path split by the `/` separator. When specified, a trailing `/` is + // ignored. For example, the paths `/abc`, `/abc/`, and `/abc/def` would all + // match the prefix `/abc`, but the path `/abcd` would not. + // + // + // +kubebuilder:validation:MaxLength=1024 + // +optional + ReplacePrefixMatch *string `json:"replacePrefixMatch,omitempty"` +} + +// HTTPRequestRedirect defines a filter that redirects a request. This filter +// MUST NOT be used on the same Route rule as a HTTPURLRewrite filter. +type HTTPRequestRedirectFilter struct { + // Scheme is the scheme to be used in the value of the `Location` + // header in the response. + // When empty, the scheme of the request is used. + // + // Support: Extended + // + // Note that values may be added to this enum, implementations + // must ensure that unknown values will not cause a crash. + // + // Unknown values here must result in the implementation setting the + // Attached Condition for the Route to `status: False`, with a + // Reason of `UnsupportedValue`. + // + // +optional + // +kubebuilder:validation:Enum=http;https + Scheme *string `json:"scheme,omitempty"` + + // Hostname is the hostname to be used in the value of the `Location` + // header in the response. + // When empty, the hostname of the request is used. + // + // Support: Core + // + // +optional + Hostname *PreciseHostname `json:"hostname,omitempty"` + + // Path defines parameters used to modify the path of the incoming request. + // The modified path is then used to construct the `Location` header. When + // empty, the request path is used as-is. + // + // Support: Extended + // + // + // +optional + Path *HTTPPathModifier `json:"path,omitempty"` + + // Port is the port to be used in the value of the `Location` + // header in the response. + // When empty, port (if specified) of the request is used. + // + // Support: Extended + // + // +optional + Port *PortNumber `json:"port,omitempty"` + + // StatusCode is the HTTP status code to be used in response. + // + // Support: Core + // + // Note that values may be added to this enum, implementations + // must ensure that unknown values will not cause a crash. + // + // Unknown values here must result in the implementation setting the + // Attached Condition for the Route to `status: False`, with a + // Reason of `UnsupportedValue`. + // + // +optional + // +kubebuilder:default=302 + // +kubebuilder:validation:Enum=301;302 + StatusCode *int `json:"statusCode,omitempty"` +} + +// HTTPURLRewriteFilter defines a filter that modifies a request during +// forwarding. At most one of these filters may be used on a Route rule. This +// MUST NOT be used on the same Route rule as a HTTPRequestRedirect filter. +// +// Support: Extended +// +// +type HTTPURLRewriteFilter struct { + // Hostname is the value to be used to replace the Host header value during + // forwarding. + // + // Support: Extended + // + // + // +optional + Hostname *PreciseHostname `json:"hostname,omitempty"` + + // Path defines a path rewrite. + // + // Support: Extended + // + // + // +optional + Path *HTTPPathModifier `json:"path,omitempty"` +} + +// HTTPRequestMirrorFilter defines configuration for the RequestMirror filter. +type HTTPRequestMirrorFilter struct { + // BackendRef references a resource where mirrored requests are sent. + // + // If the referent cannot be found, this BackendRef is invalid and must be + // dropped from the Gateway. The controller must ensure the "ResolvedRefs" + // condition on the Route status is set to `status: False` and not configure + // this backend in the underlying implementation. + // + // If there is a cross-namespace reference to an *existing* object + // that is not allowed by a ReferenceGrant, the controller must ensure the + // "ResolvedRefs" condition on the Route is set to `status: False`, + // with the "RefNotPermitted" reason and not configure this backend in the + // underlying implementation. + // + // In either error case, the Message of the `ResolvedRefs` Condition + // should be used to provide more detail about the problem. + // + // Support: Extended for Kubernetes Service + // + // Support: Custom for any other resource + BackendRef BackendObjectReference `json:"backendRef"` +} + +// HTTPBackendRef defines how a HTTPRoute should forward an HTTP request. +type HTTPBackendRef struct { + // BackendRef is a reference to a backend to forward matched requests to. + // + // A BackendRef can be invalid for the following reasons. In all cases, the + // implementation MUST ensure the `ResolvedRefs` Condition on the Route + // is set to `status: False`, with a Reason and Message that indicate + // what is the cause of the error. + // + // A BackendRef is invalid if: + // + // * It refers to an unknown or unsupported kind of resource. In this + // case, the Reason must be set to `InvalidKind` and Message of the + // Condition must explain which kind of resource is unknown or unsupported. + // + // * It refers to a resource that does not exist. In this case, the Reason must + // be set to `BackendNotFound` and the Message of the Condition must explain + // which resource does not exist. + // + // * It refers a resource in another namespace when the reference has not been + // explicitly allowed by a ReferenceGrant (or equivalent concept). In this + // case, the Reason must be set to `RefNotPermitted` and the Message of the + // Condition must explain which cross-namespace reference is not allowed. + // + // Support: Core for Kubernetes Service + // + // Support: Custom for any other resource + // + // Support for weight: Core + // + // +optional + BackendRef `json:",inline"` + + // Filters defined at this level should be executed if and only if the + // request is being forwarded to the backend defined here. + // + // Support: Custom (For broader support of filters, use the Filters field + // in HTTPRouteRule.) + // + // +optional + // +kubebuilder:validation:MaxItems=16 + Filters []HTTPRouteFilter `json:"filters,omitempty"` +} + +// HTTPRouteStatus defines the observed state of HTTPRoute. +type HTTPRouteStatus struct { + RouteStatus `json:",inline"` +} diff --git a/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/object_reference_types.go b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/object_reference_types.go new file mode 100644 index 0000000000..3cbbc0ad5e --- /dev/null +++ b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/object_reference_types.go @@ -0,0 +1,133 @@ +/* +Copyright 2020 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 v1beta1 + +// LocalObjectReference identifies an API object within the namespace of the +// referrer. +// The API object must be valid in the cluster; the Group and Kind must +// be registered in the cluster for this reference to be valid. +// +// References to objects with invalid Group and Kind are not valid, and must +// be rejected by the implementation, with appropriate Conditions set +// on the containing object. +type LocalObjectReference struct { + // Group is the group of the referent. For example, "networking.k8s.io". + // When unspecified (empty string), core API group is inferred. + Group Group `json:"group"` + + // Kind is kind of the referent. For example "HTTPRoute" or "Service". + Kind Kind `json:"kind"` + + // Name is the name of the referent. + Name ObjectName `json:"name"` +} + +// SecretObjectReference identifies an API object including its namespace, +// defaulting to Secret. +// +// The API object must be valid in the cluster; the Group and Kind must +// be registered in the cluster for this reference to be valid. +// +// References to objects with invalid Group and Kind are not valid, and must +// be rejected by the implementation, with appropriate Conditions set +// on the containing object. +type SecretObjectReference struct { + // Group is the group of the referent. For example, "networking.k8s.io". + // When unspecified (empty string), core API group is inferred. + // + // +optional + // +kubebuilder:default="" + Group *Group `json:"group"` + + // Kind is kind of the referent. For example "HTTPRoute" or "Service". + // + // +optional + // +kubebuilder:default=Secret + Kind *Kind `json:"kind"` + + // Name is the name of the referent. + Name ObjectName `json:"name"` + + // Namespace is the namespace of the backend. When unspecified, the local + // namespace is inferred. + // + // Note that when a namespace is specified, a ReferenceGrant object + // is required in the referent namespace to allow that namespace's + // owner to accept the reference. See the ReferenceGrant documentation + // for details. + // + // Support: Core + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` +} + +// BackendObjectReference defines how an ObjectReference that is +// specific to BackendRef. It includes a few additional fields and features +// than a regular ObjectReference. +// +// Note that when a namespace is specified, a ReferenceGrant object +// is required in the referent namespace to allow that namespace's +// owner to accept the reference. See the ReferenceGrant documentation +// for details. +// +// The API object must be valid in the cluster; the Group and Kind must +// be registered in the cluster for this reference to be valid. +// +// References to objects with invalid Group and Kind are not valid, and must +// be rejected by the implementation, with appropriate Conditions set +// on the containing object. +type BackendObjectReference struct { + // Group is the group of the referent. For example, "networking.k8s.io". + // When unspecified (empty string), core API group is inferred. + // + // +optional + // +kubebuilder:default="" + Group *Group `json:"group,omitempty"` + + // Kind is kind of the referent. For example "HTTPRoute" or "Service". + // Defaults to "Service" when not specified. + // + // +optional + // +kubebuilder:default=Service + Kind *Kind `json:"kind,omitempty"` + + // Name is the name of the referent. + Name ObjectName `json:"name"` + + // Namespace is the namespace of the backend. When unspecified, the local + // namespace is inferred. + // + // Note that when a namespace is specified, a ReferenceGrant object + // is required in the referent namespace to allow that namespace's + // owner to accept the reference. See the ReferenceGrant documentation + // for details. + // + // Support: Core + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` + + // Port specifies the destination port number to use for this resource. + // Port is required when the referent is a Kubernetes Service. In this + // case, the port number is the service port number, not the target port. + // For other resources, destination port might be derived from the referent + // resource or this field. + // + // +optional + Port *PortNumber `json:"port,omitempty"` +} diff --git a/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/shared_types.go b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/shared_types.go new file mode 100644 index 0000000000..c712bbc9dc --- /dev/null +++ b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/shared_types.go @@ -0,0 +1,549 @@ +/* +Copyright 2020 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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ParentReference identifies an API object (usually a Gateway) that can be considered +// a parent of this resource (usually a route). The only kind of parent resource +// with "Core" support is Gateway. This API may be extended in the future to +// support additional kinds of parent resources, such as HTTPRoute. +// +// The API object must be valid in the cluster; the Group and Kind must +// be registered in the cluster for this reference to be valid. +type ParentReference struct { + // Group is the group of the referent. + // + // Support: Core + // + // +kubebuilder:default=gateway.networking.k8s.io + // +optional + Group *Group `json:"group,omitempty"` + + // Kind is kind of the referent. + // + // Support: Core (Gateway) + // + // Support: Custom (Other Resources) + // + // +kubebuilder:default=Gateway + // +optional + Kind *Kind `json:"kind,omitempty"` + + // Namespace is the namespace of the referent. When unspecified, this refers + // to the local namespace of the Route. + // + // Support: Core + // + // +optional + Namespace *Namespace `json:"namespace,omitempty"` + + // Name is the name of the referent. + // + // Support: Core + Name ObjectName `json:"name"` + + // SectionName is the name of a section within the target resource. In the + // following resources, SectionName is interpreted as the following: + // + // * Gateway: Listener Name. When both Port (experimental) and SectionName + // are specified, the name and port of the selected listener must match + // both specified values. + // + // Implementations MAY choose to support attaching Routes to other resources. + // If that is the case, they MUST clearly document how SectionName is + // interpreted. + // + // When unspecified (empty string), this will reference the entire resource. + // For the purpose of status, an attachment is considered successful if at + // least one section in the parent resource accepts it. For example, Gateway + // listeners can restrict which Routes can attach to them by Route kind, + // namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from + // the referencing Route, the Route MUST be considered successfully + // attached. If no Gateway listeners accept attachment from this Route, the + // Route MUST be considered detached from the Gateway. + // + // Support: Core + // + // +optional + SectionName *SectionName `json:"sectionName,omitempty"` + + // Port is the network port this Route targets. It can be interpreted + // differently based on the type of parent resource. + // + // When the parent resource is a Gateway, this targets all listeners + // listening on the specified port that also support this kind of Route(and + // select this Route). It's not recommended to set `Port` unless the + // networking behaviors specified in a Route must apply to a specific port + // as opposed to a listener(s) whose port(s) may be changed. When both Port + // and SectionName are specified, the name and port of the selected listener + // must match both specified values. + // + // Implementations MAY choose to support other parent resources. + // Implementations supporting other types of parent resources MUST clearly + // document how/if Port is interpreted. + // + // For the purpose of status, an attachment is considered successful as + // long as the parent resource accepts it partially. For example, Gateway + // listeners can restrict which Routes can attach to them by Route kind, + // namespace, or hostname. If 1 of 2 Gateway listeners accept attachment + // from the referencing Route, the Route MUST be considered successfully + // attached. If no Gateway listeners accept attachment from this Route, + // the Route MUST be considered detached from the Gateway. + // + // Support: Extended + // + // +optional + // + Port *PortNumber `json:"port,omitempty"` +} + +// CommonRouteSpec defines the common attributes that all Routes MUST include +// within their spec. +type CommonRouteSpec struct { + // ParentRefs references the resources (usually Gateways) that a Route wants + // to be attached to. Note that the referenced parent resource needs to + // allow this for the attachment to be complete. For Gateways, that means + // the Gateway needs to allow attachment from Routes of this kind and + // namespace. + // + // The only kind of parent resource with "Core" support is Gateway. This API + // may be extended in the future to support additional kinds of parent + // resources such as one of the route kinds. + // + // It is invalid to reference an identical parent more than once. It is + // valid to reference multiple distinct sections within the same parent + // resource, such as 2 Listeners within a Gateway. + // + // It is possible to separately reference multiple distinct objects that may + // be collapsed by an implementation. For example, some implementations may + // choose to merge compatible Gateway Listeners together. If that is the + // case, the list of routes attached to those resources should also be + // merged. + // + // +optional + // +kubebuilder:validation:MaxItems=32 + ParentRefs []ParentReference `json:"parentRefs,omitempty"` +} + +// PortNumber defines a network port. +// +// +kubebuilder:validation:Minimum=1 +// +kubebuilder:validation:Maximum=65535 +type PortNumber int32 + +// BackendRef defines how a Route should forward a request to a Kubernetes +// resource. +// +// Note that when a namespace is specified, a ReferenceGrant object +// is required in the referent namespace to allow that namespace's +// owner to accept the reference. See the ReferenceGrant documentation +// for details. +type BackendRef struct { + // BackendObjectReference references a Kubernetes object. + BackendObjectReference `json:",inline"` + + // Weight specifies the proportion of requests forwarded to the referenced + // backend. This is computed as weight/(sum of all weights in this + // BackendRefs list). For non-zero values, there may be some epsilon from + // the exact proportion defined here depending on the precision an + // implementation supports. Weight is not a percentage and the sum of + // weights does not need to equal 100. + // + // If only one backend is specified and it has a weight greater than 0, 100% + // of the traffic is forwarded to that backend. If weight is set to 0, no + // traffic should be forwarded for this entry. If unspecified, weight + // defaults to 1. + // + // Support for this field varies based on the context where used. + // + // +optional + // +kubebuilder:default=1 + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=1000000 + Weight *int32 `json:"weight,omitempty"` +} + +// RouteConditionType is a type of condition for a route. +type RouteConditionType string + +// RouteConditionReason is a reason for a route condition. +type RouteConditionReason string + +const ( + // This condition indicates whether the route has been accepted or rejected + // by a Gateway, and why. + // + // Possible reasons for this condition to be true are: + // + // * "Accepted" + // + // Possible reasons for this condition to be False are: + // + // * "NotAllowedByListeners" + // * "NoMatchingListenerHostname" + // * "UnsupportedValue" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + RouteConditionAccepted RouteConditionType = "Accepted" + + // This reason is used with the "Accepted" condition when the Route has been + // accepted by the Gateway. + RouteReasonAccepted RouteConditionReason = "Accepted" + + // This reason is used with the "Accepted" condition when the route has not + // been accepted by a Gateway because the Gateway has no Listener whose + // allowedRoutes criteria permit the route + RouteReasonNotAllowedByListeners RouteConditionReason = "NotAllowedByListeners" + + // This reason is used with the "Accepted" condition when the Gateway has no + // compatible Listeners whose Hostname matches the route + RouteReasonNoMatchingListenerHostname RouteConditionReason = "NoMatchingListenerHostname" + + // This reason is used with the "Accepted" condition when a value for an Enum + // is not recognized. + RouteReasonUnsupportedValue RouteConditionReason = "UnsupportedValue" + + // This condition indicates whether the controller was able to resolve all + // the object references for the Route. + // + // Possible reasons for this condition to be true are: + // + // * "ResolvedRefs" + // + // Possible reasons for this condition to be false are: + // + // * "RefNotPermitted" + // * "InvalidKind" + // * "BackendNotFound" + // + // Controllers may raise this condition with other reasons, + // but should prefer to use the reasons listed above to improve + // interoperability. + RouteConditionResolvedRefs RouteConditionType = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when the condition + // is true. + RouteReasonResolvedRefs RouteConditionReason = "ResolvedRefs" + + // This reason is used with the "ResolvedRefs" condition when + // one of the Listener's Routes has a BackendRef to an object in + // another namespace, where the object in the other namespace does + // not have a ReferenceGrant explicitly allowing the reference. + RouteReasonRefNotPermitted RouteConditionReason = "RefNotPermitted" + + // This reason is used with the "ResolvedRefs" condition when + // one of the Route's rules has a reference to an unknown or unsupported + // Group and/or Kind. + RouteReasonInvalidKind RouteConditionReason = "InvalidKind" + + // This reason is used with the "ResolvedRefs" condition when one of the + // Route's rules has a reference to a resource that does not exist. + RouteReasonBackendNotFound RouteConditionReason = "BackendNotFound" +) + +// RouteParentStatus describes the status of a route with respect to an +// associated Parent. +type RouteParentStatus struct { + // ParentRef corresponds with a ParentRef in the spec that this + // RouteParentStatus struct describes the status of. + ParentRef ParentReference `json:"parentRef"` + + // ControllerName is a domain/path string that indicates the name of the + // controller that wrote this status. This corresponds with the + // controllerName field on GatewayClass. + // + // Example: "example.net/gateway-controller". + // + // The format of this field is DOMAIN "/" PATH, where DOMAIN and PATH are + // valid Kubernetes names + // (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + // + // Controllers MUST populate this field when writing status. Controllers should ensure that + // entries to status populated with their ControllerName are cleaned up when they are no + // longer necessary. + ControllerName GatewayController `json:"controllerName"` + + // Conditions describes the status of the route with respect to the Gateway. + // Note that the route's availability is also subject to the Gateway's own + // status conditions and listener status. + // + // If the Route's ParentRef specifies an existing Gateway that supports + // Routes of this kind AND that Gateway's controller has sufficient access, + // then that Gateway's controller MUST set the "Accepted" condition on the + // Route, to indicate whether the route has been accepted or rejected by the + // Gateway, and why. + // + // A Route MUST be considered "Accepted" if at least one of the Route's + // rules is implemented by the Gateway. + // + // There are a number of cases where the "Accepted" condition may not be set + // due to lack of controller visibility, that includes when: + // + // * The Route refers to a non-existent parent. + // * The Route is of a type that the controller does not support. + // * The Route is in a namespace the controller does not have access to. + // + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// RouteStatus defines the common attributes that all Routes MUST include within +// their status. +type RouteStatus struct { + // Parents is a list of parent resources (usually Gateways) that are + // associated with the route, and the status of the route with respect to + // each parent. When this route attaches to a parent, the controller that + // manages the parent must add an entry to this list when the controller + // first sees the route and should update the entry as appropriate when the + // route or gateway is modified. + // + // Note that parent references that cannot be resolved by an implementation + // of this API will not be added to this list. Implementations of this API + // can only populate Route status for the Gateways/parent resources they are + // responsible for. + // + // A maximum of 32 Gateways will be represented in this list. An empty list + // means the route has not been attached to any Gateway. + // + // +kubebuilder:validation:MaxItems=32 + Parents []RouteParentStatus `json:"parents"` +} + +// Hostname is the fully qualified domain name of a network host. This matches +// the RFC 1123 definition of a hostname with 2 notable exceptions: +// +// 1. IPs are not allowed. +// 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard +// label must appear by itself as the first label. +// +// Hostname can be "precise" which is a domain name without the terminating +// dot of a network host (e.g. "foo.example.com") or "wildcard", which is a +// domain name prefixed with a single wildcard label (e.g. `*.example.com`). +// +// Note that as per RFC1035 and RFC1123, a *label* must consist of lower case +// alphanumeric characters or '-', and must start and end with an alphanumeric +// character. No other punctuation is allowed. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` +type Hostname string + +// PreciseHostname is the fully qualified domain name of a network host. This +// matches the RFC 1123 definition of a hostname with 1 notable exception that +// numeric IP addresses are not allowed. +// +// Note that as per RFC1035 and RFC1123, a *label* must consist of lower case +// alphanumeric characters or '-', and must start and end with an alphanumeric +// character. No other punctuation is allowed. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` +type PreciseHostname string + +// Group refers to a Kubernetes Group. It must either be an empty string or a +// RFC 1123 subdomain. +// +// This validation is based off of the corresponding Kubernetes validation: +// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208 +// +// Valid values include: +// +// * "" - empty string implies core Kubernetes API group +// * "networking.k8s.io" +// * "foo.example.com" +// +// Invalid values include: +// +// * "example.com/bar" - "/" is an invalid character +// +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` +type Group string + +// Kind refers to a Kubernetes Kind. +// +// Valid values include: +// +// * "Service" +// * "HTTPRoute" +// +// Invalid values include: +// +// * "invalid/kind" - "/" is an invalid character +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=63 +// +kubebuilder:validation:Pattern=`^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$` +type Kind string + +// ObjectName refers to the name of a Kubernetes object. +// Object names can have a variety of forms, including RFC1123 subdomains, +// RFC 1123 labels, or RFC 1035 labels. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +type ObjectName string + +// Namespace refers to a Kubernetes namespace. It must be a RFC 1123 label. +// +// This validation is based off of the corresponding Kubernetes validation: +// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L187 +// +// This is used for Namespace name validation here: +// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/api/validation/generic.go#L63 +// +// Valid values include: +// +// * "example" +// +// Invalid values include: +// +// * "example.com" - "." is an invalid character +// +// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=63 +type Namespace string + +// SectionName is the name of a section in a Kubernetes resource. +// +// This validation is based off of the corresponding Kubernetes validation: +// https://github.com/kubernetes/apimachinery/blob/02cfb53916346d085a6c6c7c66f882e3c6b0eca6/pkg/util/validation/validation.go#L208 +// +// Valid values include: +// +// * "example.com" +// * "foo.example.com" +// +// Invalid values include: +// +// * "example.com/bar" - "/" is an invalid character +// +// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +type SectionName string + +// GatewayController is the name of a Gateway API controller. It must be a +// domain prefixed path. +// +// Valid values include: +// +// * "example.com/bar" +// +// Invalid values include: +// +// * "example.com" - must include path +// * "foo.example.com" - must include path +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` +type GatewayController string + +// AnnotationKey is the key of an annotation in Gateway API. This is used for +// validation of maps such as TLS options. This matches the Kubernetes +// "qualified name" validation that is used for annotations and other common +// values. +// +// Valid values include: +// +// * example +// * example.com +// * example.com/path +// * example.com/path.html +// +// Invalid values include: +// +// * example~ - "~" is an invalid character +// * example.com. - can not start or end with "." +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]/?)*$` +type AnnotationKey string + +// AnnotationValue is the value of an annotation in Gateway API. This is used +// for validation of maps such as TLS options. This roughly matches Kubernetes +// annotation validation, although the length validation in that case is based +// on the entire size of the annotations struct. +// +// +kubebuilder:validation:MinLength=0 +// +kubebuilder:validation:MaxLength=4096 +type AnnotationValue string + +// AddressType defines how a network address is represented as a text string. +// This may take two possible forms: +// +// * A predefined CamelCase string identifier (currently limited to `IPAddress` or `Hostname`) +// * A domain-prefixed string identifier (like `acme.io/CustomAddressType`) +// +// Values `IPAddress` and `Hostname` have Extended support. +// +// The `NamedAddress` value has been deprecated in favor of implementation +// specific domain-prefixed strings. +// +// All other values, including domain-prefixed values have Custom support, which +// are used in implementation-specific behaviors. Support for additional +// predefined CamelCase identifiers may be added in future releases. +// +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=253 +// +kubebuilder:validation:Pattern=`^Hostname|IPAddress|NamedAddress|[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$` +type AddressType string + +const ( + // A textual representation of a numeric IP address. IPv4 + // addresses must be in dotted-decimal form. IPv6 addresses + // must be in a standard IPv6 text representation + // (see [RFC 5952](https://tools.ietf.org/html/rfc5952)). + // + // This type is intended for specific addresses. Address ranges are not + // supported (e.g. you can not use a CIDR range like 127.0.0.0/24 as an + // IPAddress). + // + // Support: Extended + IPAddressType AddressType = "IPAddress" + + // A Hostname represents a DNS based ingress point. This is similar to the + // corresponding hostname field in Kubernetes load balancer status. For + // example, this concept may be used for cloud load balancers where a DNS + // name is used to expose a load balancer. + // + // Support: Extended + HostnameAddressType AddressType = "Hostname" + + // A NamedAddress provides a way to reference a specific IP address by name. + // For example, this may be a name or other unique identifier that refers + // to a resource on a cloud provider such as a static IP. + // + // The `NamedAddress` type has been deprecated in favor of implementation + // specific domain-prefixed strings. + // + // Support: Implementation-Specific + NamedAddressType AddressType = "NamedAddress" +) diff --git a/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/zz_generated.deepcopy.go b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..cbea355eae --- /dev/null +++ b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,1127 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AllowedRoutes) DeepCopyInto(out *AllowedRoutes) { + *out = *in + if in.Namespaces != nil { + in, out := &in.Namespaces, &out.Namespaces + *out = new(RouteNamespaces) + (*in).DeepCopyInto(*out) + } + if in.Kinds != nil { + in, out := &in.Kinds, &out.Kinds + *out = make([]RouteGroupKind, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AllowedRoutes. +func (in *AllowedRoutes) DeepCopy() *AllowedRoutes { + if in == nil { + return nil + } + out := new(AllowedRoutes) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendObjectReference) DeepCopyInto(out *BackendObjectReference) { + *out = *in + if in.Group != nil { + in, out := &in.Group, &out.Group + *out = new(Group) + **out = **in + } + if in.Kind != nil { + in, out := &in.Kind, &out.Kind + *out = new(Kind) + **out = **in + } + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(Namespace) + **out = **in + } + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(PortNumber) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendObjectReference. +func (in *BackendObjectReference) DeepCopy() *BackendObjectReference { + if in == nil { + return nil + } + out := new(BackendObjectReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendRef) DeepCopyInto(out *BackendRef) { + *out = *in + in.BackendObjectReference.DeepCopyInto(&out.BackendObjectReference) + if in.Weight != nil { + in, out := &in.Weight, &out.Weight + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendRef. +func (in *BackendRef) DeepCopy() *BackendRef { + if in == nil { + return nil + } + out := new(BackendRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CommonRouteSpec) DeepCopyInto(out *CommonRouteSpec) { + *out = *in + if in.ParentRefs != nil { + in, out := &in.ParentRefs, &out.ParentRefs + *out = make([]ParentReference, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonRouteSpec. +func (in *CommonRouteSpec) DeepCopy() *CommonRouteSpec { + if in == nil { + return nil + } + out := new(CommonRouteSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Gateway) DeepCopyInto(out *Gateway) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Gateway. +func (in *Gateway) DeepCopy() *Gateway { + if in == nil { + return nil + } + out := new(Gateway) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Gateway) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayAddress) DeepCopyInto(out *GatewayAddress) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(AddressType) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayAddress. +func (in *GatewayAddress) DeepCopy() *GatewayAddress { + if in == nil { + return nil + } + out := new(GatewayAddress) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayClass) DeepCopyInto(out *GatewayClass) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClass. +func (in *GatewayClass) DeepCopy() *GatewayClass { + if in == nil { + return nil + } + out := new(GatewayClass) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GatewayClass) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayClassList) DeepCopyInto(out *GatewayClassList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]GatewayClass, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassList. +func (in *GatewayClassList) DeepCopy() *GatewayClassList { + if in == nil { + return nil + } + out := new(GatewayClassList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GatewayClassList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayClassSpec) DeepCopyInto(out *GatewayClassSpec) { + *out = *in + if in.ParametersRef != nil { + in, out := &in.ParametersRef, &out.ParametersRef + *out = new(ParametersReference) + (*in).DeepCopyInto(*out) + } + if in.Description != nil { + in, out := &in.Description, &out.Description + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassSpec. +func (in *GatewayClassSpec) DeepCopy() *GatewayClassSpec { + if in == nil { + return nil + } + out := new(GatewayClassSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayClassStatus) DeepCopyInto(out *GatewayClassStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayClassStatus. +func (in *GatewayClassStatus) DeepCopy() *GatewayClassStatus { + if in == nil { + return nil + } + out := new(GatewayClassStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayList) DeepCopyInto(out *GatewayList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Gateway, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayList. +func (in *GatewayList) DeepCopy() *GatewayList { + if in == nil { + return nil + } + out := new(GatewayList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GatewayList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewaySpec) DeepCopyInto(out *GatewaySpec) { + *out = *in + if in.Listeners != nil { + in, out := &in.Listeners, &out.Listeners + *out = make([]Listener, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]GatewayAddress, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewaySpec. +func (in *GatewaySpec) DeepCopy() *GatewaySpec { + if in == nil { + return nil + } + out := new(GatewaySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayStatus) DeepCopyInto(out *GatewayStatus) { + *out = *in + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]GatewayAddress, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Listeners != nil { + in, out := &in.Listeners, &out.Listeners + *out = make([]ListenerStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayStatus. +func (in *GatewayStatus) DeepCopy() *GatewayStatus { + if in == nil { + return nil + } + out := new(GatewayStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayTLSConfig) DeepCopyInto(out *GatewayTLSConfig) { + *out = *in + if in.Mode != nil { + in, out := &in.Mode, &out.Mode + *out = new(TLSModeType) + **out = **in + } + if in.CertificateRefs != nil { + in, out := &in.CertificateRefs, &out.CertificateRefs + *out = make([]SecretObjectReference, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Options != nil { + in, out := &in.Options, &out.Options + *out = make(map[AnnotationKey]AnnotationValue, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayTLSConfig. +func (in *GatewayTLSConfig) DeepCopy() *GatewayTLSConfig { + if in == nil { + return nil + } + out := new(GatewayTLSConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPBackendRef) DeepCopyInto(out *HTTPBackendRef) { + *out = *in + in.BackendRef.DeepCopyInto(&out.BackendRef) + if in.Filters != nil { + in, out := &in.Filters, &out.Filters + *out = make([]HTTPRouteFilter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPBackendRef. +func (in *HTTPBackendRef) DeepCopy() *HTTPBackendRef { + if in == nil { + return nil + } + out := new(HTTPBackendRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPHeader) DeepCopyInto(out *HTTPHeader) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeader. +func (in *HTTPHeader) DeepCopy() *HTTPHeader { + if in == nil { + return nil + } + out := new(HTTPHeader) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPHeaderMatch) DeepCopyInto(out *HTTPHeaderMatch) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(HeaderMatchType) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPHeaderMatch. +func (in *HTTPHeaderMatch) DeepCopy() *HTTPHeaderMatch { + if in == nil { + return nil + } + out := new(HTTPHeaderMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPPathMatch) DeepCopyInto(out *HTTPPathMatch) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(PathMatchType) + **out = **in + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPPathMatch. +func (in *HTTPPathMatch) DeepCopy() *HTTPPathMatch { + if in == nil { + return nil + } + out := new(HTTPPathMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPPathModifier) DeepCopyInto(out *HTTPPathModifier) { + *out = *in + if in.ReplaceFullPath != nil { + in, out := &in.ReplaceFullPath, &out.ReplaceFullPath + *out = new(string) + **out = **in + } + if in.ReplacePrefixMatch != nil { + in, out := &in.ReplacePrefixMatch, &out.ReplacePrefixMatch + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPPathModifier. +func (in *HTTPPathModifier) DeepCopy() *HTTPPathModifier { + if in == nil { + return nil + } + out := new(HTTPPathModifier) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPQueryParamMatch) DeepCopyInto(out *HTTPQueryParamMatch) { + *out = *in + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(QueryParamMatchType) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPQueryParamMatch. +func (in *HTTPQueryParamMatch) DeepCopy() *HTTPQueryParamMatch { + if in == nil { + return nil + } + out := new(HTTPQueryParamMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRequestHeaderFilter) DeepCopyInto(out *HTTPRequestHeaderFilter) { + *out = *in + if in.Set != nil { + in, out := &in.Set, &out.Set + *out = make([]HTTPHeader, len(*in)) + copy(*out, *in) + } + if in.Add != nil { + in, out := &in.Add, &out.Add + *out = make([]HTTPHeader, len(*in)) + copy(*out, *in) + } + if in.Remove != nil { + in, out := &in.Remove, &out.Remove + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRequestHeaderFilter. +func (in *HTTPRequestHeaderFilter) DeepCopy() *HTTPRequestHeaderFilter { + if in == nil { + return nil + } + out := new(HTTPRequestHeaderFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRequestMirrorFilter) DeepCopyInto(out *HTTPRequestMirrorFilter) { + *out = *in + in.BackendRef.DeepCopyInto(&out.BackendRef) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRequestMirrorFilter. +func (in *HTTPRequestMirrorFilter) DeepCopy() *HTTPRequestMirrorFilter { + if in == nil { + return nil + } + out := new(HTTPRequestMirrorFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRequestRedirectFilter) DeepCopyInto(out *HTTPRequestRedirectFilter) { + *out = *in + if in.Scheme != nil { + in, out := &in.Scheme, &out.Scheme + *out = new(string) + **out = **in + } + if in.Hostname != nil { + in, out := &in.Hostname, &out.Hostname + *out = new(PreciseHostname) + **out = **in + } + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(HTTPPathModifier) + (*in).DeepCopyInto(*out) + } + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(PortNumber) + **out = **in + } + if in.StatusCode != nil { + in, out := &in.StatusCode, &out.StatusCode + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRequestRedirectFilter. +func (in *HTTPRequestRedirectFilter) DeepCopy() *HTTPRequestRedirectFilter { + if in == nil { + return nil + } + out := new(HTTPRequestRedirectFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRoute. +func (in *HTTPRoute) DeepCopy() *HTTPRoute { + if in == nil { + return nil + } + out := new(HTTPRoute) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HTTPRoute) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteFilter) DeepCopyInto(out *HTTPRouteFilter) { + *out = *in + if in.RequestHeaderModifier != nil { + in, out := &in.RequestHeaderModifier, &out.RequestHeaderModifier + *out = new(HTTPRequestHeaderFilter) + (*in).DeepCopyInto(*out) + } + if in.RequestMirror != nil { + in, out := &in.RequestMirror, &out.RequestMirror + *out = new(HTTPRequestMirrorFilter) + (*in).DeepCopyInto(*out) + } + if in.RequestRedirect != nil { + in, out := &in.RequestRedirect, &out.RequestRedirect + *out = new(HTTPRequestRedirectFilter) + (*in).DeepCopyInto(*out) + } + if in.URLRewrite != nil { + in, out := &in.URLRewrite, &out.URLRewrite + *out = new(HTTPURLRewriteFilter) + (*in).DeepCopyInto(*out) + } + if in.ExtensionRef != nil { + in, out := &in.ExtensionRef, &out.ExtensionRef + *out = new(LocalObjectReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteFilter. +func (in *HTTPRouteFilter) DeepCopy() *HTTPRouteFilter { + if in == nil { + return nil + } + out := new(HTTPRouteFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteList) DeepCopyInto(out *HTTPRouteList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]HTTPRoute, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteList. +func (in *HTTPRouteList) DeepCopy() *HTTPRouteList { + if in == nil { + return nil + } + out := new(HTTPRouteList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *HTTPRouteList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteMatch) DeepCopyInto(out *HTTPRouteMatch) { + *out = *in + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(HTTPPathMatch) + (*in).DeepCopyInto(*out) + } + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make([]HTTPHeaderMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.QueryParams != nil { + in, out := &in.QueryParams, &out.QueryParams + *out = make([]HTTPQueryParamMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Method != nil { + in, out := &in.Method, &out.Method + *out = new(HTTPMethod) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteMatch. +func (in *HTTPRouteMatch) DeepCopy() *HTTPRouteMatch { + if in == nil { + return nil + } + out := new(HTTPRouteMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteRule) DeepCopyInto(out *HTTPRouteRule) { + *out = *in + if in.Matches != nil { + in, out := &in.Matches, &out.Matches + *out = make([]HTTPRouteMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Filters != nil { + in, out := &in.Filters, &out.Filters + *out = make([]HTTPRouteFilter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.BackendRefs != nil { + in, out := &in.BackendRefs, &out.BackendRefs + *out = make([]HTTPBackendRef, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteRule. +func (in *HTTPRouteRule) DeepCopy() *HTTPRouteRule { + if in == nil { + return nil + } + out := new(HTTPRouteRule) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteSpec) DeepCopyInto(out *HTTPRouteSpec) { + *out = *in + in.CommonRouteSpec.DeepCopyInto(&out.CommonRouteSpec) + if in.Hostnames != nil { + in, out := &in.Hostnames, &out.Hostnames + *out = make([]Hostname, len(*in)) + copy(*out, *in) + } + if in.Rules != nil { + in, out := &in.Rules, &out.Rules + *out = make([]HTTPRouteRule, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteSpec. +func (in *HTTPRouteSpec) DeepCopy() *HTTPRouteSpec { + if in == nil { + return nil + } + out := new(HTTPRouteSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteStatus) DeepCopyInto(out *HTTPRouteStatus) { + *out = *in + in.RouteStatus.DeepCopyInto(&out.RouteStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteStatus. +func (in *HTTPRouteStatus) DeepCopy() *HTTPRouteStatus { + if in == nil { + return nil + } + out := new(HTTPRouteStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPURLRewriteFilter) DeepCopyInto(out *HTTPURLRewriteFilter) { + *out = *in + if in.Hostname != nil { + in, out := &in.Hostname, &out.Hostname + *out = new(PreciseHostname) + **out = **in + } + if in.Path != nil { + in, out := &in.Path, &out.Path + *out = new(HTTPPathModifier) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPURLRewriteFilter. +func (in *HTTPURLRewriteFilter) DeepCopy() *HTTPURLRewriteFilter { + if in == nil { + return nil + } + out := new(HTTPURLRewriteFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Listener) DeepCopyInto(out *Listener) { + *out = *in + if in.Hostname != nil { + in, out := &in.Hostname, &out.Hostname + *out = new(Hostname) + **out = **in + } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(GatewayTLSConfig) + (*in).DeepCopyInto(*out) + } + if in.AllowedRoutes != nil { + in, out := &in.AllowedRoutes, &out.AllowedRoutes + *out = new(AllowedRoutes) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Listener. +func (in *Listener) DeepCopy() *Listener { + if in == nil { + return nil + } + out := new(Listener) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ListenerStatus) DeepCopyInto(out *ListenerStatus) { + *out = *in + if in.SupportedKinds != nil { + in, out := &in.SupportedKinds, &out.SupportedKinds + *out = make([]RouteGroupKind, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerStatus. +func (in *ListenerStatus) DeepCopy() *ListenerStatus { + if in == nil { + return nil + } + out := new(ListenerStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LocalObjectReference) DeepCopyInto(out *LocalObjectReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalObjectReference. +func (in *LocalObjectReference) DeepCopy() *LocalObjectReference { + if in == nil { + return nil + } + out := new(LocalObjectReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ParametersReference) DeepCopyInto(out *ParametersReference) { + *out = *in + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(Namespace) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParametersReference. +func (in *ParametersReference) DeepCopy() *ParametersReference { + if in == nil { + return nil + } + out := new(ParametersReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ParentReference) DeepCopyInto(out *ParentReference) { + *out = *in + if in.Group != nil { + in, out := &in.Group, &out.Group + *out = new(Group) + **out = **in + } + if in.Kind != nil { + in, out := &in.Kind, &out.Kind + *out = new(Kind) + **out = **in + } + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(Namespace) + **out = **in + } + if in.SectionName != nil { + in, out := &in.SectionName, &out.SectionName + *out = new(SectionName) + **out = **in + } + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(PortNumber) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParentReference. +func (in *ParentReference) DeepCopy() *ParentReference { + if in == nil { + return nil + } + out := new(ParentReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteGroupKind) DeepCopyInto(out *RouteGroupKind) { + *out = *in + if in.Group != nil { + in, out := &in.Group, &out.Group + *out = new(Group) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteGroupKind. +func (in *RouteGroupKind) DeepCopy() *RouteGroupKind { + if in == nil { + return nil + } + out := new(RouteGroupKind) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteNamespaces) DeepCopyInto(out *RouteNamespaces) { + *out = *in + if in.From != nil { + in, out := &in.From, &out.From + *out = new(FromNamespaces) + **out = **in + } + if in.Selector != nil { + in, out := &in.Selector, &out.Selector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteNamespaces. +func (in *RouteNamespaces) DeepCopy() *RouteNamespaces { + if in == nil { + return nil + } + out := new(RouteNamespaces) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteParentStatus) DeepCopyInto(out *RouteParentStatus) { + *out = *in + in.ParentRef.DeepCopyInto(&out.ParentRef) + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteParentStatus. +func (in *RouteParentStatus) DeepCopy() *RouteParentStatus { + if in == nil { + return nil + } + out := new(RouteParentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteStatus) DeepCopyInto(out *RouteStatus) { + *out = *in + if in.Parents != nil { + in, out := &in.Parents, &out.Parents + *out = make([]RouteParentStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteStatus. +func (in *RouteStatus) DeepCopy() *RouteStatus { + if in == nil { + return nil + } + out := new(RouteStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretObjectReference) DeepCopyInto(out *SecretObjectReference) { + *out = *in + if in.Group != nil { + in, out := &in.Group, &out.Group + *out = new(Group) + **out = **in + } + if in.Kind != nil { + in, out := &in.Kind, &out.Kind + *out = new(Kind) + **out = **in + } + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(Namespace) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretObjectReference. +func (in *SecretObjectReference) DeepCopy() *SecretObjectReference { + if in == nil { + return nil + } + out := new(SecretObjectReference) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/zz_generated.register.go b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/zz_generated.register.go new file mode 100644 index 0000000000..7cb684d1cf --- /dev/null +++ b/vendor/sigs.k8s.io/gateway-api/apis/v1beta1/zz_generated.register.go @@ -0,0 +1,71 @@ +/* +Copyright 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. +*/ + +// Code generated by register-gen. DO NOT EDIT. + +package v1beta1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName specifies the group name used to register the objects. +const GroupName = "gateway.networking.k8s.io" + +// GroupVersion specifies the group and the version used to register the objects. +var GroupVersion = v1.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// SchemeGroupVersion is group version used to register these objects +// Deprecated: use GroupVersion instead. +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // Depreciated: use Install instead + AddToScheme = localSchemeBuilder.AddToScheme + Install = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &Gateway{}, + &GatewayClass{}, + &GatewayClassList{}, + &GatewayList{}, + &HTTPRoute{}, + &HTTPRouteList{}, + ) + // AddToGroupVersion allows the serialization of client types like ListOptions. + v1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +}