From 2b3661791428d646f81c266d8d0b4bc6480b80ba Mon Sep 17 00:00:00 2001 From: ramr Date: Mon, 9 Jul 2018 15:17:40 -0700 Subject: [PATCH] bump(*) --- .../github_com_openshift_api_image_v1.proto | 38 + glide.lock | 20 +- pkg/openapi/zz_generated.openapi.go | 126 ++ .../github.com/bcicen/go-haproxy/.gitignore | 24 + vendor/github.com/bcicen/go-haproxy/LICENSE | 21 + vendor/github.com/bcicen/go-haproxy/README.md | 28 + vendor/github.com/bcicen/go-haproxy/client.go | 78 + .../bcicen/go-haproxy/client_test.go | 52 + vendor/github.com/bcicen/go-haproxy/info.go | 73 + .../bcicen/go-haproxy/kvcodec/types.go | 193 +++ .../bcicen/go-haproxy/kvcodec/unmarshal.go | 124 ++ vendor/github.com/bcicen/go-haproxy/stat.go | 102 ++ vendor/github.com/gocarina/gocsv/.gitignore | 1 + vendor/github.com/gocarina/gocsv/.travis.yml | 1 + vendor/github.com/gocarina/gocsv/LICENSE | 21 + vendor/github.com/gocarina/gocsv/README.md | 170 +++ vendor/github.com/gocarina/gocsv/csv.go | 324 ++++ vendor/github.com/gocarina/gocsv/decode.go | 368 +++++ .../github.com/gocarina/gocsv/decode_test.go | 596 ++++++++ vendor/github.com/gocarina/gocsv/encode.go | 139 ++ .../github.com/gocarina/gocsv/encode_test.go | 295 ++++ vendor/github.com/gocarina/gocsv/reflect.go | 107 ++ vendor/github.com/gocarina/gocsv/safe_csv.go | 32 + .../gocarina/gocsv/sample_structs_test.go | 50 + vendor/github.com/gocarina/gocsv/types.go | 456 ++++++ .../github.com/gocarina/gocsv/types_test.go | 91 ++ .../github.com/gocarina/gocsv/unmarshaller.go | 115 ++ .../openshift/api/authorization/install.go | 2 +- .../openshift/api/image/v1/generated.pb.go | 1307 ++++++++++++++--- .../openshift/api/image/v1/generated.proto | 38 + .../openshift/api/image/v1/register.go | 1 + .../openshift/api/image/v1/types.go | 38 + .../image/v1/types_swagger_doc_generated.go | 31 + .../api/image/v1/zz_generated.deepcopy.go | 99 ++ .../github.com/openshift/client-go/glide.lock | 4 +- .../typed/image/v1/fake/fake_imagestream.go | 11 + .../versioned/typed/image/v1/imagestream.go | 15 + .../cmd/imagebuilder/imagebuilder.go | 2 +- .../imagebuilder/dockerclient/archive.go | 149 +- .../imagebuilder/dockerclient/archive_test.go | 33 + .../imagebuilder/dockerclient/client.go | 15 +- .../dockerclient/conformance_test.go | 19 +- .../dockerclient/copyinfo_test.go | 47 +- .../imagebuilder/dockerclient/directory.go | 87 ++ .../dockerclient/testdata/copy/Dockerfile | 3 + .../dockerclient/testdata/copy/script | 2 + .../dockerclient/testdata/copydir/Dockerfile | 3 + .../dockerclient/testdata/copydir/dir/file | 0 .../testdata/copyrename/Dockerfile | 3 + .../dockerclient/testdata/copyrename/file1 | 2 + .../service-serving-cert-signer/Dockerfile | 11 + .../service-serving-cert-signer/Makefile | 2 +- .../hack/build-images.sh | 9 +- .../hack/lib/constants.sh | 2 +- .../hack/lib/test/junit.sh | 59 - .../hack/lib/util/golang.sh | 19 - .../hack/test-go.sh | 18 +- .../hack/verify-gofmt.sh | 2 - .../hack/verify-golint.sh | 1 - .../hack/verify-govet.sh | 2 - .../hack/verify-imports.sh | 1 - .../hack/verify-upstream-commits.sh | 1 - .../service-serving-cert-signer/.cccp.yml | 1 - .../service-serving-cert-signer/Dockerfile | 20 - .../bin/.gitignore | 2 - .../pkg/operator/merge.go | 91 ++ .../pkg/operator/merge_test.go | 122 ++ .../pkg/operator/sync_v310_00.go | 19 +- .../tools/gotest2junit/gotest2junit.go | 211 +++ .../tools/gotest2junit/pkg/api/junit.xsd | 203 +++ .../tools/gotest2junit/pkg/api/string.go | 37 + .../tools/gotest2junit/pkg/api/test_case.go | 30 + .../tools/gotest2junit/pkg/api/test_suite.go | 67 + .../tools/gotest2junit/pkg/api/types.go | 108 ++ .../tools/gotest2junit/test/test_test.go | 18 + 75 files changed, 6149 insertions(+), 463 deletions(-) create mode 100644 vendor/github.com/bcicen/go-haproxy/.gitignore create mode 100644 vendor/github.com/bcicen/go-haproxy/LICENSE create mode 100644 vendor/github.com/bcicen/go-haproxy/README.md create mode 100644 vendor/github.com/bcicen/go-haproxy/client.go create mode 100644 vendor/github.com/bcicen/go-haproxy/client_test.go create mode 100644 vendor/github.com/bcicen/go-haproxy/info.go create mode 100644 vendor/github.com/bcicen/go-haproxy/kvcodec/types.go create mode 100644 vendor/github.com/bcicen/go-haproxy/kvcodec/unmarshal.go create mode 100644 vendor/github.com/bcicen/go-haproxy/stat.go create mode 100644 vendor/github.com/gocarina/gocsv/.gitignore create mode 100644 vendor/github.com/gocarina/gocsv/.travis.yml create mode 100644 vendor/github.com/gocarina/gocsv/LICENSE create mode 100644 vendor/github.com/gocarina/gocsv/README.md create mode 100644 vendor/github.com/gocarina/gocsv/csv.go create mode 100644 vendor/github.com/gocarina/gocsv/decode.go create mode 100644 vendor/github.com/gocarina/gocsv/decode_test.go create mode 100644 vendor/github.com/gocarina/gocsv/encode.go create mode 100644 vendor/github.com/gocarina/gocsv/encode_test.go create mode 100644 vendor/github.com/gocarina/gocsv/reflect.go create mode 100644 vendor/github.com/gocarina/gocsv/safe_csv.go create mode 100644 vendor/github.com/gocarina/gocsv/sample_structs_test.go create mode 100644 vendor/github.com/gocarina/gocsv/types.go create mode 100644 vendor/github.com/gocarina/gocsv/types_test.go create mode 100644 vendor/github.com/gocarina/gocsv/unmarshaller.go create mode 100644 vendor/github.com/openshift/imagebuilder/dockerclient/directory.go create mode 100644 vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copy/Dockerfile create mode 100644 vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copy/script create mode 100644 vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copydir/Dockerfile create mode 100644 vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copydir/dir/file create mode 100644 vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copyrename/Dockerfile create mode 100644 vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copyrename/file1 create mode 100644 vendor/github.com/openshift/service-serving-cert-signer/Dockerfile delete mode 100644 vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/.cccp.yml delete mode 100644 vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/Dockerfile delete mode 100644 vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/bin/.gitignore create mode 100644 vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge.go create mode 100644 vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge_test.go create mode 100644 vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/gotest2junit.go create mode 100644 vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/junit.xsd create mode 100644 vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/string.go create mode 100644 vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/test_case.go create mode 100644 vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/test_suite.go create mode 100644 vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/types.go create mode 100644 vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/test/test_test.go diff --git a/api/protobuf-spec/github_com_openshift_api_image_v1.proto b/api/protobuf-spec/github_com_openshift_api_image_v1.proto index bbbfa5df7d40..417a6c1bb29d 100644 --- a/api/protobuf-spec/github_com_openshift_api_image_v1.proto +++ b/api/protobuf-spec/github_com_openshift_api_image_v1.proto @@ -68,6 +68,20 @@ message Image { optional string dockerImageConfig = 10; } +// ImageBlobReferences describes the blob references within an image. +message ImageBlobReferences { + // layers is the list of blobs that compose this image, from base layer to top layer. + // All layers referenced by this array will be defined in the blobs map. Some images + // may have zero layers. + // +optional + repeated string layers = 1; + + // manifest, if set, is the blob that contains the image manifest. Some images do + // not have separate manifest blobs and this field will be set to nil if so. + // +optional + optional string manifest = 2; +} + // ImageImportSpec describes a request to import a specific image. message ImageImportSpec { // From is the source of an image to import; only kind DockerImage is allowed @@ -110,6 +124,16 @@ message ImageLayer { optional string mediaType = 3; } +// ImageLayerData contains metadata about an image layer. +message ImageLayerData { + // Size of the layer in bytes as defined by the underlying store. This field is + // optional if the necessary information about size is not available. + optional int64 size = 1; + + // MediaType of the referenced object. + optional string mediaType = 2; +} + // ImageList is a list of Image objects. message ImageList { // Standard object's metadata. @@ -237,6 +261,20 @@ message ImageStreamImportStatus { repeated ImageImportStatus images = 3; } +// ImageStreamLayers describes information about the layers referenced by images in this +// image stream. +message ImageStreamLayers { + // Standard object's metadata. + optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + + // blobs is a map of blob name to metadata about the blob. + map blobs = 2; + + // images is a map between an image name and the names of the blobs and manifests that + // comprise the image. + map images = 3; +} + // ImageStreamList is a list of ImageStream objects. message ImageStreamList { // Standard object's metadata. diff --git a/glide.lock b/glide.lock index 210531561003..e6805667951e 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: df63691eefa0455af08310071c1457c268b7d58f2ceb813c0c29d06ec75a5d3d -updated: 2018-07-06T14:12:33.305926721-04:00 +hash: 39269802bf8a51701d8e237475097bf81797c5d59253ef5eb16c69870ab4820d +updated: 2018-07-10T15:40:06.28695469-07:00 imports: - name: bitbucket.org/ww/goautoneg version: 75cd24fc2f2c2a2088577d12123ddee5f54e0675 @@ -81,6 +81,10 @@ imports: - autorest/date - autorest/to - autorest/validation +- name: github.com/bcicen/go-haproxy + version: ff5824fe38bede761b873cab6e247a530e89236a + subpackages: + - kvcodec - name: github.com/beorn7/perks version: 3ac7bf7a47d159a033b107610db8a1b6575507a4 subpackages: @@ -425,6 +429,8 @@ imports: version: f3f9494671f93fcff853e3c6e9e948b3eb71e590 - name: github.com/go-openapi/validate version: d509235108fcf6ab4913d2dcb3a2260c0db2108e +- name: github.com/gocarina/gocsv + version: a5c9099e2484f1551abb9433885e158610a25f4b - name: github.com/godbus/dbus version: c7fdd8b5cd55e87b4e1f4e372cdb1db61dd6c66f - name: github.com/gogo/protobuf @@ -809,7 +815,7 @@ imports: - go-selinux - go-selinux/label - name: github.com/openshift/api - version: 95626b0211df2ed778b4d68c3e9e61138677d315 + version: 04a26bf3b8d69c390642c5803fe4cfdb899112aa subpackages: - apps/v1 - authorization/v1 @@ -831,7 +837,7 @@ imports: - user/v1 - webconsole/v1 - name: github.com/openshift/client-go - version: 4688ad28de2e88110c0ea30179c51b9b205f99be + version: b22949ca0eae046da7611d0d20c8089dcec212d6 subpackages: - apps/clientset/versioned - apps/clientset/versioned/scheme @@ -938,7 +944,7 @@ imports: - user/informers/externalversions/user/v1 - user/listers/user/v1 - name: github.com/openshift/imagebuilder - version: 4670fc31fca6121da0dcf42d6b9b298479c1715a + version: bfc0aea02ce95dcfc1a83d452270dbc66933709b subpackages: - dockerclient - imageprogress @@ -957,7 +963,7 @@ imports: - pkg/operator/resource/resourcemerge - pkg/serviceability - name: github.com/openshift/service-serving-cert-signer - version: 4e91b73f7394df0fffb885c35ac9b517cc385d2e + version: 10d530a76d1e98ae342df2fa5a3cbefd5dc3f241 subpackages: - pkg/controller/servingcert - pkg/controller/servingcert/cryptoextensions @@ -1827,7 +1833,7 @@ imports: - pkg/util/proto/testing - pkg/util/proto/validation - name: k8s.io/kubernetes - version: 5200705703cbf4abe250da3822f67e244e11d5b0 + version: aebe0498deb85f935a0126a4859b2a7610bd69c5 repo: https://github.com/openshift/kubernetes.git subpackages: - cmd/controller-manager/app diff --git a/pkg/openapi/zz_generated.openapi.go b/pkg/openapi/zz_generated.openapi.go index 8a1b2fa35633..f56dfc230c0f 100644 --- a/pkg/openapi/zz_generated.openapi.go +++ b/pkg/openapi/zz_generated.openapi.go @@ -131,9 +131,11 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/openshift/api/config/v1.ServingInfo": schema_openshift_api_config_v1_ServingInfo(ref), "github.com/openshift/api/image/v1.DockerImageReference": schema_openshift_api_image_v1_DockerImageReference(ref), "github.com/openshift/api/image/v1.Image": schema_openshift_api_image_v1_Image(ref), + "github.com/openshift/api/image/v1.ImageBlobReferences": schema_openshift_api_image_v1_ImageBlobReferences(ref), "github.com/openshift/api/image/v1.ImageImportSpec": schema_openshift_api_image_v1_ImageImportSpec(ref), "github.com/openshift/api/image/v1.ImageImportStatus": schema_openshift_api_image_v1_ImageImportStatus(ref), "github.com/openshift/api/image/v1.ImageLayer": schema_openshift_api_image_v1_ImageLayer(ref), + "github.com/openshift/api/image/v1.ImageLayerData": schema_openshift_api_image_v1_ImageLayerData(ref), "github.com/openshift/api/image/v1.ImageList": schema_openshift_api_image_v1_ImageList(ref), "github.com/openshift/api/image/v1.ImageLookupPolicy": schema_openshift_api_image_v1_ImageLookupPolicy(ref), "github.com/openshift/api/image/v1.ImageSignature": schema_openshift_api_image_v1_ImageSignature(ref), @@ -142,6 +144,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/openshift/api/image/v1.ImageStreamImport": schema_openshift_api_image_v1_ImageStreamImport(ref), "github.com/openshift/api/image/v1.ImageStreamImportSpec": schema_openshift_api_image_v1_ImageStreamImportSpec(ref), "github.com/openshift/api/image/v1.ImageStreamImportStatus": schema_openshift_api_image_v1_ImageStreamImportStatus(ref), + "github.com/openshift/api/image/v1.ImageStreamLayers": schema_openshift_api_image_v1_ImageStreamLayers(ref), "github.com/openshift/api/image/v1.ImageStreamList": schema_openshift_api_image_v1_ImageStreamList(ref), "github.com/openshift/api/image/v1.ImageStreamMapping": schema_openshift_api_image_v1_ImageStreamMapping(ref), "github.com/openshift/api/image/v1.ImageStreamSpec": schema_openshift_api_image_v1_ImageStreamSpec(ref), @@ -6832,6 +6835,40 @@ func schema_openshift_api_image_v1_Image(ref common.ReferenceCallback) common.Op } } +func schema_openshift_api_image_v1_ImageBlobReferences(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ImageBlobReferences describes the blob references within an image.", + Properties: map[string]spec.Schema{ + "layers": { + SchemaProps: spec.SchemaProps{ + Description: "layers is the list of blobs that compose this image, from base layer to top layer. All layers referenced by this array will be defined in the blobs map. Some images may have zero layers.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + "manifest": { + SchemaProps: spec.SchemaProps{ + Description: "manifest, if set, is the blob that contains the image manifest. Some images do not have separate manifest blobs and this field will be set to nil if so.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, + Dependencies: []string{}, + } +} + func schema_openshift_api_image_v1_ImageImportSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -6947,6 +6984,34 @@ func schema_openshift_api_image_v1_ImageLayer(ref common.ReferenceCallback) comm } } +func schema_openshift_api_image_v1_ImageLayerData(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ImageLayerData contains metadata about an image layer.", + Properties: map[string]spec.Schema{ + "size": { + SchemaProps: spec.SchemaProps{ + Description: "Size of the layer in bytes as defined by the underlying store. This field is optional if the necessary information about size is not available.", + Type: []string{"integer"}, + Format: "int64", + }, + }, + "mediaType": { + SchemaProps: spec.SchemaProps{ + Description: "MediaType of the referenced object.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"size", "mediaType"}, + }, + }, + Dependencies: []string{}, + } +} + func schema_openshift_api_image_v1_ImageList(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -7338,6 +7403,67 @@ func schema_openshift_api_image_v1_ImageStreamImportStatus(ref common.ReferenceC } } +func schema_openshift_api_image_v1_ImageStreamLayers(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ImageStreamLayers describes information about the layers referenced by images in this image stream.", + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Description: "Standard object's metadata.", + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "blobs": { + SchemaProps: spec.SchemaProps{ + Description: "blobs is a map of blob name to metadata about the blob.", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/openshift/api/image/v1.ImageLayerData"), + }, + }, + }, + }, + }, + "images": { + SchemaProps: spec.SchemaProps{ + Description: "images is a map between an image name and the names of the blobs and manifests that comprise the image.", + Type: []string{"object"}, + AdditionalProperties: &spec.SchemaOrBool{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/openshift/api/image/v1.ImageBlobReferences"), + }, + }, + }, + }, + }, + }, + Required: []string{"blobs", "images"}, + }, + }, + Dependencies: []string{ + "github.com/openshift/api/image/v1.ImageBlobReferences", "github.com/openshift/api/image/v1.ImageLayerData", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + func schema_openshift_api_image_v1_ImageStreamList(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/vendor/github.com/bcicen/go-haproxy/.gitignore b/vendor/github.com/bcicen/go-haproxy/.gitignore new file mode 100644 index 000000000000..daf913b1b347 --- /dev/null +++ b/vendor/github.com/bcicen/go-haproxy/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/bcicen/go-haproxy/LICENSE b/vendor/github.com/bcicen/go-haproxy/LICENSE new file mode 100644 index 000000000000..b9911fa2fbca --- /dev/null +++ b/vendor/github.com/bcicen/go-haproxy/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 bradley + +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/bcicen/go-haproxy/README.md b/vendor/github.com/bcicen/go-haproxy/README.md new file mode 100644 index 000000000000..9a8dde698068 --- /dev/null +++ b/vendor/github.com/bcicen/go-haproxy/README.md @@ -0,0 +1,28 @@ +[![GoDoc](https://godoc.org/github.com/bcicen/go-haproxy?status.svg)](https://godoc.org/github.com/bcicen/go-haproxy) +[![codebeat badge](https://codebeat.co/badges/f947c19e-0d7b-47d0-87b4-4e2e555ba806)](https://codebeat.co/projects/github-com-bcicen-go-haproxy) + +# go-haproxy +Go library for interacting with HAProxys stats socket. + +## Usage + +Initialize a client object. Supported address schemas are `tcp://` and `unix:///` +```go +client := &haproxy.HAProxyClient{ + Addr: "tcp://localhost:9999", +} +``` + +Fetch results for a built in command(currently supports `show stats` and `show info`): +```go +stats, err := client.Stats() +for _, i := range stats { + fmt.Printf("%s: %s\n", i.SvName, i.Status) +} +``` + +Or retrieve the result body from an arbitrary command string: +```go +result, err := h.RunCommand("show info") +fmt.Println(result.String()) +``` diff --git a/vendor/github.com/bcicen/go-haproxy/client.go b/vendor/github.com/bcicen/go-haproxy/client.go new file mode 100644 index 000000000000..db7898358584 --- /dev/null +++ b/vendor/github.com/bcicen/go-haproxy/client.go @@ -0,0 +1,78 @@ +// Package haproxy provides a minimal client for communicating with, and issuing commands to, HAproxy over a network or file socket. +package haproxy + +import ( + "bytes" + "fmt" + "io" + "net" + "strings" + "time" +) + +const ( + socketSchema = "unix://" + tcpSchema = "tcp://" +) + +// HAProxyClient is the main structure of the library. +type HAProxyClient struct { + Addr string + Timeout int + conn net.Conn +} + +// RunCommand is the entrypoint to the client. Sends an arbitray command string to HAProxy. +func (h *HAProxyClient) RunCommand(cmd string) (*bytes.Buffer, error) { + err := h.dial() + if err != nil { + return nil, err + } + defer h.conn.Close() + + result := bytes.NewBuffer(nil) + + _, err = h.conn.Write([]byte(cmd + "\n")) + if err != nil { + return nil, err + } + + _, err = io.Copy(result, h.conn) + if err != nil { + return nil, err + } + + if strings.HasPrefix(result.String(), "Unknown command") { + return nil, fmt.Errorf("Unknown command: %s", cmd) + } + + return result, nil +} + +func (h *HAProxyClient) dial() (err error) { + if h.Timeout == 0 { + h.Timeout = 30 + } + + timeout := time.Duration(h.Timeout) * time.Second + + switch h.schema() { + case "socket": + h.conn, err = net.DialTimeout("unix", strings.Replace(h.Addr, socketSchema, "", 1), timeout) + case "tcp": + h.conn, err = net.DialTimeout("tcp", strings.Replace(h.Addr, tcpSchema, "", 1), timeout) + default: + return fmt.Errorf("unknown schema") + } + return err +} + +func (h *HAProxyClient) schema() string { + if strings.HasPrefix(h.Addr, socketSchema) { + return "socket" + } + if strings.HasPrefix(h.Addr, tcpSchema) { + return "tcp" + } + return "" +} diff --git a/vendor/github.com/bcicen/go-haproxy/client_test.go b/vendor/github.com/bcicen/go-haproxy/client_test.go new file mode 100644 index 000000000000..eb8f6e965e35 --- /dev/null +++ b/vendor/github.com/bcicen/go-haproxy/client_test.go @@ -0,0 +1,52 @@ +package haproxy_test + +import ( + "fmt" + + "github.com/bcicen/go-haproxy" +) + +func ExampleHAProxyClient_Stats() { + client := &haproxy.HAProxyClient{ + Addr: "unix:///var/run/haproxy.sock", + } + stats, err := client.Stats() + if err != nil { + fmt.Println(err) + return + } + for _, s := range stats { + fmt.Printf("%s: %s\n", s.SvName, s.Status) + } + // Output: + //static: DOWN + //app1: UP + //app2: UP + //... +} + +func ExampleHAProxyClient_Info() { + client := &haproxy.HAProxyClient{ + Addr: "unix:///var/run/haproxy.sock", + } + info, err := client.Info() + if err != nil { + fmt.Println(err) + return + } + fmt.Printf("%s version %s\n", info.Name, info.Version) + // Output: + //HAProxy version 1.6.3 +} + +func ExampleHAProxyClient_RunCommand() { + client := &haproxy.HAProxyClient{ + Addr: "unix:///var/run/haproxy.sock", + } + result, err := client.RunCommand("show info") + if err != nil { + fmt.Println(err) + return + } + fmt.Println(result.String()) +} diff --git a/vendor/github.com/bcicen/go-haproxy/info.go b/vendor/github.com/bcicen/go-haproxy/info.go new file mode 100644 index 000000000000..f64e63db2ab6 --- /dev/null +++ b/vendor/github.com/bcicen/go-haproxy/info.go @@ -0,0 +1,73 @@ +package haproxy + +import ( + "fmt" + + "github.com/bcicen/go-haproxy/kvcodec" +) + +// Response from HAProxy "show info" command. +type Info struct { + Name string `kv:"Name"` + Version string `kv:"Version"` + ReleaseDate string `kv:"Release_date"` + Nbproc uint64 `kv:"Nbproc"` + ProcessNum uint64 `kv:"Process_num"` + Pid uint64 `kv:"Pid"` + Uptime string `kv:"Uptime"` + UptimeSec uint64 `kv:"Uptime_sec"` + MemMaxMB uint64 `kv:"Memmax_MB"` + UlimitN uint64 `kv:"Ulimit-n"` + Maxsock uint64 `kv:"Maxsock"` + Maxconn uint64 `kv:"Maxconn"` + HardMaxconn uint64 `kv:"Hard_maxconn"` + CurrConns uint64 `kv:"CurrConns"` + CumConns uint64 `kv:"CumConns"` + CumReq uint64 `kv:"CumReq"` + MaxSslConns uint64 `kv:"MaxSslConns"` + CurrSslConns uint64 `kv:"CurrSslConns"` + CumSslConns uint64 `kv:"CumSslConns"` + Maxpipes uint64 `kv:"Maxpipes"` + PipesUsed uint64 `kv:"PipesUsed"` + PipesFree uint64 `kv:"PipesFree"` + ConnRate uint64 `kv:"ConnRate"` + ConnRateLimit uint64 `kv:"ConnRateLimit"` + MaxConnRate uint64 `kv:"MaxConnRate"` + SessRate uint64 `kv:"SessRate"` + SessRateLimit uint64 `kv:"SessRateLimit"` + MaxSessRate uint64 `kv:"MaxSessRate"` + SslRate uint64 `kv:"SslRate"` + SslRateLimit uint64 `kv:"SslRateLimit"` + MaxSslRate uint64 `kv:"MaxSslRate"` + SslFrontendKeyRate uint64 `kv:"SslFrontendKeyRate"` + SslFrontendMaxKeyRate uint64 `kv:"SslFrontendMaxKeyRate"` + SslFrontendSessionReusePct uint64 `kv:"SslFrontendSessionReuse_pct"` + SslBackendKeyRate uint64 `kv:"SslBackendKeyRate"` + SslBackendMaxKeyRate uint64 `kv:"SslBackendMaxKeyRate"` + SslCacheLookups uint64 `kv:"SslCacheLookups"` + SslCacheMisses uint64 `kv:"SslCacheMisses"` + CompressBpsIn uint64 `kv:"CompressBpsIn"` + CompressBpsOut uint64 `kv:"CompressBpsOut"` + CompressBpsRateLim uint64 `kv:"CompressBpsRateLim"` + ZlibMemUsage uint64 `kv:"ZlibMemUsage"` + MaxZlibMemUsage uint64 `kv:"MaxZlibMemUsage"` + Tasks uint64 `kv:"Tasks"` + RunQueue uint64 `kv:"Run_queue"` + IdlePct uint64 `kv:"Idle_pct"` + Node string `kv:"node"` + Description string `kv:"description"` +} + +// Equivalent to HAProxy "show info" command. +func (h *HAProxyClient) Info() (*Info, error) { + res, err := h.RunCommand("show info") + if err != nil { + return nil, err + } + info := &Info{} + err = kvcodec.Unmarshal(res, info) + if err != nil { + return nil, fmt.Errorf("error decoding response: %s", err) + } + return info, nil +} diff --git a/vendor/github.com/bcicen/go-haproxy/kvcodec/types.go b/vendor/github.com/bcicen/go-haproxy/kvcodec/types.go new file mode 100644 index 000000000000..d4733dfe647f --- /dev/null +++ b/vendor/github.com/bcicen/go-haproxy/kvcodec/types.go @@ -0,0 +1,193 @@ +package kvcodec + +import ( + "fmt" + "reflect" + "strconv" + "strings" +) + +func toString(in interface{}) (string, error) { + inValue := reflect.ValueOf(in) + + switch inValue.Kind() { + case reflect.String: + return inValue.String(), nil + case reflect.Bool: + b := inValue.Bool() + if b { + return "true", nil + } + return "false", nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return fmt.Sprintf("%v", inValue.Int()), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return fmt.Sprintf("%v", inValue.Uint()), nil + case reflect.Float32: + return strconv.FormatFloat(inValue.Float(), byte('f'), -1, 32), nil + case reflect.Float64: + return strconv.FormatFloat(inValue.Float(), byte('f'), -1, 64), nil + } + return "", fmt.Errorf("unable to cast " + inValue.Type().String() + " to string") +} + +func toBool(in interface{}) (bool, error) { + inValue := reflect.ValueOf(in) + + switch inValue.Kind() { + case reflect.String: + s := inValue.String() + switch s { + case "yes": + return true, nil + case "no", "": + return false, nil + default: + return strconv.ParseBool(s) + } + case reflect.Bool: + return inValue.Bool(), nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + i := inValue.Int() + if i != 0 { + return true, nil + } + return false, nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + i := inValue.Uint() + if i != 0 { + return true, nil + } + return false, nil + case reflect.Float32, reflect.Float64: + f := inValue.Float() + if f != 0 { + return true, nil + } + return false, nil + } + return false, fmt.Errorf("unable to cast " + inValue.Type().String() + " to bool") +} + +func toInt(in interface{}) (int64, error) { + inValue := reflect.ValueOf(in) + + switch inValue.Kind() { + case reflect.String: + s := strings.TrimSpace(inValue.String()) + if s == "" { + return 0, nil + } + return strconv.ParseInt(s, 0, 64) + case reflect.Bool: + if inValue.Bool() { + return 1, nil + } + return 0, nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return inValue.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return int64(inValue.Uint()), nil + case reflect.Float32, reflect.Float64: + return int64(inValue.Float()), nil + } + return 0, fmt.Errorf("unable to cast " + inValue.Type().String() + " to int") +} + +func toUint(in interface{}) (uint64, error) { + inValue := reflect.ValueOf(in) + + switch inValue.Kind() { + case reflect.String: + s := strings.TrimSpace(inValue.String()) + if s == "" { + return 0, nil + } + + // float input + if strings.Contains(s, ".") { + f, err := strconv.ParseFloat(s, 64) + if err != nil { + return 0, err + } + return uint64(f), nil + } + return strconv.ParseUint(s, 0, 64) + case reflect.Bool: + if inValue.Bool() { + return 1, nil + } + return 0, nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return uint64(inValue.Int()), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return inValue.Uint(), nil + case reflect.Float32, reflect.Float64: + return uint64(inValue.Float()), nil + } + return 0, fmt.Errorf("unable to cast " + inValue.Type().String() + " to uint") +} + +func toFloat(in interface{}) (float64, error) { + inValue := reflect.ValueOf(in) + + switch inValue.Kind() { + case reflect.String: + s := strings.TrimSpace(inValue.String()) + if s == "" { + return 0, nil + } + return strconv.ParseFloat(s, 64) + case reflect.Bool: + if inValue.Bool() { + return 1, nil + } + return 0, nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return float64(inValue.Int()), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return float64(inValue.Uint()), nil + case reflect.Float32, reflect.Float64: + return inValue.Float(), nil + } + return 0, fmt.Errorf("unable to cast " + inValue.Type().String() + " to float") +} + +func setField(field reflect.Value, value string) error { + switch field.Kind() { + case reflect.String: + s, err := toString(value) + if err != nil { + return err + } + field.SetString(s) + case reflect.Bool: + b, err := toBool(value) + if err != nil { + return err + } + field.SetBool(b) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + i, err := toInt(value) + if err != nil { + return err + } + field.SetInt(i) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + ui, err := toUint(value) + if err != nil { + return err + } + field.SetUint(ui) + case reflect.Float32, reflect.Float64: + f, err := toFloat(value) + if err != nil { + return err + } + field.SetFloat(f) + default: + err := fmt.Errorf("unable to set field of type %s", field.Kind()) + return err + } + return nil +} diff --git a/vendor/github.com/bcicen/go-haproxy/kvcodec/unmarshal.go b/vendor/github.com/bcicen/go-haproxy/kvcodec/unmarshal.go new file mode 100644 index 000000000000..bff131f6ef8b --- /dev/null +++ b/vendor/github.com/bcicen/go-haproxy/kvcodec/unmarshal.go @@ -0,0 +1,124 @@ +package kvcodec + +import ( + "bufio" + "fmt" + "io" + "reflect" + "regexp" + "strings" + "sync" +) + +const ( + tagLabel = "kv" + kvDelim = ":" +) + +type structFields map[string]fieldMeta + +type fieldMeta struct { + Key string + Name string + OmitAlways bool + OmitEmpty bool +} + +func newfieldMeta(field reflect.StructField) (meta fieldMeta) { + meta = fieldMeta{ + Name: field.Name, + } + fieldTags := strings.Split(field.Tag.Get(tagLabel), ",") + for _, tag := range fieldTags { + if tag == "-" { + meta.OmitAlways = true + return meta + } + if tag == "omitempty" { + meta.OmitEmpty = true + } else if tag != "" { + meta.Key = tag + } else { + meta.Key = field.Name + } + } + return meta +} + +var err error +var structMap = make(map[reflect.Type]structFields) +var structMapMutex sync.RWMutex + +func getStructFields(rType reflect.Type) (structFields, error) { + structMapMutex.RLock() + stInfo, ok := structMap[rType] + if !ok { + stInfo, err = newStructFields(rType) + if err != nil { + return nil, err + } + structMap[rType] = stInfo + } + structMapMutex.RUnlock() + return stInfo, nil +} + +func newStructFields(rType reflect.Type) (structFields, error) { + fieldsCount := rType.NumField() + fieldMap := make(structFields) + + for i := 0; i < fieldsCount; i++ { + field := rType.Field(i) + meta := newfieldMeta(field) + + if field.PkgPath != "" { + continue + } + + if field.Anonymous && field.Type.Kind() == reflect.Struct { + return nil, fmt.Errorf("embedded structs not supported") + } + + if !meta.OmitAlways { + fieldMap[meta.Key] = meta + } + } + + return fieldMap, nil +} + +func trim(s string) string { + re := regexp.MustCompile("(\\S+|\\S+)") + return strings.Join(re.FindAllString(s, -1), " ") +} + +func Unmarshal(in io.Reader, out interface{}) error { + outValue := reflect.ValueOf(out) + if outValue.Kind() == reflect.Ptr { + outValue = outValue.Elem() + } + + fields, err := getStructFields(outValue.Type()) + if fields == nil { + panic(err) + } + if err != nil { + return err + } + + scanner := bufio.NewScanner(in) + for scanner.Scan() { + if strings.Contains(scanner.Text(), kvDelim) { + s := strings.Split(scanner.Text(), kvDelim) + k, v := trim(s[0]), trim(s[1]) + if meta, ok := fields[k]; ok { + field := outValue.FieldByName(meta.Name) + err = setField(field, v) + if err != nil { + return err + } + } + } + } + return nil +} diff --git a/vendor/github.com/bcicen/go-haproxy/stat.go b/vendor/github.com/bcicen/go-haproxy/stat.go new file mode 100644 index 000000000000..392864621407 --- /dev/null +++ b/vendor/github.com/bcicen/go-haproxy/stat.go @@ -0,0 +1,102 @@ +package haproxy + +import ( + "encoding/csv" + "fmt" + + "github.com/gocarina/gocsv" +) + +// Response from HAProxy "show stat" command. +type Stat struct { + PxName string `csv:"# pxname"` + SvName string `csv:"svname"` + Qcur uint64 `csv:"qcur"` + Qmax uint64 `csv:"qmax"` + Scur uint64 `csv:"scur"` + Smax uint64 `csv:"smax"` + Slim uint64 `csv:"slim"` + Stot uint64 `csv:"stot"` + Bin uint64 `csv:"bin"` + Bout uint64 `csv:"bout"` + Dreq uint64 `csv:"dreq"` + Dresp uint64 `csv:"dresp"` + Ereq uint64 `csv:"ereq"` + Econ uint64 `csv:"econ"` + Eresp uint64 `csv:"eresp"` + Wretr uint64 `csv:"wretr"` + Wredis uint64 `csv:"wredis"` + Status string `csv:"status"` + Weight uint64 `csv:"weight"` + Act uint64 `csv:"act"` + Bck uint64 `csv:"bck"` + ChkFail uint64 `csv:"chkfail"` + ChkDown uint64 `csv:"chkdown"` + Lastchg uint64 `csv:"lastchg"` + Downtime uint64 `csv:"downtime"` + Qlimit uint64 `csv:"qlimit"` + Pid uint64 `csv:"pid"` + Iid uint64 `csv:"iid"` + Sid uint64 `csv:"sid"` + Throttle uint64 `csv:"throttle"` + Lbtot uint64 `csv:"lbtot"` + Tracked uint64 `csv:"tracked"` + Type uint64 `csv:"type"` + Rate uint64 `csv:"rate"` + RateLim uint64 `csv:"rate_lim"` + RateMax uint64 `csv:"rate_max"` + CheckStatus string `csv:"check_status"` + CheckCode uint64 `csv:"check_code"` + CheckDuration uint64 `csv:"check_duration"` + Hrsp1xx uint64 `csv:"hrsp_1xx"` + Hrsp2xx uint64 `csv:"hrsp_2xx"` + Hrsp3xx uint64 `csv:"hrsp_3xx"` + Hrsp4xx uint64 `csv:"hrsp_4xx"` + Hrsp5xx uint64 `csv:"hrsp_5xx"` + HrspOther uint64 `csv:"hrsp_other"` + Hanafail uint64 `csv:"hanafail"` + ReqRate uint64 `csv:"req_rate"` + ReqRateMax uint64 `csv:"req_rate_max"` + ReqTot uint64 `csv:"req_tot"` + CliAbrt uint64 `csv:"cli_abrt"` + SrvAbrt uint64 `csv:"srv_abrt"` + CompIn uint64 `csv:"comp_in"` + CompOut uint64 `csv:"comp_out"` + CompByp uint64 `csv:"comp_byp"` + CompRsp uint64 `csv:"comp_rsp"` + LastSess int64 `csv:"lastsess"` + LastChk string `csv:"last_chk"` + LastAgt uint64 `csv:"last_agt"` + Qtime uint64 `csv:"qtime"` + Ctime uint64 `csv:"ctime"` + Rtime uint64 `csv:"rtime"` + Ttime uint64 `csv:"ttime"` +} + +// Equivalent to HAProxy "show stat" command. +func (h *HAProxyClient) Stats() (stats []*Stat, err error) { + res, err := h.RunCommand("show stat") + if err != nil { + return nil, err + } + + reader := csv.NewReader(res) + reader.TrailingComma = true + err = gocsv.UnmarshalCSV(reader, &stats) + if err != nil { + return nil, fmt.Errorf("error reading csv: %s", err) + } + + // for _, s := range allStats { + // switch s.SvName { + // case "FRONTEND": + // services.Frontends = append(services.Frontends, s) + // case "BACKEND": + // services.Backends = append(services.Backends, s) + // default: + // services.Listeners = append(services.Listeners, s) + // } + // } + + return stats, nil +} diff --git a/vendor/github.com/gocarina/gocsv/.gitignore b/vendor/github.com/gocarina/gocsv/.gitignore new file mode 100644 index 000000000000..485dee64bcfb --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/.gitignore @@ -0,0 +1 @@ +.idea diff --git a/vendor/github.com/gocarina/gocsv/.travis.yml b/vendor/github.com/gocarina/gocsv/.travis.yml new file mode 100644 index 000000000000..4f2ee4d97338 --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/.travis.yml @@ -0,0 +1 @@ +language: go diff --git a/vendor/github.com/gocarina/gocsv/LICENSE b/vendor/github.com/gocarina/gocsv/LICENSE new file mode 100644 index 000000000000..052a371193e4 --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Jonathan Picques + +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. \ No newline at end of file diff --git a/vendor/github.com/gocarina/gocsv/README.md b/vendor/github.com/gocarina/gocsv/README.md new file mode 100644 index 000000000000..c3fae623bb50 --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/README.md @@ -0,0 +1,170 @@ +Go CSV +===== + +The GoCSV package aims to provide easy serialization and deserialization functions to use CSV in Golang + +API and techniques inspired from https://godoc.org/gopkg.in/mgo.v2 + +[![GoDoc](https://godoc.org/github.com/gocarina/gocsv?status.png)](https://godoc.org/github.com/gocarina/gocsv) +[![Build Status](https://travis-ci.org/gocarina/gocsv.svg?branch=master)](https://travis-ci.org/gocarina/gocsv) + +Installation +===== + +```go get -u github.com/gocarina/gocsv``` + +Full example +===== + +Consider the following CSV file + +```csv + +client_id,client_name,client_age +1,Jose,42 +2,Daniel,26 +3,Vincent,32 + +``` + +Easy binding in Go! +--- + +```go + +package main + +import ( + "fmt" + "gocsv" + "os" +) + +type Client struct { // Our example struct, you can use "-" to ignore a field + Id string `csv:"client_id"` + Name string `csv:"client_name"` + Age string `csv:"client_age"` + NotUsed string `csv:"-"` +} + +func main() { + clientsFile, err := os.OpenFile("clients.csv", os.O_RDWR|os.O_CREATE, os.ModePerm) + if err != nil { + panic(err) + } + defer clientsFile.Close() + + clients := []*Client{} + + if err := gocsv.UnmarshalFile(clientsFile, &clients); err != nil { // Load clients from file + panic(err) + } + for _, client := range clients { + fmt.Println("Hello", client.Name) + } + + if _, err := clientsFile.Seek(0, 0); err != nil { // Go to the start of the file + panic(err) + } + + clients = append(clients, &Client{Id: "12", Name: "John", Age: "21"}) // Add clients + clients = append(clients, &Client{Id: "13", Name: "Fred"}) + clients = append(clients, &Client{Id: "14", Name: "James", Age: "32"}) + clients = append(clients, &Client{Id: "15", Name: "Danny"}) + csvContent, err := gocsv.MarshalString(&clients) // Get all clients as CSV string + //err = gocsv.MarshalFile(&clients, clientsFile) // Use this to save the CSV back to the file + if err != nil { + panic(err) + } + fmt.Println(csvContent) // Display all clients as CSV string + +} + +``` + +Customizable Converters +--- + +```go + +type DateTime struct { + time.Time +} + +// Convert the internal date as CSV string +func (date *DateTime) MarshalCSV() (string, error) { + return date.Time.Format("20060201"), nil +} + +// You could also use the standard Stringer interface +func (date *DateTime) String() (string) { + return date.String() // Redundant, just for example +} + +// Convert the CSV string as internal date +func (date *DateTime) UnmarshalCSV(csv string) (err error) { + date.Time, err = time.Parse("20060201", csv) + if err != nil { + return err + } + return nil +} + +type Client struct { // Our example struct with a custom type (DateTime) + Id string `csv:"id"` + Name string `csv:"name"` + Employed DateTime `csv:"employed"` +} + +``` + +Customizable CSV Reader / Writer +--- + +```go + +func main() { + ... + + gocsv.SetCSVReader(func(in io.Reader) gocsv.CSVReader { + r := csv.NewReader(in) + r.Comma = '|' + return r // Allows use pipe as delimiter + }) + + ... + + gocsv.SetCSVReader(func(in io.Reader) gocsv.CSVReader { + r := csv.NewReader(in) + r.LazyQuotes = true + r.Comma = '.' + return r // Allows use dot as delimiter and use quotes in CSV + }) + + ... + + gocsv.SetCSVReader(func(in io.Reader) gocsv.CSVReader { + //return csv.NewReader(in) + return gocsv.LazyCSVReader(in) // Allows use of quotes in CSV + }) + + ... + + gocsv.UnmarshalFile(file, &clients) + + ... + + gocsv.SetCSVWriter(func(out io.Writer) *SafeCSVWriter { + writer := csv.NewWriter(out) + writer.Comma = '|' + return gocsv.NewSafeCSVWriter(writer) + }) + + ... + + gocsv.MarshalFile(&clients, file) + + ... +} + +``` diff --git a/vendor/github.com/gocarina/gocsv/csv.go b/vendor/github.com/gocarina/gocsv/csv.go new file mode 100644 index 000000000000..83e2ed47fbb4 --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/csv.go @@ -0,0 +1,324 @@ +// Copyright 2014 Jonathan Picques. All rights reserved. +// Use of this source code is governed by a MIT license +// The license can be found in the LICENSE file. + +// The GoCSV package aims to provide easy CSV serialization and deserialization to the golang programming language + +package gocsv + +import ( + "bytes" + "encoding/csv" + "fmt" + "io" + "os" + "reflect" + "strings" +) + +// FailIfUnmatchedStructTags indicates whether it is considered an error when there is an unmatched +// struct tag. +var FailIfUnmatchedStructTags = false + +// FailIfDoubleHeaderNames indicates whether it is considered an error when a header name is repeated +// in the csv header. +var FailIfDoubleHeaderNames = false + +// ShouldAlignDuplicateHeadersWithStructFieldOrder indicates whether we should align duplicate CSV +// headers per their alignment in the struct definition. +var ShouldAlignDuplicateHeadersWithStructFieldOrder = false + +// TagSeparator defines seperator string for multiple csv tags in struct fields +var TagSeparator = "," + +// -------------------------------------------------------------------------- +// CSVWriter used to format CSV + +var selfCSVWriter = DefaultCSVWriter + +// DefaultCSVWriter is the default SafeCSVWriter used to format CSV (cf. csv.NewWriter) +func DefaultCSVWriter(out io.Writer) *SafeCSVWriter { + writer := NewSafeCSVWriter(csv.NewWriter(out)) + + // As only one rune can be defined as a CSV separator, we are going to trim + // the custom tag separator and use the first rune. + if runes := []rune(strings.TrimSpace(TagSeparator)); len(runes) > 0 { + writer.Comma = runes[0] + } + + return writer +} + +// SetCSVWriter sets the SafeCSVWriter used to format CSV. +func SetCSVWriter(csvWriter func(io.Writer) *SafeCSVWriter) { + selfCSVWriter = csvWriter +} + +func getCSVWriter(out io.Writer) *SafeCSVWriter { + return selfCSVWriter(out) +} + +// -------------------------------------------------------------------------- +// CSVReader used to parse CSV + +var selfCSVReader = DefaultCSVReader + +// DefaultCSVReader is the default CSV reader used to parse CSV (cf. csv.NewReader) +func DefaultCSVReader(in io.Reader) CSVReader { + return csv.NewReader(in) +} + +// LazyCSVReader returns a lazy CSV reader, with LazyQuotes and TrimLeadingSpace. +func LazyCSVReader(in io.Reader) CSVReader { + csvReader := csv.NewReader(in) + csvReader.LazyQuotes = true + csvReader.TrimLeadingSpace = true + return csvReader +} + +// SetCSVReader sets the CSV reader used to parse CSV. +func SetCSVReader(csvReader func(io.Reader) CSVReader) { + selfCSVReader = csvReader +} + +func getCSVReader(in io.Reader) CSVReader { + return selfCSVReader(in) +} + +// -------------------------------------------------------------------------- +// Marshal functions + +// MarshalFile saves the interface as CSV in the file. +func MarshalFile(in interface{}, file *os.File) (err error) { + return Marshal(in, file) +} + +// MarshalString returns the CSV string from the interface. +func MarshalString(in interface{}) (out string, err error) { + bufferString := bytes.NewBufferString(out) + if err := Marshal(in, bufferString); err != nil { + return "", err + } + return bufferString.String(), nil +} + +// MarshalBytes returns the CSV bytes from the interface. +func MarshalBytes(in interface{}) (out []byte, err error) { + bufferString := bytes.NewBuffer(out) + if err := Marshal(in, bufferString); err != nil { + return nil, err + } + return bufferString.Bytes(), nil +} + +// Marshal returns the CSV in writer from the interface. +func Marshal(in interface{}, out io.Writer) (err error) { + writer := getCSVWriter(out) + return writeTo(writer, in, false) +} + +// Marshal returns the CSV in writer from the interface. +func MarshalWithoutHeaders(in interface{}, out io.Writer) (err error) { + writer := getCSVWriter(out) + return writeTo(writer, in, true) +} + +// MarshalChan returns the CSV read from the channel. +func MarshalChan(c <-chan interface{}, out *SafeCSVWriter) error { + return writeFromChan(out, c) +} + +// MarshalCSV returns the CSV in writer from the interface. +func MarshalCSV(in interface{}, out *SafeCSVWriter) (err error) { + return writeTo(out, in, false) +} + +// MarshalCSVWithoutHeaders returns the CSV in writer from the interface. +func MarshalCSVWithoutHeaders(in interface{}, out *SafeCSVWriter) (err error) { + return writeTo(out, in, true) +} + +// -------------------------------------------------------------------------- +// Unmarshal functions + +// UnmarshalFile parses the CSV from the file in the interface. +func UnmarshalFile(in *os.File, out interface{}) error { + return Unmarshal(in, out) +} + +// UnmarshalString parses the CSV from the string in the interface. +func UnmarshalString(in string, out interface{}) error { + return Unmarshal(strings.NewReader(in), out) +} + +// UnmarshalBytes parses the CSV from the bytes in the interface. +func UnmarshalBytes(in []byte, out interface{}) error { + return Unmarshal(bytes.NewReader(in), out) +} + +// Unmarshal parses the CSV from the reader in the interface. +func Unmarshal(in io.Reader, out interface{}) error { + return readTo(newDecoder(in), out) +} + +// UnmarshalWithoutHeaders parses the CSV from the reader in the interface. +func UnmarshalWithoutHeaders(in io.Reader, out interface{}) error { + return readToWithoutHeaders(newDecoder(in), out) +} + +// UnmarshalDecoder parses the CSV from the decoder in the interface +func UnmarshalDecoder(in Decoder, out interface{}) error { + return readTo(in, out) +} + +// UnmarshalCSV parses the CSV from the reader in the interface. +func UnmarshalCSV(in CSVReader, out interface{}) error { + return readTo(csvDecoder{in}, out) +} + +// UnmarshalToChan parses the CSV from the reader and send each value in the chan c. +// The channel must have a concrete type. +func UnmarshalToChan(in io.Reader, c interface{}) error { + if c == nil { + return fmt.Errorf("goscv: channel is %v", c) + } + return readEach(newDecoder(in), c) +} + +// UnmarshalDecoderToChan parses the CSV from the decoder and send each value in the chan c. +// The channel must have a concrete type. +func UnmarshalDecoderToChan(in SimpleDecoder, c interface{}) error { + if c == nil { + return fmt.Errorf("goscv: channel is %v", c) + } + return readEach(in, c) +} + +// UnmarshalStringToChan parses the CSV from the string and send each value in the chan c. +// The channel must have a concrete type. +func UnmarshalStringToChan(in string, c interface{}) error { + return UnmarshalToChan(strings.NewReader(in), c) +} + +// UnmarshalBytesToChan parses the CSV from the bytes and send each value in the chan c. +// The channel must have a concrete type. +func UnmarshalBytesToChan(in []byte, c interface{}) error { + return UnmarshalToChan(bytes.NewReader(in), c) +} + +// UnmarshalToCallback parses the CSV from the reader and send each value to the given func f. +// The func must look like func(Struct). +func UnmarshalToCallback(in io.Reader, f interface{}) error { + valueFunc := reflect.ValueOf(f) + t := reflect.TypeOf(f) + if t.NumIn() != 1 { + return fmt.Errorf("the given function must have exactly one parameter") + } + cerr := make(chan error) + c := reflect.MakeChan(reflect.ChanOf(reflect.BothDir, t.In(0)), 0) + go func() { + cerr <- UnmarshalToChan(in, c.Interface()) + }() + for { + select { + case err := <-cerr: + return err + default: + } + v, notClosed := c.Recv() + if !notClosed || v.Interface() == nil { + break + } + valueFunc.Call([]reflect.Value{v}) + } + return nil +} + +// UnmarshalDecoderToCallback parses the CSV from the decoder and send each value to the given func f. +// The func must look like func(Struct). +func UnmarshalDecoderToCallback(in SimpleDecoder, f interface{}) error { + valueFunc := reflect.ValueOf(f) + t := reflect.TypeOf(f) + if t.NumIn() != 1 { + return fmt.Errorf("the given function must have exactly one parameter") + } + cerr := make(chan error) + c := reflect.MakeChan(reflect.ChanOf(reflect.BothDir, t.In(0)), 0) + go func() { + cerr <- UnmarshalDecoderToChan(in, c.Interface()) + }() + for { + select { + case err := <-cerr: + return err + default: + } + v, notClosed := c.Recv() + if !notClosed || v.Interface() == nil { + break + } + valueFunc.Call([]reflect.Value{v}) + } + return nil +} + +// UnmarshalBytesToCallback parses the CSV from the bytes and send each value to the given func f. +// The func must look like func(Struct). +func UnmarshalBytesToCallback(in []byte, f interface{}) error { + return UnmarshalToCallback(bytes.NewReader(in), f) +} + +// UnmarshalStringToCallback parses the CSV from the string and send each value to the given func f. +// The func must look like func(Struct). +func UnmarshalStringToCallback(in string, c interface{}) (err error) { + return UnmarshalToCallback(strings.NewReader(in), c) +} + +// CSVToMap creates a simple map from a CSV of 2 columns. +func CSVToMap(in io.Reader) (map[string]string, error) { + decoder := newDecoder(in) + header, err := decoder.getCSVRow() + if err != nil { + return nil, err + } + if len(header) != 2 { + return nil, fmt.Errorf("maps can only be created for csv of two columns") + } + m := make(map[string]string) + for { + line, err := decoder.getCSVRow() + if err == io.EOF { + break + } else if err != nil { + return nil, err + } + m[line[0]] = line[1] + } + return m, nil +} + +// CSVToMaps takes a reader and returns an array of dictionaries, using the header row as the keys +func CSVToMaps(reader io.Reader) ([]map[string]string, error) { + r := csv.NewReader(reader) + rows := []map[string]string{} + var header []string + for { + record, err := r.Read() + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + if header == nil { + header = record + } else { + dict := map[string]string{} + for i := range header { + dict[header[i]] = record[i] + } + rows = append(rows, dict) + } + } + return rows, nil +} diff --git a/vendor/github.com/gocarina/gocsv/decode.go b/vendor/github.com/gocarina/gocsv/decode.go new file mode 100644 index 000000000000..1ef3b274d1ea --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/decode.go @@ -0,0 +1,368 @@ +package gocsv + +import ( + "encoding/csv" + "errors" + "fmt" + "io" + "reflect" +) + +// Decoder . +type Decoder interface { + getCSVRows() ([][]string, error) +} + +// SimpleDecoder . +type SimpleDecoder interface { + getCSVRow() ([]string, error) +} + +type decoder struct { + in io.Reader + csvDecoder *csvDecoder +} + +func newDecoder(in io.Reader) *decoder { + return &decoder{in: in} +} + +func (decode *decoder) getCSVRows() ([][]string, error) { + return getCSVReader(decode.in).ReadAll() +} + +func (decode *decoder) getCSVRow() ([]string, error) { + if decode.csvDecoder == nil { + decode.csvDecoder = &csvDecoder{getCSVReader(decode.in)} + } + return decode.csvDecoder.Read() +} + +type CSVReader interface { + Read() ([]string, error) + ReadAll() ([][]string, error) +} + +type csvDecoder struct { + CSVReader +} + +func (c csvDecoder) getCSVRows() ([][]string, error) { + return c.ReadAll() +} + +func (c csvDecoder) getCSVRow() ([]string, error) { + return c.Read() +} + +func mismatchStructFields(structInfo []fieldInfo, headers []string) []string { + missing := make([]string, 0) + if len(structInfo) == 0 { + return missing + } + + headerMap := make(map[string]struct{}, len(headers)) + for idx := range headers { + headerMap[headers[idx]] = struct{}{} + } + + for _, info := range structInfo { + found := false + for _, key := range info.keys { + if _, ok := headerMap[key]; ok { + found = true + break + } + } + if !found { + missing = append(missing, info.keys...) + } + } + return missing +} + +func mismatchHeaderFields(structInfo []fieldInfo, headers []string) []string { + missing := make([]string, 0) + if len(headers) == 0 { + return missing + } + + keyMap := make(map[string]struct{}, 0) + for _, info := range structInfo { + for _, key := range info.keys { + keyMap[key] = struct{}{} + } + } + + for _, header := range headers { + if _, ok := keyMap[header]; !ok { + missing = append(missing, header) + } + } + return missing +} + +func maybeMissingStructFields(structInfo []fieldInfo, headers []string) error { + missing := mismatchStructFields(structInfo, headers) + if len(missing) != 0 { + return fmt.Errorf("found unmatched struct field with tags %v", missing) + } + return nil +} + +// Check that no header name is repeated twice +func maybeDoubleHeaderNames(headers []string) error { + headerMap := make(map[string]bool, len(headers)) + for _, v := range headers { + if _, ok := headerMap[v]; ok { + return fmt.Errorf("Repeated header name: %v", v) + } + headerMap[v] = true + } + return nil +} + +func readTo(decoder Decoder, out interface{}) error { + outValue, outType := getConcreteReflectValueAndType(out) // Get the concrete type (not pointer) (Slice or Array) + if err := ensureOutType(outType); err != nil { + return err + } + outInnerWasPointer, outInnerType := getConcreteContainerInnerType(outType) // Get the concrete inner type (not pointer) (Container<"?">) + if err := ensureOutInnerType(outInnerType); err != nil { + return err + } + csvRows, err := decoder.getCSVRows() // Get the CSV csvRows + if err != nil { + return err + } + if len(csvRows) == 0 { + return errors.New("empty csv file given") + } + if err := ensureOutCapacity(&outValue, len(csvRows)); err != nil { // Ensure the container is big enough to hold the CSV content + return err + } + outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations + if len(outInnerStructInfo.Fields) == 0 { + return errors.New("no csv struct tags found") + } + + headers := csvRows[0] + body := csvRows[1:] + + csvHeadersLabels := make(map[int]*fieldInfo, len(outInnerStructInfo.Fields)) // Used to store the correspondance header <-> position in CSV + + headerCount := map[string]int{} + for i, csvColumnHeader := range headers { + curHeaderCount := headerCount[csvColumnHeader] + if fieldInfo := getCSVFieldPosition(csvColumnHeader, outInnerStructInfo, curHeaderCount); fieldInfo != nil { + csvHeadersLabels[i] = fieldInfo + if ShouldAlignDuplicateHeadersWithStructFieldOrder { + curHeaderCount++ + headerCount[csvColumnHeader] = curHeaderCount + } + } + } + + if FailIfUnmatchedStructTags { + if err := maybeMissingStructFields(outInnerStructInfo.Fields, headers); err != nil { + return err + } + } + if FailIfDoubleHeaderNames { + if err := maybeDoubleHeaderNames(headers); err != nil { + return err + } + } + + for i, csvRow := range body { + outInner := createNewOutInner(outInnerWasPointer, outInnerType) + for j, csvColumnContent := range csvRow { + if fieldInfo, ok := csvHeadersLabels[j]; ok { // Position found accordingly to header name + if err := setInnerField(&outInner, outInnerWasPointer, fieldInfo.IndexChain, csvColumnContent, fieldInfo.omitEmpty); err != nil { // Set field of struct + return &csv.ParseError{ + Line: i + 2, //add 2 to account for the header & 0-indexing of arrays + Column: j + 1, + Err: err, + } + } + } + } + outValue.Index(i).Set(outInner) + } + return nil +} + +func readEach(decoder SimpleDecoder, c interface{}) error { + headers, err := decoder.getCSVRow() + if err != nil { + return err + } + outValue, outType := getConcreteReflectValueAndType(c) // Get the concrete type (not pointer) (Slice or Array) + if err := ensureOutType(outType); err != nil { + return err + } + defer outValue.Close() + outInnerWasPointer, outInnerType := getConcreteContainerInnerType(outType) // Get the concrete inner type (not pointer) (Container<"?">) + if err := ensureOutInnerType(outInnerType); err != nil { + return err + } + outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations + if len(outInnerStructInfo.Fields) == 0 { + return errors.New("no csv struct tags found") + } + csvHeadersLabels := make(map[int]*fieldInfo, len(outInnerStructInfo.Fields)) // Used to store the correspondance header <-> position in CSV + headerCount := map[string]int{} + for i, csvColumnHeader := range headers { + curHeaderCount := headerCount[csvColumnHeader] + if fieldInfo := getCSVFieldPosition(csvColumnHeader, outInnerStructInfo, curHeaderCount); fieldInfo != nil { + csvHeadersLabels[i] = fieldInfo + if ShouldAlignDuplicateHeadersWithStructFieldOrder { + curHeaderCount++ + headerCount[csvColumnHeader] = curHeaderCount + } + } + } + if err := maybeMissingStructFields(outInnerStructInfo.Fields, headers); err != nil { + if FailIfUnmatchedStructTags { + return err + } + } + if FailIfDoubleHeaderNames { + if err := maybeDoubleHeaderNames(headers); err != nil { + return err + } + } + i := 0 + for { + line, err := decoder.getCSVRow() + if err == io.EOF { + break + } else if err != nil { + return err + } + outInner := createNewOutInner(outInnerWasPointer, outInnerType) + for j, csvColumnContent := range line { + if fieldInfo, ok := csvHeadersLabels[j]; ok { // Position found accordingly to header name + if err := setInnerField(&outInner, outInnerWasPointer, fieldInfo.IndexChain, csvColumnContent, fieldInfo.omitEmpty); err != nil { // Set field of struct + return &csv.ParseError{ + Line: i + 2, //add 2 to account for the header & 0-indexing of arrays + Column: j + 1, + Err: err, + } + } + } + } + outValue.Send(outInner) + i++ + } + return nil +} + +func readToWithoutHeaders(decoder Decoder, out interface{}) error { + outValue, outType := getConcreteReflectValueAndType(out) // Get the concrete type (not pointer) (Slice or Array) + if err := ensureOutType(outType); err != nil { + return err + } + outInnerWasPointer, outInnerType := getConcreteContainerInnerType(outType) // Get the concrete inner type (not pointer) (Container<"?">) + if err := ensureOutInnerType(outInnerType); err != nil { + return err + } + csvRows, err := decoder.getCSVRows() // Get the CSV csvRows + if err != nil { + return err + } + if len(csvRows) == 0 { + return errors.New("empty csv file given") + } + if err := ensureOutCapacity(&outValue, len(csvRows)+1); err != nil { // Ensure the container is big enough to hold the CSV content + return err + } + outInnerStructInfo := getStructInfo(outInnerType) // Get the inner struct info to get CSV annotations + if len(outInnerStructInfo.Fields) == 0 { + return errors.New("no csv struct tags found") + } + + for i, csvRow := range csvRows { + outInner := createNewOutInner(outInnerWasPointer, outInnerType) + for j, csvColumnContent := range csvRow { + fieldInfo := outInnerStructInfo.Fields[j] + if err := setInnerField(&outInner, outInnerWasPointer, fieldInfo.IndexChain, csvColumnContent, fieldInfo.omitEmpty); err != nil { // Set field of struct + return &csv.ParseError{ + Line: i + 1, + Column: j + 1, + Err: err, + } + } + } + outValue.Index(i).Set(outInner) + } + + return nil +} + +// Check if the outType is an array or a slice +func ensureOutType(outType reflect.Type) error { + switch outType.Kind() { + case reflect.Slice: + fallthrough + case reflect.Chan: + fallthrough + case reflect.Array: + return nil + } + return fmt.Errorf("cannot use " + outType.String() + ", only slice or array supported") +} + +// Check if the outInnerType is of type struct +func ensureOutInnerType(outInnerType reflect.Type) error { + switch outInnerType.Kind() { + case reflect.Struct: + return nil + } + return fmt.Errorf("cannot use " + outInnerType.String() + ", only struct supported") +} + +func ensureOutCapacity(out *reflect.Value, csvLen int) error { + switch out.Kind() { + case reflect.Array: + if out.Len() < csvLen-1 { // Array is not big enough to hold the CSV content (arrays are not addressable) + return fmt.Errorf("array capacity problem: cannot store %d %s in %s", csvLen-1, out.Type().Elem().String(), out.Type().String()) + } + case reflect.Slice: + if !out.CanAddr() && out.Len() < csvLen-1 { // Slice is not big enough tho hold the CSV content and is not addressable + return fmt.Errorf("slice capacity problem and is not addressable (did you forget &?)") + } else if out.CanAddr() && out.Len() < csvLen-1 { + out.Set(reflect.MakeSlice(out.Type(), csvLen-1, csvLen-1)) // Slice is not big enough, so grows it + } + } + return nil +} + +func getCSVFieldPosition(key string, structInfo *structInfo, curHeaderCount int) *fieldInfo { + matchedFieldCount := 0 + for _, field := range structInfo.Fields { + if field.matchesKey(key) { + if matchedFieldCount >= curHeaderCount { + return &field + } else { + matchedFieldCount++ + } + } + } + return nil +} + +func createNewOutInner(outInnerWasPointer bool, outInnerType reflect.Type) reflect.Value { + if outInnerWasPointer { + return reflect.New(outInnerType) + } + return reflect.New(outInnerType).Elem() +} + +func setInnerField(outInner *reflect.Value, outInnerWasPointer bool, index []int, value string, omitEmpty bool) error { + oi := *outInner + if outInnerWasPointer { + oi = outInner.Elem() + } + return setField(oi.FieldByIndex(index), value, omitEmpty) +} diff --git a/vendor/github.com/gocarina/gocsv/decode_test.go b/vendor/github.com/gocarina/gocsv/decode_test.go new file mode 100644 index 000000000000..c3872bcb8b6b --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/decode_test.go @@ -0,0 +1,596 @@ +package gocsv + +import ( + "bytes" + "encoding/csv" + "io" + "reflect" + "strconv" + "strings" + "testing" + "time" +) + +func Test_readTo(t *testing.T) { + blah := 0 + sptr := "*string" + sptr2 := "" + b := bytes.NewBufferString(`foo,BAR,Baz,Blah,SPtr,Omit +f,1,baz,,*string,*string +e,3,b,,,`) + d := &decoder{in: b} + + var samples []Sample + if err := readTo(d, &samples); err != nil { + t.Fatal(err) + } + if len(samples) != 2 { + t.Fatalf("expected 2 sample instances, got %d", len(samples)) + } + + expected := Sample{Foo: "f", Bar: 1, Baz: "baz", Blah: &blah, SPtr: &sptr, Omit: &sptr} + if !reflect.DeepEqual(expected, samples[0]) { + t.Fatalf("expected first sample %v, got %v", expected, samples[0]) + } + + expected = Sample{Foo: "e", Bar: 3, Baz: "b", Blah: &blah, SPtr: &sptr2} + if !reflect.DeepEqual(expected, samples[1]) { + t.Fatalf("expected second sample %v, got %v", expected, samples[1]) + } + + b = bytes.NewBufferString(`foo,BAR,Baz +f,1,baz +e,BAD_INPUT,b`) + d = &decoder{in: b} + samples = []Sample{} + err := readTo(d, &samples) + if err == nil { + t.Fatalf("Expected error from bad input, got: %+v", samples) + } + switch actualErr := err.(type) { + case *csv.ParseError: + if actualErr.Line != 3 { + t.Fatalf("Expected csv.ParseError on line 3, got: %d", actualErr.Line) + } + if actualErr.Column != 2 { + t.Fatalf("Expected csv.ParseError in column 2, got: %d", actualErr.Column) + } + default: + t.Fatalf("incorrect error type: %T", err) + } + +} + +func Test_readTo_Time(t *testing.T) { + b := bytes.NewBufferString(`Foo +1970-01-01T03:01:00+03:00`) + d := &decoder{in: b} + + var samples []DateTime + if err := readTo(d, &samples); err != nil { + t.Fatal(err) + } + + rt, _ := time.Parse(time.RFC3339, "1970-01-01T03:01:00+03:00") + + expected := DateTime{Foo: rt} + + if !reflect.DeepEqual(expected, samples[0]) { + t.Fatalf("expected first sample %v, got %v", expected, samples[0]) + } +} + +func Test_readTo_complex_embed(t *testing.T) { + b := bytes.NewBufferString(`first,foo,BAR,Baz,last,abc +aa,bb,11,cc,dd,ee +ff,gg,22,hh,ii,jj`) + d := &decoder{in: b} + + var samples []SkipFieldSample + if err := readTo(d, &samples); err != nil { + t.Fatal(err) + } + if len(samples) != 2 { + t.Fatalf("expected 2 sample instances, got %d", len(samples)) + } + expected := SkipFieldSample{ + EmbedSample: EmbedSample{ + Qux: "aa", + Sample: Sample{ + Foo: "bb", + Bar: 11, + Baz: "cc", + }, + Quux: "dd", + }, + Corge: "ee", + } + if expected != samples[0] { + t.Fatalf("expected first sample %v, got %v", expected, samples[0]) + } + expected = SkipFieldSample{ + EmbedSample: EmbedSample{ + Qux: "ff", + Sample: Sample{ + Foo: "gg", + Bar: 22, + Baz: "hh", + }, + Quux: "ii", + }, + Corge: "jj", + } + if expected != samples[1] { + t.Fatalf("expected first sample %v, got %v", expected, samples[1]) + } +} + +func Test_readEach(t *testing.T) { + b := bytes.NewBufferString(`first,foo,BAR,Baz,last,abc +aa,bb,11,cc,dd,ee +ff,gg,22,hh,ii,jj`) + d := &decoder{in: b} + + c := make(chan SkipFieldSample) + var samples []SkipFieldSample + go func() { + if err := readEach(d, c); err != nil { + t.Fatal(err) + } + }() + for v := range c { + samples = append(samples, v) + } + if len(samples) != 2 { + t.Fatalf("expected 2 sample instances, got %d", len(samples)) + } + expected := SkipFieldSample{ + EmbedSample: EmbedSample{ + Qux: "aa", + Sample: Sample{ + Foo: "bb", + Bar: 11, + Baz: "cc", + }, + Quux: "dd", + }, + Corge: "ee", + } + if expected != samples[0] { + t.Fatalf("expected first sample %v, got %v", expected, samples[0]) + } + expected = SkipFieldSample{ + EmbedSample: EmbedSample{ + Qux: "ff", + Sample: Sample{ + Foo: "gg", + Bar: 22, + Baz: "hh", + }, + Quux: "ii", + }, + Corge: "jj", + } + if expected != samples[1] { + t.Fatalf("expected first sample %v, got %v", expected, samples[1]) + } +} + +func Test_maybeMissingStructFields(t *testing.T) { + structTags := []fieldInfo{ + {keys: []string{"foo"}}, + {keys: []string{"bar"}}, + {keys: []string{"baz"}}, + } + badHeaders := []string{"hi", "mom", "bacon"} + goodHeaders := []string{"foo", "bar", "baz"} + + // no tags to match, expect no error + if err := maybeMissingStructFields([]fieldInfo{}, goodHeaders); err != nil { + t.Fatal(err) + } + + // bad headers, expect an error + if err := maybeMissingStructFields(structTags, badHeaders); err == nil { + t.Fatal("expected an error, but no error found") + } + + // good headers, expect no error + if err := maybeMissingStructFields(structTags, goodHeaders); err != nil { + t.Fatal(err) + } + + // extra headers, but all structtags match; expect no error + moarHeaders := append(goodHeaders, "qux", "quux", "corge", "grault") + if err := maybeMissingStructFields(structTags, moarHeaders); err != nil { + t.Fatal(err) + } + + // not all structTags match, but there's plenty o' headers; expect + // error + mismatchedHeaders := []string{"foo", "qux", "quux", "corgi"} + if err := maybeMissingStructFields(structTags, mismatchedHeaders); err == nil { + t.Fatal("expected an error, but no error found") + } +} + +func Test_maybeDoubleHeaderNames(t *testing.T) { + b := bytes.NewBufferString(`foo,BAR,foo +f,1,baz +e,3,b`) + d := &decoder{in: b} + var samples []Sample + + // *** check maybeDoubleHeaderNames + if err := maybeDoubleHeaderNames([]string{"foo", "BAR", "foo"}); err == nil { + t.Fatal("maybeDoubleHeaderNames did not raise an error when a should have.") + } + + // *** check readTo + if err := readTo(d, &samples); err != nil { + t.Fatal(err) + } + // Double header allowed, value should be of third row + if samples[0].Foo != "baz" { + t.Fatal("Double header allowed, value should be of third row but is not. Function called is readTo.") + } + + b = bytes.NewBufferString(`foo,BAR,foo +f,1,baz +e,3,b`) + d = &decoder{in: b} + ShouldAlignDuplicateHeadersWithStructFieldOrder = true + if err := readTo(d, &samples); err != nil { + t.Fatal(err) + } + // Double header allowed, value should be of first row + if samples[0].Foo != "f" { + t.Fatal("Double header allowed, value should be of first row but is not. Function called is readTo.") + } + + ShouldAlignDuplicateHeadersWithStructFieldOrder = false + // Double header not allowed, should fail + FailIfDoubleHeaderNames = true + if err := readTo(d, &samples); err == nil { + t.Fatal("Double header not allowed but no error raised. Function called is readTo.") + } + + // *** check readEach + FailIfDoubleHeaderNames = false + b = bytes.NewBufferString(`foo,BAR,foo +f,1,baz +e,3,b`) + d = &decoder{in: b} + samples = samples[:0] + c := make(chan Sample) + go func() { + if err := readEach(d, c); err != nil { + t.Fatal(err) + } + }() + for v := range c { + samples = append(samples, v) + } + // Double header allowed, value should be of third row + if samples[0].Foo != "baz" { + t.Fatal("Double header allowed, value should be of third row but is not. Function called is readEach.") + } + // Double header not allowed, should fail + FailIfDoubleHeaderNames = true + b = bytes.NewBufferString(`foo,BAR,foo +f,1,baz +e,3,b`) + d = &decoder{in: b} + c = make(chan Sample) + go func() { + if err := readEach(d, c); err == nil { + t.Fatal("Double header not allowed but no error raised. Function called is readEach.") + } + }() + for v := range c { + samples = append(samples, v) + } +} + +func TestUnmarshalToCallback(t *testing.T) { + b := bytes.NewBufferString(`first,foo,BAR,Baz,last,abc +aa,bb,11,cc,dd,ee +ff,gg,22,hh,ii,jj`) + var samples []SkipFieldSample + if err := UnmarshalBytesToCallback(b.Bytes(), func(s SkipFieldSample) { + samples = append(samples, s) + }); err != nil { + t.Fatal(err) + } + if len(samples) != 2 { + t.Fatalf("expected 2 sample instances, got %d", len(samples)) + } + expected := SkipFieldSample{ + EmbedSample: EmbedSample{ + Qux: "aa", + Sample: Sample{ + Foo: "bb", + Bar: 11, + Baz: "cc", + }, + Quux: "dd", + }, + Corge: "ee", + } + if expected != samples[0] { + t.Fatalf("expected first sample %v, got %v", expected, samples[0]) + } + expected = SkipFieldSample{ + EmbedSample: EmbedSample{ + Qux: "ff", + Sample: Sample{ + Foo: "gg", + Bar: 22, + Baz: "hh", + }, + Quux: "ii", + }, + Corge: "jj", + } + if expected != samples[1] { + t.Fatalf("expected first sample %v, got %v", expected, samples[1]) + } +} + +// TestRenamedTypes tests for unmarshaling functions on redefined basic types. +func TestRenamedTypesUnmarshal(t *testing.T) { + b := bytes.NewBufferString(`foo;bar +1,4;1.5 +2,3;2.4`) + d := &decoder{in: b} + var samples []RenamedSample + + // Set different csv field separator to enable comma in floats + SetCSVReader(func(in io.Reader) CSVReader { + csvin := csv.NewReader(in) + csvin.Comma = ';' + return csvin + }) + // Switch back to default for tests executed after this + defer SetCSVReader(DefaultCSVReader) + + if err := readTo(d, &samples); err != nil { + t.Fatal(err) + } + if samples[0].RenamedFloatUnmarshaler != 1.4 { + t.Fatalf("Parsed float value wrong for renamed float64 type. Expected 1.4, got %v.", samples[0].RenamedFloatUnmarshaler) + } + if samples[0].RenamedFloatDefault != 1.5 { + t.Fatalf("Parsed float value wrong for renamed float64 type without an explicit unmarshaler function. Expected 1.5, got %v.", samples[0].RenamedFloatDefault) + } + + // Test that errors raised by UnmarshalCSV are correctly reported + b = bytes.NewBufferString(`foo;bar +4.2;2.4`) + d = &decoder{in: b} + samples = samples[:0] + if perr, _ := readTo(d, &samples).(*csv.ParseError); perr == nil { + t.Fatalf("Expected ParseError, got nil.") + } else if _, ok := perr.Err.(UnmarshalError); !ok { + t.Fatalf("Expected UnmarshalError, got %v", perr.Err) + } +} + +func (rf *RenamedFloat64Unmarshaler) UnmarshalCSV(csv string) (err error) { + // Purely for testing purposes: Raise error on specific string + if csv == "4.2" { + return UnmarshalError{"Test error: Invalid float 4.2"} + } + + // Convert , to . before parsing to create valid float strings + converted := strings.Replace(csv, ",", ".", -1) + var f float64 + if f, err = strconv.ParseFloat(converted, 64); err != nil { + return err + } + *rf = RenamedFloat64Unmarshaler(f) + return nil +} + +type UnmarshalError struct { + msg string +} + +func (e UnmarshalError) Error() string { + return e.msg +} + +func TestMultipleStructTags(t *testing.T) { + b := bytes.NewBufferString(`foo,BAR,Baz +e,3,b`) + d := &decoder{in: b} + + var samples []MultiTagSample + if err := readTo(d, &samples); err != nil { + t.Fatal(err) + } + if samples[0].Foo != "b" { + t.Fatalf("expected second tag value 'b' in multi tag struct field, got %v", samples[0].Foo) + } + + b = bytes.NewBufferString(`foo,BAR +e,3`) + d = &decoder{in: b} + + if err := readTo(d, &samples); err != nil { + t.Fatal(err) + } + if samples[0].Foo != "e" { + t.Fatalf("wrong value in multi tag struct field, expected 'e', got %v", samples[0].Foo) + } + + b = bytes.NewBufferString(`BAR,Baz +3,b`) + d = &decoder{in: b} + + if err := readTo(d, &samples); err != nil { + t.Fatal(err) + } + if samples[0].Foo != "b" { + t.Fatal("wrong value in multi tag struct field") + } +} + +func TestStructTagSeparator(t *testing.T) { + b := bytes.NewBufferString(`foo,BAR,Baz +e,3,b`) + d := &decoder{in: b} + + defaultTagSeparator := TagSeparator + TagSeparator = "|" + defer func() { + TagSeparator = defaultTagSeparator + }() + + var samples []TagSeparatorSample + if err := readTo(d, &samples); err != nil { + t.Fatal(err) + } + + if samples[0].Foo != "b" { + t.Fatal("expected second tag value in multi tag struct field.") + } +} + +func TestCSVToMap(t *testing.T) { + b := bytes.NewBufferString(`foo,BAR +4,Jose +2,Daniel +5,Vincent`) + m, err := CSVToMap(bytes.NewReader(b.Bytes())) + if err != nil { + t.Fatal(err) + } + if m["4"] != "Jose" { + t.Fatal("Expected Jose got", m["4"]) + } + if m["2"] != "Daniel" { + t.Fatal("Expected Daniel got", m["2"]) + } + if m["5"] != "Vincent" { + t.Fatal("Expected Vincent got", m["5"]) + } + + b = bytes.NewBufferString(`foo,BAR,Baz +e,3,b`) + _, err = CSVToMap(bytes.NewReader(b.Bytes())) + if err == nil { + t.Fatal("Something went wrong") + } + b = bytes.NewBufferString(`foo +e`) + _, err = CSVToMap(bytes.NewReader(b.Bytes())) + if err == nil { + t.Fatal("Something went wrong") + } +} + +func TestCSVToMaps(t *testing.T) { + b := bytes.NewBufferString(`foo,BAR,Baz +4,Jose,42 +2,Daniel,21 +5,Vincent,84`) + m, err := CSVToMaps(bytes.NewReader(b.Bytes())) + if err != nil { + t.Fatal(err) + } + firstRecord := m[0] + if firstRecord["foo"] != "4" { + t.Fatal("Expected 4 got", firstRecord["foo"]) + } + if firstRecord["BAR"] != "Jose" { + t.Fatal("Expected Jose got", firstRecord["BAR"]) + } + if firstRecord["Baz"] != "42" { + t.Fatal("Expected 42 got", firstRecord["Baz"]) + } + secondRecord := m[1] + if secondRecord["foo"] != "2" { + t.Fatal("Expected 2 got", secondRecord["foo"]) + } + if secondRecord["BAR"] != "Daniel" { + t.Fatal("Expected Daniel got", secondRecord["BAR"]) + } + if secondRecord["Baz"] != "21" { + t.Fatal("Expected 21 got", secondRecord["Baz"]) + } + thirdRecord := m[2] + if thirdRecord["foo"] != "5" { + t.Fatal("Expected 5 got", thirdRecord["foo"]) + } + if thirdRecord["BAR"] != "Vincent" { + t.Fatal("Expected Vincent got", thirdRecord["BAR"]) + } + if thirdRecord["Baz"] != "84" { + t.Fatal("Expected 84 got", thirdRecord["Baz"]) + } +} + +type trimDecoder struct { + csvReader CSVReader +} + +func (c *trimDecoder) getCSVRow() ([]string, error) { + recoder, err := c.csvReader.Read() + for i, r := range recoder { + recoder[i] = strings.TrimRight(r, " ") + } + return recoder, err +} + +func TestUnmarshalToDecoder(t *testing.T) { + blah := 0 + sptr := "*string" + sptr2 := "" + b := bytes.NewBufferString(`foo,BAR,Baz,Blah,SPtr +f,1,baz,, *string +e,3,b,, `) + + var samples []Sample + if err := UnmarshalDecoderToCallback(&trimDecoder{LazyCSVReader(b)}, func(s Sample) { + samples = append(samples, s) + }); err != nil { + t.Fatal(err) + } + if len(samples) != 2 { + t.Fatalf("expected 2 sample instances, got %d", len(samples)) + } + + expected := Sample{Foo: "f", Bar: 1, Baz: "baz", Blah: &blah, SPtr: &sptr} + if !reflect.DeepEqual(expected, samples[0]) { + t.Fatalf("expected first sample %v, got %v", expected, samples[0]) + } + + expected = Sample{Foo: "e", Bar: 3, Baz: "b", Blah: &blah, SPtr: &sptr2} + if !reflect.DeepEqual(expected, samples[1]) { + t.Fatalf("expected second sample %v, got %v", expected, samples[1]) + } +} + +func TestUnmarshalWithoutHeader(t *testing.T) { + blah := 0 + sptr := "" + b := bytes.NewBufferString(`f,1,baz,1.66,,, +e,3,b,,,,`) + d := &decoder{in: b} + + var samples []Sample + if err := readToWithoutHeaders(d, &samples); err != nil { + t.Fatal(err) + } + + expected := Sample{Foo: "f", Bar: 1, Baz: "baz", Frop: 1.66, Blah: &blah, SPtr: &sptr} + if !reflect.DeepEqual(expected, samples[0]) { + t.Fatalf("expected first sample %v, got %v", expected, samples[0]) + } + + expected = Sample{Foo: "e", Bar: 3, Baz: "b", Frop: 0, Blah: &blah, SPtr: &sptr} + if !reflect.DeepEqual(expected, samples[1]) { + t.Fatalf("expected second sample %v, got %v", expected, samples[1]) + } +} diff --git a/vendor/github.com/gocarina/gocsv/encode.go b/vendor/github.com/gocarina/gocsv/encode.go new file mode 100644 index 000000000000..7a41f9fcb6a7 --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/encode.go @@ -0,0 +1,139 @@ +package gocsv + +import ( + "fmt" + "io" + "reflect" +) + +type encoder struct { + out io.Writer +} + +func newEncoder(out io.Writer) *encoder { + return &encoder{out} +} + +func writeFromChan(writer *SafeCSVWriter, c <-chan interface{}) error { + // Get the first value. It wil determine the header structure. + firstValue, ok := <-c + if !ok { + return fmt.Errorf("channel is closed") + } + inValue, inType := getConcreteReflectValueAndType(firstValue) // Get the concrete type + if err := ensureStructOrPtr(inType); err != nil { + return err + } + inInnerWasPointer := inType.Kind() == reflect.Ptr + inInnerStructInfo := getStructInfo(inType) // Get the inner struct info to get CSV annotations + csvHeadersLabels := make([]string, len(inInnerStructInfo.Fields)) + for i, fieldInfo := range inInnerStructInfo.Fields { // Used to write the header (first line) in CSV + csvHeadersLabels[i] = fieldInfo.getFirstKey() + } + if err := writer.Write(csvHeadersLabels); err != nil { + return err + } + write := func(val reflect.Value) error { + for j, fieldInfo := range inInnerStructInfo.Fields { + csvHeadersLabels[j] = "" + inInnerFieldValue, err := getInnerField(val, inInnerWasPointer, fieldInfo.IndexChain) // Get the correct field header <-> position + if err != nil { + return err + } + csvHeadersLabels[j] = inInnerFieldValue + } + if err := writer.Write(csvHeadersLabels); err != nil { + return err + } + return nil + } + if err := write(inValue); err != nil { + return err + } + for v := range c { + val, _ := getConcreteReflectValueAndType(v) // Get the concrete type (not pointer) (Slice or Array) + if err := ensureStructOrPtr(inType); err != nil { + return err + } + if err := write(val); err != nil { + return err + } + } + writer.Flush() + return writer.Error() +} + +func writeTo(writer *SafeCSVWriter, in interface{}, omitHeaders bool) error { + inValue, inType := getConcreteReflectValueAndType(in) // Get the concrete type (not pointer) (Slice or Array) + if err := ensureInType(inType); err != nil { + return err + } + inInnerWasPointer, inInnerType := getConcreteContainerInnerType(inType) // Get the concrete inner type (not pointer) (Container<"?">) + if err := ensureInInnerType(inInnerType); err != nil { + return err + } + inInnerStructInfo := getStructInfo(inInnerType) // Get the inner struct info to get CSV annotations + csvHeadersLabels := make([]string, len(inInnerStructInfo.Fields)) + for i, fieldInfo := range inInnerStructInfo.Fields { // Used to write the header (first line) in CSV + csvHeadersLabels[i] = fieldInfo.getFirstKey() + } + if !omitHeaders { + if err := writer.Write(csvHeadersLabels); err != nil { + return err + } + } + inLen := inValue.Len() + for i := 0; i < inLen; i++ { // Iterate over container rows + for j, fieldInfo := range inInnerStructInfo.Fields { + csvHeadersLabels[j] = "" + inInnerFieldValue, err := getInnerField(inValue.Index(i), inInnerWasPointer, fieldInfo.IndexChain) // Get the correct field header <-> position + if err != nil { + return err + } + csvHeadersLabels[j] = inInnerFieldValue + } + if err := writer.Write(csvHeadersLabels); err != nil { + return err + } + } + writer.Flush() + return writer.Error() +} + +func ensureStructOrPtr(t reflect.Type) error { + switch t.Kind() { + case reflect.Struct: + fallthrough + case reflect.Ptr: + return nil + } + return fmt.Errorf("cannot use " + t.String() + ", only slice or array supported") +} + +// Check if the inType is an array or a slice +func ensureInType(outType reflect.Type) error { + switch outType.Kind() { + case reflect.Slice: + fallthrough + case reflect.Array: + return nil + } + return fmt.Errorf("cannot use " + outType.String() + ", only slice or array supported") +} + +// Check if the inInnerType is of type struct +func ensureInInnerType(outInnerType reflect.Type) error { + switch outInnerType.Kind() { + case reflect.Struct: + return nil + } + return fmt.Errorf("cannot use " + outInnerType.String() + ", only struct supported") +} + +func getInnerField(outInner reflect.Value, outInnerWasPointer bool, index []int) (string, error) { + oi := outInner + if outInnerWasPointer { + oi = outInner.Elem() + } + return getFieldAsString(oi.FieldByIndex(index)) +} diff --git a/vendor/github.com/gocarina/gocsv/encode_test.go b/vendor/github.com/gocarina/gocsv/encode_test.go new file mode 100644 index 000000000000..85e807b4c2e1 --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/encode_test.go @@ -0,0 +1,295 @@ +package gocsv + +import ( + "bytes" + "encoding/csv" + "io" + "math" + "strconv" + "strings" + "testing" + "time" +) + +func assertLine(t *testing.T, expected, actual []string) { + if len(expected) != len(actual) { + t.Fatalf("line length mismatch between expected: %d and actual: %d", len(expected), len(actual)) + } + for i := range expected { + if expected[i] != actual[i] { + t.Fatalf("mismatch on field %d at line `%s`: %s != %s", i, expected, expected[i], actual[i]) + } + } +} + +func Test_writeTo(t *testing.T) { + b := bytes.Buffer{} + e := &encoder{out: &b} + blah := 2 + sptr := "*string" + s := []Sample{ + {Foo: "f", Bar: 1, Baz: "baz", Frop: 0.1, Blah: &blah, SPtr: &sptr}, + {Foo: "e", Bar: 3, Baz: "b", Frop: 6.0 / 13, Blah: nil, SPtr: nil}, + } + if err := writeTo(NewSafeCSVWriter(csv.NewWriter(e.out)), s, false); err != nil { + t.Fatal(err) + } + + lines, err := csv.NewReader(&b).ReadAll() + if err != nil { + t.Fatal(err) + } + if len(lines) != 3 { + t.Fatalf("expected 3 lines, got %d", len(lines)) + } + assertLine(t, []string{"foo", "BAR", "Baz", "Quux", "Blah", "SPtr", "Omit"}, lines[0]) + assertLine(t, []string{"f", "1", "baz", "0.1", "2", "*string", ""}, lines[1]) + assertLine(t, []string{"e", "3", "b", "0.46153846153846156", "", "", ""}, lines[2]) +} + +func Test_writeTo_Time(t *testing.T) { + b := bytes.Buffer{} + e := &encoder{out: &b} + d := time.Unix(60, 0) + s := []DateTime{ + {Foo: d}, + } + if err := writeTo(NewSafeCSVWriter(csv.NewWriter(e.out)), s, true); err != nil { + t.Fatal(err) + } + + lines, err := csv.NewReader(&b).ReadAll() + if err != nil { + t.Fatal(err) + } + + ft := time.Now() + ft.UnmarshalText([]byte(lines[0][0])) + if err != nil { + t.Fatal(err) + } + if ft.Sub(d) != 0 { + t.Fatalf("Dates doesn't match: %s and actual: %s", d, d) + } + + m, _ := d.MarshalText() + assertLine(t, []string{string(m)}, lines[0]) +} + +func Test_writeTo_NoHeaders(t *testing.T) { + b := bytes.Buffer{} + e := &encoder{out: &b} + blah := 2 + sptr := "*string" + s := []Sample{ + {Foo: "f", Bar: 1, Baz: "baz", Frop: 0.1, Blah: &blah, SPtr: &sptr}, + {Foo: "e", Bar: 3, Baz: "b", Frop: 6.0 / 13, Blah: nil, SPtr: nil}, + } + if err := writeTo(NewSafeCSVWriter(csv.NewWriter(e.out)), s, true); err != nil { + t.Fatal(err) + } + + lines, err := csv.NewReader(&b).ReadAll() + if err != nil { + t.Fatal(err) + } + if len(lines) != 2 { + t.Fatalf("expected 2 lines, got %d", len(lines)) + } + assertLine(t, []string{"f", "1", "baz", "0.1", "2", "*string", ""}, lines[0]) + assertLine(t, []string{"e", "3", "b", "0.46153846153846156", "", "", ""}, lines[1]) +} + +func Test_writeTo_multipleTags(t *testing.T) { + b := bytes.Buffer{} + e := &encoder{out: &b} + s := []MultiTagSample{ + {Foo: "abc", Bar: 123}, + {Foo: "def", Bar: 234}, + } + if err := writeTo(NewSafeCSVWriter(csv.NewWriter(e.out)), s, false); err != nil { + t.Fatal(err) + } + + lines, err := csv.NewReader(&b).ReadAll() + if err != nil { + t.Fatal(err) + } + if len(lines) != 3 { + t.Fatalf("expected 3 lines, got %d", len(lines)) + } + // the first tag for each field is the encoding CSV header + assertLine(t, []string{"Baz", "BAR"}, lines[0]) + assertLine(t, []string{"abc", "123"}, lines[1]) + assertLine(t, []string{"def", "234"}, lines[2]) +} + +func Test_writeTo_embed(t *testing.T) { + b := bytes.Buffer{} + e := &encoder{out: &b} + blah := 2 + sptr := "*string" + s := []EmbedSample{ + { + Qux: "aaa", + Sample: Sample{Foo: "f", Bar: 1, Baz: "baz", Frop: 0.2, Blah: &blah, SPtr: &sptr}, + Ignore: "shouldn't be marshalled", + Quux: "zzz", + Grault: math.Pi, + }, + } + if err := writeTo(NewSafeCSVWriter(csv.NewWriter(e.out)), s, false); err != nil { + t.Fatal(err) + } + + lines, err := csv.NewReader(&b).ReadAll() + if err != nil { + t.Fatal(err) + } + if len(lines) != 2 { + t.Fatalf("expected 2 lines, got %d", len(lines)) + } + assertLine(t, []string{"first", "foo", "BAR", "Baz", "Quux", "Blah", "SPtr", "Omit", "garply", "last"}, lines[0]) + assertLine(t, []string{"aaa", "f", "1", "baz", "0.2", "2", "*string", "", "3.141592653589793", "zzz"}, lines[1]) +} + +func Test_writeTo_complex_embed(t *testing.T) { + b := bytes.Buffer{} + e := &encoder{out: &b} + sptr := "*string" + sfs := []SkipFieldSample{ + { + EmbedSample: EmbedSample{ + Qux: "aaa", + Sample: Sample{ + Foo: "bbb", + Bar: 111, + Baz: "ddd", + Frop: 1.2e22, + Blah: nil, + SPtr: &sptr, + }, + Ignore: "eee", + Grault: 0.1, + Quux: "fff", + }, + MoreIgnore: "ggg", + Corge: "hhh", + }, + } + if err := writeTo(NewSafeCSVWriter(csv.NewWriter(e.out)), sfs, false); err != nil { + t.Fatal(err) + } + lines, err := csv.NewReader(&b).ReadAll() + if err != nil { + t.Fatal(err) + } + if len(lines) != 2 { + t.Fatalf("expected 2 lines, got %d", len(lines)) + } + assertLine(t, []string{"first", "foo", "BAR", "Baz", "Quux", "Blah", "SPtr", "Omit", "garply", "last", "abc"}, lines[0]) + assertLine(t, []string{"aaa", "bbb", "111", "ddd", "12000000000000000000000", "", "*string", "", "0.1", "fff", "hhh"}, lines[1]) +} + +func Test_writeToChan(t *testing.T) { + b := bytes.Buffer{} + e := &encoder{out: &b} + c := make(chan interface{}) + sptr := "*string" + go func() { + for i := 0; i < 100; i++ { + v := Sample{Foo: "f", Bar: i, Baz: "baz" + strconv.Itoa(i), Frop: float64(i), Blah: nil, SPtr: &sptr} + c <- v + } + close(c) + }() + if err := MarshalChan(c, NewSafeCSVWriter(csv.NewWriter(e.out))); err != nil { + t.Fatal(err) + } + lines, err := csv.NewReader(&b).ReadAll() + if err != nil { + t.Fatal(err) + } + if len(lines) != 101 { + t.Fatalf("expected 100 lines, got %d", len(lines)) + } + for i, l := range lines { + if i == 0 { + assertLine(t, []string{"foo", "BAR", "Baz", "Quux", "Blah", "SPtr", "Omit"}, l) + continue + } + assertLine(t, []string{"f", strconv.Itoa(i - 1), "baz" + strconv.Itoa(i-1), strconv.FormatFloat(float64(i-1), 'f', -1, 64), "", "*string", ""}, l) + } +} + +// TestRenamedTypes tests for marshaling functions on redefined basic types. +func TestRenamedTypesMarshal(t *testing.T) { + samples := []RenamedSample{ + {RenamedFloatUnmarshaler: 1.4, RenamedFloatDefault: 1.5}, + {RenamedFloatUnmarshaler: 2.3, RenamedFloatDefault: 2.4}, + } + + SetCSVWriter(func(out io.Writer) *SafeCSVWriter { + csvout := NewSafeCSVWriter(csv.NewWriter(out)) + csvout.Comma = ';' + return csvout + }) + // Switch back to default for tests executed after this + defer SetCSVWriter(DefaultCSVWriter) + + csvContent, err := MarshalString(&samples) + if err != nil { + t.Fatal(err) + } + if csvContent != "foo;bar\n1,4;1.5\n2,3;2.4\n" { + t.Fatalf("Error marshaling floats with , as separator. Expected \nfoo;bar\n1,4;1.5\n2,3;2.4\ngot:\n%v", csvContent) + } + + // Test that errors raised by MarshalCSV are correctly reported + samples = []RenamedSample{ + {RenamedFloatUnmarshaler: 4.2, RenamedFloatDefault: 1.5}, + } + _, err = MarshalString(&samples) + if _, ok := err.(MarshalError); !ok { + t.Fatalf("Expected UnmarshalError, got %v", err) + } +} + +// TestCustomTagSeparatorMarshal tests for custom tag separator in marshalling. +func TestCustomTagSeparatorMarshal(t *testing.T) { + samples := []RenamedSample{ + {RenamedFloatUnmarshaler: 1.4, RenamedFloatDefault: 1.5}, + {RenamedFloatUnmarshaler: 2.3, RenamedFloatDefault: 2.4}, + } + + TagSeparator = " | " + // Switch back to default TagSeparator after this + defer func() { + TagSeparator = "," + }() + + csvContent, err := MarshalString(&samples) + if err != nil { + t.Fatal(err) + } + if csvContent != "foo|bar\n1,4|1.5\n2,3|2.4\n" { + t.Fatalf("Error marshaling floats with , as separator. Expected \nfoo|bar\n1,4|1.5\n2,3|2.4\ngot:\n%v", csvContent) + } +} + +func (rf *RenamedFloat64Unmarshaler) MarshalCSV() (csv string, err error) { + if *rf == RenamedFloat64Unmarshaler(4.2) { + return "", MarshalError{"Test error: Invalid float 4.2"} + } + csv = strconv.FormatFloat(float64(*rf), 'f', 1, 64) + csv = strings.Replace(csv, ".", ",", -1) + return csv, nil +} + +type MarshalError struct { + msg string +} + +func (e MarshalError) Error() string { + return e.msg +} diff --git a/vendor/github.com/gocarina/gocsv/reflect.go b/vendor/github.com/gocarina/gocsv/reflect.go new file mode 100644 index 000000000000..9217e30b9106 --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/reflect.go @@ -0,0 +1,107 @@ +package gocsv + +import ( + "reflect" + "strings" + "sync" +) + +// -------------------------------------------------------------------------- +// Reflection helpers + +type structInfo struct { + Fields []fieldInfo +} + +// fieldInfo is a struct field that should be mapped to a CSV column, or vice-versa +// Each IndexChain element before the last is the index of an the embedded struct field +// that defines Key as a tag +type fieldInfo struct { + keys []string + omitEmpty bool + IndexChain []int +} + +func (f fieldInfo) getFirstKey() string { + return f.keys[0] +} + +func (f fieldInfo) matchesKey(key string) bool { + for _, k := range f.keys { + if key == k || strings.TrimSpace(key) == k { + return true + } + } + return false +} + +var structMap = make(map[reflect.Type]*structInfo) +var structMapMutex sync.RWMutex + +func getStructInfo(rType reflect.Type) *structInfo { + structMapMutex.RLock() + stInfo, ok := structMap[rType] + structMapMutex.RUnlock() + if ok { + return stInfo + } + fieldsList := getFieldInfos(rType, []int{}) + stInfo = &structInfo{fieldsList} + return stInfo +} + +func getFieldInfos(rType reflect.Type, parentIndexChain []int) []fieldInfo { + fieldsCount := rType.NumField() + fieldsList := make([]fieldInfo, 0, fieldsCount) + for i := 0; i < fieldsCount; i++ { + field := rType.Field(i) + if field.PkgPath != "" { + continue + } + indexChain := append(parentIndexChain, i) + // if the field is an embedded struct, create a fieldInfo for each of its fields + if field.Anonymous && field.Type.Kind() == reflect.Struct { + fieldsList = append(fieldsList, getFieldInfos(field.Type, indexChain)...) + continue + } + fieldInfo := fieldInfo{IndexChain: indexChain} + fieldTag := field.Tag.Get("csv") + fieldTags := strings.Split(fieldTag, TagSeparator) + filteredTags := []string{} + for _, fieldTagEntry := range fieldTags { + if fieldTagEntry != "omitempty" { + filteredTags = append(filteredTags, fieldTagEntry) + } else { + fieldInfo.omitEmpty = true + } + } + + if len(filteredTags) == 1 && filteredTags[0] == "-" { + continue + } else if len(filteredTags) > 0 && filteredTags[0] != "" { + fieldInfo.keys = filteredTags + } else { + fieldInfo.keys = []string{field.Name} + } + fieldsList = append(fieldsList, fieldInfo) + } + return fieldsList +} + +func getConcreteContainerInnerType(in reflect.Type) (inInnerWasPointer bool, inInnerType reflect.Type) { + inInnerType = in.Elem() + inInnerWasPointer = false + if inInnerType.Kind() == reflect.Ptr { + inInnerWasPointer = true + inInnerType = inInnerType.Elem() + } + return inInnerWasPointer, inInnerType +} + +func getConcreteReflectValueAndType(in interface{}) (reflect.Value, reflect.Type) { + value := reflect.ValueOf(in) + if value.Kind() == reflect.Ptr { + value = value.Elem() + } + return value, value.Type() +} diff --git a/vendor/github.com/gocarina/gocsv/safe_csv.go b/vendor/github.com/gocarina/gocsv/safe_csv.go new file mode 100644 index 000000000000..4b2882f1c425 --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/safe_csv.go @@ -0,0 +1,32 @@ +package gocsv + +//Wraps around SafeCSVWriter and makes it thread safe. +import ( + "encoding/csv" + "sync" +) + +type SafeCSVWriter struct { + *csv.Writer + m sync.Mutex +} + +func NewSafeCSVWriter(original *csv.Writer) *SafeCSVWriter { + return &SafeCSVWriter{ + Writer: original, + } +} + +//Override write +func (w *SafeCSVWriter) Write(row []string) error { + w.m.Lock() + defer w.m.Unlock() + return w.Writer.Write(row) +} + +//Override flush +func (w *SafeCSVWriter) Flush() { + w.m.Lock() + w.Writer.Flush() + w.m.Unlock() +} diff --git a/vendor/github.com/gocarina/gocsv/sample_structs_test.go b/vendor/github.com/gocarina/gocsv/sample_structs_test.go new file mode 100644 index 000000000000..e5e1b09dfb33 --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/sample_structs_test.go @@ -0,0 +1,50 @@ +package gocsv + +import "time" + +type Sample struct { + Foo string `csv:"foo"` + Bar int `csv:"BAR"` + Baz string `csv:"Baz"` + Frop float64 `csv:"Quux"` + Blah *int `csv:"Blah"` + SPtr *string `csv:"SPtr"` + Omit *string `csv:"Omit,omitempty"` +} + +type EmbedSample struct { + Qux string `csv:"first"` + Sample + Ignore string `csv:"-"` + Grault float64 `csv:"garply"` + Quux string `csv:"last"` +} + +type SkipFieldSample struct { + EmbedSample + MoreIgnore string `csv:"-"` + Corge string `csv:"abc"` +} + +// Testtype for unmarshal/marshal functions on renamed basic types +type RenamedFloat64Unmarshaler float64 +type RenamedFloat64Default float64 + +type RenamedSample struct { + RenamedFloatUnmarshaler RenamedFloat64Unmarshaler `csv:"foo"` + RenamedFloatDefault RenamedFloat64Default `csv:"bar"` +} + +type MultiTagSample struct { + Foo string `csv:"Baz,foo"` + Bar int `csv:"BAR"` +} + +type TagSeparatorSample struct { + Foo string `csv:"Baz|foo"` + Bar int `csv:"BAR"` +} + +type DateTime struct { + Foo time.Time `csv:"Foo"` +} diff --git a/vendor/github.com/gocarina/gocsv/types.go b/vendor/github.com/gocarina/gocsv/types.go new file mode 100644 index 000000000000..50d88ce1849d --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/types.go @@ -0,0 +1,456 @@ +package gocsv + +import ( + "encoding" + "fmt" + "reflect" + "strconv" + "strings" +) + +// -------------------------------------------------------------------------- +// Conversion interfaces + +// TypeMarshaller is implemented by any value that has a MarshalCSV method +// This converter is used to convert the value to it string representation +type TypeMarshaller interface { + MarshalCSV() (string, error) +} + +// Stringer is implemented by any value that has a String method +// This converter is used to convert the value to it string representation +// This converter will be used if your value does not implement TypeMarshaller +type Stringer interface { + String() string +} + +// TypeUnmarshaller is implemented by any value that has an UnmarshalCSV method +// This converter is used to convert a string to your value representation of that string +type TypeUnmarshaller interface { + UnmarshalCSV(string) error +} + +// NoUnmarshalFuncError is the custom error type to be raised in case there is no unmarshal function defined on type +type NoUnmarshalFuncError struct { + msg string +} + +func (e NoUnmarshalFuncError) Error() string { + return e.msg +} + +// NoMarshalFuncError is the custom error type to be raised in case there is no marshal function defined on type +type NoMarshalFuncError struct { + msg string +} + +func (e NoMarshalFuncError) Error() string { + return e.msg +} + +var ( + stringerType = reflect.TypeOf((*Stringer)(nil)).Elem() + marshallerType = reflect.TypeOf((*TypeMarshaller)(nil)).Elem() + unMarshallerType = reflect.TypeOf((*TypeUnmarshaller)(nil)).Elem() + textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() + textUnMarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() +) + +// -------------------------------------------------------------------------- +// Conversion helpers + +func toString(in interface{}) (string, error) { + inValue := reflect.ValueOf(in) + + switch inValue.Kind() { + case reflect.String: + return inValue.String(), nil + case reflect.Bool: + b := inValue.Bool() + if b { + return "true", nil + } + return "false", nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return fmt.Sprintf("%v", inValue.Int()), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return fmt.Sprintf("%v", inValue.Uint()), nil + case reflect.Float32: + return strconv.FormatFloat(inValue.Float(), byte('f'), -1, 32), nil + case reflect.Float64: + return strconv.FormatFloat(inValue.Float(), byte('f'), -1, 64), nil + } + return "", fmt.Errorf("No known conversion from " + inValue.Type().String() + " to string") +} + +func toBool(in interface{}) (bool, error) { + inValue := reflect.ValueOf(in) + + switch inValue.Kind() { + case reflect.String: + s := inValue.String() + switch s { + case "yes": + return true, nil + case "no", "": + return false, nil + default: + return strconv.ParseBool(s) + } + case reflect.Bool: + return inValue.Bool(), nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + i := inValue.Int() + if i != 0 { + return true, nil + } + return false, nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + i := inValue.Uint() + if i != 0 { + return true, nil + } + return false, nil + case reflect.Float32, reflect.Float64: + f := inValue.Float() + if f != 0 { + return true, nil + } + return false, nil + } + return false, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to bool") +} + +func toInt(in interface{}) (int64, error) { + inValue := reflect.ValueOf(in) + + switch inValue.Kind() { + case reflect.String: + s := strings.TrimSpace(inValue.String()) + if s == "" { + return 0, nil + } + return strconv.ParseInt(s, 0, 64) + case reflect.Bool: + if inValue.Bool() { + return 1, nil + } + return 0, nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return inValue.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return int64(inValue.Uint()), nil + case reflect.Float32, reflect.Float64: + return int64(inValue.Float()), nil + } + return 0, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to int") +} + +func toUint(in interface{}) (uint64, error) { + inValue := reflect.ValueOf(in) + + switch inValue.Kind() { + case reflect.String: + s := strings.TrimSpace(inValue.String()) + if s == "" { + return 0, nil + } + + // support the float input + if strings.Contains(s, ".") { + f, err := strconv.ParseFloat(s, 64) + if err != nil { + return 0, err + } + return uint64(f), nil + } + return strconv.ParseUint(s, 0, 64) + case reflect.Bool: + if inValue.Bool() { + return 1, nil + } + return 0, nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return uint64(inValue.Int()), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return inValue.Uint(), nil + case reflect.Float32, reflect.Float64: + return uint64(inValue.Float()), nil + } + return 0, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to uint") +} + +func toFloat(in interface{}) (float64, error) { + inValue := reflect.ValueOf(in) + + switch inValue.Kind() { + case reflect.String: + s := strings.TrimSpace(inValue.String()) + if s == "" { + return 0, nil + } + return strconv.ParseFloat(s, 64) + case reflect.Bool: + if inValue.Bool() { + return 1, nil + } + return 0, nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return float64(inValue.Int()), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return float64(inValue.Uint()), nil + case reflect.Float32, reflect.Float64: + return inValue.Float(), nil + } + return 0, fmt.Errorf("No known conversion from " + inValue.Type().String() + " to float") +} + +func setField(field reflect.Value, value string, omitEmpty bool) error { + if field.Kind() == reflect.Ptr { + if omitEmpty && value == "" { + return nil + } + if field.IsNil() { + field.Set(reflect.New(field.Type().Elem())) + } + field = field.Elem() + } + + switch field.Interface().(type) { + case string: + s, err := toString(value) + if err != nil { + return err + } + field.SetString(s) + case bool: + b, err := toBool(value) + if err != nil { + return err + } + field.SetBool(b) + case int, int8, int16, int32, int64: + i, err := toInt(value) + if err != nil { + return err + } + field.SetInt(i) + case uint, uint8, uint16, uint32, uint64: + ui, err := toUint(value) + if err != nil { + return err + } + field.SetUint(ui) + case float32, float64: + f, err := toFloat(value) + if err != nil { + return err + } + field.SetFloat(f) + default: + // Not a native type, check for unmarshal method + if err := unmarshall(field, value); err != nil { + if _, ok := err.(NoUnmarshalFuncError); !ok { + return err + } + // Could not unmarshal, check for kind, e.g. renamed type from basic type + switch field.Kind() { + case reflect.String: + s, err := toString(value) + if err != nil { + return err + } + field.SetString(s) + case reflect.Bool: + b, err := toBool(value) + if err != nil { + return err + } + field.SetBool(b) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + i, err := toInt(value) + if err != nil { + return err + } + field.SetInt(i) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + ui, err := toUint(value) + if err != nil { + return err + } + field.SetUint(ui) + case reflect.Float32, reflect.Float64: + f, err := toFloat(value) + if err != nil { + return err + } + field.SetFloat(f) + default: + return err + } + } else { + return nil + } + } + return nil +} + +func getFieldAsString(field reflect.Value) (str string, err error) { + switch field.Kind() { + case reflect.Interface: + case reflect.Ptr: + if field.IsNil() { + return "", nil + } + return getFieldAsString(field.Elem()) + default: + // Check if field is go native type + switch field.Interface().(type) { + case string: + return field.String(), nil + case bool: + str, err = toString(field.Bool()) + if err != nil { + return str, err + } + case int, int8, int16, int32, int64: + str, err = toString(field.Int()) + if err != nil { + return str, err + } + case uint, uint8, uint16, uint32, uint64: + str, err = toString(field.Uint()) + if err != nil { + return str, err + } + case float32: + str, err = toString(float32(field.Float())) + if err != nil { + return str, err + } + case float64: + str, err = toString(field.Float()) + if err != nil { + return str, err + } + default: + // Not a native type, check for marshal method + str, err = marshall(field) + if err != nil { + if _, ok := err.(NoMarshalFuncError); !ok { + return str, err + } + // If not marshal method, is field compatible with/renamed from native type + switch field.Kind() { + case reflect.String: + return field.String(), nil + case reflect.Bool: + str, err = toString(field.Bool()) + if err != nil { + return str, err + } + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + str, err = toString(field.Int()) + if err != nil { + return str, err + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + str, err = toString(field.Uint()) + if err != nil { + return str, err + } + case reflect.Float32: + str, err = toString(float32(field.Float())) + if err != nil { + return str, err + } + case reflect.Float64: + str, err = toString(field.Float()) + if err != nil { + return str, err + } + } + } else { + return str, nil + } + } + } + return str, nil +} + +// -------------------------------------------------------------------------- +// Un/serializations helpers + +func unmarshall(field reflect.Value, value string) error { + dupField := field + unMarshallIt := func(finalField reflect.Value) error { + if finalField.CanInterface() { + fieldIface := finalField.Interface() + + fieldTypeUnmarshaller, ok := fieldIface.(TypeUnmarshaller) + if ok { + return fieldTypeUnmarshaller.UnmarshalCSV(value) + } + + // Otherwise try to use TextUnmarshaler + fieldTextUnmarshaler, ok := fieldIface.(encoding.TextUnmarshaler) + if ok { + return fieldTextUnmarshaler.UnmarshalText([]byte(value)) + } + } + + return NoUnmarshalFuncError{"No known conversion from string to " + field.Type().String() + ", " + field.Type().String() + " does not implement TypeUnmarshaller"} + } + for dupField.Kind() == reflect.Interface || dupField.Kind() == reflect.Ptr { + if dupField.IsNil() { + dupField = reflect.New(field.Type().Elem()) + field.Set(dupField) + return unMarshallIt(dupField) + } + dupField = dupField.Elem() + } + if dupField.CanAddr() { + return unMarshallIt(dupField.Addr()) + } + return NoUnmarshalFuncError{"No known conversion from string to " + field.Type().String() + ", " + field.Type().String() + " does not implement TypeUnmarshaller"} +} + +func marshall(field reflect.Value) (value string, err error) { + dupField := field + marshallIt := func(finalField reflect.Value) (string, error) { + if finalField.CanInterface() { + fieldIface := finalField.Interface() + + // Use TypeMarshaller when possible + fieldTypeMarhaller, ok := fieldIface.(TypeMarshaller) + if ok { + return fieldTypeMarhaller.MarshalCSV() + } + + // Otherwise try to use TextMarshaller + fieldTextMarshaler, ok := fieldIface.(encoding.TextMarshaler) + if ok { + text, err := fieldTextMarshaler.MarshalText() + return string(text), err + } + + // Otherwise try to use Stringer + fieldStringer, ok := fieldIface.(Stringer) + if ok { + return fieldStringer.String(), nil + } + } + + return value, NoMarshalFuncError{"No known conversion from " + field.Type().String() + " to string, " + field.Type().String() + " does not implement TypeMarshaller nor Stringer"} + } + for dupField.Kind() == reflect.Interface || dupField.Kind() == reflect.Ptr { + if dupField.IsNil() { + return value, nil + } + dupField = dupField.Elem() + } + if dupField.CanAddr() { + return marshallIt(dupField.Addr()) + } + return value, NoMarshalFuncError{"No known conversion from " + field.Type().String() + " to string, " + field.Type().String() + " does not implement TypeMarshaller nor Stringer"} +} diff --git a/vendor/github.com/gocarina/gocsv/types_test.go b/vendor/github.com/gocarina/gocsv/types_test.go new file mode 100644 index 000000000000..5828cda16bdf --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/types_test.go @@ -0,0 +1,91 @@ +package gocsv + +import ( + "reflect" + "testing" +) + +type sampleTypeUnmarshaller struct { + val string +} + +func (s *sampleTypeUnmarshaller) UnmarshalCSV(val string) error { + s.val = val + return nil +} + +func (s sampleTypeUnmarshaller) MarshalCSV() (string, error) { + return s.val, nil +} + +type sampleTextUnmarshaller struct { + val []byte +} + +func (s *sampleTextUnmarshaller) UnmarshalText(text []byte) error { + s.val = text + return nil +} + +func (s sampleTextUnmarshaller) MarshalText() ([]byte, error) { + return s.val, nil +} + +type sampleStringer string + +func (s sampleStringer) String() string { + return string(s) +} + +func Benchmark_unmarshall_TypeUnmarshaller(b *testing.B) { + sample := sampleTypeUnmarshaller{} + val := reflect.ValueOf(&sample) + for n := 0; n < b.N; n++ { + if err := unmarshall(val, "foo"); err != nil { + b.Fatalf("unmarshall error: %s", err.Error()) + } + } +} + +func Benchmark_unmarshall_TextUnmarshaller(b *testing.B) { + sample := sampleTextUnmarshaller{} + val := reflect.ValueOf(&sample) + for n := 0; n < b.N; n++ { + if err := unmarshall(val, "foo"); err != nil { + b.Fatalf("unmarshall error: %s", err.Error()) + } + } +} + +func Benchmark_marshall_TypeMarshaller(b *testing.B) { + sample := sampleTypeUnmarshaller{"foo"} + val := reflect.ValueOf(&sample) + for n := 0; n < b.N; n++ { + _, err := marshall(val) + if err != nil { + b.Fatalf("marshall error: %s", err.Error()) + } + } +} + +func Benchmark_marshall_TextMarshaller(b *testing.B) { + sample := sampleTextUnmarshaller{[]byte("foo")} + val := reflect.ValueOf(&sample) + for n := 0; n < b.N; n++ { + _, err := marshall(val) + if err != nil { + b.Fatalf("marshall error: %s", err.Error()) + } + } +} + +func Benchmark_marshall_Stringer(b *testing.B) { + sample := sampleStringer("foo") + val := reflect.ValueOf(&sample) + for n := 0; n < b.N; n++ { + _, err := marshall(val) + if err != nil { + b.Fatalf("marshall error: %s", err.Error()) + } + } +} diff --git a/vendor/github.com/gocarina/gocsv/unmarshaller.go b/vendor/github.com/gocarina/gocsv/unmarshaller.go new file mode 100644 index 000000000000..17837ea4688d --- /dev/null +++ b/vendor/github.com/gocarina/gocsv/unmarshaller.go @@ -0,0 +1,115 @@ +package gocsv + +import ( + "encoding/csv" + "errors" + "fmt" + "reflect" +) + +// Unmarshaller is a CSV to struct unmarshaller. +type Unmarshaller struct { + reader *csv.Reader + headerMap map[int]string + fieldInfoMap map[int]*fieldInfo + MismatchedHeaders []string + MismatchedStructFields []string + outType reflect.Type +} + +// NewUnmarshaller creates an unmarshaller from a csv.Reader and a struct. +func NewUnmarshaller(reader *csv.Reader, out interface{}) (*Unmarshaller, error) { + headers, err := reader.Read() + if err != nil { + return nil, err + } + + um := &Unmarshaller{reader: reader, outType: reflect.TypeOf(out)} + err = validate(um, out, headers) + if err != nil { + return nil, err + } + return um, nil +} + +// Read returns an interface{} whose runtime type is the same as the struct that +// was used to create the Unmarshaller. +func (um *Unmarshaller) Read() (interface{}, error) { + row, err := um.reader.Read() + if err != nil { + return nil, err + } + return um.unmarshalRow(row, nil) +} + +// The same as Read(), but returns a map of the columns that didn't match a field in the struct +func (um *Unmarshaller) ReadUnmatched() (interface{}, map[string]string, error) { + row, err := um.reader.Read() + if err != nil { + return nil, nil, err + } + unmatched := make(map[string]string) + value, err := um.unmarshalRow(row, unmatched) + return value, unmatched, err +} + +// validate ensures that a struct was used to create the Unmarshaller, and validates +// CSV headers against the CSV tags in the struct. +func validate(um *Unmarshaller, s interface{}, headers []string) error { + concreteType := reflect.TypeOf(s) + if concreteType.Kind() == reflect.Ptr { + concreteType = concreteType.Elem() + } + if err := ensureOutInnerType(concreteType); err != nil { + return err + } + structInfo := getStructInfo(concreteType) // Get struct info to get CSV annotations. + if len(structInfo.Fields) == 0 { + return errors.New("no csv struct tags found") + } + csvHeaders := make(map[int]string) // Map of columm index to header name + csvHeadersLabels := make(map[int]*fieldInfo, len(structInfo.Fields)) // Used to store the corresponding header <-> position in CSV + headerCount := map[string]int{} + for i, csvColumnHeader := range headers { + csvHeaders[i] = csvColumnHeader + curHeaderCount := headerCount[csvColumnHeader] + if fieldInfo := getCSVFieldPosition(csvColumnHeader, structInfo, curHeaderCount); fieldInfo != nil { + csvHeadersLabels[i] = fieldInfo + if ShouldAlignDuplicateHeadersWithStructFieldOrder { + curHeaderCount++ + headerCount[csvColumnHeader] = curHeaderCount + } + } + } + if err := maybeDoubleHeaderNames(headers); err != nil { + return err + } + + um.headerMap = csvHeaders + um.fieldInfoMap = csvHeadersLabels + um.MismatchedHeaders = mismatchHeaderFields(structInfo.Fields, headers) + um.MismatchedStructFields = mismatchStructFields(structInfo.Fields, headers) + return nil +} + +// unmarshalRow converts a CSV row to a struct, based on CSV struct tags. +// If unmatched is non nil, it is populated with any columns that don't map to a struct field +func (um *Unmarshaller) unmarshalRow(row []string, unmatched map[string]string) (interface{}, error) { + isPointer := false + concreteOutType := um.outType + if um.outType.Kind() == reflect.Ptr { + isPointer = true + concreteOutType = concreteOutType.Elem() + } + outValue := createNewOutInner(isPointer, concreteOutType) + for j, csvColumnContent := range row { + if fieldInfo, ok := um.fieldInfoMap[j]; ok { + if err := setInnerField(&outValue, isPointer, fieldInfo.IndexChain, csvColumnContent, fieldInfo.omitEmpty); err != nil { // Set field of struct + return nil, fmt.Errorf("cannot assign field at %v to %s through index chain %v: %v", j, outValue.Type(), fieldInfo.IndexChain, err) + } + } else if unmatched != nil { + unmatched[um.headerMap[j]] = csvColumnContent + } + } + return outValue.Interface(), nil +} diff --git a/vendor/github.com/openshift/api/authorization/install.go b/vendor/github.com/openshift/api/authorization/install.go index 2cb6e4369a49..08ecc95f49d7 100644 --- a/vendor/github.com/openshift/api/authorization/install.go +++ b/vendor/github.com/openshift/api/authorization/install.go @@ -1,4 +1,4 @@ -package apps +package authorization import ( "k8s.io/apimachinery/pkg/runtime" diff --git a/vendor/github.com/openshift/api/image/v1/generated.pb.go b/vendor/github.com/openshift/api/image/v1/generated.pb.go index cf5b1a799525..cec6c04de6fd 100644 --- a/vendor/github.com/openshift/api/image/v1/generated.pb.go +++ b/vendor/github.com/openshift/api/image/v1/generated.pb.go @@ -11,9 +11,11 @@ It has these top-level messages: DockerImageReference Image + ImageBlobReferences ImageImportSpec ImageImportStatus ImageLayer + ImageLayerData ImageList ImageLookupPolicy ImageSignature @@ -22,6 +24,7 @@ ImageStreamImport ImageStreamImportSpec ImageStreamImportStatus + ImageStreamLayers ImageStreamList ImageStreamMapping ImageStreamSpec @@ -76,130 +79,144 @@ func (m *Image) Reset() { *m = Image{} } func (*Image) ProtoMessage() {} func (*Image) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{1} } +func (m *ImageBlobReferences) Reset() { *m = ImageBlobReferences{} } +func (*ImageBlobReferences) ProtoMessage() {} +func (*ImageBlobReferences) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{2} } + func (m *ImageImportSpec) Reset() { *m = ImageImportSpec{} } func (*ImageImportSpec) ProtoMessage() {} -func (*ImageImportSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{2} } +func (*ImageImportSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{3} } func (m *ImageImportStatus) Reset() { *m = ImageImportStatus{} } func (*ImageImportStatus) ProtoMessage() {} -func (*ImageImportStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{3} } +func (*ImageImportStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{4} } func (m *ImageLayer) Reset() { *m = ImageLayer{} } func (*ImageLayer) ProtoMessage() {} -func (*ImageLayer) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{4} } +func (*ImageLayer) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{5} } + +func (m *ImageLayerData) Reset() { *m = ImageLayerData{} } +func (*ImageLayerData) ProtoMessage() {} +func (*ImageLayerData) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{6} } func (m *ImageList) Reset() { *m = ImageList{} } func (*ImageList) ProtoMessage() {} -func (*ImageList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{5} } +func (*ImageList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{7} } func (m *ImageLookupPolicy) Reset() { *m = ImageLookupPolicy{} } func (*ImageLookupPolicy) ProtoMessage() {} -func (*ImageLookupPolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{6} } +func (*ImageLookupPolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{8} } func (m *ImageSignature) Reset() { *m = ImageSignature{} } func (*ImageSignature) ProtoMessage() {} -func (*ImageSignature) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{7} } +func (*ImageSignature) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{9} } func (m *ImageStream) Reset() { *m = ImageStream{} } func (*ImageStream) ProtoMessage() {} -func (*ImageStream) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{8} } +func (*ImageStream) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{10} } func (m *ImageStreamImage) Reset() { *m = ImageStreamImage{} } func (*ImageStreamImage) ProtoMessage() {} -func (*ImageStreamImage) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{9} } +func (*ImageStreamImage) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{11} } func (m *ImageStreamImport) Reset() { *m = ImageStreamImport{} } func (*ImageStreamImport) ProtoMessage() {} -func (*ImageStreamImport) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{10} } +func (*ImageStreamImport) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} } func (m *ImageStreamImportSpec) Reset() { *m = ImageStreamImportSpec{} } func (*ImageStreamImportSpec) ProtoMessage() {} -func (*ImageStreamImportSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{11} } +func (*ImageStreamImportSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } func (m *ImageStreamImportStatus) Reset() { *m = ImageStreamImportStatus{} } func (*ImageStreamImportStatus) ProtoMessage() {} func (*ImageStreamImportStatus) Descriptor() ([]byte, []int) { - return fileDescriptorGenerated, []int{12} + return fileDescriptorGenerated, []int{14} } +func (m *ImageStreamLayers) Reset() { *m = ImageStreamLayers{} } +func (*ImageStreamLayers) ProtoMessage() {} +func (*ImageStreamLayers) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } + func (m *ImageStreamList) Reset() { *m = ImageStreamList{} } func (*ImageStreamList) ProtoMessage() {} -func (*ImageStreamList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } +func (*ImageStreamList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } func (m *ImageStreamMapping) Reset() { *m = ImageStreamMapping{} } func (*ImageStreamMapping) ProtoMessage() {} -func (*ImageStreamMapping) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } +func (*ImageStreamMapping) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{17} } func (m *ImageStreamSpec) Reset() { *m = ImageStreamSpec{} } func (*ImageStreamSpec) ProtoMessage() {} -func (*ImageStreamSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } +func (*ImageStreamSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{18} } func (m *ImageStreamStatus) Reset() { *m = ImageStreamStatus{} } func (*ImageStreamStatus) ProtoMessage() {} -func (*ImageStreamStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} } +func (*ImageStreamStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{19} } func (m *ImageStreamTag) Reset() { *m = ImageStreamTag{} } func (*ImageStreamTag) ProtoMessage() {} -func (*ImageStreamTag) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{17} } +func (*ImageStreamTag) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{20} } func (m *ImageStreamTagList) Reset() { *m = ImageStreamTagList{} } func (*ImageStreamTagList) ProtoMessage() {} -func (*ImageStreamTagList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{18} } +func (*ImageStreamTagList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{21} } func (m *NamedTagEventList) Reset() { *m = NamedTagEventList{} } func (*NamedTagEventList) ProtoMessage() {} -func (*NamedTagEventList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{19} } +func (*NamedTagEventList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{22} } func (m *RepositoryImportSpec) Reset() { *m = RepositoryImportSpec{} } func (*RepositoryImportSpec) ProtoMessage() {} -func (*RepositoryImportSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{20} } +func (*RepositoryImportSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{23} } func (m *RepositoryImportStatus) Reset() { *m = RepositoryImportStatus{} } func (*RepositoryImportStatus) ProtoMessage() {} -func (*RepositoryImportStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{21} } +func (*RepositoryImportStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} } func (m *SignatureCondition) Reset() { *m = SignatureCondition{} } func (*SignatureCondition) ProtoMessage() {} -func (*SignatureCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{22} } +func (*SignatureCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} } func (m *SignatureGenericEntity) Reset() { *m = SignatureGenericEntity{} } func (*SignatureGenericEntity) ProtoMessage() {} -func (*SignatureGenericEntity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{23} } +func (*SignatureGenericEntity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} } func (m *SignatureIssuer) Reset() { *m = SignatureIssuer{} } func (*SignatureIssuer) ProtoMessage() {} -func (*SignatureIssuer) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} } +func (*SignatureIssuer) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{27} } func (m *SignatureSubject) Reset() { *m = SignatureSubject{} } func (*SignatureSubject) ProtoMessage() {} -func (*SignatureSubject) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} } +func (*SignatureSubject) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{28} } func (m *TagEvent) Reset() { *m = TagEvent{} } func (*TagEvent) ProtoMessage() {} -func (*TagEvent) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} } +func (*TagEvent) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{29} } func (m *TagEventCondition) Reset() { *m = TagEventCondition{} } func (*TagEventCondition) ProtoMessage() {} -func (*TagEventCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{27} } +func (*TagEventCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{30} } func (m *TagImportPolicy) Reset() { *m = TagImportPolicy{} } func (*TagImportPolicy) ProtoMessage() {} -func (*TagImportPolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{28} } +func (*TagImportPolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{31} } func (m *TagReference) Reset() { *m = TagReference{} } func (*TagReference) ProtoMessage() {} -func (*TagReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{29} } +func (*TagReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{32} } func (m *TagReferencePolicy) Reset() { *m = TagReferencePolicy{} } func (*TagReferencePolicy) ProtoMessage() {} -func (*TagReferencePolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{30} } +func (*TagReferencePolicy) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{33} } func init() { proto.RegisterType((*DockerImageReference)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.DockerImageReference") proto.RegisterType((*Image)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.Image") + proto.RegisterType((*ImageBlobReferences)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageBlobReferences") proto.RegisterType((*ImageImportSpec)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageImportSpec") proto.RegisterType((*ImageImportStatus)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageImportStatus") proto.RegisterType((*ImageLayer)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageLayer") + proto.RegisterType((*ImageLayerData)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageLayerData") proto.RegisterType((*ImageList)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageList") proto.RegisterType((*ImageLookupPolicy)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageLookupPolicy") proto.RegisterType((*ImageSignature)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageSignature") @@ -208,6 +225,7 @@ func init() { proto.RegisterType((*ImageStreamImport)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageStreamImport") proto.RegisterType((*ImageStreamImportSpec)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageStreamImportSpec") proto.RegisterType((*ImageStreamImportStatus)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageStreamImportStatus") + proto.RegisterType((*ImageStreamLayers)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageStreamLayers") proto.RegisterType((*ImageStreamList)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageStreamList") proto.RegisterType((*ImageStreamMapping)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageStreamMapping") proto.RegisterType((*ImageStreamSpec)(nil), "ytb.ewangdian.workers.dev.openshift.api.image.v1.ImageStreamSpec") @@ -351,6 +369,45 @@ func (m *Image) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ImageBlobReferences) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ImageBlobReferences) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Layers) > 0 { + for _, s := range m.Layers { + dAtA[i] = 0xa + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } + if m.Manifest != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(*m.Manifest))) + i += copy(dAtA[i:], *m.Manifest) + } + return i, nil +} + func (m *ImageImportSpec) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -480,6 +537,33 @@ func (m *ImageLayer) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ImageLayerData) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ImageLayerData) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.LayerSize != nil { + dAtA[i] = 0x8 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(*m.LayerSize)) + } + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(m.MediaType))) + i += copy(dAtA[i:], m.MediaType) + return i, nil +} + func (m *ImageList) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -864,6 +948,94 @@ func (m *ImageStreamImportStatus) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ImageStreamLayers) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ImageStreamLayers) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) + n25, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n25 + if len(m.Blobs) > 0 { + keysForBlobs := make([]string, 0, len(m.Blobs)) + for k := range m.Blobs { + keysForBlobs = append(keysForBlobs, string(k)) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForBlobs) + for _, k := range keysForBlobs { + dAtA[i] = 0x12 + i++ + v := m.Blobs[string(k)] + msgSize := 0 + if (&v) != nil { + msgSize = (&v).Size() + msgSize += 1 + sovGenerated(uint64(msgSize)) + } + mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + msgSize + i = encodeVarintGenerated(dAtA, i, uint64(mapSize)) + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(k))) + i += copy(dAtA[i:], k) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) + n26, err := (&v).MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n26 + } + } + if len(m.Images) > 0 { + keysForImages := make([]string, 0, len(m.Images)) + for k := range m.Images { + keysForImages = append(keysForImages, string(k)) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForImages) + for _, k := range keysForImages { + dAtA[i] = 0x1a + i++ + v := m.Images[string(k)] + msgSize := 0 + if (&v) != nil { + msgSize = (&v).Size() + msgSize += 1 + sovGenerated(uint64(msgSize)) + } + mapSize := 1 + len(k) + sovGenerated(uint64(len(k))) + msgSize + i = encodeVarintGenerated(dAtA, i, uint64(mapSize)) + dAtA[i] = 0xa + i++ + i = encodeVarintGenerated(dAtA, i, uint64(len(k))) + i += copy(dAtA[i:], k) + dAtA[i] = 0x12 + i++ + i = encodeVarintGenerated(dAtA, i, uint64((&v).Size())) + n27, err := (&v).MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n27 + } + } + return i, nil +} + func (m *ImageStreamList) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -882,11 +1054,11 @@ func (m *ImageStreamList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n25, err := m.ListMeta.MarshalTo(dAtA[i:]) + n28, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n25 + i += n28 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -920,19 +1092,19 @@ func (m *ImageStreamMapping) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n26, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n29, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n26 + i += n29 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Image.Size())) - n27, err := m.Image.MarshalTo(dAtA[i:]) + n30, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n27 + i += n30 dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Tag))) @@ -974,11 +1146,11 @@ func (m *ImageStreamSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LookupPolicy.Size())) - n28, err := m.LookupPolicy.MarshalTo(dAtA[i:]) + n31, err := m.LookupPolicy.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n28 + i += n31 return i, nil } @@ -1038,20 +1210,20 @@ func (m *ImageStreamTag) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size())) - n29, err := m.ObjectMeta.MarshalTo(dAtA[i:]) + n32, err := m.ObjectMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n29 + i += n32 if m.Tag != nil { dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Tag.Size())) - n30, err := m.Tag.MarshalTo(dAtA[i:]) + n33, err := m.Tag.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n30 + i += n33 } dAtA[i] = 0x18 i++ @@ -1071,19 +1243,19 @@ func (m *ImageStreamTag) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Image.Size())) - n31, err := m.Image.MarshalTo(dAtA[i:]) + n34, err := m.Image.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n31 + i += n34 dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LookupPolicy.Size())) - n32, err := m.LookupPolicy.MarshalTo(dAtA[i:]) + n35, err := m.LookupPolicy.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n32 + i += n35 return i, nil } @@ -1105,11 +1277,11 @@ func (m *ImageStreamTagList) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size())) - n33, err := m.ListMeta.MarshalTo(dAtA[i:]) + n36, err := m.ListMeta.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n33 + i += n36 if len(m.Items) > 0 { for _, msg := range m.Items { dAtA[i] = 0x12 @@ -1189,19 +1361,19 @@ func (m *RepositoryImportSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.From.Size())) - n34, err := m.From.MarshalTo(dAtA[i:]) + n37, err := m.From.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n34 + i += n37 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ImportPolicy.Size())) - n35, err := m.ImportPolicy.MarshalTo(dAtA[i:]) + n38, err := m.ImportPolicy.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n35 + i += n38 dAtA[i] = 0x18 i++ if m.IncludeManifest { @@ -1213,11 +1385,11 @@ func (m *RepositoryImportSpec) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ReferencePolicy.Size())) - n36, err := m.ReferencePolicy.MarshalTo(dAtA[i:]) + n39, err := m.ReferencePolicy.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n36 + i += n39 return i, nil } @@ -1239,11 +1411,11 @@ func (m *RepositoryImportStatus) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size())) - n37, err := m.Status.MarshalTo(dAtA[i:]) + n40, err := m.Status.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n37 + i += n40 if len(m.Images) > 0 { for _, msg := range m.Images { dAtA[i] = 0x12 @@ -1300,19 +1472,19 @@ func (m *SignatureCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastProbeTime.Size())) - n38, err := m.LastProbeTime.MarshalTo(dAtA[i:]) + n41, err := m.LastProbeTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n38 + i += n41 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n39, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n42, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n39 + i += n42 dAtA[i] = 0x2a i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -1368,11 +1540,11 @@ func (m *SignatureIssuer) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SignatureGenericEntity.Size())) - n40, err := m.SignatureGenericEntity.MarshalTo(dAtA[i:]) + n43, err := m.SignatureGenericEntity.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n40 + i += n43 return i, nil } @@ -1394,11 +1566,11 @@ func (m *SignatureSubject) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.SignatureGenericEntity.Size())) - n41, err := m.SignatureGenericEntity.MarshalTo(dAtA[i:]) + n44, err := m.SignatureGenericEntity.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n41 + i += n44 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.PublicKeyID))) @@ -1424,11 +1596,11 @@ func (m *TagEvent) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0xa i++ i = encodeVarintGenerated(dAtA, i, uint64(m.Created.Size())) - n42, err := m.Created.MarshalTo(dAtA[i:]) + n45, err := m.Created.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n42 + i += n45 dAtA[i] = 0x12 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.DockerImageReference))) @@ -1469,11 +1641,11 @@ func (m *TagEventCondition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size())) - n43, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) + n46, err := m.LastTransitionTime.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n43 + i += n46 dAtA[i] = 0x22 i++ i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason))) @@ -1567,11 +1739,11 @@ func (m *TagReference) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.From.Size())) - n44, err := m.From.MarshalTo(dAtA[i:]) + n47, err := m.From.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n44 + i += n47 } dAtA[i] = 0x20 i++ @@ -1589,19 +1761,19 @@ func (m *TagReference) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x32 i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ImportPolicy.Size())) - n45, err := m.ImportPolicy.MarshalTo(dAtA[i:]) + n48, err := m.ImportPolicy.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n45 + i += n48 dAtA[i] = 0x3a i++ i = encodeVarintGenerated(dAtA, i, uint64(m.ReferencePolicy.Size())) - n46, err := m.ReferencePolicy.MarshalTo(dAtA[i:]) + n49, err := m.ReferencePolicy.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n46 + i += n49 return i, nil } @@ -1708,6 +1880,22 @@ func (m *Image) Size() (n int) { return n } +func (m *ImageBlobReferences) Size() (n int) { + var l int + _ = l + if len(m.Layers) > 0 { + for _, s := range m.Layers { + l = len(s) + n += 1 + l + sovGenerated(uint64(l)) + } + } + if m.Manifest != nil { + l = len(*m.Manifest) + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + func (m *ImageImportSpec) Size() (n int) { var l int _ = l @@ -1750,6 +1938,17 @@ func (m *ImageLayer) Size() (n int) { return n } +func (m *ImageLayerData) Size() (n int) { + var l int + _ = l + if m.LayerSize != nil { + n += 1 + sovGenerated(uint64(*m.LayerSize)) + } + l = len(m.MediaType) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + func (m *ImageList) Size() (n int) { var l int _ = l @@ -1884,6 +2083,32 @@ func (m *ImageStreamImportStatus) Size() (n int) { return n } +func (m *ImageStreamLayers) Size() (n int) { + var l int + _ = l + l = m.ObjectMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Blobs) > 0 { + for k, v := range m.Blobs { + _ = k + _ = v + l = v.Size() + mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + l + sovGenerated(uint64(l)) + n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) + } + } + if len(m.Images) > 0 { + for k, v := range m.Images { + _ = k + _ = v + l = v.Size() + mapEntrySize := 1 + len(k) + sovGenerated(uint64(len(k))) + 1 + l + sovGenerated(uint64(l)) + n += mapEntrySize + 1 + sovGenerated(uint64(mapEntrySize)) + } + } + return n +} + func (m *ImageStreamList) Size() (n int) { var l int _ = l @@ -2198,6 +2423,17 @@ func (this *Image) String() string { }, "") return s } +func (this *ImageBlobReferences) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ImageBlobReferences{`, + `Layers:` + fmt.Sprintf("%v", this.Layers) + `,`, + `Manifest:` + valueToStringGenerated(this.Manifest) + `,`, + `}`, + }, "") + return s +} func (this *ImageImportSpec) String() string { if this == nil { return "nil" @@ -2236,6 +2472,17 @@ func (this *ImageLayer) String() string { }, "") return s } +func (this *ImageLayerData) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ImageLayerData{`, + `LayerSize:` + valueToStringGenerated(this.LayerSize) + `,`, + `MediaType:` + fmt.Sprintf("%v", this.MediaType) + `,`, + `}`, + }, "") + return s +} func (this *ImageList) String() string { if this == nil { return "nil" @@ -2344,6 +2591,38 @@ func (this *ImageStreamImportStatus) String() string { }, "") return s } +func (this *ImageStreamLayers) String() string { + if this == nil { + return "nil" + } + keysForBlobs := make([]string, 0, len(this.Blobs)) + for k := range this.Blobs { + keysForBlobs = append(keysForBlobs, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForBlobs) + mapStringForBlobs := "map[string]ImageLayerData{" + for _, k := range keysForBlobs { + mapStringForBlobs += fmt.Sprintf("%v: %v,", k, this.Blobs[k]) + } + mapStringForBlobs += "}" + keysForImages := make([]string, 0, len(this.Images)) + for k := range this.Images { + keysForImages = append(keysForImages, k) + } + github_com_gogo_protobuf_sortkeys.Strings(keysForImages) + mapStringForImages := "map[string]ImageBlobReferences{" + for _, k := range keysForImages { + mapStringForImages += fmt.Sprintf("%v: %v,", k, this.Images[k]) + } + mapStringForImages += "}" + s := strings.Join([]string{`&ImageStreamLayers{`, + `ObjectMeta:` + strings.Replace(strings.Replace(this.ObjectMeta.String(), "ObjectMeta", "k8s_io_apimachinery_pkg_apis_meta_v1.ObjectMeta", 1), `&`, ``, 1) + `,`, + `Blobs:` + mapStringForBlobs + `,`, + `Images:` + mapStringForImages + `,`, + `}`, + }, "") + return s +} func (this *ImageStreamList) String() string { if this == nil { return "nil" @@ -3125,7 +3404,7 @@ func (m *Image) Unmarshal(dAtA []byte) error { } return nil } -func (m *ImageImportSpec) Unmarshal(dAtA []byte) error { +func (m *ImageBlobReferences) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -3148,17 +3427,17 @@ func (m *ImageImportSpec) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: ImageImportSpec: wiretype end group for non-group") + return fmt.Errorf("proto: ImageBlobReferences: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: ImageImportSpec: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ImageBlobReferences: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field From", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Layers", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -3168,27 +3447,26 @@ func (m *ImageImportSpec) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.From.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } + m.Layers = append(m.Layers, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field To", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Manifest", wireType) } - var msglen int + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -3198,32 +3476,142 @@ func (m *ImageImportSpec) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= (int(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + intStringLen := int(stringLen) + if intStringLen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + msglen + postIndex := iNdEx + intStringLen if postIndex > l { return io.ErrUnexpectedEOF } - if m.To == nil { - m.To = &k8s_io_api_core_v1.LocalObjectReference{} - } - if err := m.To.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + s := string(dAtA[iNdEx:postIndex]) + m.Manifest = &s + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { return err } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ImportPolicy", wireType) + if skippy < 0 { + return ErrInvalidLengthGenerated } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ImageImportSpec) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ImageImportSpec: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ImageImportSpec: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field From", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.From.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field To", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.To == nil { + m.To = &k8s_io_api_core_v1.LocalObjectReference{} + } + if err := m.To.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ImportPolicy", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { return ErrIntOverflowGenerated } if iNdEx >= l { @@ -3587,6 +3975,105 @@ func (m *ImageLayer) Unmarshal(dAtA []byte) error { } return nil } +func (m *ImageLayerData) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ImageLayerData: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ImageLayerData: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LayerSize", wireType) + } + var v int64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.LayerSize = &v + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MediaType", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MediaType = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *ImageList) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -4854,6 +5341,328 @@ func (m *ImageStreamImportStatus) Unmarshal(dAtA []byte) error { } return nil } +func (m *ImageStreamLayers) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ImageStreamLayers: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ImageStreamLayers: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Blobs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + var keykey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + keykey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthGenerated + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + if m.Blobs == nil { + m.Blobs = make(map[string]ImageLayerData) + } + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return ErrInvalidLengthGenerated + } + postmsgIndex := iNdEx + mapmsglen + if mapmsglen < 0 { + return ErrInvalidLengthGenerated + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue := &ImageLayerData{} + if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + m.Blobs[mapkey] = *mapvalue + } else { + var mapvalue ImageLayerData + m.Blobs[mapkey] = mapvalue + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Images", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + var keykey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + keykey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthGenerated + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + if m.Images == nil { + m.Images = make(map[string]ImageBlobReferences) + } + if iNdEx < postIndex { + var valuekey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + valuekey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var mapmsglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapmsglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if mapmsglen < 0 { + return ErrInvalidLengthGenerated + } + postmsgIndex := iNdEx + mapmsglen + if mapmsglen < 0 { + return ErrInvalidLengthGenerated + } + if postmsgIndex > l { + return io.ErrUnexpectedEOF + } + mapvalue := &ImageBlobReferences{} + if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil { + return err + } + iNdEx = postmsgIndex + m.Images[mapkey] = *mapvalue + } else { + var mapvalue ImageBlobReferences + m.Images[mapkey] = mapvalue + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *ImageStreamList) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -7660,148 +8469,158 @@ func init() { } var fileDescriptorGenerated = []byte{ - // 2284 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x59, 0x4d, 0x8c, 0x1b, 0x49, - 0x15, 0x4e, 0xbb, 0xed, 0xb1, 0xe7, 0x8d, 0x33, 0x93, 0xa9, 0x64, 0xb2, 0xde, 0x49, 0xd6, 0x13, - 0x3a, 0x64, 0x15, 0x20, 0xdb, 0x66, 0x66, 0xb3, 0x90, 0x04, 0x09, 0x36, 0x8e, 0xc3, 0xca, 0x30, - 0x43, 0x66, 0x6b, 0x4c, 0x0e, 0x51, 0x90, 0xa8, 0x69, 0xd7, 0xf4, 0x14, 0x63, 0x77, 0x5b, 0xdd, - 0xed, 0xd9, 0x9d, 0x08, 0x24, 0x0e, 0x68, 0xb5, 0x07, 0x0e, 0x70, 0xde, 0x23, 0x42, 0x88, 0x33, - 0x02, 0x71, 0x07, 0xa4, 0x88, 0x0b, 0xab, 0xe5, 0xb2, 0x17, 0x46, 0xc4, 0x70, 0xe6, 0xc6, 0x65, - 0x4f, 0xa8, 0xaa, 0xab, 0x7f, 0xdd, 0x9e, 0xb4, 0x43, 0xc6, 0x82, 0x9b, 0x5d, 0xef, 0xbd, 0xaf, - 0x5e, 0xbd, 0x57, 0xef, 0xa7, 0x5e, 0xc3, 0xba, 0xc9, 0xbc, 0xfd, 0xe1, 0xae, 0x6e, 0xd8, 0xfd, - 0x86, 0x3d, 0xa0, 0x96, 0xbb, 0xcf, 0xf6, 0xbc, 0x06, 0x19, 0xb0, 0x06, 0xeb, 0x13, 0x93, 0x36, - 0x0e, 0xd7, 0x1b, 0x26, 0xb5, 0xa8, 0x43, 0x3c, 0xda, 0xd5, 0x07, 0x8e, 0xed, 0xd9, 0xe8, 0x73, - 0x91, 0x88, 0x1e, 0x8a, 0xe8, 0x64, 0xc0, 0x74, 0x21, 0xa2, 0x1f, 0xae, 0xaf, 0xbe, 0x11, 0x43, - 0x35, 0x6d, 0xd3, 0x6e, 0x08, 0xc9, 0xdd, 0xe1, 0x9e, 0xf8, 0x27, 0xfe, 0x88, 0x5f, 0x3e, 0xe2, - 0xaa, 0x76, 0x70, 0xcb, 0xd5, 0x99, 0x2d, 0xb6, 0x35, 0x6c, 0x27, 0x6b, 0xd7, 0xd5, 0x9b, 0x11, - 0x4f, 0x9f, 0x18, 0xfb, 0xcc, 0xa2, 0xce, 0x51, 0x63, 0x70, 0x60, 0xf2, 0x05, 0xb7, 0xd1, 0xa7, - 0x1e, 0xc9, 0x92, 0x6a, 0x4c, 0x92, 0x72, 0x86, 0x96, 0xc7, 0xfa, 0x74, 0x4c, 0xe0, 0x2b, 0xcf, - 0x13, 0x70, 0x8d, 0x7d, 0xda, 0x27, 0x63, 0x72, 0x6f, 0x4e, 0x92, 0x1b, 0x7a, 0xac, 0xd7, 0x60, - 0x96, 0xe7, 0x7a, 0x4e, 0x5a, 0x48, 0xfb, 0x44, 0x81, 0x0b, 0x2d, 0xdb, 0x38, 0xa0, 0x4e, 0x9b, - 0x5b, 0x0e, 0xd3, 0x3d, 0xea, 0x50, 0xcb, 0xa0, 0xe8, 0x06, 0x54, 0x1c, 0x6a, 0x32, 0xd7, 0x73, - 0x8e, 0x6a, 0xca, 0x15, 0xe5, 0xfa, 0x7c, 0xf3, 0xdc, 0xd3, 0xe3, 0xb5, 0x33, 0xa3, 0xe3, 0xb5, - 0x0a, 0x96, 0xeb, 0x38, 0xe4, 0x40, 0x0d, 0x98, 0xb7, 0x48, 0x9f, 0xba, 0x03, 0x62, 0xd0, 0x5a, - 0x41, 0xb0, 0x2f, 0x4b, 0xf6, 0xf9, 0xef, 0x04, 0x04, 0x1c, 0xf1, 0xa0, 0x2b, 0x50, 0xe4, 0x7f, - 0x6a, 0xaa, 0xe0, 0xad, 0x4a, 0xde, 0x22, 0xe7, 0xc5, 0x82, 0x82, 0x5e, 0x03, 0xd5, 0x23, 0x66, - 0xad, 0x28, 0x18, 0x16, 0x24, 0x83, 0xda, 0x21, 0x26, 0xe6, 0xeb, 0x68, 0x15, 0x0a, 0xac, 0x55, - 0x2b, 0x09, 0x2a, 0x48, 0x6a, 0xa1, 0xdd, 0xc2, 0x05, 0xd6, 0xd2, 0xfe, 0x52, 0x86, 0x92, 0x38, - 0x0e, 0xfa, 0x3e, 0x54, 0xb8, 0x5f, 0xba, 0xc4, 0x23, 0xe2, 0x14, 0x0b, 0x1b, 0x5f, 0xd6, 0x7d, - 0x33, 0xe9, 0x71, 0x33, 0xe9, 0x83, 0x03, 0x93, 0x2f, 0xb8, 0x3a, 0xe7, 0xd6, 0x0f, 0xd7, 0xf5, - 0x07, 0xbb, 0x3f, 0xa0, 0x86, 0xb7, 0x45, 0x3d, 0xd2, 0x44, 0x12, 0x1d, 0xa2, 0x35, 0x1c, 0xa2, - 0xa2, 0x6d, 0xb8, 0xd0, 0xcd, 0xb0, 0x9f, 0x34, 0xc2, 0x65, 0x29, 0x9b, 0x69, 0x63, 0x9c, 0x29, - 0x89, 0x7e, 0x08, 0xe7, 0x63, 0xeb, 0x5b, 0x81, 0xfa, 0xaa, 0x50, 0xff, 0x8d, 0x89, 0xea, 0xcb, - 0xdb, 0xa1, 0x63, 0xf2, 0xde, 0xfd, 0xf7, 0x3d, 0x6a, 0xb9, 0xcc, 0xb6, 0x9a, 0x97, 0xe4, 0xfe, - 0xe7, 0x5b, 0xe3, 0x88, 0x38, 0x6b, 0x1b, 0xb4, 0x0b, 0xab, 0x19, 0xcb, 0x0f, 0xa9, 0xc3, 0xf1, - 0xa4, 0x37, 0x34, 0x89, 0xba, 0xda, 0x9a, 0xc8, 0x89, 0x4f, 0x40, 0x41, 0x5b, 0xc9, 0x13, 0x12, - 0x8b, 0xed, 0x51, 0xd7, 0x93, 0xce, 0xcc, 0x54, 0x59, 0xb2, 0xe0, 0x2c, 0x39, 0x74, 0x08, 0xcb, - 0xb1, 0xe5, 0x4d, 0x72, 0x44, 0x1d, 0xb7, 0x36, 0x77, 0x45, 0x15, 0xe6, 0x7a, 0x6e, 0xa6, 0xd0, - 0x23, 0xa9, 0xe6, 0xab, 0x72, 0xef, 0xe5, 0x56, 0x1a, 0x0f, 0x8f, 0x6f, 0x81, 0x28, 0x80, 0xcb, - 0x4c, 0x8b, 0x78, 0x43, 0x87, 0xba, 0xb5, 0xb2, 0xd8, 0x70, 0x3d, 0xef, 0x86, 0x3b, 0x81, 0x64, - 0x74, 0xbf, 0xc2, 0x25, 0x17, 0xc7, 0x80, 0xd1, 0x03, 0x58, 0x89, 0xed, 0x1d, 0x31, 0xd5, 0x2a, - 0x57, 0xd4, 0xeb, 0xd5, 0xe6, 0xab, 0xa3, 0xe3, 0xb5, 0x95, 0x56, 0x16, 0x03, 0xce, 0x96, 0x43, - 0xfb, 0x70, 0x39, 0xc3, 0x8c, 0x5b, 0xb4, 0xcb, 0x48, 0xe7, 0x68, 0x40, 0x6b, 0xf3, 0xc2, 0x0f, - 0x9f, 0x97, 0x6a, 0x5d, 0x6e, 0x9d, 0xc0, 0x8b, 0x4f, 0x44, 0x42, 0xef, 0x24, 0x3c, 0x73, 0xcf, - 0xb6, 0xf6, 0x98, 0x59, 0x03, 0x01, 0x9f, 0x65, 0x6a, 0x9f, 0x01, 0x8f, 0xcb, 0x68, 0x7f, 0x52, - 0x61, 0x49, 0xfc, 0x6f, 0xf7, 0x07, 0xb6, 0xe3, 0xed, 0x0c, 0xa8, 0x81, 0xee, 0x43, 0x71, 0xcf, - 0xb1, 0xfb, 0x32, 0xae, 0xaf, 0xc6, 0x02, 0x43, 0xe7, 0x19, 0x3c, 0x8a, 0xe2, 0x30, 0xb4, 0xa2, - 0x3c, 0xf3, 0x4d, 0xc7, 0xee, 0x63, 0x21, 0x8e, 0xde, 0x86, 0x82, 0x67, 0x8b, 0x70, 0x5d, 0xd8, - 0xb8, 0x9e, 0x05, 0xb2, 0x69, 0x1b, 0xa4, 0x97, 0x46, 0x9a, 0xe3, 0xe9, 0xa6, 0x63, 0xe3, 0x82, - 0x67, 0xa3, 0x1e, 0x54, 0x99, 0x50, 0x6b, 0xdb, 0xee, 0x31, 0xe3, 0x48, 0x46, 0xea, 0x46, 0x8e, - 0x9b, 0xd0, 0x21, 0x66, 0x3b, 0x26, 0xd9, 0xbc, 0x20, 0xf5, 0xab, 0xc6, 0x57, 0x71, 0x02, 0x1d, - 0xdd, 0x85, 0x25, 0x66, 0x19, 0xbd, 0x61, 0x37, 0x0a, 0x1c, 0x1e, 0x95, 0x95, 0xe6, 0x2b, 0x52, - 0x78, 0xa9, 0x9d, 0x24, 0xe3, 0x34, 0x3f, 0x7a, 0x1f, 0x96, 0x9c, 0xe0, 0x24, 0x52, 0xe7, 0x92, - 0xd0, 0xf9, 0xad, 0x7c, 0x3a, 0xe3, 0xa4, 0x70, 0xb4, 0x73, 0x8a, 0x80, 0xd3, 0xdb, 0x68, 0x7f, - 0x55, 0x60, 0x39, 0xee, 0x47, 0x8f, 0x78, 0x43, 0x17, 0x75, 0x60, 0xce, 0x15, 0xbf, 0xa4, 0x2f, - 0x6f, 0xe4, 0xcb, 0xd1, 0xbe, 0x74, 0x73, 0x51, 0xee, 0x3e, 0xe7, 0xff, 0xc7, 0x12, 0x0b, 0xb5, - 0xa1, 0x24, 0x94, 0x0e, 0x7d, 0x9b, 0x33, 0x32, 0x9b, 0xf3, 0xa3, 0xe3, 0x35, 0xbf, 0x7e, 0x60, - 0x1f, 0x21, 0xa8, 0x45, 0x6a, 0x76, 0x2d, 0xd2, 0x3e, 0x50, 0x00, 0xa2, 0xc4, 0x10, 0xd6, 0x36, - 0x65, 0x62, 0x6d, 0xbb, 0x06, 0x45, 0x97, 0x3d, 0xf1, 0x35, 0x53, 0xa3, 0x4a, 0x29, 0xc4, 0x77, - 0xd8, 0x13, 0x8a, 0x05, 0x99, 0x57, 0xd5, 0x7e, 0x18, 0x95, 0x6a, 0xb2, 0xaa, 0x46, 0x21, 0x18, - 0xf1, 0x68, 0xbf, 0x57, 0x60, 0xde, 0x57, 0x84, 0xb9, 0x1e, 0x7a, 0x3c, 0x56, 0xfc, 0xf4, 0x7c, - 0x86, 0xe5, 0xd2, 0xa2, 0xf4, 0x85, 0x25, 0x3f, 0x58, 0x89, 0x15, 0xbe, 0x2d, 0x28, 0x31, 0x8f, - 0xf6, 0xdd, 0x5a, 0x41, 0x24, 0xbe, 0xfc, 0xe6, 0x3d, 0x2b, 0x41, 0x4b, 0x6d, 0x2e, 0x8e, 0x7d, - 0x14, 0xed, 0x96, 0xbc, 0x18, 0x9b, 0xb6, 0x7d, 0x30, 0x1c, 0xc8, 0xbb, 0x7e, 0x15, 0x4a, 0x3d, - 0x1e, 0x7d, 0xe2, 0xf0, 0x95, 0x48, 0x52, 0x84, 0x24, 0xf6, 0x69, 0xda, 0x6f, 0xe6, 0x60, 0x31, - 0x99, 0xe2, 0x66, 0x50, 0xf6, 0xaf, 0x40, 0xd1, 0xe3, 0x5e, 0x29, 0x24, 0x7d, 0x2c, 0x1c, 0x22, - 0x28, 0xe8, 0x1a, 0x94, 0x0d, 0xdb, 0xf2, 0xa8, 0xe5, 0x09, 0xed, 0xab, 0xcd, 0x85, 0xd1, 0xf1, - 0x5a, 0xf9, 0x9e, 0xbf, 0x84, 0x03, 0x1a, 0x62, 0x00, 0x86, 0x6d, 0x75, 0x99, 0xc7, 0x6c, 0xcb, - 0xad, 0x15, 0x85, 0x2d, 0xf3, 0x84, 0x61, 0x78, 0xd8, 0x7b, 0x81, 0x74, 0xa4, 0x71, 0xb8, 0xe4, - 0xe2, 0x18, 0x38, 0xfa, 0x1a, 0x9c, 0x15, 0xe2, 0xed, 0x2e, 0xb5, 0x3c, 0xe6, 0x1d, 0xc9, 0x82, - 0xbb, 0x22, 0xc5, 0xce, 0xb6, 0xe3, 0x44, 0x9c, 0xe4, 0x45, 0x3f, 0x82, 0x2a, 0xaf, 0x49, 0xb4, - 0x7b, 0xaf, 0x47, 0x58, 0x3f, 0xa8, 0xaf, 0xf7, 0xa6, 0x2e, 0x77, 0x42, 0xf1, 0x00, 0xe5, 0xbe, - 0xe5, 0x39, 0xb1, 0xac, 0x17, 0x27, 0xe1, 0xc4, 0x76, 0xe8, 0x5d, 0x28, 0x1b, 0x0e, 0xe5, 0x8d, - 0x6b, 0xad, 0x2c, 0x1c, 0xfa, 0xc5, 0x7c, 0x0e, 0xed, 0xb0, 0x3e, 0x95, 0x96, 0xf7, 0xc5, 0x71, - 0x80, 0xc3, 0xc3, 0x83, 0xb9, 0xee, 0x90, 0x76, 0x9b, 0x47, 0xb5, 0x4a, 0xee, 0x94, 0x1d, 0x1e, - 0xa4, 0xcd, 0x65, 0x9d, 0x66, 0x95, 0x87, 0x47, 0x5b, 0xe2, 0xe0, 0x10, 0x11, 0x7d, 0x2f, 0x40, - 0xef, 0xd8, 0xa2, 0xa0, 0x2e, 0x6c, 0xbc, 0x39, 0x0d, 0xfa, 0xce, 0x50, 0xdc, 0xba, 0x38, 0x7c, - 0xc7, 0xc6, 0x21, 0xe4, 0xea, 0x37, 0x60, 0x79, 0xcc, 0x90, 0xe8, 0x1c, 0xa8, 0x07, 0x54, 0xb6, - 0xeb, 0x98, 0xff, 0x44, 0x17, 0xa0, 0x74, 0x48, 0x7a, 0x43, 0x79, 0x4f, 0xb1, 0xff, 0xe7, 0x4e, - 0xe1, 0x96, 0xa2, 0xfd, 0xa2, 0x00, 0x0b, 0xbe, 0x67, 0x3c, 0x87, 0x92, 0xfe, 0x0c, 0x42, 0xa6, - 0x03, 0x45, 0x77, 0x40, 0x0d, 0x99, 0x8e, 0x37, 0x72, 0xdf, 0x1c, 0xa1, 0x1f, 0xaf, 0xf8, 0x51, - 0x98, 0xf1, 0x7f, 0x58, 0xa0, 0xa1, 0xc7, 0x61, 0xed, 0xf0, 0xcb, 0xee, 0xcd, 0x29, 0x71, 0x4f, - 0xac, 0x21, 0xda, 0x1f, 0x14, 0x38, 0x17, 0xe3, 0x9e, 0xd5, 0xa3, 0x62, 0xeb, 0x45, 0x4b, 0x57, - 0x94, 0x5b, 0x63, 0xe5, 0x4b, 0xfb, 0x6d, 0x41, 0x26, 0xd7, 0xe0, 0x14, 0xbc, 0xf6, 0xce, 0xe0, - 0x18, 0x8f, 0x12, 0x1e, 0xbf, 0x35, 0x9d, 0x67, 0xa2, 0x4e, 0x2f, 0xd3, 0xef, 0xbb, 0x29, 0xbf, - 0xdf, 0x79, 0x21, 0xf4, 0x93, 0xbd, 0xff, 0x93, 0x02, 0xac, 0x64, 0x6a, 0x84, 0x5e, 0x87, 0x39, - 0xbf, 0x29, 0x13, 0x96, 0xab, 0x44, 0x08, 0x3e, 0x0f, 0x96, 0x54, 0x64, 0x02, 0x38, 0x74, 0x60, - 0xbb, 0xcc, 0xb3, 0x9d, 0x23, 0x69, 0x87, 0xaf, 0xe6, 0xd0, 0x14, 0x87, 0x42, 0x31, 0x33, 0x2c, - 0x72, 0x43, 0x47, 0x14, 0x1c, 0x83, 0x46, 0x8f, 0xb8, 0x42, 0xc4, 0xa4, 0xdc, 0x1c, 0xea, 0x34, - 0xe1, 0x15, 0xc7, 0x8f, 0x0e, 0xc1, 0x91, 0xb0, 0x44, 0xd4, 0x7e, 0x57, 0x80, 0x57, 0x26, 0x98, - 0x0e, 0xe1, 0x84, 0x21, 0x78, 0x87, 0x31, 0x95, 0x1b, 0x9a, 0x90, 0x61, 0x34, 0x96, 0x61, 0xb4, - 0xdb, 0x2f, 0x62, 0x34, 0xe9, 0xdd, 0x13, 0xcc, 0xf6, 0x38, 0x65, 0xb6, 0x9b, 0x53, 0x9a, 0x2d, - 0x75, 0x7f, 0x52, 0x86, 0xfb, 0xa3, 0x22, 0x5f, 0x2d, 0xfe, 0x61, 0x67, 0xd0, 0x94, 0xed, 0x24, - 0x9b, 0xb2, 0x69, 0xbd, 0x91, 0xdd, 0x9a, 0xfd, 0x53, 0x01, 0x14, 0xe3, 0xda, 0x22, 0x83, 0x01, - 0xb3, 0xcc, 0xff, 0xbb, 0x34, 0xf8, 0xbc, 0x2e, 0xfe, 0xd7, 0x85, 0x84, 0xb7, 0x44, 0x9c, 0xef, - 0x24, 0xde, 0xde, 0xd1, 0x25, 0x92, 0xbd, 0xfd, 0x6b, 0x12, 0x64, 0xa5, 0x95, 0xc5, 0x84, 0xb3, - 0x65, 0xd1, 0xbb, 0x50, 0xf4, 0x88, 0x19, 0xf8, 0xa8, 0x31, 0xe5, 0x9b, 0x2b, 0xd6, 0x6c, 0x12, - 0xd3, 0xc5, 0x02, 0x0a, 0x59, 0x50, 0xed, 0xc5, 0x1a, 0xe7, 0x69, 0x6b, 0x61, 0xbc, 0xe9, 0x8e, - 0xda, 0xb1, 0xf8, 0x2a, 0x4e, 0xe0, 0x6b, 0xbf, 0x4a, 0x56, 0x14, 0x99, 0x0c, 0x4e, 0xc5, 0x5a, - 0x0f, 0x13, 0xd6, 0xca, 0x73, 0x24, 0xfe, 0xd0, 0xea, 0x76, 0x88, 0x79, 0xff, 0x90, 0x5a, 0x1e, - 0x0f, 0x92, 0x4c, 0x93, 0x51, 0xb8, 0x34, 0x18, 0xee, 0xf6, 0x98, 0x91, 0xa9, 0x8d, 0xbc, 0x25, - 0x57, 0xa5, 0xe0, 0xa5, 0xed, 0xc9, 0xac, 0xf8, 0x24, 0x1c, 0xed, 0xa3, 0x62, 0xf0, 0x3a, 0x11, - 0x96, 0xea, 0x90, 0x59, 0x04, 0xce, 0xb7, 0xfc, 0x9b, 0xee, 0x87, 0xcd, 0xd4, 0x17, 0xac, 0x9c, - 0x18, 0xb4, 0x6e, 0x00, 0xc8, 0xa1, 0x31, 0xb3, 0x2d, 0x61, 0x16, 0x35, 0xda, 0xfd, 0x9d, 0x90, - 0x82, 0x63, 0x5c, 0x68, 0x3f, 0xe3, 0x51, 0x73, 0x33, 0x9f, 0x1a, 0xc2, 0x69, 0xf9, 0xdf, 0x34, - 0x61, 0x8a, 0x28, 0xbd, 0x94, 0x14, 0x91, 0x8e, 0xa3, 0xb9, 0x53, 0x8e, 0xa3, 0x3f, 0x27, 0x53, - 0x6b, 0x87, 0x98, 0x33, 0x28, 0x12, 0x0f, 0x93, 0x45, 0x62, 0x7d, 0xba, 0x22, 0xd1, 0x21, 0xe6, - 0x84, 0x3a, 0xf1, 0x2f, 0x05, 0x96, 0xc7, 0x62, 0x2f, 0xc8, 0xba, 0xca, 0x84, 0x39, 0xfe, 0x76, - 0x52, 0x99, 0x2f, 0x4d, 0x71, 0x4b, 0xb2, 0xd5, 0x48, 0x5d, 0x3e, 0xf5, 0xf4, 0x2e, 0x9f, 0xf6, - 0xa1, 0x0a, 0x17, 0xb2, 0x3a, 0xb5, 0x97, 0x35, 0x9a, 0x4c, 0x0f, 0x16, 0x0b, 0xb3, 0x1e, 0x2c, - 0xaa, 0xff, 0xfd, 0x60, 0xb1, 0x38, 0x9b, 0xc1, 0xe2, 0x87, 0x05, 0xb8, 0x98, 0xdd, 0xff, 0x9d, - 0xd2, 0x74, 0x31, 0xea, 0x1c, 0x0b, 0x2f, 0xbf, 0x73, 0x44, 0x77, 0x60, 0x91, 0x74, 0xfd, 0x6b, - 0x46, 0x7a, 0xbc, 0x68, 0x89, 0x7b, 0x3c, 0xdf, 0x44, 0xa3, 0xe3, 0xb5, 0xc5, 0xbb, 0x09, 0x0a, - 0x4e, 0x71, 0x6a, 0x9f, 0xa8, 0x80, 0xc6, 0xa7, 0x43, 0xe8, 0x8e, 0x9c, 0x58, 0xf9, 0x81, 0xf8, - 0x7a, 0x7c, 0x62, 0xf5, 0xd9, 0xf1, 0xda, 0xc5, 0x71, 0x89, 0xd8, 0x2c, 0x6b, 0x33, 0x34, 0xa1, - 0x3f, 0xef, 0xba, 0x99, 0x34, 0xca, 0x67, 0xc7, 0x6b, 0x19, 0xdf, 0x4f, 0xf5, 0x10, 0x29, 0x65, - 0x3a, 0x13, 0xce, 0xf6, 0x88, 0xeb, 0x6d, 0x3b, 0xf6, 0x2e, 0xed, 0x30, 0xf9, 0x11, 0x70, 0xba, - 0x89, 0x4e, 0x38, 0xb3, 0xda, 0x8c, 0x03, 0xe1, 0x24, 0x2e, 0x3a, 0x04, 0xc4, 0x17, 0x3a, 0x0e, - 0xb1, 0x5c, 0xff, 0x48, 0x7c, 0xb7, 0xe2, 0xd4, 0xbb, 0xad, 0xca, 0xdd, 0xd0, 0xe6, 0x18, 0x1a, - 0xce, 0xd8, 0x81, 0xbf, 0x0e, 0x1d, 0x4a, 0x5c, 0xdb, 0x92, 0x13, 0xb6, 0xd0, 0xcb, 0x58, 0xac, - 0x62, 0x49, 0x45, 0x5f, 0x80, 0x72, 0x9f, 0xba, 0x2e, 0x2f, 0x5f, 0x73, 0x82, 0x71, 0x49, 0x32, - 0x96, 0xb7, 0xfc, 0x65, 0x1c, 0xd0, 0xb5, 0x0f, 0x14, 0x88, 0x5c, 0x24, 0xaa, 0x2e, 0x33, 0xee, - 0xfb, 0x93, 0xb9, 0x5b, 0x50, 0xb5, 0x1d, 0x93, 0x58, 0xec, 0x89, 0x5f, 0xa2, 0x7d, 0x07, 0x87, - 0x11, 0xff, 0x20, 0x46, 0xc3, 0x09, 0x4e, 0x5e, 0xda, 0x0d, 0xbb, 0xdf, 0xb7, 0x2d, 0x9e, 0xb5, - 0xa5, 0x6b, 0x63, 0x39, 0x2f, 0xa0, 0xe0, 0x18, 0x97, 0xf6, 0x4b, 0x05, 0x96, 0x52, 0x33, 0x30, - 0xf4, 0x73, 0x05, 0x2e, 0xba, 0x99, 0xca, 0xc9, 0x90, 0xbb, 0x3d, 0xcd, 0xe8, 0x2b, 0x01, 0xd0, - 0xac, 0x4b, 0x7d, 0x26, 0x9c, 0x1e, 0x4f, 0xd8, 0x58, 0xfb, 0x9b, 0x02, 0xe7, 0xd2, 0xd3, 0xb4, - 0xff, 0x45, 0x45, 0xd1, 0x5b, 0xb0, 0xe0, 0xf7, 0x8f, 0xdf, 0xa6, 0x47, 0xed, 0x96, 0xf4, 0xc2, - 0x79, 0x09, 0xb6, 0xb0, 0x1d, 0x91, 0x70, 0x9c, 0x4f, 0xfb, 0x69, 0x01, 0x2a, 0x41, 0xc5, 0x42, - 0xdf, 0x8d, 0xa6, 0xa3, 0xca, 0xd4, 0xb7, 0x3b, 0xbc, 0x74, 0x63, 0x13, 0xd2, 0x97, 0xff, 0x6d, - 0xfb, 0x6a, 0xd0, 0xae, 0xf9, 0xed, 0x75, 0x76, 0x13, 0x96, 0xec, 0x38, 0x8b, 0x79, 0x3a, 0x4e, - 0xed, 0x23, 0x15, 0x96, 0xc7, 0x0a, 0x38, 0xba, 0x9d, 0xc8, 0x79, 0xd7, 0x52, 0x39, 0x6f, 0x65, - 0x4c, 0xe0, 0xd4, 0x52, 0x5e, 0x76, 0x26, 0x52, 0x67, 0x98, 0x89, 0x8a, 0x79, 0x33, 0x51, 0xe9, - 0xe4, 0x4c, 0x94, 0xf2, 0xce, 0x5c, 0x2e, 0xef, 0x0c, 0x60, 0x29, 0xd5, 0x91, 0xa0, 0x1b, 0x50, - 0x61, 0x96, 0x4b, 0x8d, 0xa1, 0x43, 0xe5, 0x0c, 0x2d, 0x6c, 0x59, 0xdb, 0x72, 0x1d, 0x87, 0x1c, - 0xa8, 0x01, 0xf3, 0xae, 0xb1, 0x4f, 0xbb, 0xc3, 0x1e, 0xed, 0x0a, 0x87, 0x54, 0xa2, 0x2f, 0x61, - 0x3b, 0x01, 0x01, 0x47, 0x3c, 0xda, 0xbf, 0x8b, 0x50, 0x8d, 0x37, 0x14, 0x39, 0x3e, 0xca, 0xbd, - 0x07, 0x0b, 0xc4, 0xb2, 0x6c, 0x8f, 0xf8, 0x8d, 0xa3, 0x5f, 0xd6, 0xdf, 0x9e, 0xb2, 0x71, 0xd1, - 0xef, 0x46, 0x10, 0xfe, 0xd7, 0x8d, 0x30, 0x94, 0x63, 0x14, 0x1c, 0xdf, 0x09, 0xdd, 0x95, 0xdd, - 0xa2, 0x9a, 0xbf, 0x5b, 0xac, 0xa4, 0x3a, 0xc5, 0x06, 0xcc, 0x87, 0x1d, 0x91, 0xfc, 0x1c, 0x1c, - 0xda, 0x27, 0x8a, 0xc9, 0x88, 0x07, 0xe9, 0x09, 0x2f, 0x96, 0x84, 0x17, 0x17, 0x4f, 0x78, 0xd1, - 0xa5, 0x5b, 0xd1, 0xb9, 0x53, 0x6d, 0x45, 0x33, 0xfa, 0xc8, 0xf2, 0x4c, 0xfa, 0xc8, 0xd5, 0xaf, - 0xc3, 0xb9, 0xb4, 0x07, 0xa7, 0xfa, 0xac, 0xb2, 0x0d, 0x68, 0x7c, 0xff, 0xe7, 0xf5, 0x5e, 0xe3, - 0x12, 0x51, 0x22, 0x6a, 0x5e, 0x7f, 0xfa, 0xac, 0x7e, 0xe6, 0xe3, 0x67, 0xf5, 0x33, 0x9f, 0x3e, - 0xab, 0x9f, 0xf9, 0xf1, 0xa8, 0xae, 0x3c, 0x1d, 0xd5, 0x95, 0x8f, 0x47, 0x75, 0xe5, 0xd3, 0x51, - 0x5d, 0xf9, 0xfb, 0xa8, 0xae, 0xfc, 0xec, 0x1f, 0xf5, 0x33, 0x8f, 0x0a, 0x87, 0xeb, 0xff, 0x09, - 0x00, 0x00, 0xff, 0xff, 0x9e, 0x09, 0x46, 0xf1, 0x49, 0x27, 0x00, 0x00, + // 2445 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5a, 0x4f, 0x6c, 0xdb, 0xc8, + 0xd5, 0x0f, 0x45, 0x49, 0x96, 0x9f, 0x1d, 0x3b, 0x9e, 0xc4, 0x59, 0xad, 0x92, 0xb5, 0xbd, 0xcc, + 0x97, 0x20, 0x5f, 0x9b, 0xa5, 0x6a, 0x6f, 0x76, 0x9b, 0xa4, 0x40, 0x77, 0xa3, 0x28, 0x0d, 0xd4, + 0xda, 0x8d, 0x77, 0xac, 0xe6, 0x10, 0xa4, 0x40, 0x69, 0x6a, 0x4c, 0x4f, 0x2d, 0x91, 0x2a, 0x49, + 0x79, 0xd7, 0x41, 0x0b, 0xf4, 0x50, 0x2c, 0xf6, 0xd0, 0x43, 0x7b, 0xde, 0x63, 0xb1, 0x28, 0x7a, + 0x2e, 0x5a, 0xf4, 0xde, 0x16, 0x08, 0x7a, 0xe9, 0x62, 0x7b, 0xd9, 0x4b, 0x8d, 0x46, 0xed, 0xb9, + 0xb7, 0x5e, 0xf6, 0x54, 0xcc, 0x70, 0x48, 0x0e, 0x29, 0xca, 0xa6, 0xd2, 0xd8, 0x68, 0x6f, 0xe2, + 0xcc, 0x7b, 0xbf, 0xf7, 0xf8, 0xde, 0xbc, 0x3f, 0xf3, 0x28, 0x58, 0xb5, 0xa8, 0xbf, 0x3b, 0xd8, + 0xd6, 0x4d, 0xa7, 0x57, 0x77, 0xfa, 0xc4, 0xf6, 0x76, 0xe9, 0x8e, 0x5f, 0x37, 0xfa, 0xb4, 0x4e, + 0x7b, 0x86, 0x45, 0xea, 0xfb, 0xab, 0x75, 0x8b, 0xd8, 0xc4, 0x35, 0x7c, 0xd2, 0xd1, 0xfb, 0xae, + 0xe3, 0x3b, 0xe8, 0xf5, 0x98, 0x45, 0x8f, 0x58, 0x74, 0xa3, 0x4f, 0x75, 0xce, 0xa2, 0xef, 0xaf, + 0xd6, 0xde, 0x90, 0x50, 0x2d, 0xc7, 0x72, 0xea, 0x9c, 0x73, 0x7b, 0xb0, 0xc3, 0x9f, 0xf8, 0x03, + 0xff, 0x15, 0x20, 0xd6, 0xb4, 0xbd, 0x5b, 0x9e, 0x4e, 0x1d, 0x2e, 0xd6, 0x74, 0xdc, 0x2c, 0xa9, + 0xb5, 0x9b, 0x31, 0x4d, 0xcf, 0x30, 0x77, 0xa9, 0x4d, 0xdc, 0x83, 0x7a, 0x7f, 0xcf, 0x62, 0x0b, + 0x5e, 0xbd, 0x47, 0x7c, 0x23, 0x8b, 0xab, 0x3e, 0x8e, 0xcb, 0x1d, 0xd8, 0x3e, 0xed, 0x91, 0x11, + 0x86, 0xb7, 0x8f, 0x63, 0xf0, 0xcc, 0x5d, 0xd2, 0x33, 0x46, 0xf8, 0xde, 0x1c, 0xc7, 0x37, 0xf0, + 0x69, 0xb7, 0x4e, 0x6d, 0xdf, 0xf3, 0xdd, 0x34, 0x93, 0xf6, 0x99, 0x02, 0x17, 0x9a, 0x8e, 0xb9, + 0x47, 0xdc, 0x16, 0xb3, 0x1c, 0x26, 0x3b, 0xc4, 0x25, 0xb6, 0x49, 0xd0, 0x0d, 0xa8, 0xb8, 0xc4, + 0xa2, 0x9e, 0xef, 0x1e, 0x54, 0x95, 0x15, 0xe5, 0xfa, 0x74, 0xe3, 0xdc, 0xb3, 0xc3, 0xe5, 0x33, + 0xc3, 0xc3, 0xe5, 0x0a, 0x16, 0xeb, 0x38, 0xa2, 0x40, 0x75, 0x98, 0xb6, 0x8d, 0x1e, 0xf1, 0xfa, + 0x86, 0x49, 0xaa, 0x05, 0x4e, 0xbe, 0x20, 0xc8, 0xa7, 0xbf, 0x1d, 0x6e, 0xe0, 0x98, 0x06, 0xad, + 0x40, 0x91, 0x3d, 0x54, 0x55, 0x4e, 0x3b, 0x2b, 0x68, 0x8b, 0x8c, 0x16, 0xf3, 0x1d, 0xf4, 0x1a, + 0xa8, 0xbe, 0x61, 0x55, 0x8b, 0x9c, 0x60, 0x46, 0x10, 0xa8, 0x6d, 0xc3, 0xc2, 0x6c, 0x1d, 0xd5, + 0xa0, 0x40, 0x9b, 0xd5, 0x12, 0xdf, 0x05, 0xb1, 0x5b, 0x68, 0x35, 0x71, 0x81, 0x36, 0xb5, 0x3f, + 0x4f, 0x41, 0x89, 0xbf, 0x0e, 0xfa, 0x1e, 0x54, 0x98, 0x5f, 0x3a, 0x86, 0x6f, 0xf0, 0xb7, 0x98, + 0x59, 0xfb, 0x8a, 0x1e, 0x98, 0x49, 0x97, 0xcd, 0xa4, 0xf7, 0xf7, 0x2c, 0xb6, 0xe0, 0xe9, 0x8c, + 0x5a, 0xdf, 0x5f, 0xd5, 0x1f, 0x6e, 0x7f, 0x9f, 0x98, 0xfe, 0x06, 0xf1, 0x8d, 0x06, 0x12, 0xe8, + 0x10, 0xaf, 0xe1, 0x08, 0x15, 0x6d, 0xc2, 0x85, 0x4e, 0x86, 0xfd, 0x84, 0x11, 0x2e, 0x0b, 0xde, + 0x4c, 0x1b, 0xe3, 0x4c, 0x4e, 0xf4, 0x43, 0x38, 0x2f, 0xad, 0x6f, 0x84, 0xea, 0xab, 0x5c, 0xfd, + 0x37, 0xc6, 0xaa, 0x2f, 0x4e, 0x87, 0x8e, 0x8d, 0xf7, 0xef, 0x7f, 0xe0, 0x13, 0xdb, 0xa3, 0x8e, + 0xdd, 0xb8, 0x24, 0xe4, 0x9f, 0x6f, 0x8e, 0x22, 0xe2, 0x2c, 0x31, 0x68, 0x1b, 0x6a, 0x19, 0xcb, + 0x8f, 0x88, 0xcb, 0xf0, 0x84, 0x37, 0x34, 0x81, 0x5a, 0x6b, 0x8e, 0xa5, 0xc4, 0x47, 0xa0, 0xa0, + 0x8d, 0xe4, 0x1b, 0x1a, 0x36, 0xdd, 0x21, 0x9e, 0x2f, 0x9c, 0x99, 0xa9, 0xb2, 0x20, 0xc1, 0x59, + 0x7c, 0x68, 0x1f, 0x16, 0xa4, 0xe5, 0x75, 0xe3, 0x80, 0xb8, 0x5e, 0xb5, 0xbc, 0xa2, 0x72, 0x73, + 0x1d, 0x9b, 0x29, 0xf4, 0x98, 0xab, 0xf1, 0xaa, 0x90, 0xbd, 0xd0, 0x4c, 0xe3, 0xe1, 0x51, 0x11, + 0x88, 0x00, 0x78, 0xd4, 0xb2, 0x0d, 0x7f, 0xe0, 0x12, 0xaf, 0x3a, 0xc5, 0x05, 0xae, 0xe6, 0x15, + 0xb8, 0x15, 0x72, 0xc6, 0xe7, 0x2b, 0x5a, 0xf2, 0xb0, 0x04, 0x8c, 0x1e, 0xc2, 0xa2, 0x24, 0x3b, + 0x26, 0xaa, 0x56, 0x56, 0xd4, 0xeb, 0xb3, 0x8d, 0x57, 0x87, 0x87, 0xcb, 0x8b, 0xcd, 0x2c, 0x02, + 0x9c, 0xcd, 0x87, 0x76, 0xe1, 0x72, 0x86, 0x19, 0x37, 0x48, 0x87, 0x1a, 0xed, 0x83, 0x3e, 0xa9, + 0x4e, 0x73, 0x3f, 0xfc, 0x9f, 0x50, 0xeb, 0x72, 0xf3, 0x08, 0x5a, 0x7c, 0x24, 0x12, 0x7a, 0x90, + 0xf0, 0xcc, 0x3d, 0xc7, 0xde, 0xa1, 0x56, 0x15, 0x38, 0x7c, 0x96, 0xa9, 0x03, 0x02, 0x3c, 0xca, + 0xa3, 0x99, 0x70, 0x9e, 0x3f, 0x36, 0xba, 0xce, 0x76, 0x14, 0x29, 0x1e, 0xd2, 0xa0, 0xdc, 0x0d, + 0xdc, 0xad, 0xac, 0xa8, 0x2c, 0x11, 0x0c, 0x0f, 0x97, 0xcb, 0xc2, 0x61, 0x62, 0x07, 0x5d, 0x87, + 0x4a, 0x2f, 0x3c, 0x61, 0x41, 0x50, 0xce, 0xb2, 0x24, 0x16, 0x1d, 0xa9, 0x68, 0x57, 0xfb, 0xa3, + 0x0a, 0xf3, 0x5c, 0x4a, 0xab, 0xd7, 0x77, 0x5c, 0x7f, 0xab, 0x4f, 0x4c, 0x74, 0x1f, 0x8a, 0x3b, + 0xae, 0xd3, 0x13, 0xc9, 0xe3, 0x8a, 0x14, 0x7d, 0x3a, 0x2b, 0x13, 0x71, 0xaa, 0x88, 0xb4, 0x8a, + 0x93, 0xd9, 0x37, 0x5c, 0xa7, 0x87, 0x39, 0x3b, 0x7a, 0x17, 0x0a, 0xbe, 0xc3, 0xc5, 0xcf, 0xac, + 0x5d, 0xcf, 0x02, 0x59, 0x77, 0x4c, 0xa3, 0x9b, 0x46, 0x2a, 0xb3, 0x9c, 0xd6, 0x76, 0x70, 0xc1, + 0x77, 0x50, 0x17, 0x66, 0x29, 0x57, 0x6b, 0xd3, 0xe9, 0x52, 0xf3, 0x40, 0xa4, 0x83, 0xb5, 0x1c, + 0xc7, 0xad, 0x6d, 0x58, 0x2d, 0x89, 0xb3, 0x71, 0x41, 0xe8, 0x37, 0x2b, 0xaf, 0xe2, 0x04, 0x3a, + 0xba, 0x0b, 0xf3, 0xd4, 0x36, 0xbb, 0x83, 0x4e, 0x1c, 0x9d, 0x2c, 0xf4, 0x2b, 0x8d, 0x57, 0x04, + 0xf3, 0x7c, 0x2b, 0xb9, 0x8d, 0xd3, 0xf4, 0xe8, 0x03, 0x98, 0x77, 0xc3, 0x37, 0x11, 0x3a, 0x97, + 0xb8, 0xce, 0x6f, 0xe5, 0xd3, 0x19, 0x27, 0x99, 0x63, 0xc9, 0xa9, 0x0d, 0x9c, 0x16, 0xa3, 0xfd, + 0x45, 0x81, 0x05, 0xd9, 0x8f, 0xbe, 0xe1, 0x0f, 0x3c, 0xd4, 0x86, 0xb2, 0xc7, 0x7f, 0x09, 0x5f, + 0xde, 0xc8, 0x57, 0x08, 0x02, 0xee, 0xc6, 0x9c, 0x90, 0x5e, 0x0e, 0x9e, 0xb1, 0xc0, 0x42, 0x2d, + 0x28, 0x71, 0xa5, 0x23, 0xdf, 0xe6, 0x0c, 0xff, 0xc6, 0xf4, 0xf0, 0x70, 0x39, 0x28, 0x52, 0x38, + 0x40, 0x08, 0x0b, 0x9e, 0x9a, 0x5d, 0xf0, 0xb4, 0x0f, 0x15, 0x80, 0x38, 0xfb, 0x44, 0x05, 0x54, + 0x19, 0x5b, 0x40, 0xaf, 0x42, 0xd1, 0xa3, 0x4f, 0x03, 0xcd, 0xd4, 0xb8, 0x1c, 0x73, 0xf6, 0x2d, + 0xfa, 0x94, 0x60, 0xbe, 0xcd, 0x4a, 0x77, 0x2f, 0x0a, 0x7d, 0x35, 0x59, 0xba, 0xe3, 0x38, 0x8f, + 0x69, 0xb4, 0x0e, 0xcc, 0xc5, 0x7a, 0x34, 0x59, 0xcd, 0x78, 0x5d, 0x48, 0x52, 0xb8, 0xa4, 0xb3, + 0xc7, 0x4a, 0x29, 0xe4, 0x90, 0xf2, 0x3b, 0x05, 0xa6, 0x03, 0x31, 0xd4, 0xf3, 0xd1, 0x93, 0x91, + 0x3a, 0xae, 0xe7, 0x73, 0x1f, 0xe3, 0xe6, 0x55, 0x3c, 0xea, 0x5e, 0xc2, 0x15, 0xa9, 0x86, 0x6f, + 0x40, 0x89, 0xfa, 0xa4, 0xe7, 0x55, 0x0b, 0x3c, 0x87, 0xe7, 0x77, 0xe2, 0x59, 0x01, 0x5a, 0x6a, + 0x31, 0x76, 0x1c, 0xa0, 0x68, 0xb7, 0xc4, 0xf1, 0x5b, 0x77, 0x9c, 0xbd, 0x41, 0x5f, 0x44, 0xd4, + 0x15, 0x28, 0x75, 0x59, 0x8c, 0x73, 0x13, 0x57, 0x62, 0x4e, 0x1e, 0xf8, 0x38, 0xd8, 0xd3, 0x7e, + 0x5d, 0x16, 0xb6, 0x8d, 0xb2, 0xf5, 0x29, 0x74, 0x30, 0x2b, 0x50, 0xf4, 0x63, 0xaf, 0x44, 0x27, + 0x89, 0x3b, 0x84, 0xef, 0xa0, 0xab, 0x30, 0x65, 0x3a, 0xb6, 0x4f, 0x6c, 0x9f, 0x6b, 0x3f, 0xdb, + 0x98, 0x19, 0x1e, 0x2e, 0x4f, 0xdd, 0x0b, 0x96, 0x70, 0xb8, 0x87, 0x28, 0x80, 0xe9, 0xd8, 0x1d, + 0xea, 0x53, 0xc7, 0xf6, 0xaa, 0x45, 0x6e, 0xcb, 0x3c, 0xc1, 0x1e, 0xbd, 0xec, 0xbd, 0x90, 0x3b, + 0xd6, 0x38, 0x5a, 0xf2, 0xb0, 0x04, 0x8e, 0xbe, 0x06, 0x67, 0x39, 0x7b, 0xab, 0x43, 0x6c, 0x9f, + 0xfa, 0x07, 0xa2, 0x77, 0x58, 0x14, 0x6c, 0x67, 0x5b, 0xf2, 0x26, 0x4e, 0xd2, 0xa2, 0x1f, 0xc1, + 0x2c, 0x2b, 0xaf, 0xa4, 0x73, 0xaf, 0x6b, 0xd0, 0x5e, 0xd8, 0x2a, 0xdc, 0x9b, 0xb8, 0x72, 0x73, + 0xc5, 0x43, 0x94, 0xfb, 0xb6, 0xef, 0x4a, 0xb9, 0x55, 0xde, 0xc2, 0x09, 0x71, 0xe8, 0x3d, 0x98, + 0x32, 0x5d, 0xc2, 0x7a, 0xf0, 0xea, 0x14, 0x77, 0xe8, 0x97, 0xf2, 0x39, 0xb4, 0x4d, 0x7b, 0x44, + 0x58, 0x3e, 0x60, 0xc7, 0x21, 0x0e, 0x0b, 0x0f, 0xea, 0x79, 0x03, 0xd2, 0x69, 0x1c, 0x54, 0x2b, + 0xb9, 0x0b, 0x43, 0xf4, 0x22, 0x2d, 0xc6, 0xeb, 0x06, 0x75, 0xb1, 0x25, 0x70, 0x70, 0x84, 0x88, + 0xbe, 0x1b, 0xa2, 0xb7, 0x1d, 0xde, 0x1b, 0xcc, 0xac, 0xbd, 0x39, 0x09, 0xfa, 0xd6, 0x80, 0x9f, + 0x3a, 0x19, 0xbe, 0xed, 0xe0, 0x08, 0xb2, 0xf6, 0x0e, 0x2c, 0x8c, 0x18, 0x12, 0x9d, 0x03, 0x75, + 0x8f, 0x88, 0x9b, 0x07, 0x66, 0x3f, 0xd1, 0x05, 0x28, 0xed, 0x1b, 0xdd, 0x81, 0x38, 0xa7, 0x38, + 0x78, 0xb8, 0x53, 0xb8, 0xa5, 0x68, 0xbf, 0x28, 0xc0, 0x4c, 0xe0, 0x19, 0xdf, 0x25, 0x46, 0xef, + 0x14, 0x42, 0xa6, 0x0d, 0x45, 0xaf, 0x4f, 0x4c, 0x91, 0xf4, 0xd7, 0x72, 0x9f, 0x1c, 0xae, 0x1f, + 0xeb, 0x2b, 0xe2, 0x30, 0x63, 0x4f, 0x98, 0xa3, 0xa1, 0x27, 0x51, 0x85, 0x0a, 0x8a, 0xfb, 0xcd, + 0x09, 0x71, 0x8f, 0xac, 0x54, 0xda, 0xef, 0x15, 0x38, 0x27, 0x51, 0x9f, 0xd6, 0xfd, 0x68, 0xe3, + 0x45, 0x0b, 0x64, 0x9c, 0x5b, 0xa5, 0x22, 0xa9, 0xfd, 0xa6, 0x20, 0x92, 0x6b, 0xf8, 0x16, 0xac, + 0xc2, 0x9f, 0xc2, 0x6b, 0x3c, 0x4e, 0x78, 0xfc, 0xd6, 0x64, 0x9e, 0x89, 0xfb, 0xc9, 0x4c, 0xbf, + 0x6f, 0xa7, 0xfc, 0x7e, 0xe7, 0x85, 0xd0, 0x8f, 0xf6, 0xfe, 0x4f, 0x0a, 0xb0, 0x98, 0xa9, 0x11, + 0xba, 0x06, 0xe5, 0xa0, 0xf5, 0xe3, 0x96, 0xab, 0xc4, 0x08, 0x01, 0x0d, 0x16, 0xbb, 0xc8, 0x02, + 0x70, 0x49, 0xdf, 0xf1, 0xa8, 0xef, 0xb8, 0x07, 0xc2, 0x0e, 0x5f, 0xcd, 0xa1, 0x29, 0x8e, 0x98, + 0x24, 0x33, 0xcc, 0x31, 0x43, 0xc7, 0x3b, 0x58, 0x82, 0x46, 0x8f, 0x99, 0x42, 0x86, 0x45, 0x98, + 0x39, 0xd4, 0x49, 0xc2, 0x4b, 0xc6, 0x8f, 0x5f, 0x82, 0x21, 0x61, 0x81, 0xa8, 0xfd, 0xb6, 0x00, + 0xaf, 0x8c, 0x31, 0x1d, 0xc2, 0x09, 0x43, 0xb0, 0x0e, 0x63, 0x22, 0x37, 0x04, 0x97, 0x8f, 0x94, + 0xd1, 0x68, 0x86, 0xd1, 0x6e, 0xbf, 0x88, 0xd1, 0x84, 0x77, 0x8f, 0x30, 0xdb, 0x93, 0x94, 0xd9, + 0x6e, 0x4e, 0x68, 0xb6, 0xd4, 0xf9, 0x49, 0x19, 0xee, 0x93, 0x62, 0x22, 0xee, 0xc4, 0x0d, 0xf8, + 0xe4, 0xe3, 0xae, 0x03, 0xa5, 0xed, 0xae, 0xb3, 0x1d, 0xb6, 0x66, 0xef, 0x4c, 0xe6, 0x93, 0x40, + 0x4d, 0x9d, 0xdd, 0x1a, 0x45, 0x81, 0x8e, 0xb2, 0x0a, 0x5f, 0xc3, 0x01, 0x38, 0xda, 0x4d, 0xd9, + 0xee, 0xdd, 0x17, 0x12, 0x13, 0x98, 0x2c, 0x90, 0x33, 0xc6, 0x8e, 0xb5, 0x3d, 0x80, 0x58, 0x9b, + 0x8c, 0x2a, 0xf7, 0x40, 0xae, 0x72, 0x13, 0x8c, 0x13, 0xa2, 0x66, 0x5c, 0x2a, 0x8c, 0xb5, 0x1f, + 0x88, 0xba, 0x38, 0x56, 0xda, 0x7a, 0x52, 0xda, 0xdb, 0xb9, 0x93, 0x73, 0xe2, 0x1a, 0x2e, 0xd7, + 0xe2, 0x3f, 0x28, 0xe2, 0x0e, 0x2d, 0x2c, 0x73, 0xf2, 0xcd, 0xfb, 0x56, 0xb2, 0x79, 0x9f, 0x34, + 0x6a, 0xb3, 0x5b, 0xf8, 0x7f, 0x28, 0x80, 0x24, 0xaa, 0x0d, 0xa3, 0xdf, 0xa7, 0xb6, 0xf5, 0x3f, + 0x57, 0x2e, 0x8f, 0xbb, 0x53, 0xfe, 0xaa, 0x90, 0xf0, 0x16, 0xaf, 0x07, 0x5b, 0x89, 0x71, 0x53, + 0x9c, 0x6c, 0xc4, 0x4d, 0xf3, 0x35, 0x01, 0xb2, 0xd8, 0xcc, 0x22, 0xc2, 0xd9, 0xbc, 0xe8, 0x3d, + 0x28, 0xfa, 0x86, 0x15, 0xfa, 0xa8, 0x3e, 0xe1, 0x04, 0x40, 0xba, 0x94, 0x18, 0x96, 0x87, 0x39, + 0x14, 0xb2, 0x61, 0xb6, 0x2b, 0x5d, 0xb0, 0x26, 0xed, 0x99, 0xe4, 0xcb, 0x59, 0xdc, 0xb6, 0xcb, + 0xab, 0x38, 0x81, 0xaf, 0xfd, 0x32, 0xd9, 0x79, 0x88, 0xa2, 0x71, 0x22, 0xd6, 0x7a, 0x94, 0xb0, + 0x56, 0x9e, 0x57, 0x62, 0xd7, 0xfe, 0x4e, 0xdb, 0xb0, 0xee, 0xef, 0x13, 0xdb, 0x67, 0x41, 0x92, + 0x69, 0x32, 0x02, 0x97, 0xfa, 0x83, 0xed, 0x2e, 0x35, 0x33, 0xb5, 0x11, 0xa7, 0xe4, 0x8a, 0x60, + 0xbc, 0xb4, 0x39, 0x9e, 0x14, 0x1f, 0x85, 0xa3, 0x7d, 0x5c, 0x0c, 0x6f, 0xb1, 0xdc, 0x52, 0x6d, + 0xe3, 0x34, 0x02, 0xe7, 0x9b, 0xc1, 0x49, 0x0f, 0xc2, 0x66, 0xe2, 0x03, 0x36, 0x95, 0xf8, 0xb6, + 0xb0, 0x06, 0x20, 0xbe, 0x93, 0x50, 0xc7, 0xe6, 0x66, 0x51, 0x63, 0xe9, 0x0f, 0xa2, 0x1d, 0x2c, + 0x51, 0xa1, 0xdd, 0x8c, 0xcb, 0xef, 0xcd, 0x7c, 0x6a, 0x70, 0xa7, 0xe5, 0xbf, 0xfb, 0x46, 0x29, + 0xa2, 0xf4, 0x52, 0x52, 0x44, 0x3a, 0x8e, 0xca, 0x27, 0x1c, 0x47, 0x7f, 0x4a, 0xa6, 0xd6, 0xb6, + 0x61, 0x9d, 0x42, 0x91, 0x78, 0x94, 0x2c, 0x12, 0xab, 0x93, 0x15, 0x89, 0xb6, 0x61, 0x8d, 0xa9, + 0x13, 0xff, 0x54, 0x60, 0x61, 0x24, 0xf6, 0xc2, 0xac, 0xab, 0x8c, 0xf9, 0x74, 0xb5, 0x99, 0x54, + 0xe6, 0xcb, 0x13, 0x9c, 0x92, 0x6c, 0x35, 0x52, 0x87, 0x4f, 0x3d, 0xb9, 0xc3, 0xa7, 0x7d, 0xa4, + 0xc2, 0x85, 0xac, 0x8e, 0xfe, 0x65, 0x0d, 0xca, 0xd3, 0x63, 0xee, 0xc2, 0x69, 0x8f, 0xb9, 0xd5, + 0xff, 0x7c, 0xcc, 0x5d, 0x3c, 0x9d, 0x31, 0xf7, 0x47, 0x05, 0xb8, 0x98, 0x7d, 0x4f, 0x38, 0xa1, + 0x59, 0x77, 0x7c, 0xc3, 0x28, 0xbc, 0xfc, 0x1b, 0x06, 0xba, 0x03, 0x73, 0x46, 0x27, 0x38, 0x66, + 0x46, 0x97, 0x15, 0x2d, 0x7e, 0x8e, 0xa7, 0x1b, 0x68, 0x78, 0xb8, 0x3c, 0x77, 0x37, 0xb1, 0x83, + 0x53, 0x94, 0xda, 0x67, 0x2a, 0xa0, 0xd1, 0x29, 0x22, 0xba, 0x23, 0x26, 0x9b, 0x41, 0x20, 0x5e, + 0x93, 0x27, 0x9b, 0x5f, 0x1c, 0x2e, 0x5f, 0x1c, 0xe5, 0x90, 0x66, 0x9e, 0xeb, 0x91, 0x09, 0x83, + 0xb9, 0xe8, 0xcd, 0xa4, 0x51, 0xbe, 0x38, 0x5c, 0xce, 0xf8, 0xcb, 0x80, 0x1e, 0x21, 0xa5, 0x4c, + 0x67, 0xc1, 0xd9, 0xae, 0xe1, 0xf9, 0x9b, 0xae, 0xb3, 0x4d, 0xda, 0x54, 0x7c, 0xf7, 0x9e, 0x6c, + 0xf2, 0x17, 0xcd, 0x36, 0xd7, 0x65, 0x20, 0x9c, 0xc4, 0x45, 0xfb, 0x80, 0xd8, 0x42, 0xdb, 0x35, + 0x6c, 0x2f, 0x78, 0x25, 0x26, 0xad, 0x38, 0xb1, 0xb4, 0x9a, 0x90, 0x86, 0xd6, 0x47, 0xd0, 0x70, + 0x86, 0x04, 0x74, 0x0d, 0xca, 0x2e, 0x31, 0x3c, 0xc7, 0x16, 0x93, 0xd8, 0xc8, 0xcb, 0x98, 0xaf, + 0x62, 0xb1, 0x8b, 0xfe, 0x1f, 0xa6, 0x7a, 0xc4, 0xf3, 0x58, 0xf9, 0x2a, 0x73, 0xc2, 0x79, 0x41, + 0x38, 0xb5, 0x11, 0x2c, 0xe3, 0x70, 0x5f, 0xfb, 0x50, 0x81, 0xd8, 0x45, 0xbc, 0xea, 0x52, 0xf3, + 0x7e, 0x30, 0xc1, 0xbd, 0x05, 0xb3, 0x8e, 0x6b, 0x19, 0x36, 0x7d, 0x1a, 0x94, 0xe8, 0xc0, 0xc1, + 0x51, 0xc4, 0x3f, 0x94, 0xf6, 0x70, 0x82, 0x92, 0x95, 0x76, 0xd3, 0xe9, 0xf5, 0x1c, 0x9b, 0x65, + 0x6d, 0xe1, 0x5a, 0x29, 0xe7, 0x85, 0x3b, 0x58, 0xa2, 0xd2, 0x3e, 0x51, 0x60, 0x3e, 0x35, 0x2b, + 0x45, 0x3f, 0x57, 0xe0, 0xa2, 0x97, 0xa9, 0x9c, 0x08, 0xb9, 0xdb, 0x93, 0x8c, 0x48, 0x13, 0x00, + 0x8d, 0x25, 0xa1, 0xcf, 0x98, 0xb7, 0xc7, 0x63, 0x04, 0x6b, 0x7f, 0x55, 0xe0, 0x5c, 0x7a, 0xea, + 0xfa, 0xdf, 0xa8, 0x28, 0x7a, 0x0b, 0x66, 0x82, 0xfe, 0xf1, 0x5b, 0xe4, 0xa0, 0xd5, 0x14, 0x5e, + 0x38, 0x2f, 0xc0, 0x66, 0x36, 0xe3, 0x2d, 0x2c, 0xd3, 0x69, 0x3f, 0x2d, 0x40, 0x25, 0xac, 0x58, + 0xe8, 0x3b, 0xf1, 0x14, 0x5d, 0x99, 0xf8, 0x74, 0x47, 0x87, 0x6e, 0x64, 0x92, 0xfe, 0xf2, 0xff, + 0xce, 0x71, 0x25, 0x6c, 0xd7, 0x82, 0xf6, 0x3a, 0xbb, 0x09, 0x4b, 0x76, 0x9c, 0xc5, 0x3c, 0x1d, + 0xa7, 0xf6, 0xb1, 0x0a, 0x0b, 0x23, 0x05, 0x1c, 0xdd, 0x4e, 0xe4, 0xbc, 0xab, 0xa9, 0x9c, 0xb7, + 0x38, 0xc2, 0x70, 0x62, 0x29, 0x2f, 0x3b, 0x13, 0xa9, 0xa7, 0x98, 0x89, 0x8a, 0x79, 0x33, 0x51, + 0xe9, 0xe8, 0x4c, 0x94, 0xf2, 0x4e, 0x39, 0x97, 0x77, 0xfa, 0x30, 0x9f, 0xea, 0x48, 0xd0, 0x0d, + 0xa8, 0x50, 0xdb, 0x23, 0xe6, 0xc0, 0x25, 0x62, 0xd6, 0x1a, 0xb5, 0xac, 0x2d, 0xb1, 0x8e, 0x23, + 0x0a, 0x54, 0x87, 0x69, 0xcf, 0xdc, 0x25, 0x9d, 0x41, 0x97, 0x74, 0xb8, 0x43, 0x2a, 0xf1, 0x17, + 0xd3, 0xad, 0x70, 0x03, 0xc7, 0x34, 0xda, 0xbf, 0x8a, 0x30, 0x2b, 0x37, 0x14, 0x39, 0x3e, 0x11, + 0xbf, 0x0f, 0x33, 0x86, 0x6d, 0x3b, 0xbe, 0x11, 0x34, 0x8e, 0x85, 0xdc, 0xc3, 0x2f, 0x59, 0x8e, + 0x7e, 0x37, 0x86, 0x08, 0x86, 0x5f, 0x51, 0x28, 0x4b, 0x3b, 0x58, 0x96, 0x84, 0xee, 0x8a, 0x6e, + 0x51, 0xcd, 0xdf, 0x2d, 0x56, 0x52, 0x9d, 0x62, 0x1d, 0xa6, 0xa3, 0x8e, 0x48, 0xfc, 0x39, 0x21, + 0xb2, 0x4f, 0x1c, 0x93, 0x31, 0x0d, 0xd2, 0x13, 0x5e, 0x2c, 0x71, 0x2f, 0xce, 0x1d, 0x71, 0xa3, + 0x4b, 0xb7, 0xa2, 0xe5, 0x13, 0x6d, 0x45, 0x33, 0xfa, 0xc8, 0xa9, 0x53, 0xe9, 0x23, 0x6b, 0x5f, + 0x87, 0x73, 0x69, 0x0f, 0x4e, 0xf4, 0xf9, 0x6d, 0x13, 0xd0, 0xa8, 0xfc, 0xe3, 0x7a, 0xaf, 0x51, + 0x8e, 0x38, 0x11, 0x35, 0xae, 0x3f, 0x7b, 0xbe, 0x74, 0xe6, 0xd3, 0xe7, 0x4b, 0x67, 0x3e, 0x7f, + 0xbe, 0x74, 0xe6, 0xc7, 0xc3, 0x25, 0xe5, 0xd9, 0x70, 0x49, 0xf9, 0x74, 0xb8, 0xa4, 0x7c, 0x3e, + 0x5c, 0x52, 0xfe, 0x36, 0x5c, 0x52, 0x7e, 0xf6, 0xf7, 0xa5, 0x33, 0x8f, 0x0b, 0xfb, 0xab, 0xff, + 0x0e, 0x00, 0x00, 0xff, 0xff, 0x09, 0x41, 0xe3, 0x7d, 0x3c, 0x2a, 0x00, 0x00, } diff --git a/vendor/github.com/openshift/api/image/v1/generated.proto b/vendor/github.com/openshift/api/image/v1/generated.proto index bbbfa5df7d40..417a6c1bb29d 100644 --- a/vendor/github.com/openshift/api/image/v1/generated.proto +++ b/vendor/github.com/openshift/api/image/v1/generated.proto @@ -68,6 +68,20 @@ message Image { optional string dockerImageConfig = 10; } +// ImageBlobReferences describes the blob references within an image. +message ImageBlobReferences { + // layers is the list of blobs that compose this image, from base layer to top layer. + // All layers referenced by this array will be defined in the blobs map. Some images + // may have zero layers. + // +optional + repeated string layers = 1; + + // manifest, if set, is the blob that contains the image manifest. Some images do + // not have separate manifest blobs and this field will be set to nil if so. + // +optional + optional string manifest = 2; +} + // ImageImportSpec describes a request to import a specific image. message ImageImportSpec { // From is the source of an image to import; only kind DockerImage is allowed @@ -110,6 +124,16 @@ message ImageLayer { optional string mediaType = 3; } +// ImageLayerData contains metadata about an image layer. +message ImageLayerData { + // Size of the layer in bytes as defined by the underlying store. This field is + // optional if the necessary information about size is not available. + optional int64 size = 1; + + // MediaType of the referenced object. + optional string mediaType = 2; +} + // ImageList is a list of Image objects. message ImageList { // Standard object's metadata. @@ -237,6 +261,20 @@ message ImageStreamImportStatus { repeated ImageImportStatus images = 3; } +// ImageStreamLayers describes information about the layers referenced by images in this +// image stream. +message ImageStreamLayers { + // Standard object's metadata. + optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + + // blobs is a map of blob name to metadata about the blob. + map blobs = 2; + + // images is a map between an image name and the names of the blobs and manifests that + // comprise the image. + map images = 3; +} + // ImageStreamList is a list of ImageStream objects. message ImageStreamList { // Standard object's metadata. diff --git a/vendor/github.com/openshift/api/image/v1/register.go b/vendor/github.com/openshift/api/image/v1/register.go index 5377b4cade6d..46f785c471aa 100644 --- a/vendor/github.com/openshift/api/image/v1/register.go +++ b/vendor/github.com/openshift/api/image/v1/register.go @@ -43,6 +43,7 @@ func addKnownTypes(scheme *runtime.Scheme) error { &ImageStreamTag{}, &ImageStreamTagList{}, &ImageStreamImage{}, + &ImageStreamLayers{}, &ImageStreamImport{}, &corev1.SecretList{}, ) diff --git a/vendor/github.com/openshift/api/image/v1/types.go b/vendor/github.com/openshift/api/image/v1/types.go index 2d268174e723..9887fe542a88 100644 --- a/vendor/github.com/openshift/api/image/v1/types.go +++ b/vendor/github.com/openshift/api/image/v1/types.go @@ -159,6 +159,7 @@ type ImageStreamList struct { // +genclient // +genclient:method=Secrets,verb=get,subresource=secrets,result=k8s.io/api/core/v1.SecretList +// +genclient:method=Layers,verb=get,subresource=layers,result=github.com/openshift/api/image/v1.ImageStreamLayers // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // ImageStream stores a mapping of tags to images, metadata overrides that are applied @@ -417,6 +418,43 @@ type DockerImageReference struct { ID string `protobuf:"bytes,5,opt,name=iD"` } +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ImageStreamLayers describes information about the layers referenced by images in this +// image stream. +type ImageStreamLayers struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // blobs is a map of blob name to metadata about the blob. + Blobs map[string]ImageLayerData `json:"blobs" protobuf:"bytes,2,rep,name=blobs"` + // images is a map between an image name and the names of the blobs and manifests that + // comprise the image. + Images map[string]ImageBlobReferences `json:"images" protobuf:"bytes,3,rep,name=images"` +} + +// ImageBlobReferences describes the blob references within an image. +type ImageBlobReferences struct { + // layers is the list of blobs that compose this image, from base layer to top layer. + // All layers referenced by this array will be defined in the blobs map. Some images + // may have zero layers. + // +optional + Layers []string `json:"layers" protobuf:"bytes,1,rep,name=layers"` + // manifest, if set, is the blob that contains the image manifest. Some images do + // not have separate manifest blobs and this field will be set to nil if so. + // +optional + Manifest *string `json:"manifest" protobuf:"bytes,2,opt,name=manifest"` +} + +// ImageLayerData contains metadata about an image layer. +type ImageLayerData struct { + // Size of the layer in bytes as defined by the underlying store. This field is + // optional if the necessary information about size is not available. + LayerSize *int64 `json:"size" protobuf:"varint,1,opt,name=size"` + // MediaType of the referenced object. + MediaType string `json:"mediaType" protobuf:"bytes,2,opt,name=mediaType"` +} + // +genclient // +genclient:onlyVerbs=create // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/vendor/github.com/openshift/api/image/v1/types_swagger_doc_generated.go b/vendor/github.com/openshift/api/image/v1/types_swagger_doc_generated.go index 43f9d8951bcb..dc9b83c49779 100644 --- a/vendor/github.com/openshift/api/image/v1/types_swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/image/v1/types_swagger_doc_generated.go @@ -42,6 +42,16 @@ func (Image) SwaggerDoc() map[string]string { return map_Image } +var map_ImageBlobReferences = map[string]string{ + "": "ImageBlobReferences describes the blob references within an image.", + "layers": "layers is the list of blobs that compose this image, from base layer to top layer. All layers referenced by this array will be defined in the blobs map. Some images may have zero layers.", + "manifest": "manifest, if set, is the blob that contains the image manifest. Some images do not have separate manifest blobs and this field will be set to nil if so.", +} + +func (ImageBlobReferences) SwaggerDoc() map[string]string { + return map_ImageBlobReferences +} + var map_ImageImportSpec = map[string]string{ "": "ImageImportSpec describes a request to import a specific image.", "from": "From is the source of an image to import; only kind DockerImage is allowed", @@ -77,6 +87,16 @@ func (ImageLayer) SwaggerDoc() map[string]string { return map_ImageLayer } +var map_ImageLayerData = map[string]string{ + "": "ImageLayerData contains metadata about an image layer.", + "size": "Size of the layer in bytes as defined by the underlying store. This field is optional if the necessary information about size is not available.", + "mediaType": "MediaType of the referenced object.", +} + +func (ImageLayerData) SwaggerDoc() map[string]string { + return map_ImageLayerData +} + var map_ImageList = map[string]string{ "": "ImageList is a list of Image objects.", "metadata": "Standard object's metadata.", @@ -167,6 +187,17 @@ func (ImageStreamImportStatus) SwaggerDoc() map[string]string { return map_ImageStreamImportStatus } +var map_ImageStreamLayers = map[string]string{ + "": "ImageStreamLayers describes information about the layers referenced by images in this image stream.", + "metadata": "Standard object's metadata.", + "blobs": "blobs is a map of blob name to metadata about the blob.", + "images": "images is a map between an image name and the names of the blobs and manifests that comprise the image.", +} + +func (ImageStreamLayers) SwaggerDoc() map[string]string { + return map_ImageStreamLayers +} + var map_ImageStreamList = map[string]string{ "": "ImageStreamList is a list of ImageStream objects.", "metadata": "Standard object's metadata.", diff --git a/vendor/github.com/openshift/api/image/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/api/image/v1/zz_generated.deepcopy.go index fd84d5c30817..6aa13046be40 100644 --- a/vendor/github.com/openshift/api/image/v1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/api/image/v1/zz_generated.deepcopy.go @@ -75,6 +75,36 @@ func (in *Image) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageBlobReferences) DeepCopyInto(out *ImageBlobReferences) { + *out = *in + if in.Layers != nil { + in, out := &in.Layers, &out.Layers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Manifest != nil { + in, out := &in.Manifest, &out.Manifest + if *in == nil { + *out = nil + } else { + *out = new(string) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageBlobReferences. +func (in *ImageBlobReferences) DeepCopy() *ImageBlobReferences { + if in == nil { + return nil + } + out := new(ImageBlobReferences) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageImportSpec) DeepCopyInto(out *ImageImportSpec) { *out = *in @@ -145,6 +175,31 @@ func (in *ImageLayer) DeepCopy() *ImageLayer { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageLayerData) DeepCopyInto(out *ImageLayerData) { + *out = *in + if in.LayerSize != nil { + in, out := &in.LayerSize, &out.LayerSize + if *in == nil { + *out = nil + } else { + *out = new(int64) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageLayerData. +func (in *ImageLayerData) DeepCopy() *ImageLayerData { + if in == nil { + return nil + } + out := new(ImageLayerData) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageList) DeepCopyInto(out *ImageList) { *out = *in @@ -421,6 +476,50 @@ func (in *ImageStreamImportStatus) DeepCopy() *ImageStreamImportStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageStreamLayers) DeepCopyInto(out *ImageStreamLayers) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.Blobs != nil { + in, out := &in.Blobs, &out.Blobs + *out = make(map[string]ImageLayerData, len(*in)) + for key, val := range *in { + newVal := new(ImageLayerData) + val.DeepCopyInto(newVal) + (*out)[key] = *newVal + } + } + if in.Images != nil { + in, out := &in.Images, &out.Images + *out = make(map[string]ImageBlobReferences, len(*in)) + for key, val := range *in { + newVal := new(ImageBlobReferences) + val.DeepCopyInto(newVal) + (*out)[key] = *newVal + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageStreamLayers. +func (in *ImageStreamLayers) DeepCopy() *ImageStreamLayers { + if in == nil { + return nil + } + out := new(ImageStreamLayers) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ImageStreamLayers) 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 *ImageStreamList) DeepCopyInto(out *ImageStreamList) { *out = *in diff --git a/vendor/github.com/openshift/client-go/glide.lock b/vendor/github.com/openshift/client-go/glide.lock index 046d6e411796..9991bea1ac0e 100644 --- a/vendor/github.com/openshift/client-go/glide.lock +++ b/vendor/github.com/openshift/client-go/glide.lock @@ -1,5 +1,5 @@ hash: 91748cede774246187f6a8627e0a335015261f8e28708731a279c6ce205d9254 -updated: 2018-06-29T15:11:35.519708105-04:00 +updated: 2018-07-10T15:41:29.920958699-04:00 imports: - name: github.com/davecgh/go-spew version: 782f4967f2dc4564575ca782fe2d04090b5faca8 @@ -49,7 +49,7 @@ imports: - name: github.com/modern-go/reflect2 version: 05fbef0ca5da472bbf96c9322b84a53edc03c9fd - name: github.com/openshift/api - version: 31a7bbd2266d178da3c12bb83f5274d387f775e6 + version: 04a26bf3b8d69c390642c5803fe4cfdb899112aa subpackages: - apps/v1 - authorization/v1 diff --git a/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/fake/fake_imagestream.go b/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/fake/fake_imagestream.go index 15d18fa8888d..b193c7d793bf 100644 --- a/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/fake/fake_imagestream.go +++ b/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/fake/fake_imagestream.go @@ -134,3 +134,14 @@ func (c *FakeImageStreams) Secrets(imageStreamName string, options v1.GetOptions } return obj.(*core_v1.SecretList), err } + +// Layers takes name of the imageStream, and returns the corresponding imageStreamLayers object, and an error if there is any. +func (c *FakeImageStreams) Layers(imageStreamName string, options v1.GetOptions) (result *image_v1.ImageStreamLayers, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetSubresourceAction(imagestreamsResource, c.ns, "layers", imageStreamName), &image_v1.ImageStreamLayers{}) + + if obj == nil { + return nil, err + } + return obj.(*image_v1.ImageStreamLayers), err +} diff --git a/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/imagestream.go b/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/imagestream.go index 1e1cc2e24f9d..307afcfff68e 100644 --- a/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/imagestream.go +++ b/vendor/github.com/openshift/client-go/image/clientset/versioned/typed/image/v1/imagestream.go @@ -30,6 +30,7 @@ type ImageStreamInterface interface { Watch(opts meta_v1.ListOptions) (watch.Interface, error) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ImageStream, err error) Secrets(imageStreamName string, options meta_v1.GetOptions) (*core_v1.SecretList, error) + Layers(imageStreamName string, options meta_v1.GetOptions) (*v1.ImageStreamLayers, error) ImageStreamExpansion } @@ -173,3 +174,17 @@ func (c *imageStreams) Secrets(imageStreamName string, options meta_v1.GetOption Into(result) return } + +// Layers takes name of the imageStream, and returns the corresponding v1.ImageStreamLayers object, and an error if there is any. +func (c *imageStreams) Layers(imageStreamName string, options meta_v1.GetOptions) (result *v1.ImageStreamLayers, err error) { + result = &v1.ImageStreamLayers{} + err = c.client.Get(). + Namespace(c.ns). + Resource("imagestreams"). + Name(imageStreamName). + SubResource("layers"). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} diff --git a/vendor/github.com/openshift/imagebuilder/cmd/imagebuilder/imagebuilder.go b/vendor/github.com/openshift/imagebuilder/cmd/imagebuilder/imagebuilder.go index 62a932c27049..499e466f987b 100644 --- a/vendor/github.com/openshift/imagebuilder/cmd/imagebuilder/imagebuilder.go +++ b/vendor/github.com/openshift/imagebuilder/cmd/imagebuilder/imagebuilder.go @@ -82,7 +82,7 @@ func main() { if glog.V(2) { log.Printf("Builder: "+format, args...) } else { - fmt.Fprintf(options.ErrOut, "--> %s\n", fmt.Sprintf(format, args...)) + fmt.Fprintf(options.Out, "--> %s\n", fmt.Sprintf(format, args...)) } } diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/archive.go b/vendor/github.com/openshift/imagebuilder/dockerclient/archive.go index ee5ca9a30e51..c8c0f68bc92f 100644 --- a/vendor/github.com/openshift/imagebuilder/dockerclient/archive.go +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/archive.go @@ -38,7 +38,9 @@ func FilterArchive(r io.Reader, w io.Writer, fn TransformFileFunc) error { } var body io.Reader = tr + name := h.Name data, ok, skip, err := fn(h, tr) + glog.V(6).Infof("Transform %s -> %s: data=%t ok=%t skip=%t err=%v", name, h.Name, data != nil, ok, skip, err) if err != nil { return err } @@ -100,7 +102,7 @@ func NewLazyArchive(fn CreateFileFunc) io.ReadCloser { return pr } -func archiveFromURL(src, dst, tempDir string) (io.Reader, io.Closer, error) { +func archiveFromURL(src, dst, tempDir string, check DirectoryCheck) (io.Reader, io.Closer, error) { // get filename from URL u, err := url.Parse(src) if err != nil { @@ -151,7 +153,7 @@ func archiveFromURL(src, dst, tempDir string) (io.Reader, io.Closer, error) { return archive, closers{resp.Body.Close, archive.Close}, nil } -func archiveFromDisk(directory string, src, dst string, allowDownload bool, excludes []string) (io.Reader, io.Closer, error) { +func archiveFromDisk(directory string, src, dst string, allowDownload bool, excludes []string, check DirectoryCheck) (io.Reader, io.Closer, error) { var err error if filepath.IsAbs(src) { src, err = filepath.Rel(filepath.Dir(src), src) @@ -173,13 +175,66 @@ func archiveFromDisk(directory string, src, dst string, allowDownload bool, excl directory = filepath.Dir(directory) } - options := archiveOptionsFor(infos, dst, excludes) + options, err := archiveOptionsFor(infos, dst, excludes, check) + if err != nil { + return nil, nil, err + } glog.V(4).Infof("Tar of %s %#v", directory, options) rc, err := archive.TarWithOptions(directory, options) return rc, rc, err } +func archiveFromFile(file string, src, dst string, excludes []string, check DirectoryCheck) (io.Reader, io.Closer, error) { + var err error + if filepath.IsAbs(src) { + src, err = filepath.Rel(filepath.Dir(src), src) + if err != nil { + return nil, nil, err + } + } + + mapper, _, err := newArchiveMapper(src, dst, excludes, true, check) + if err != nil { + return nil, nil, err + } + + f, err := os.Open(file) + if err != nil { + return nil, nil, err + } + + r, err := transformArchive(f, true, mapper.Filter) + return r, f, err +} + +func archiveFromContainer(in io.Reader, src, dst string, excludes []string, check DirectoryCheck) (io.Reader, string, error) { + mapper, archiveRoot, err := newArchiveMapper(src, dst, excludes, false, check) + if err != nil { + return nil, "", err + } + + r, err := transformArchive(in, false, mapper.Filter) + return r, archiveRoot, err +} + +func transformArchive(r io.Reader, compressed bool, fn TransformFileFunc) (io.Reader, error) { + pr, pw := io.Pipe() + go func() { + if compressed { + in, err := archive.DecompressStream(r) + if err != nil { + pw.CloseWithError(err) + return + } + r = in + } + err := FilterArchive(r, pw, fn) + pw.CloseWithError(err) + }() + return pr, nil +} + // * -> test // a (dir) -> test // a (file) -> test @@ -193,9 +248,15 @@ func archivePathMapper(src, dst string, isDestDir bool) (fn func(name string, is } pattern := filepath.Base(srcPattern) + glog.V(6).Infof("creating mapper for srcPattern=%s pattern=%s dst=%s isDestDir=%t", srcPattern, pattern, dst, isDestDir) + // no wildcards if !containsWildcards(pattern) { return func(name string, isDir bool) (string, bool) { + // when extracting from the working directory, Docker prefaces with ./ + if strings.HasPrefix(name, "."+string(filepath.Separator)) { + name = name[2:] + } if name == srcPattern { if isDir { return "", false @@ -232,7 +293,7 @@ func archivePathMapper(src, dst string, isDestDir bool) (fn func(name string, is } prefix += string(filepath.Separator) - // nested with pattern pattern + // nested with pattern return func(name string, isDir bool) (string, bool) { remainder := strings.TrimPrefix(name, prefix) if remainder == name { @@ -251,56 +312,6 @@ func archivePathMapper(src, dst string, isDestDir bool) (fn func(name string, is } } -func archiveFromFile(file string, src, dst string, excludes []string) (io.Reader, io.Closer, error) { - var err error - if filepath.IsAbs(src) { - src, err = filepath.Rel(filepath.Dir(src), src) - if err != nil { - return nil, nil, err - } - } - - mapper, _, err := newArchiveMapper(src, dst, excludes, true) - if err != nil { - return nil, nil, err - } - - f, err := os.Open(file) - if err != nil { - return nil, nil, err - } - - r, err := transformArchive(f, true, mapper.Filter) - return r, f, err -} - -func archiveFromContainer(in io.Reader, src, dst string, excludes []string) (io.Reader, string, error) { - mapper, archiveRoot, err := newArchiveMapper(src, dst, excludes, false) - if err != nil { - return nil, "", err - } - - r, err := transformArchive(in, false, mapper.Filter) - return r, archiveRoot, err -} - -func transformArchive(r io.Reader, compressed bool, fn TransformFileFunc) (io.Reader, error) { - pr, pw := io.Pipe() - go func() { - if compressed { - in, err := archive.DecompressStream(r) - if err != nil { - pw.CloseWithError(err) - return - } - r = in - } - err := FilterArchive(r, pw, fn) - pw.CloseWithError(err) - }() - return pr, nil -} - type archiveMapper struct { exclude *fileutils.PatternMatcher rename func(name string, isDir bool) (string, bool) @@ -308,7 +319,7 @@ type archiveMapper struct { resetOwners bool } -func newArchiveMapper(src, dst string, excludes []string, resetOwners bool) (*archiveMapper, string, error) { +func newArchiveMapper(src, dst string, excludes []string, resetOwners bool, check DirectoryCheck) (*archiveMapper, string, error) { ex, err := fileutils.NewPatternMatcher(excludes) if err != nil { return nil, "", err @@ -316,6 +327,13 @@ func newArchiveMapper(src, dst string, excludes []string, resetOwners bool) (*ar isDestDir := strings.HasSuffix(dst, "/") || path.Base(dst) == "." dst = path.Clean(dst) + if !isDestDir && check != nil { + isDir, err := check.IsDirectory(dst) + if err != nil { + return nil, "", err + } + isDestDir = isDir + } var prefix string archiveRoot := src @@ -380,19 +398,27 @@ func (m *archiveMapper) Filter(h *tar.Header, r io.Reader) ([]byte, bool, bool, return nil, false, false, nil } -func archiveOptionsFor(infos []CopyInfo, dst string, excludes []string) *archive.TarOptions { +func archiveOptionsFor(infos []CopyInfo, dst string, excludes []string, check DirectoryCheck) (*archive.TarOptions, error) { dst = trimLeadingPath(dst) dstIsDir := strings.HasSuffix(dst, "/") || dst == "." || dst == "/" || strings.HasSuffix(dst, "/.") dst = trimTrailingSlash(dst) dstIsRoot := dst == "." || dst == "/" + if !dstIsDir && check != nil { + isDir, err := check.IsDirectory(dst) + if err != nil { + return nil, fmt.Errorf("unable to check whether %s is a directory: %v", dst, err) + } + dstIsDir = isDir + } + options := &archive.TarOptions{ ChownOpts: &idtools.IDPair{UID: 0, GID: 0}, } pm, err := fileutils.NewPatternMatcher(excludes) if err != nil { - return options + return options, nil } for _, info := range infos { @@ -418,12 +444,9 @@ func archiveOptionsFor(infos []CopyInfo, dst string, excludes []string) *archive case len(infos) > 1: // put each input into the target, which is assumed to be a directory ([Dockerfile, dir] -> [a/Dockerfile, a/dir]) options.RebaseNames[infoPath] = path.Join(dst, path.Base(infoPath)) - case info.FileInfo.IsDir() && dstIsDir: - // mapping a directory to an explicit directory ([dir] -> [a]) - options.RebaseNames[infoPath] = dst case info.FileInfo.IsDir(): - // mapping a directory to an implicit directory ([Dockerfile] -> [dir/Dockerfile]) - options.RebaseNames[infoPath] = path.Join(dst, path.Base(infoPath)) + // mapping a directory to a destination, explicit or not ([dir] -> [a]) + options.RebaseNames[infoPath] = dst case info.FromDir: // this is a file that was part of an explicit directory request, no transformation options.RebaseNames[infoPath] = path.Join(dst, path.Base(infoPath)) @@ -437,7 +460,7 @@ func archiveOptionsFor(infos []CopyInfo, dst string, excludes []string) *archive } options.ExcludePatterns = excludes - return options + return options, nil } func sourceToDestinationName(src, dst string, forceDir bool) string { diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/archive_test.go b/vendor/github.com/openshift/imagebuilder/dockerclient/archive_test.go index 89961c769b63..978c8564bfd3 100644 --- a/vendor/github.com/openshift/imagebuilder/dockerclient/archive_test.go +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/archive_test.go @@ -13,6 +13,20 @@ import ( "github.com/docker/docker/pkg/archive" ) +type testDirectoryCheck map[string]bool + +func (c testDirectoryCheck) IsDirectory(path string) (bool, error) { + if c == nil { + return false, nil + } + + isDir, ok := c[path] + if !ok { + return false, fmt.Errorf("no path defined for %s", path) + } + return isDir, nil +} + type archiveGenerator struct { Headers []*tar.Header } @@ -81,6 +95,7 @@ func Test_archiveFromFile(t *testing.T) { dst string excludes []string expect []string + check map[string]bool }{ { file: testArchive, @@ -233,6 +248,7 @@ func Test_archiveFromFile(t *testing.T) { testCase.src, testCase.dst, testCase.excludes, + testDirectoryCheck(testCase.check), ) if err != nil { t.Fatal(err) @@ -266,6 +282,7 @@ func Test_archiveFromContainer(t *testing.T) { excludes []string expect []string path string + check map[string]bool }{ { gen: newArchiveGenerator().File("file").Dir("test").File("test/file2"), @@ -394,6 +411,14 @@ func Test_archiveFromContainer(t *testing.T) { path: "/a", expect: nil, }, + { + gen: newArchiveGenerator().File("b"), + src: "/a/b", + dst: "/a", + check: map[string]bool{"/a": true}, + path: "/a", + expect: nil, + }, { gen: newArchiveGenerator().Dir("a/").File("a/b"), src: "/a/b", @@ -403,6 +428,13 @@ func Test_archiveFromContainer(t *testing.T) { "/a", }, }, + { + gen: newArchiveGenerator().Dir("./a").File("./a/b"), + src: "a", + dst: "/a", + path: ".", + expect: []string{"/a/b"}, + }, } for i := range testCases { testCase := testCases[i] @@ -412,6 +444,7 @@ func Test_archiveFromContainer(t *testing.T) { testCase.src, testCase.dst, testCase.excludes, + testDirectoryCheck(testCase.check), ) if err != nil { t.Fatal(err) diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/client.go b/vendor/github.com/openshift/imagebuilder/dockerclient/client.go index bbf1ab0ec2ae..fa8b4a8fa2be 100644 --- a/vendor/github.com/openshift/imagebuilder/dockerclient/client.go +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/client.go @@ -799,8 +799,9 @@ func (e *ClientExecutor) archiveFromContainer(from string, src, dst string) (io. e.Deferred = append([]func() error{func() error { return e.removeContainer(containerID) }}, e.Deferred...) } + check := newDirectoryCheck(e.Client, e.Container.ID) pr, pw := io.Pipe() - ar, archiveRoot, err := archiveFromContainer(pr, src, dst, nil) + ar, archiveRoot, err := archiveFromContainer(pr, src, dst, nil, check) if err != nil { pr.Close() return nil, nil, err @@ -818,26 +819,30 @@ func (e *ClientExecutor) archiveFromContainer(from string, src, dst string) (io. // TODO: this does not support decompressing nested archives for ADD (when the source is a compressed file) func (e *ClientExecutor) Archive(fromFS bool, src, dst string, allowDownload bool, excludes []string) (io.Reader, io.Closer, error) { + var check DirectoryCheck + if e.Container != nil { + check = newDirectoryCheck(e.Client, e.Container.ID) + } if isURL(src) { if !allowDownload { return nil, nil, fmt.Errorf("source can't be a URL") } glog.V(5).Infof("Archiving %s -> %s from URL", src, dst) - return archiveFromURL(src, dst, e.TempDir) + return archiveFromURL(src, dst, e.TempDir, check) } // the input is from the filesystem, use the source as the input if fromFS { glog.V(5).Infof("Archiving %s %s -> %s from a filesystem location", src, ".", dst) - return archiveFromDisk(src, ".", dst, allowDownload, excludes) + return archiveFromDisk(src, ".", dst, allowDownload, excludes, check) } // if the context is in archive form, read from it without decompressing if len(e.ContextArchive) > 0 { glog.V(5).Infof("Archiving %s %s -> %s from context archive", e.ContextArchive, src, dst) - return archiveFromFile(e.ContextArchive, src, dst, excludes) + return archiveFromFile(e.ContextArchive, src, dst, excludes, check) } // if the context is a directory, we only allow relative includes glog.V(5).Infof("Archiving %q %q -> %q from disk", e.Directory, src, dst) - return archiveFromDisk(e.Directory, src, dst, allowDownload, excludes) + return archiveFromDisk(e.Directory, src, dst, allowDownload, excludes, check) } // ContainerVolumeTracker manages tracking archives of specific paths inside a container. diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/conformance_test.go b/vendor/github.com/openshift/imagebuilder/dockerclient/conformance_test.go index 4a5c8fc9d510..911083ada297 100644 --- a/vendor/github.com/openshift/imagebuilder/dockerclient/conformance_test.go +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/conformance_test.go @@ -111,6 +111,8 @@ func TestCopyFrom(t *testing.T) { {name: "copy file to deeper directory with explicit slash", create: "mkdir -p /a && touch /a/1", copy: "/a/1 /a/b/c/", expect: "ls -al /a/b/c/1 && ! ls -al /a/b/1"}, {name: "copy file to deeper directory without explicit slash", create: "mkdir -p /a && touch /a/1", copy: "/a/1 /a/b/c", expect: "ls -al /a/b/c && ! ls -al /a/b/1"}, {name: "copy directory to deeper directory without explicit slash", create: "mkdir -p /a && touch /a/1", copy: "/a /a/b/c", expect: "ls -al /a/b/c/1 && ! ls -al /a/b/1"}, + {name: "copy directory to root without explicit slash", create: "mkdir -p /a && touch /a/1", copy: "a /a", expect: "ls -al /a/1 && ! ls -al /a/a"}, + {name: "copy directory trailing to root without explicit slash", create: "mkdir -p /a && touch /a/1", copy: "a/. /a", expect: "ls -al /a/1 && ! ls -al /a/a"}, } for i, testCase := range testCases { name := fmt.Sprintf("%d", i) @@ -143,6 +145,7 @@ func TestCopyFrom(t *testing.T) { stages := imagebuilder.NewStages(node, b) if _, err := e.Stages(b, stages, ""); err != nil { + t.Log(out.String()) t.Fatal(err) } }) @@ -250,6 +253,18 @@ func TestConformanceInternal(t *testing.T) { Name: "directory", ContextDir: "testdata/dir", }, + { + Name: "copy to dir", + ContextDir: "testdata/copy", + }, + { + Name: "copy dir", + ContextDir: "testdata/copydir", + }, + { + Name: "copy to renamed file", + ContextDir: "testdata/copyrename", + }, { Name: "directory with slash", ContextDir: "testdata/overlapdir", @@ -391,8 +406,8 @@ func TestTransientMount(t *testing.T) { e.AllowPull = true e.Directory = "testdata" e.TransientMounts = []Mount{ - {SourcePath: "dir", DestinationPath: "/mountdir"}, - {SourcePath: "Dockerfile.env", DestinationPath: "/mountfile"}, + {SourcePath: "testdata/dir", DestinationPath: "/mountdir"}, + {SourcePath: "testdata/Dockerfile.env", DestinationPath: "/mountfile"}, } e.Tag = fmt.Sprintf("conformance%d", rand.Int63()) diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/copyinfo_test.go b/vendor/github.com/openshift/imagebuilder/dockerclient/copyinfo_test.go index 7828e3511850..24854441b945 100644 --- a/vendor/github.com/openshift/imagebuilder/dockerclient/copyinfo_test.go +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/copyinfo_test.go @@ -17,6 +17,7 @@ func TestCalcCopyInfo(t *testing.T) { paths map[string]struct{} excludes []string rebaseNames map[string]string + check map[string]bool }{ { origPath: "subdir/*", @@ -106,6 +107,33 @@ func TestCalcCopyInfo(t *testing.T) { "Dockerfile": "copy/Dockerfile", }, }, + { + origPath: "Dockerfile", + dstPath: "copy", + rootPath: "testdata/singlefile", + allowWildcards: true, + errFn: nilErr, + paths: map[string]struct{}{ + "Dockerfile": {}, + }, + rebaseNames: map[string]string{ + "Dockerfile": "copy", + }, + }, + { + origPath: "Dockerfile", + dstPath: "copy", + check: map[string]bool{"copy": true}, + rootPath: "testdata/singlefile", + allowWildcards: true, + errFn: nilErr, + paths: map[string]struct{}{ + "Dockerfile": {}, + }, + rebaseNames: map[string]string{ + "Dockerfile": "copy/Dockerfile", + }, + }, { origPath: "existing/", dstPath: ".", @@ -185,6 +213,20 @@ func TestCalcCopyInfo(t *testing.T) { "subdir": "test", }, }, + { + origPath: "dir", + dstPath: "/dir", + check: map[string]bool{"dir": false}, + rootPath: "testdata/copydir", + allowWildcards: true, + errFn: nilErr, + paths: map[string]struct{}{ + "dir": {}, + }, + rebaseNames: map[string]string{ + "dir": "dir", + }, + }, } for i, test := range tests { @@ -211,7 +253,10 @@ func TestCalcCopyInfo(t *testing.T) { t.Errorf("did not see paths: %#v", expect) } - options := archiveOptionsFor(infos, test.dstPath, test.excludes) + options, err := archiveOptionsFor(infos, test.dstPath, test.excludes, testDirectoryCheck(test.check)) + if err != nil { + t.Fatal(err) + } if !reflect.DeepEqual(test.rebaseNames, options.RebaseNames) { t.Errorf("rebase names did not match:\n%#v\n%#v", test.rebaseNames, options.RebaseNames) } diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/directory.go b/vendor/github.com/openshift/imagebuilder/dockerclient/directory.go new file mode 100644 index 000000000000..4e0a9f8bf01a --- /dev/null +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/directory.go @@ -0,0 +1,87 @@ +package dockerclient + +import ( + "archive/tar" + "context" + "io" + "io/ioutil" + + "github.com/golang/glog" + + docker "github.com/fsouza/go-dockerclient" +) + +type DirectoryCheck interface { + IsDirectory(path string) (bool, error) +} + +type directoryCheck struct { + containerID string + client *docker.Client +} + +func newDirectoryCheck(client *docker.Client, containerID string) *directoryCheck { + return &directoryCheck{ + containerID: containerID, + client: client, + } +} + +func (c *directoryCheck) IsDirectory(path string) (bool, error) { + if path == "/" || path == "." || path == "./" { + return true, nil + } + + dir, err := isContainerPathDirectory(c.client, c.containerID, path) + if err != nil { + return false, err + } + + return dir, nil +} + +func isContainerPathDirectory(client *docker.Client, containerID, path string) (bool, error) { + pr, pw := io.Pipe() + defer pw.Close() + ctx, cancel := context.WithCancel(context.TODO()) + go func() { + err := client.DownloadFromContainer(containerID, docker.DownloadFromContainerOptions{ + OutputStream: pw, + Path: path, + Context: ctx, + }) + if err != nil { + if apiErr, ok := err.(*docker.Error); ok && apiErr.Status == 404 { + glog.V(4).Infof("path %s did not exist in container %s: %v", path, containerID, err) + err = nil + } + if err != nil && err != context.Canceled { + glog.V(6).Infof("error while checking directory contents for container %s at path %s: %v", containerID, path, err) + } + } + pw.CloseWithError(err) + }() + + tr := tar.NewReader(pr) + + h, err := tr.Next() + if err != nil { + if err == io.EOF { + err = nil + } + return false, err + } + + glog.V(4).Infof("Retrieved first header from container %s at path %s: %#v", containerID, path, h) + + // take the remainder of the input and discard it + go func() { + cancel() + n, err := io.Copy(ioutil.Discard, pr) + if n > 0 || err != nil { + glog.V(6).Infof("Discarded %d bytes from end of container directory check, and got error: %v", n, err) + } + }() + + return h.FileInfo().IsDir(), nil +} diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copy/Dockerfile b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copy/Dockerfile new file mode 100644 index 000000000000..815de493ba73 --- /dev/null +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copy/Dockerfile @@ -0,0 +1,3 @@ +FROM centos:7 +COPY script /usr/bin +RUN ls -al /usr/bin/script \ No newline at end of file diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copy/script b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copy/script new file mode 100644 index 000000000000..c3c3f3f53f62 --- /dev/null +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copy/script @@ -0,0 +1,2 @@ +#!/bin/bash +exit 0 \ No newline at end of file diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copydir/Dockerfile b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copydir/Dockerfile new file mode 100644 index 000000000000..92c53fdf6dad --- /dev/null +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copydir/Dockerfile @@ -0,0 +1,3 @@ +FROM centos:7 +COPY dir /dir +RUN ls -al /dir/file \ No newline at end of file diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copydir/dir/file b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copydir/dir/file new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copyrename/Dockerfile b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copyrename/Dockerfile new file mode 100644 index 000000000000..575bf2cd4de4 --- /dev/null +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copyrename/Dockerfile @@ -0,0 +1,3 @@ +FROM centos:7 +COPY file1 /usr/bin/file2 +RUN ls -al /usr/bin/file2 && ! ls -al /usr/bin/file1 \ No newline at end of file diff --git a/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copyrename/file1 b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copyrename/file1 new file mode 100644 index 000000000000..c3c3f3f53f62 --- /dev/null +++ b/vendor/github.com/openshift/imagebuilder/dockerclient/testdata/copyrename/file1 @@ -0,0 +1,2 @@ +#!/bin/bash +exit 0 \ No newline at end of file diff --git a/vendor/github.com/openshift/service-serving-cert-signer/Dockerfile b/vendor/github.com/openshift/service-serving-cert-signer/Dockerfile new file mode 100644 index 000000000000..6243895c8c2d --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/Dockerfile @@ -0,0 +1,11 @@ +# +# This is the integrated OpenShift Service Serving Cert Signer. It signs serving certificates for use inside the platform. +# +# The standard name for this image is openshift/origin-service-serving-cert-signer +# +FROM openshift/origin-release:golang-1.10 +COPY . /go/src/github.com/openshift/service-serving-cert-signer +RUN cd /go/src/github.com/openshift/service-serving-cert-signer && go build ./cmd/service-serving-cert-signer + +FROM centos:7 +COPY --from=0 /go/src/github.com/openshift/service-serving-cert-signer/service-serving-cert-signer /usr/bin/service-serving-cert-signer diff --git a/vendor/github.com/openshift/service-serving-cert-signer/Makefile b/vendor/github.com/openshift/service-serving-cert-signer/Makefile index b7fba95c867b..4e48a3a570ac 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/Makefile +++ b/vendor/github.com/openshift/service-serving-cert-signer/Makefile @@ -120,6 +120,6 @@ build-rpms: # # Example: # make build-images -build-images: build-rpms +build-images: hack/build-images.sh .PHONY: build-images diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/build-images.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/build-images.sh index c45ebc5884f1..d3eb62c3c3e3 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/build-images.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/build-images.sh @@ -20,6 +20,13 @@ os::util::ensure::gopath_binary_exists imagebuilder os::build::release::check_for_rpms # we need to mount RPMs into the container builds for installation -OS_BUILD_IMAGE_ARGS="${OS_BUILD_IMAGE_ARGS:-} -mount ${OS_OUTPUT_RPMPATH}/:/srv/origin-local-release/" +cat < "${OS_OUTPUT_RPMPATH}/_local.repo" +[origin-local-release] +name = OpenShift Origin Release from Local Source +baseurl = file:///srv/origin-local-release/ +gpgcheck = 0 +enabled = 0 +END +OS_BUILD_IMAGE_ARGS="${OS_BUILD_IMAGE_ARGS:-} -mount ${OS_OUTPUT_RPMPATH}/:/srv/origin-local-release/ -mount ${OS_OUTPUT_RPMPATH}/_local.repo:/etc/yum.repos.d/origin-local-release.repo" os::build::images \ No newline at end of file diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/constants.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/constants.sh index f615360b83d4..6f74078ac614 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/constants.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/constants.sh @@ -146,5 +146,5 @@ readonly OS_ALL_IMAGES=( # os::build::images builds all images in this repo. function os::build::images() { tag_prefix="${OS_IMAGE_PREFIX:-"openshift/origin"}" - os::build::image "${tag_prefix}-service-serving-cert-signer" images/service-serving-cert-signer + os::build::image "${tag_prefix}-service-serving-cert-signer" . } \ No newline at end of file diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/test/junit.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/test/junit.sh index 21026f89faff..45cdf4b9104b 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/test/junit.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/test/junit.sh @@ -143,62 +143,3 @@ function os::test::junit::reconcile_output() { done } readonly -f os::test::junit::reconcile_output - -# os::test::junit::generate_report determines which type of report is to -# be generated and does so from the raw output of the tests. -# -# Globals: -# - JUNIT_REPORT_OUTPUT -# - ARTIFACT_DIR -# Arguments: -# None -# Returns: -# None -function os::test::junit::generate_report() { - if [[ -z "${JUNIT_REPORT_OUTPUT:-}" || - -n "${JUNIT_REPORT_OUTPUT:-}" && ! -s "${JUNIT_REPORT_OUTPUT:-}" ]]; then - # we can't generate a report - return - fi - - if grep -q "=== END TEST CASE ===" "${JUNIT_REPORT_OUTPUT}"; then - os::test::junit::reconcile_output - os::test::junit::check_test_counters - os::test::junit::internal::generate_report "oscmd" - else - os::test::junit::internal::generate_report "gotest" - fi -} - -# os::test::junit::internal::generate_report generats an XML jUnit -# report for either `os::cmd` or `go test`, based on the passed -# argument. If the `junitreport` binary is not present, it will be built. -# -# Globals: -# - JUNIT_REPORT_OUTPUT -# - ARTIFACT_DIR -# Arguments: -# - 1: specify which type of tests command output should junitreport read -# Returns: -# export JUNIT_REPORT_NUM_FAILED -function os::test::junit::internal::generate_report() { - local report_type="$1" - os::util::ensure::built_binary_exists 'junitreport' - - local report_file - report_file="$( mktemp "${ARTIFACT_DIR}/${report_type}_report_XXXXX" ).xml" - os::log::info "jUnit XML report placed at $( os::util::repository_relative_path ${report_file} )" - junitreport --type "${report_type}" \ - --suites nested \ - --roots github.com/openshift/origin \ - --output "${report_file}" \ - <"${JUNIT_REPORT_OUTPUT}" - - local summary - summary=$( junitreport summarize <"${report_file}" ) - - JUNIT_REPORT_NUM_FAILED="$( grep -oE "[0-9]+ failed" <<<"${summary}" )" - export JUNIT_REPORT_NUM_FAILED - - echo "${summary}" -} \ No newline at end of file diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/util/golang.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/util/golang.sh index 3bbb1ebf48b0..2ae80ce24e30 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/util/golang.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/lib/util/golang.sh @@ -1,22 +1,3 @@ #!/bin/bash # # This library holds golang related utility functions. - -# os::golang::verify_go_version ensure the go tool exists and is a viable version. -function os::golang::verify_go_version() { - os::util::ensure::system_binary_exists 'go' - - local go_version - go_version=($(go version)) - if [[ "${go_version[2]}" != go1.8* ]]; then - os::log::info "Detected go version: ${go_version[*]}." - if [[ -z "${PERMISSIVE_GO:-}" ]]; then - os::log::fatal "Please install Go version ${OS_REQUIRED_GO_VERSION} or use PERMISSIVE_GO=y to bypass this check." - else - os::log::warning "Detected golang version doesn't match required Go version." - os::log::warning "This version mismatch could lead to differences in execution between this run and the CI systems." - return 0 - fi - fi -} -readonly -f os::golang::verify_go_version diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/test-go.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/test-go.sh index 61743037de29..08d1731aa261 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/test-go.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/test-go.sh @@ -21,14 +21,6 @@ function cleanup() { return_code=$? - os::test::junit::generate_report - if [[ "${JUNIT_REPORT_NUM_FAILED:-}" == "0 failed" ]]; then - if [[ "${return_code}" -ne "0" ]]; then - os::log::warning "While the jUnit report found no failed tests, the \`go test\` process failed." - os::log::warning "This usually means that the unit test suite failed to compile." - fi - fi - os::util::describe_return_code "${return_code}" exit "${return_code}" } @@ -135,11 +127,15 @@ if [[ -n "${junit_report}" ]]; then # we don't care if the `go test` fails in this pipe, as we want to generate the report and summarize the output anyway set +o pipefail - go test -i ${gotest_flags} ${test_packages} - go test ${gotest_flags} ${test_packages} 2>"${test_error_file}" | tee "${JUNIT_REPORT_OUTPUT}" + os::util::ensure::built_binary_exists 'gotest2junit' + report_file="$( mktemp "${ARTIFACT_DIR}/unit_report_XXXXX" ).xml" + go test -json ${gotest_flags} ${test_packages} 2>"${test_error_file}" | tee "${JUNIT_REPORT_OUTPUT}" | gotest2junit > "${report_file}" test_return_code="${PIPESTATUS[0]}" + gzip "${test_error_file}" -c > "${ARTIFACT_DIR}/unit-error.log.gz" + gzip "${JUNIT_REPORT_OUTPUT}" -c > "${ARTIFACT_DIR}/unit.log.gz" + set -o pipefail if [[ -s "${test_error_file}" ]]; then @@ -162,7 +158,6 @@ $( cat "${test_error_file}") " elif [[ -n "${coverage_output_dir}" ]]; then # we need to generate coverage reports - go test -i ${gotest_flags} ${test_packages} for test_package in ${test_packages}; do mkdir -p "${coverage_output_dir}/${test_package}" local_gotest_flags="${gotest_flags} -coverprofile=${coverage_output_dir}/${test_package}/profile.out" @@ -187,6 +182,5 @@ elif [[ -n "${dlv_debug}" ]]; then dlv test ${test_packages} else # we need to generate neither jUnit XML nor coverage reports - go test -i ${gotest_flags} ${test_packages} go test ${gotest_flags} ${test_packages} fi diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-gofmt.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-gofmt.sh index 95d477f61014..3ff24e84c394 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-gofmt.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-gofmt.sh @@ -8,8 +8,6 @@ function cleanup() { } trap "cleanup" EXIT -os::golang::verify_go_version - bad_files=$(os::util::list_go_src_files | xargs gofmt -s -l) if [[ -n "${bad_files}" ]]; then os::log::warning "!!! gofmt needs to be run on the listed files" diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-golint.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-golint.sh index 3c7ba6e27cb7..c61e20d83228 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-golint.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-golint.sh @@ -1,7 +1,6 @@ #!/bin/bash source "$(dirname "${BASH_SOURCE}")/lib/init.sh" -os::golang::verify_go_version os::util::ensure::system_binary_exists 'golint' arg="${1:-""}" diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-govet.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-govet.sh index c8cee8e9be51..f1746cdf3f10 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-govet.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-govet.sh @@ -8,8 +8,6 @@ function cleanup() { } trap "cleanup" EXIT -os::golang::verify_go_version - govet_blacklist=( "${OS_GOVET_BLACKLIST[@]-}" ) function govet_blacklist_contains() { diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-imports.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-imports.sh index 6e00177feac1..a5c510499343 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-imports.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-imports.sh @@ -6,7 +6,6 @@ source "$(dirname "${BASH_SOURCE}")/lib/init.sh" function cleanup() { return_code=$? - os::test::junit::generate_report os::util::describe_return_code "${return_code}" exit "${return_code}" } diff --git a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-upstream-commits.sh b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-upstream-commits.sh index d3c2f988b21e..b5fc0aa4cb81 100755 --- a/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-upstream-commits.sh +++ b/vendor/github.com/openshift/service-serving-cert-signer/hack/verify-upstream-commits.sh @@ -3,7 +3,6 @@ source "$(dirname "${BASH_SOURCE}")/lib/init.sh" function cleanup() { return_code=$? - os::test::junit::generate_report os::util::describe_return_code "${return_code}" exit "${return_code}" } diff --git a/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/.cccp.yml b/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/.cccp.yml deleted file mode 100644 index f555da819426..000000000000 --- a/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/.cccp.yml +++ /dev/null @@ -1 +0,0 @@ -job-id: origin-service-serving-cert-signer diff --git a/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/Dockerfile b/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/Dockerfile deleted file mode 100644 index c6c50457d76a..000000000000 --- a/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -# -# This is the integrated OpenShift Service Serving Cert Signer. It signs serving certificates for use inside the platform. -# -# The standard name for this image is openshift/origin-service-serving-cert-signer -# -FROM openshift/origin-base - -RUN INSTALL_PKGS="origin-service-serving-cert-signer" && \ - yum --enablerepo=origin-local-release install -y ${INSTALL_PKGS} && \ - rpm -V ${INSTALL_PKGS} && \ - yum clean all - -LABEL io.k8s.display-name="OpenShift Service Serving Cert Signer" \ - io.k8s.description="This is a component of OpenShift that signs serving certificates for use inside the platform." \ - io.openshift.tags="openshift" - -# The process doesn't require a root user. -USER 1001 - -CMD /usr/bin/service-serving-cert-signer diff --git a/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/bin/.gitignore b/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/bin/.gitignore deleted file mode 100644 index d6b7ef32c847..000000000000 --- a/vendor/github.com/openshift/service-serving-cert-signer/images/service-serving-cert-signer/bin/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge.go new file mode 100644 index 000000000000..952373d25acb --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge.go @@ -0,0 +1,91 @@ +package operator + +import ( + "github.com/golang/glog" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + kyaml "k8s.io/apimachinery/pkg/util/yaml" +) + +func mergeProcessConfig(defaultConfigYAML, userConfigYAML []byte, specialCases map[string]mergeFunc) ([]byte, error) { + defaultConfigJSON, err := kyaml.ToJSON(defaultConfigYAML) + if err != nil { + return nil, err + } + defaultConfigObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, defaultConfigJSON) + if err != nil { + return nil, err + } + defaultConfig := defaultConfigObj.(*unstructured.Unstructured) + + if len(userConfigYAML) > 0 { + userConfigJSON, err := kyaml.ToJSON(userConfigYAML) + if err != nil { + glog.Warning(err) + // maybe it's just yaml + userConfigJSON = userConfigYAML + } + userConfigObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, userConfigJSON) + if err != nil { + return nil, err + } + userConfig := userConfigObj.(*unstructured.Unstructured) + if err := mergeConfig(defaultConfig.Object, userConfig.Object, "", specialCases); err != nil { + return nil, err + } + } + + configBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, defaultConfig) + if err != nil { + return nil, err + } + return configBytes, nil +} + +type mergeFunc func(dst, src interface{}, currentPath string) (interface{}, error) + +// mergeConfig overwrites entries in curr by additional. It modifies curr. +func mergeConfig(curr, additional map[string]interface{}, currentPath string, specialCases map[string]mergeFunc) error { + for additionalKey, additionalVal := range additional { + fullKey := currentPath + "." + additionalKey + specialCase, ok := specialCases[fullKey] + if ok { + var err error + curr[additionalKey], err = specialCase(curr[additionalKey], additionalVal, currentPath) + if err != nil { + return err + } + continue + } + + currVal, ok := curr[additionalKey] + if !ok { + curr[additionalKey] = additionalVal + continue + } + + // only some scalars are accepted + switch castVal := additionalVal.(type) { + case map[string]interface{}: + currValAsMap, ok := currVal.(map[string]interface{}) + if !ok { + currValAsMap = map[string]interface{}{} + curr[additionalKey] = currValAsMap + } + + err := mergeConfig(currValAsMap, castVal, fullKey, specialCases) + if err != nil { + return err + } + continue + + default: + if err := unstructured.SetNestedField(curr, castVal, additionalKey); err != nil { + return err + } + } + + } + + return nil +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge_test.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge_test.go new file mode 100644 index 000000000000..c2a200c66ae5 --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/merge_test.go @@ -0,0 +1,122 @@ +package operator + +import ( + "reflect" + "strings" + "testing" + + "k8s.io/apimachinery/pkg/util/diff" +) + +func TestMergeConfig(t *testing.T) { + tests := []struct { + name string + curr map[string]interface{} + additional map[string]interface{} + specialCases map[string]mergeFunc + + expected map[string]interface{} + expectedErr string + }{ + { + name: "add non-conflicting", + curr: map[string]interface{}{ + "alpha": "first", + "bravo": map[string]interface{}{ + "apple": "one", + }, + }, + additional: map[string]interface{}{ + "bravo": map[string]interface{}{ + "banana": "two", + "cake": map[string]interface{}{ + "armadillo": "uno", + }, + }, + "charlie": "third", + }, + + expected: map[string]interface{}{ + "alpha": "first", + "bravo": map[string]interface{}{ + "apple": "one", + "banana": "two", + "cake": map[string]interface{}{ + "armadillo": "uno", + }, + }, + "charlie": "third", + }, + }, + { + name: "add conflicting, replace type", + curr: map[string]interface{}{ + "alpha": "first", + "bravo": map[string]interface{}{ + "apple": "one", + }, + }, + additional: map[string]interface{}{ + "bravo": map[string]interface{}{ + "apple": map[string]interface{}{ + "armadillo": "uno", + }, + }, + }, + + expected: map[string]interface{}{ + "alpha": "first", + "bravo": map[string]interface{}{ + "apple": map[string]interface{}{ + "armadillo": "uno", + }, + }, + }, + }, + { + name: "nil out", + curr: map[string]interface{}{ + "alpha": "first", + }, + additional: map[string]interface{}{ + "alpha": nil, + }, + + expected: map[string]interface{}{ + "alpha": nil, + }, + }, + { + name: "force empty", + curr: map[string]interface{}{ + "alpha": "first", + }, + additional: map[string]interface{}{ + "alpha": "", + }, + + expected: map[string]interface{}{ + "alpha": "", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + err := mergeConfig(test.curr, test.additional, "", test.specialCases) + switch { + case err == nil && len(test.expectedErr) == 0: + case err == nil && len(test.expectedErr) != 0: + t.Fatalf("missing %q", test.expectedErr) + case err != nil && len(test.expectedErr) == 0: + t.Fatal(err) + case err != nil && len(test.expectedErr) != 0 && !strings.Contains(err.Error(), test.expectedErr): + t.Fatalf("expected %q, got %q", test.expectedErr, err) + } + + if !reflect.DeepEqual(test.expected, test.curr) { + t.Error(diff.ObjectDiff(test.expected, test.curr)) + } + }) + } +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_v310_00.go b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_v310_00.go index a27bfdb717f8..eb2477821a2d 100644 --- a/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_v310_00.go +++ b/vendor/github.com/openshift/service-serving-cert-signer/pkg/operator/sync_v310_00.go @@ -9,8 +9,6 @@ import ( corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" operatorsv1alpha1 "github.com/openshift/api/operator/v1alpha1" scsv1alpha1 "github.com/openshift/api/servicecertsigner/v1alpha1" @@ -41,6 +39,9 @@ func sync_v310_00_to_latest(c ServiceCertSignerOperator, operatorConfig *scsv1al if signingVersionAvailability.ReadyReplicas > 0 && apiServiceInjectorVersionAvailability.ReadyReplicas > 0 { mergedVersionAvailability.ReadyReplicas = 1 } + for _, err := range allErrors { + mergedVersionAvailability.Errors = append(mergedVersionAvailability.Errors, err.Error()) + } return mergedVersionAvailability, allErrors } @@ -213,12 +214,7 @@ func manageSigningSecret(c ServiceCertSignerOperator) (*corev1.Secret, bool, err } func ensureServingSignerConfigMap_v310_00_to_latest(c ServiceCertSignerOperator, options scsv1alpha1.ServiceCertSignerOperatorConfigSpec) (*corev1.ConfigMap, bool, error) { - // TODO use an unstructured object to merge configs - config, err := readServiceServingCertSignerConfig(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/defaultconfig.yaml")) - if err != nil { - return nil, false, err - } - configBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, config) + configBytes, err := mergeProcessConfig(v310_00_assets.MustAsset("v3.10.0/service-serving-cert-signer-controller/defaultconfig.yaml"), options.ServiceServingCertSignerConfig.Raw, nil) if err != nil { return nil, false, err } @@ -251,12 +247,7 @@ func serviceServingCertSignerName() string { } func ensureAPIServiceInjectorConfigMap_v310_00_to_latest(c ServiceCertSignerOperator, options scsv1alpha1.ServiceCertSignerOperatorConfigSpec) (*corev1.ConfigMap, bool, error) { - // TODO use an unstructured object to merge configs - config, err := readServiceServingCertSignerConfig(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/defaultconfig.yaml")) - if err != nil { - return nil, false, err - } - configBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, config) + configBytes, err := mergeProcessConfig(v310_00_assets.MustAsset("v3.10.0/apiservice-cabundle-controller/defaultconfig.yaml"), options.APIServiceCABundleInjectorConfig.Raw, nil) if err != nil { return nil, false, err } diff --git a/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/gotest2junit.go b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/gotest2junit.go new file mode 100644 index 000000000000..026d43698836 --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/gotest2junit.go @@ -0,0 +1,211 @@ +package main + +import ( + "bufio" + "encoding/json" + "encoding/xml" + "flag" + "fmt" + "io" + "os" + "sort" + "strings" + "time" + + "github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api" +) + +type Record struct { + Package string + Test string + + Time time.Time + Action string + Output string + Elapsed float64 +} + +type testSuite struct { + suite *api.TestSuite + tests map[string]*api.TestCase +} + +func main() { + summarize := false + verbose := false + flag.BoolVar(&summarize, "summary", true, "display a summary as items are processed") + flag.BoolVar(&verbose, "v", false, "display passing results") + flag.Parse() + + if err := process(os.Stdin, summarize, verbose); err != nil { + fmt.Fprintf(os.Stderr, "error: %v\n", err) + os.Exit(1) + } +} + +func process(r io.Reader, summarize, verbose bool) error { + suites, err := stream(r, summarize, verbose) + if err != nil { + return err + } + obj := newTestSuites(suites) + out, err := xml.MarshalIndent(obj, "", " ") + if err != nil { + return err + } + fmt.Fprintf(os.Stdout, "%s\n", string(out)) + return nil +} + +func newTestSuites(suites map[string]*testSuite) *api.TestSuites { + all := &api.TestSuites{} + for _, suite := range suites { + for _, test := range suite.suite.TestCases { + suite.suite.NumTests++ + if test.SkipMessage != nil { + suite.suite.NumSkipped++ + continue + } + if test.FailureOutput != nil { + suite.suite.NumFailed++ + continue + } + } + // suites with no tests are usually empty packages, ignore them + if suite.suite.NumTests == 0 { + continue + } + // always return the test cases in consistent order + sort.Slice(suite.suite.TestCases, func(i, j int) bool { + return suite.suite.TestCases[i].Name < suite.suite.TestCases[j].Name + }) + all.Suites = append(all.Suites, suite.suite) + } + // always return the test suites in consistent order + sort.Slice(all.Suites, func(i, j int) bool { + return all.Suites[i].Name < all.Suites[j].Name + }) + return all +} + +func stream(r io.Reader, summarize, verbose bool) (map[string]*testSuite, error) { + suites := make(map[string]*testSuite) + defaultTest := &api.TestCase{ + Name: "build and execution", + } + defaultSuite := &testSuite{ + suite: &api.TestSuite{Name: "go test", TestCases: []*api.TestCase{defaultTest}}, + } + suites[""] = defaultSuite + + rdr := bufio.NewReader(r) + for { + // some output from go test -json is not valid JSON - read the line to see whether it + // starts with { - if not, just mirror it to stderr and continue. + line, err := rdr.ReadString('\n') + if err != nil { + if err != io.EOF { + return suites, err + } + break + } + if len(line) == 0 || line[0] != '{' { + defaultTest.SystemOut += line + if strings.HasPrefix(line, "FAIL") { + defaultTest.FailureOutput = &api.FailureOutput{} + } + fmt.Fprint(os.Stderr, line) + continue + } + var r Record + if err := json.Unmarshal([]byte(line), &r); err != nil { + if err == io.EOF { + return suites, nil + } + fmt.Fprintf(os.Stderr, "error: Unable to parse remainder of output %v\n", err) + return suites, nil + } + + suite, ok := suites[r.Package] + if !ok { + suite = &testSuite{ + suite: &api.TestSuite{ + Name: r.Package, + }, + tests: make(map[string]*api.TestCase), + } + suites[r.Package] = suite + } + + // if this is package level output, we only care about pass/fail duration + if len(r.Test) == 0 { + switch r.Action { + case "pass", "fail": + suite.suite.Duration = r.Elapsed + } + continue + } + + test, ok := suite.tests[r.Test] + if !ok { + test = &api.TestCase{ + Name: r.Test, + } + suite.suite.TestCases = append(suite.suite.TestCases, test) + suite.tests[r.Test] = test + } + + switch r.Action { + case "run": + case "pause": + case "cont": + case "bench": + case "skip": + if summarize { + fmt.Fprintf(os.Stderr, "SKIP: %s %s\n", r.Package, r.Test) + } + test.SkipMessage = &api.SkipMessage{ + Message: r.Output, + } + case "pass": + if summarize && verbose { + fmt.Fprintf(os.Stderr, "PASS: %s %s %s\n", r.Package, r.Test, time.Duration(r.Elapsed*float64(time.Second))) + } + test.SystemOut = "" + test.Duration = r.Elapsed + case "fail": + if summarize { + fmt.Fprintf(os.Stderr, "FAIL: %s %s %s\n", r.Package, r.Test, time.Duration(r.Elapsed*float64(time.Second))) + } + test.Duration = r.Elapsed + if len(r.Output) == 0 { + r.Output = test.SystemOut + if len(r.Output) > 50 { + r.Output = r.Output[:50] + " ..." + } + } + test.FailureOutput = &api.FailureOutput{ + Message: r.Output, + Output: r.Output, + } + case "output": + test.SystemOut += r.Output + default: + // usually a bug in go test -json + out := fmt.Sprintf("error: Unrecognized go test action %s: %#v\n", r.Action, r) + defaultTest.SystemOut += line + defaultTest.SystemOut += out + defaultTest.FailureOutput = &api.FailureOutput{} + fmt.Fprintf(os.Stderr, out) + } + } + + // if we recorded any failure output + if defaultTest.FailureOutput != nil { + defaultTest.FailureOutput.Message = "Some packages failed during test execution" + defaultTest.FailureOutput.Output = defaultTest.SystemOut + defaultTest.SystemOut = "" + } + + return suites, nil +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/junit.xsd b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/junit.xsd new file mode 100644 index 000000000000..92552b33db5d --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/junit.xsd @@ -0,0 +1,203 @@ + + + + JUnit test result schema for the Apache Ant JUnit and JUnitReport tasks +Copyright © 2011, Windy Road Technology Pty. Limited +The Apache Ant JUnit XML Schema is distributed under the terms of the GNU Lesser General Public License (LGPL) http://www.gnu.org/licenses/lgpl.html +Permission to waive conditions of this license may be requested from Windy Road Support (http://windyroad.org/support). + + + + + + + + + + Contains an aggregation of testsuite results + + + + + + + + + + Derived from testsuite/@name in the non-aggregated documents + + + + + Starts at '0' for the first testsuite and is incremented by 1 for each following testsuite + + + + + + + + + + + + Contains the results of exexuting a testsuite + + + + + Properties (e.g., environment settings) set during test execution + + + + + + + + + + + + + + + + + + + + + + + + Indicates that the test errored. An errored test is one that had an unanticipated problem. e.g., an unchecked throwable; or a problem with the implementation of the test. Contains as a text node relevant data for the error, e.g., a stack trace + + + + + + + The error message. e.g., if a java exception is thrown, the return value of getMessage() + + + + + The type of error that occured. e.g., if a java execption is thrown the full class name of the exception. + + + + + + + + + Indicates that the test failed. A failure is a test which the code has explicitly failed by using the mechanisms for that purpose. e.g., via an assertEquals. Contains as a text node relevant data for the failure, e.g., a stack trace + + + + + + + The message specified in the assert + + + + + The type of the assert. + + + + + + + + + + Name of the test method + + + + + Full class name for the class the test method is in. + + + + + Time taken (in seconds) to execute the test + + + + + + + Data that was written to standard out while the test was executed + + + + + + + + + + Data that was written to standard error while the test was executed + + + + + + + + + + + Full class name of the test for non-aggregated testsuite documents. Class name without the package for aggregated testsuites documents + + + + + + + + + + when the test was executed. Timezone may not be specified. + + + + + Host on which the tests were executed. 'localhost' should be used if the hostname cannot be determined. + + + + + + + + + + The total number of tests in the suite + + + + + The total number of tests in the suite that failed. A failure is a test which the code has explicitly failed by using the mechanisms for that purpose. e.g., via an assertEquals + + + + + The total number of tests in the suite that errorrd. An errored test is one that had an unanticipated problem. e.g., an unchecked throwable; or a problem with the implementation of the test. + + + + + Time taken (in seconds) to execute the tests in the suite + + + + + + + + + \ No newline at end of file diff --git a/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/string.go b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/string.go new file mode 100644 index 000000000000..be8e650f4af5 --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/string.go @@ -0,0 +1,37 @@ +package api + +import "fmt" + +// This file implements Stringer for the API types for ease of debugging + +func (t *TestSuites) String() string { + return fmt.Sprintf("Test Suites with suites: %s.", t.Suites) +} + +func (t *TestSuite) String() string { + childDescriptions := []string{} + for _, child := range t.Children { + childDescriptions = append(childDescriptions, child.String()) + } + return fmt.Sprintf("Test Suite %q with properties: %s, %d test cases, of which %d failed and %d were skipped: %s, and children: %s.", t.Name, t.Properties, t.NumTests, t.NumFailed, t.NumSkipped, t.TestCases, childDescriptions) +} + +func (t *TestCase) String() string { + var result, message, output string + result = "passed" + if t.SkipMessage != nil { + result = "skipped" + message = t.SkipMessage.Message + } + if t.FailureOutput != nil { + result = "failed" + message = t.FailureOutput.Message + output = t.FailureOutput.Output + } + + return fmt.Sprintf("Test Case %q %s after %f seconds with message %q and output %q.", t.Name, result, t.Duration, message, output) +} + +func (p *TestSuiteProperty) String() string { + return fmt.Sprintf("%q=%q", p.Name, p.Value) +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/test_case.go b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/test_case.go new file mode 100644 index 000000000000..ec83e2dddde3 --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/test_case.go @@ -0,0 +1,30 @@ +package api + +import "time" + +// SetDuration sets the runtime duration of the test case +func (t *TestCase) SetDuration(duration string) error { + parsedDuration, err := time.ParseDuration(duration) + if err != nil { + return err + } + + // we round to the millisecond on duration + t.Duration = float64(int(parsedDuration.Seconds()*1000)) / 1000 + return nil +} + +// MarkSkipped marks the test as skipped with the given message +func (t *TestCase) MarkSkipped(message string) { + t.SkipMessage = &SkipMessage{ + Message: message, + } +} + +// MarkFailed marks the test as failed with the given message and output +func (t *TestCase) MarkFailed(message, output string) { + t.FailureOutput = &FailureOutput{ + Message: message, + Output: output, + } +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/test_suite.go b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/test_suite.go new file mode 100644 index 000000000000..1e36d06ca33a --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/test_suite.go @@ -0,0 +1,67 @@ +package api + +import "time" + +// AddProperty adds a property to the test suite, deduplicating multiple additions of the same property +// by overwriting the previous record to reflect the new values +func (t *TestSuite) AddProperty(name, value string) { + for _, property := range t.Properties { + if property.Name == name { + property.Value = value + return + } + } + + t.Properties = append(t.Properties, &TestSuiteProperty{Name: name, Value: value}) +} + +// AddTestCase adds a test case to the test suite and updates test suite metrics as necessary +func (t *TestSuite) AddTestCase(testCase *TestCase) { + t.NumTests += 1 + + switch { + case testCase.SkipMessage != nil: + t.NumSkipped += 1 + case testCase.FailureOutput != nil: + t.NumFailed += 1 + default: + // we do not preserve output on tests that are not failures or skips + testCase.SystemOut = "" + testCase.SystemErr = "" + } + + t.Duration += testCase.Duration + // we round to the millisecond on duration + t.Duration = float64(int(t.Duration*1000)) / 1000 + + t.TestCases = append(t.TestCases, testCase) +} + +// SetDuration sets the duration of the test suite if this value is not calculated by aggregating the durations +// of all of the substituent test cases. This should *not* be used if the total duration of the test suite is +// calculated as that sum, as AddTestCase will handle that case. +func (t *TestSuite) SetDuration(duration string) error { + parsedDuration, err := time.ParseDuration(duration) + if err != nil { + return err + } + + // we round to the millisecond on duration + t.Duration = float64(int(parsedDuration.Seconds()*1000)) / 1000 + return nil +} + +// ByName implements sort.Interface for []*TestSuite based on the Name field +type ByName []*TestSuite + +func (n ByName) Len() int { + return len(n) +} + +func (n ByName) Swap(i, j int) { + n[i], n[j] = n[j], n[i] +} + +func (n ByName) Less(i, j int) bool { + return n[i].Name < n[j].Name +} diff --git a/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/types.go b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/types.go new file mode 100644 index 000000000000..58339044c589 --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/pkg/api/types.go @@ -0,0 +1,108 @@ +package api + +import "encoding/xml" + +// The below types are directly marshalled into XML. The types correspond to jUnit +// XML schema, but do not contain all valid fields. For instance, the class name +// field for test cases is omitted, as this concept does not directly apply to Go. +// For XML specifications see http://help.catchsoftware.com/display/ET/JUnit+Format +// or view the XSD included in this package as 'junit.xsd' + +// TestSuites represents a flat collection of jUnit test suites. +type TestSuites struct { + XMLName xml.Name `xml:"testsuites"` + + // Suites are the jUnit test suites held in this collection + Suites []*TestSuite `xml:"testsuite"` +} + +// TestSuite represents a single jUnit test suite, potentially holding child suites. +type TestSuite struct { + XMLName xml.Name `xml:"testsuite"` + + // Name is the name of the test suite + Name string `xml:"name,attr"` + + // NumTests records the number of tests in the TestSuite + NumTests uint `xml:"tests,attr"` + + // NumSkipped records the number of skipped tests in the suite + NumSkipped uint `xml:"skipped,attr"` + + // NumFailed records the number of failed tests in the suite + NumFailed uint `xml:"failures,attr"` + + // Duration is the time taken in seconds to run all tests in the suite + Duration float64 `xml:"time,attr"` + + // Properties holds other properties of the test suite as a mapping of name to value + Properties []*TestSuiteProperty `xml:"properties,omitempty"` + + // TestCases are the test cases contained in the test suite + TestCases []*TestCase `xml:"testcase"` + + // Children holds nested test suites + Children []*TestSuite `xml:"testsuite"` +} + +// TestSuiteProperty contains a mapping of a property name to a value +type TestSuiteProperty struct { + XMLName xml.Name `xml:"property"` + + Name string `xml:"name,attr"` + Value string `xml:"value,attr"` +} + +// TestCase represents a jUnit test case +type TestCase struct { + XMLName xml.Name `xml:"testcase"` + + // Name is the name of the test case + Name string `xml:"name,attr"` + + // Classname is an attribute set by the package type and is required + Classname string `xml:"classname,attr,omitempty"` + + // Duration is the time taken in seconds to run the test + Duration float64 `xml:"time,attr"` + + // SkipMessage holds the reason why the test was skipped + SkipMessage *SkipMessage `xml:"skipped"` + + // FailureOutput holds the output from a failing test + FailureOutput *FailureOutput `xml:"failure"` + + // SystemOut is output written to stdout during the execution of this test case + SystemOut string `xml:"system-out,omitempty"` + + // SystemErr is output written to stderr during the execution of this test case + SystemErr string `xml:"system-err,omitempty"` +} + +// SkipMessage holds a message explaining why a test was skipped +type SkipMessage struct { + XMLName xml.Name `xml:"skipped"` + + // Message explains why the test was skipped + Message string `xml:"message,attr,omitempty"` +} + +// FailureOutput holds the output from a failing test +type FailureOutput struct { + XMLName xml.Name `xml:"failure"` + + // Message holds the failure message from the test + Message string `xml:"message,attr"` + + // Output holds verbose failure output from the test + Output string `xml:",chardata"` +} + +// TestResult is the result of a test case +type TestResult string + +const ( + TestResultPass TestResult = "pass" + TestResultSkip TestResult = "skip" + TestResultFail TestResult = "fail" +) diff --git a/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/test/test_test.go b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/test/test_test.go new file mode 100644 index 000000000000..21f4695e8a4f --- /dev/null +++ b/vendor/github.com/openshift/service-serving-cert-signer/tools/gotest2junit/test/test_test.go @@ -0,0 +1,18 @@ +// +build output + +package test + +import ( + "testing" +) + +func TestFoo(t *testing.T) { + t.Run("panic", func(t *testing.T) { + panic("here") + }) + t.Run("pass", func(t *testing.T) { + }) + t.Run("skip", func(t *testing.T) { + t.Skip("skipped") + }) +}