From 1d6e6cf21915dc4f51ea4150f3a0d3c89b672e74 Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Wed, 23 Oct 2019 15:46:23 +0530 Subject: [PATCH 1/5] Vendors serving v0.9.0 --- go.mod | 4 +- go.sum | 8 +- vendor/go.uber.org/atomic/.codecov.yml | 15 + vendor/go.uber.org/atomic/.gitignore | 11 + vendor/go.uber.org/atomic/.travis.yml | 27 + vendor/go.uber.org/atomic/LICENSE.txt | 19 + vendor/go.uber.org/atomic/Makefile | 51 ++ vendor/go.uber.org/atomic/README.md | 36 ++ vendor/go.uber.org/atomic/atomic.go | 351 ++++++++++++ vendor/go.uber.org/atomic/error.go | 55 ++ vendor/go.uber.org/atomic/glide.lock | 17 + vendor/go.uber.org/atomic/glide.yaml | 6 + vendor/go.uber.org/atomic/string.go | 49 ++ vendor/go.uber.org/multierr/.codecov.yml | 15 + vendor/go.uber.org/multierr/.gitignore | 1 + vendor/go.uber.org/multierr/.travis.yml | 33 ++ vendor/go.uber.org/multierr/CHANGELOG.md | 35 ++ vendor/go.uber.org/multierr/LICENSE.txt | 19 + vendor/go.uber.org/multierr/Makefile | 74 +++ vendor/go.uber.org/multierr/README.md | 23 + vendor/go.uber.org/multierr/error.go | 399 +++++++++++++ vendor/go.uber.org/multierr/glide.lock | 19 + vendor/go.uber.org/multierr/glide.yaml | 8 + vendor/go.uber.org/multierr/go113.go | 52 ++ vendor/go.uber.org/zap/.codecov.yml | 17 + vendor/go.uber.org/zap/.gitignore | 28 + vendor/go.uber.org/zap/.readme.tmpl | 108 ++++ vendor/go.uber.org/zap/.travis.yml | 21 + vendor/go.uber.org/zap/CHANGELOG.md | 327 +++++++++++ vendor/go.uber.org/zap/CODE_OF_CONDUCT.md | 75 +++ vendor/go.uber.org/zap/CONTRIBUTING.md | 81 +++ vendor/go.uber.org/zap/FAQ.md | 155 ++++++ vendor/go.uber.org/zap/LICENSE.txt | 19 + vendor/go.uber.org/zap/Makefile | 76 +++ vendor/go.uber.org/zap/README.md | 136 +++++ vendor/go.uber.org/zap/array.go | 320 +++++++++++ vendor/go.uber.org/zap/buffer/buffer.go | 115 ++++ vendor/go.uber.org/zap/buffer/pool.go | 49 ++ vendor/go.uber.org/zap/check_license.sh | 17 + vendor/go.uber.org/zap/config.go | 243 ++++++++ vendor/go.uber.org/zap/doc.go | 113 ++++ vendor/go.uber.org/zap/encoder.go | 75 +++ vendor/go.uber.org/zap/error.go | 80 +++ vendor/go.uber.org/zap/field.go | 310 +++++++++++ vendor/go.uber.org/zap/flag.go | 39 ++ vendor/go.uber.org/zap/glide.lock | 76 +++ vendor/go.uber.org/zap/glide.yaml | 35 ++ vendor/go.uber.org/zap/global.go | 168 ++++++ vendor/go.uber.org/zap/global_go112.go | 26 + vendor/go.uber.org/zap/global_prego112.go | 26 + vendor/go.uber.org/zap/http_handler.go | 81 +++ .../zap/internal/bufferpool/bufferpool.go | 31 ++ .../go.uber.org/zap/internal/color/color.go | 44 ++ vendor/go.uber.org/zap/internal/exit/exit.go | 64 +++ vendor/go.uber.org/zap/level.go | 132 +++++ vendor/go.uber.org/zap/logger.go | 305 ++++++++++ vendor/go.uber.org/zap/options.go | 109 ++++ vendor/go.uber.org/zap/sink.go | 161 ++++++ vendor/go.uber.org/zap/stacktrace.go | 126 +++++ vendor/go.uber.org/zap/sugar.go | 304 ++++++++++ vendor/go.uber.org/zap/time.go | 27 + vendor/go.uber.org/zap/writer.go | 99 ++++ .../zap/zapcore/console_encoder.go | 147 +++++ vendor/go.uber.org/zap/zapcore/core.go | 113 ++++ vendor/go.uber.org/zap/zapcore/doc.go | 24 + vendor/go.uber.org/zap/zapcore/encoder.go | 348 ++++++++++++ vendor/go.uber.org/zap/zapcore/entry.go | 257 +++++++++ vendor/go.uber.org/zap/zapcore/error.go | 120 ++++ vendor/go.uber.org/zap/zapcore/field.go | 212 +++++++ vendor/go.uber.org/zap/zapcore/hook.go | 68 +++ .../go.uber.org/zap/zapcore/json_encoder.go | 505 +++++++++++++++++ vendor/go.uber.org/zap/zapcore/level.go | 175 ++++++ .../go.uber.org/zap/zapcore/level_strings.go | 46 ++ vendor/go.uber.org/zap/zapcore/marshaler.go | 53 ++ .../go.uber.org/zap/zapcore/memory_encoder.go | 179 ++++++ vendor/go.uber.org/zap/zapcore/sampler.go | 134 +++++ vendor/go.uber.org/zap/zapcore/tee.go | 81 +++ .../go.uber.org/zap/zapcore/write_syncer.go | 123 ++++ .../knative.dev/pkg/apis/condition_types.go | 2 +- vendor/knative.dev/pkg/apis/duck/patch.go | 13 + .../pkg/apis/duck/v1/addressable_types.go | 114 ++++ vendor/knative.dev/pkg/apis/duck/v1/doc.go | 23 + .../knative.dev/pkg/apis/duck/v1/register.go | 55 ++ .../pkg/apis/duck/v1/source_types.go | 157 ++++++ .../pkg/apis/duck/v1/status_types.go | 141 +++++ .../pkg/apis/duck/v1/zz_generated.deepcopy.go | 361 ++++++++++++ .../apis/duck/v1alpha1/addressable_types.go | 42 +- .../apis/duck/v1alpha1/conditions_types.go | 2 +- .../duck/v1alpha1/zz_generated.deepcopy.go | 8 +- .../apis/duck/v1beta1/addressable_types.go | 34 +- .../duck/v1beta1/zz_generated.deepcopy.go | 6 +- vendor/knative.dev/pkg/apis/field_error.go | 13 +- vendor/knative.dev/pkg/apis/url.go | 42 +- .../pkg/apis/v1alpha1/destination.go | 122 +--- .../apis/v1alpha1/zz_generated.deepcopy.go | 9 +- vendor/knative.dev/pkg/configmap/filter.go | 32 +- .../pkg/configmap/informed_watcher.go | 35 +- .../pkg/configmap/manual_watcher.go | 10 +- .../pkg/configmap/static_watcher.go | 13 +- vendor/knative.dev/pkg/configmap/store.go | 16 +- vendor/knative.dev/pkg/configmap/watcher.go | 8 +- vendor/knative.dev/pkg/kmeta/accessor.go | 51 +- vendor/knative.dev/pkg/network/OWNERS | 4 + vendor/knative.dev/pkg/network/doc.go | 19 + .../{serving => }/pkg/network/domain.go | 0 .../apis/autoscaling/annotation_validation.go | 28 +- .../serving/pkg/apis/autoscaling/register.go | 4 + .../autoscaling/v1alpha1/metric_lifecycle.go | 47 ++ .../apis/autoscaling/v1alpha1/metric_types.go | 5 +- .../apis/autoscaling/v1alpha1/pa_lifecycle.go | 49 +- .../pkg/apis/autoscaling/v1alpha1/pa_types.go | 36 +- .../autoscaling/v1alpha1/pa_validation.go | 39 +- .../v1alpha1/zz_generated.deepcopy.go | 13 +- .../serving/pkg/apis/config/defaults.go | 17 + .../serving/pkg/apis/networking/register.go | 11 + .../v1alpha1/certificate_lifecycle.go | 13 +- .../networking/v1alpha1/certificate_types.go | 4 +- .../networking/v1alpha1/ingress_lifecycle.go | 9 +- .../apis/networking/v1alpha1/ingress_types.go | 4 +- .../v1alpha1/serverlessservice_lifecycle.go | 4 +- .../v1alpha1/serverlessservice_types.go | 4 +- .../serving/pkg/apis/serving/k8s_lifecycle.go | 78 +++ .../pkg/apis/serving/k8s_validation.go | 31 +- .../pkg/apis/serving/metadata_validation.go | 44 +- .../serving/pkg/apis/serving/register.go | 3 + .../serving/v1/configuration_conversion.go | 34 ++ .../apis/serving/v1/configuration_defaults.go | 34 ++ .../serving/v1/configuration_lifecycle.go | 35 ++ .../apis/serving/v1/configuration_types.go | 102 ++++ .../serving/v1/configuration_validation.go | 93 ++++ .../apis/serving/{v1beta1 => v1}/contexts.go | 6 +- .../serving/pkg/apis/serving/v1/doc.go | 21 + .../serving/pkg/apis/serving/v1/register.go | 61 ++ .../apis/serving/v1/revision_conversion.go | 34 ++ .../pkg/apis/serving/v1/revision_defaults.go | 102 ++++ .../pkg/apis/serving/v1/revision_lifecycle.go | 55 ++ .../pkg/apis/serving/v1/revision_types.go | 125 +++++ .../apis/serving/v1/revision_validation.go | 144 +++++ .../pkg/apis/serving/v1/route_conversion.go | 34 ++ .../pkg/apis/serving/v1/route_defaults.go | 50 ++ .../pkg/apis/serving/v1/route_lifecycle.go | 35 ++ .../pkg/apis/serving/v1/route_types.go | 159 ++++++ .../pkg/apis/serving/v1/route_validation.go | 211 +++++++ .../pkg/apis/serving/v1/service_conversion.go | 34 ++ .../pkg/apis/serving/v1/service_defaults.go | 57 ++ .../pkg/apis/serving/v1/service_lifecycle.go | 35 ++ .../pkg/apis/serving/v1/service_types.go | 113 ++++ .../pkg/apis/serving/v1/service_validation.go | 79 +++ .../apis/serving/v1/zz_generated.deepcopy.go | 526 ++++++++++++++++++ .../v1alpha1/configuration_conversion.go | 25 +- .../v1alpha1/configuration_defaults.go | 10 +- .../v1alpha1/configuration_lifecycle.go | 4 +- .../serving/v1alpha1/configuration_types.go | 6 +- .../serving/v1alpha1/revision_conversion.go | 18 +- .../serving/v1alpha1/revision_defaults.go | 18 +- .../serving/v1alpha1/revision_lifecycle.go | 72 ++- .../apis/serving/v1alpha1/revision_types.go | 10 +- .../serving/v1alpha1/revision_validation.go | 4 +- .../apis/serving/v1alpha1/route_conversion.go | 32 +- .../apis/serving/v1alpha1/route_defaults.go | 16 +- .../apis/serving/v1alpha1/route_lifecycle.go | 4 +- .../pkg/apis/serving/v1alpha1/route_types.go | 14 +- .../apis/serving/v1alpha1/route_validation.go | 8 +- .../serving/v1alpha1/service_conversion.go | 51 +- .../apis/serving/v1alpha1/service_defaults.go | 12 +- .../serving/v1alpha1/service_lifecycle.go | 4 +- .../apis/serving/v1alpha1/service_types.go | 4 +- .../serving/v1alpha1/service_validation.go | 4 +- .../serving/v1beta1/configuration_defaults.go | 5 - .../v1beta1/configuration_lifecycle.go | 13 +- .../serving/v1beta1/configuration_types.go | 35 +- .../v1beta1/configuration_validation.go | 19 +- .../pkg/apis/serving/v1beta1/register.go | 3 - .../apis/serving/v1beta1/revision_defaults.go | 71 --- .../serving/v1beta1/revision_lifecycle.go | 5 - .../apis/serving/v1beta1/revision_types.go | 68 +-- .../serving/v1beta1/revision_validation.go | 85 +-- .../apis/serving/v1beta1/route_defaults.go | 23 - .../apis/serving/v1beta1/route_lifecycle.go | 13 +- .../pkg/apis/serving/v1beta1/route_types.go | 83 +-- .../apis/serving/v1beta1/route_validation.go | 163 +----- .../apis/serving/v1beta1/service_defaults.go | 6 - .../apis/serving/v1beta1/service_lifecycle.go | 13 +- .../pkg/apis/serving/v1beta1/service_types.go | 37 +- .../serving/v1beta1/service_validation.go | 18 +- .../serving/v1beta1/zz_generated.deepcopy.go | 247 -------- .../clientset/versioned/scheme/register.go | 2 + .../serving/pkg/network/error_handler.go | 43 ++ .../serving/pkg/network/network.go | 4 + .../serving/pkg/network/probe_handler.go | 52 ++ .../serving/pkg/network/transports.go | 8 +- .../pkg/reconciler/route/config/domain.go | 2 +- vendor/modules.txt | 24 +- 193 files changed, 12142 insertions(+), 1300 deletions(-) create mode 100644 vendor/go.uber.org/atomic/.codecov.yml create mode 100644 vendor/go.uber.org/atomic/.gitignore create mode 100644 vendor/go.uber.org/atomic/.travis.yml create mode 100644 vendor/go.uber.org/atomic/LICENSE.txt create mode 100644 vendor/go.uber.org/atomic/Makefile create mode 100644 vendor/go.uber.org/atomic/README.md create mode 100644 vendor/go.uber.org/atomic/atomic.go create mode 100644 vendor/go.uber.org/atomic/error.go create mode 100644 vendor/go.uber.org/atomic/glide.lock create mode 100644 vendor/go.uber.org/atomic/glide.yaml create mode 100644 vendor/go.uber.org/atomic/string.go create mode 100644 vendor/go.uber.org/multierr/.codecov.yml create mode 100644 vendor/go.uber.org/multierr/.gitignore create mode 100644 vendor/go.uber.org/multierr/.travis.yml create mode 100644 vendor/go.uber.org/multierr/CHANGELOG.md create mode 100644 vendor/go.uber.org/multierr/LICENSE.txt create mode 100644 vendor/go.uber.org/multierr/Makefile create mode 100644 vendor/go.uber.org/multierr/README.md create mode 100644 vendor/go.uber.org/multierr/error.go create mode 100644 vendor/go.uber.org/multierr/glide.lock create mode 100644 vendor/go.uber.org/multierr/glide.yaml create mode 100644 vendor/go.uber.org/multierr/go113.go create mode 100644 vendor/go.uber.org/zap/.codecov.yml create mode 100644 vendor/go.uber.org/zap/.gitignore create mode 100644 vendor/go.uber.org/zap/.readme.tmpl create mode 100644 vendor/go.uber.org/zap/.travis.yml create mode 100644 vendor/go.uber.org/zap/CHANGELOG.md create mode 100644 vendor/go.uber.org/zap/CODE_OF_CONDUCT.md create mode 100644 vendor/go.uber.org/zap/CONTRIBUTING.md create mode 100644 vendor/go.uber.org/zap/FAQ.md create mode 100644 vendor/go.uber.org/zap/LICENSE.txt create mode 100644 vendor/go.uber.org/zap/Makefile create mode 100644 vendor/go.uber.org/zap/README.md create mode 100644 vendor/go.uber.org/zap/array.go create mode 100644 vendor/go.uber.org/zap/buffer/buffer.go create mode 100644 vendor/go.uber.org/zap/buffer/pool.go create mode 100644 vendor/go.uber.org/zap/check_license.sh create mode 100644 vendor/go.uber.org/zap/config.go create mode 100644 vendor/go.uber.org/zap/doc.go create mode 100644 vendor/go.uber.org/zap/encoder.go create mode 100644 vendor/go.uber.org/zap/error.go create mode 100644 vendor/go.uber.org/zap/field.go create mode 100644 vendor/go.uber.org/zap/flag.go create mode 100644 vendor/go.uber.org/zap/glide.lock create mode 100644 vendor/go.uber.org/zap/glide.yaml create mode 100644 vendor/go.uber.org/zap/global.go create mode 100644 vendor/go.uber.org/zap/global_go112.go create mode 100644 vendor/go.uber.org/zap/global_prego112.go create mode 100644 vendor/go.uber.org/zap/http_handler.go create mode 100644 vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go create mode 100644 vendor/go.uber.org/zap/internal/color/color.go create mode 100644 vendor/go.uber.org/zap/internal/exit/exit.go create mode 100644 vendor/go.uber.org/zap/level.go create mode 100644 vendor/go.uber.org/zap/logger.go create mode 100644 vendor/go.uber.org/zap/options.go create mode 100644 vendor/go.uber.org/zap/sink.go create mode 100644 vendor/go.uber.org/zap/stacktrace.go create mode 100644 vendor/go.uber.org/zap/sugar.go create mode 100644 vendor/go.uber.org/zap/time.go create mode 100644 vendor/go.uber.org/zap/writer.go create mode 100644 vendor/go.uber.org/zap/zapcore/console_encoder.go create mode 100644 vendor/go.uber.org/zap/zapcore/core.go create mode 100644 vendor/go.uber.org/zap/zapcore/doc.go create mode 100644 vendor/go.uber.org/zap/zapcore/encoder.go create mode 100644 vendor/go.uber.org/zap/zapcore/entry.go create mode 100644 vendor/go.uber.org/zap/zapcore/error.go create mode 100644 vendor/go.uber.org/zap/zapcore/field.go create mode 100644 vendor/go.uber.org/zap/zapcore/hook.go create mode 100644 vendor/go.uber.org/zap/zapcore/json_encoder.go create mode 100644 vendor/go.uber.org/zap/zapcore/level.go create mode 100644 vendor/go.uber.org/zap/zapcore/level_strings.go create mode 100644 vendor/go.uber.org/zap/zapcore/marshaler.go create mode 100644 vendor/go.uber.org/zap/zapcore/memory_encoder.go create mode 100644 vendor/go.uber.org/zap/zapcore/sampler.go create mode 100644 vendor/go.uber.org/zap/zapcore/tee.go create mode 100644 vendor/go.uber.org/zap/zapcore/write_syncer.go create mode 100644 vendor/knative.dev/pkg/apis/duck/v1/addressable_types.go create mode 100644 vendor/knative.dev/pkg/apis/duck/v1/doc.go create mode 100644 vendor/knative.dev/pkg/apis/duck/v1/register.go create mode 100644 vendor/knative.dev/pkg/apis/duck/v1/source_types.go create mode 100644 vendor/knative.dev/pkg/apis/duck/v1/status_types.go create mode 100644 vendor/knative.dev/pkg/apis/duck/v1/zz_generated.deepcopy.go create mode 100644 vendor/knative.dev/pkg/network/OWNERS create mode 100644 vendor/knative.dev/pkg/network/doc.go rename vendor/knative.dev/{serving => }/pkg/network/domain.go (100%) create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/k8s_lifecycle.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_conversion.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_defaults.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_lifecycle.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_types.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_validation.go rename vendor/knative.dev/serving/pkg/apis/serving/{v1beta1 => v1}/contexts.go (96%) create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/doc.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/register.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/revision_conversion.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/revision_defaults.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/revision_lifecycle.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/revision_types.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/revision_validation.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/route_conversion.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/route_defaults.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/route_lifecycle.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/route_types.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/route_validation.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/service_conversion.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/service_defaults.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/service_lifecycle.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/service_types.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/service_validation.go create mode 100644 vendor/knative.dev/serving/pkg/apis/serving/v1/zz_generated.deepcopy.go create mode 100644 vendor/knative.dev/serving/pkg/network/error_handler.go create mode 100644 vendor/knative.dev/serving/pkg/network/probe_handler.go diff --git a/go.mod b/go.mod index b1b526a839..dd6ec451fe 100644 --- a/go.mod +++ b/go.mod @@ -44,8 +44,8 @@ require ( k8s.io/cli-runtime v0.0.0-20190325194458-f2b4781c3ae1 k8s.io/client-go v0.0.0-20190226174127-78295b709ec6 k8s.io/kube-openapi v0.0.0-20190722073852-5e22f3d471e6 // indirect - knative.dev/pkg v0.0.0-20190815170108-426561fd098d - knative.dev/serving v0.8.0 + knative.dev/pkg v0.0.0-20191022181926-0b19b4ad9139 + knative.dev/serving v0.9.0 knative.dev/test-infra v0.0.0-20190730202142-17f2331e80ad sigs.k8s.io/yaml v1.1.0 ) diff --git a/go.sum b/go.sum index 6acfdeec87..69a1d86938 100644 --- a/go.sum +++ b/go.sum @@ -181,10 +181,10 @@ k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8 k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/kube-openapi v0.0.0-20190722073852-5e22f3d471e6 h1:s9IxTKe9GwDH0S/WaX62nFYr0or32DsTWex9AileL7U= k8s.io/kube-openapi v0.0.0-20190722073852-5e22f3d471e6/go.mod h1:RZvgC8MSN6DjiMV6oIfEE9pDL9CYXokkfaCKZeHm3nc= -knative.dev/pkg v0.0.0-20190815170108-426561fd098d h1:lU2PpEszinc2Xazu456C/hlRALzzGK8uT92HxO4FGzQ= -knative.dev/pkg v0.0.0-20190815170108-426561fd098d/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q= -knative.dev/serving v0.8.0 h1:4SHZgkUnABOnEfvU86TCgVNi/twvekTUNr76ObC4ovA= -knative.dev/serving v0.8.0/go.mod h1:x2n255JS2XBI39tmjZ8CwTxIf9EKNMCrkVuiOttLRm0= +knative.dev/pkg v0.0.0-20191022181926-0b19b4ad9139 h1:wUapryP4MZmajUymSs5i3rL5Xh+SoZAqw/M5aFf0wvA= +knative.dev/pkg v0.0.0-20191022181926-0b19b4ad9139/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q= +knative.dev/serving v0.9.0 h1:GVnsksAEX6vMXGygvzsGPIrFTypiesaseK7emm0LKWQ= +knative.dev/serving v0.9.0/go.mod h1:x2n255JS2XBI39tmjZ8CwTxIf9EKNMCrkVuiOttLRm0= knative.dev/test-infra v0.0.0-20190730202142-17f2331e80ad h1:pXN0DA06tXwn4vgzIqJ13rf4U412rS+fRRww1JWJ+o4= knative.dev/test-infra v0.0.0-20190730202142-17f2331e80ad/go.mod h1:xcdUkMJrLlBswIZqL5zCuBFOC22WIPMQoVX1L35i0vQ= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= diff --git a/vendor/go.uber.org/atomic/.codecov.yml b/vendor/go.uber.org/atomic/.codecov.yml new file mode 100644 index 0000000000..6d4d1be7b5 --- /dev/null +++ b/vendor/go.uber.org/atomic/.codecov.yml @@ -0,0 +1,15 @@ +coverage: + range: 80..100 + round: down + precision: 2 + + status: + project: # measuring the overall project coverage + default: # context, you can create multiple ones with custom titles + enabled: yes # must be yes|true to enable this status + target: 100 # specify the target coverage for each commit status + # option: "auto" (must increase from parent commit or pull request base) + # option: "X%" a static target percentage to hit + if_not_found: success # if parent is not found report status as success, error, or failure + if_ci_failed: error # if ci fails report status as success, error, or failure + diff --git a/vendor/go.uber.org/atomic/.gitignore b/vendor/go.uber.org/atomic/.gitignore new file mode 100644 index 0000000000..0a4504f110 --- /dev/null +++ b/vendor/go.uber.org/atomic/.gitignore @@ -0,0 +1,11 @@ +.DS_Store +/vendor +/cover +cover.out +lint.log + +# Binaries +*.test + +# Profiling output +*.prof diff --git a/vendor/go.uber.org/atomic/.travis.yml b/vendor/go.uber.org/atomic/.travis.yml new file mode 100644 index 0000000000..0f3769e5fa --- /dev/null +++ b/vendor/go.uber.org/atomic/.travis.yml @@ -0,0 +1,27 @@ +sudo: false +language: go +go_import_path: go.uber.org/atomic + +go: + - 1.11.x + - 1.12.x + +matrix: + include: + - go: 1.12.x + env: NO_TEST=yes LINT=yes + +cache: + directories: + - vendor + +install: + - make install_ci + +script: + - test -n "$NO_TEST" || make test_ci + - test -n "$NO_TEST" || scripts/test-ubergo.sh + - test -z "$LINT" || make install_lint lint + +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/go.uber.org/atomic/LICENSE.txt b/vendor/go.uber.org/atomic/LICENSE.txt new file mode 100644 index 0000000000..8765c9fbc6 --- /dev/null +++ b/vendor/go.uber.org/atomic/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2016 Uber Technologies, Inc. + +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/go.uber.org/atomic/Makefile b/vendor/go.uber.org/atomic/Makefile new file mode 100644 index 0000000000..1ef263075d --- /dev/null +++ b/vendor/go.uber.org/atomic/Makefile @@ -0,0 +1,51 @@ +# Many Go tools take file globs or directories as arguments instead of packages. +PACKAGE_FILES ?= *.go + +# For pre go1.6 +export GO15VENDOREXPERIMENT=1 + + +.PHONY: build +build: + go build -i ./... + + +.PHONY: install +install: + glide --version || go get github.com/Masterminds/glide + glide install + + +.PHONY: test +test: + go test -cover -race ./... + + +.PHONY: install_ci +install_ci: install + go get github.com/wadey/gocovmerge + go get github.com/mattn/goveralls + go get golang.org/x/tools/cmd/cover + +.PHONY: install_lint +install_lint: + go get golang.org/x/lint/golint + + +.PHONY: lint +lint: + @rm -rf lint.log + @echo "Checking formatting..." + @gofmt -d -s $(PACKAGE_FILES) 2>&1 | tee lint.log + @echo "Checking vet..." + @go vet ./... 2>&1 | tee -a lint.log;) + @echo "Checking lint..." + @golint $$(go list ./...) 2>&1 | tee -a lint.log + @echo "Checking for unresolved FIXMEs..." + @git grep -i fixme | grep -v -e vendor -e Makefile | tee -a lint.log + @[ ! -s lint.log ] + + +.PHONY: test_ci +test_ci: install_ci build + ./scripts/cover.sh $(shell go list $(PACKAGES)) diff --git a/vendor/go.uber.org/atomic/README.md b/vendor/go.uber.org/atomic/README.md new file mode 100644 index 0000000000..62eb8e5760 --- /dev/null +++ b/vendor/go.uber.org/atomic/README.md @@ -0,0 +1,36 @@ +# atomic [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] [![Go Report Card][reportcard-img]][reportcard] + +Simple wrappers for primitive types to enforce atomic access. + +## Installation +`go get -u go.uber.org/atomic` + +## Usage +The standard library's `sync/atomic` is powerful, but it's easy to forget which +variables must be accessed atomically. `go.uber.org/atomic` preserves all the +functionality of the standard library, but wraps the primitive types to +provide a safer, more convenient API. + +```go +var atom atomic.Uint32 +atom.Store(42) +atom.Sub(2) +atom.CAS(40, 11) +``` + +See the [documentation][doc] for a complete API specification. + +## Development Status +Stable. + +___ +Released under the [MIT License](LICENSE.txt). + +[doc-img]: https://godoc.org/github.com/uber-go/atomic?status.svg +[doc]: https://godoc.org/go.uber.org/atomic +[ci-img]: https://travis-ci.com/uber-go/atomic.svg?branch=master +[ci]: https://travis-ci.com/uber-go/atomic +[cov-img]: https://codecov.io/gh/uber-go/atomic/branch/master/graph/badge.svg +[cov]: https://codecov.io/gh/uber-go/atomic +[reportcard-img]: https://goreportcard.com/badge/go.uber.org/atomic +[reportcard]: https://goreportcard.com/report/go.uber.org/atomic diff --git a/vendor/go.uber.org/atomic/atomic.go b/vendor/go.uber.org/atomic/atomic.go new file mode 100644 index 0000000000..1db6849fca --- /dev/null +++ b/vendor/go.uber.org/atomic/atomic.go @@ -0,0 +1,351 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +// Package atomic provides simple wrappers around numerics to enforce atomic +// access. +package atomic + +import ( + "math" + "sync/atomic" + "time" +) + +// Int32 is an atomic wrapper around an int32. +type Int32 struct{ v int32 } + +// NewInt32 creates an Int32. +func NewInt32(i int32) *Int32 { + return &Int32{i} +} + +// Load atomically loads the wrapped value. +func (i *Int32) Load() int32 { + return atomic.LoadInt32(&i.v) +} + +// Add atomically adds to the wrapped int32 and returns the new value. +func (i *Int32) Add(n int32) int32 { + return atomic.AddInt32(&i.v, n) +} + +// Sub atomically subtracts from the wrapped int32 and returns the new value. +func (i *Int32) Sub(n int32) int32 { + return atomic.AddInt32(&i.v, -n) +} + +// Inc atomically increments the wrapped int32 and returns the new value. +func (i *Int32) Inc() int32 { + return i.Add(1) +} + +// Dec atomically decrements the wrapped int32 and returns the new value. +func (i *Int32) Dec() int32 { + return i.Sub(1) +} + +// CAS is an atomic compare-and-swap. +func (i *Int32) CAS(old, new int32) bool { + return atomic.CompareAndSwapInt32(&i.v, old, new) +} + +// Store atomically stores the passed value. +func (i *Int32) Store(n int32) { + atomic.StoreInt32(&i.v, n) +} + +// Swap atomically swaps the wrapped int32 and returns the old value. +func (i *Int32) Swap(n int32) int32 { + return atomic.SwapInt32(&i.v, n) +} + +// Int64 is an atomic wrapper around an int64. +type Int64 struct{ v int64 } + +// NewInt64 creates an Int64. +func NewInt64(i int64) *Int64 { + return &Int64{i} +} + +// Load atomically loads the wrapped value. +func (i *Int64) Load() int64 { + return atomic.LoadInt64(&i.v) +} + +// Add atomically adds to the wrapped int64 and returns the new value. +func (i *Int64) Add(n int64) int64 { + return atomic.AddInt64(&i.v, n) +} + +// Sub atomically subtracts from the wrapped int64 and returns the new value. +func (i *Int64) Sub(n int64) int64 { + return atomic.AddInt64(&i.v, -n) +} + +// Inc atomically increments the wrapped int64 and returns the new value. +func (i *Int64) Inc() int64 { + return i.Add(1) +} + +// Dec atomically decrements the wrapped int64 and returns the new value. +func (i *Int64) Dec() int64 { + return i.Sub(1) +} + +// CAS is an atomic compare-and-swap. +func (i *Int64) CAS(old, new int64) bool { + return atomic.CompareAndSwapInt64(&i.v, old, new) +} + +// Store atomically stores the passed value. +func (i *Int64) Store(n int64) { + atomic.StoreInt64(&i.v, n) +} + +// Swap atomically swaps the wrapped int64 and returns the old value. +func (i *Int64) Swap(n int64) int64 { + return atomic.SwapInt64(&i.v, n) +} + +// Uint32 is an atomic wrapper around an uint32. +type Uint32 struct{ v uint32 } + +// NewUint32 creates a Uint32. +func NewUint32(i uint32) *Uint32 { + return &Uint32{i} +} + +// Load atomically loads the wrapped value. +func (i *Uint32) Load() uint32 { + return atomic.LoadUint32(&i.v) +} + +// Add atomically adds to the wrapped uint32 and returns the new value. +func (i *Uint32) Add(n uint32) uint32 { + return atomic.AddUint32(&i.v, n) +} + +// Sub atomically subtracts from the wrapped uint32 and returns the new value. +func (i *Uint32) Sub(n uint32) uint32 { + return atomic.AddUint32(&i.v, ^(n - 1)) +} + +// Inc atomically increments the wrapped uint32 and returns the new value. +func (i *Uint32) Inc() uint32 { + return i.Add(1) +} + +// Dec atomically decrements the wrapped int32 and returns the new value. +func (i *Uint32) Dec() uint32 { + return i.Sub(1) +} + +// CAS is an atomic compare-and-swap. +func (i *Uint32) CAS(old, new uint32) bool { + return atomic.CompareAndSwapUint32(&i.v, old, new) +} + +// Store atomically stores the passed value. +func (i *Uint32) Store(n uint32) { + atomic.StoreUint32(&i.v, n) +} + +// Swap atomically swaps the wrapped uint32 and returns the old value. +func (i *Uint32) Swap(n uint32) uint32 { + return atomic.SwapUint32(&i.v, n) +} + +// Uint64 is an atomic wrapper around a uint64. +type Uint64 struct{ v uint64 } + +// NewUint64 creates a Uint64. +func NewUint64(i uint64) *Uint64 { + return &Uint64{i} +} + +// Load atomically loads the wrapped value. +func (i *Uint64) Load() uint64 { + return atomic.LoadUint64(&i.v) +} + +// Add atomically adds to the wrapped uint64 and returns the new value. +func (i *Uint64) Add(n uint64) uint64 { + return atomic.AddUint64(&i.v, n) +} + +// Sub atomically subtracts from the wrapped uint64 and returns the new value. +func (i *Uint64) Sub(n uint64) uint64 { + return atomic.AddUint64(&i.v, ^(n - 1)) +} + +// Inc atomically increments the wrapped uint64 and returns the new value. +func (i *Uint64) Inc() uint64 { + return i.Add(1) +} + +// Dec atomically decrements the wrapped uint64 and returns the new value. +func (i *Uint64) Dec() uint64 { + return i.Sub(1) +} + +// CAS is an atomic compare-and-swap. +func (i *Uint64) CAS(old, new uint64) bool { + return atomic.CompareAndSwapUint64(&i.v, old, new) +} + +// Store atomically stores the passed value. +func (i *Uint64) Store(n uint64) { + atomic.StoreUint64(&i.v, n) +} + +// Swap atomically swaps the wrapped uint64 and returns the old value. +func (i *Uint64) Swap(n uint64) uint64 { + return atomic.SwapUint64(&i.v, n) +} + +// Bool is an atomic Boolean. +type Bool struct{ v uint32 } + +// NewBool creates a Bool. +func NewBool(initial bool) *Bool { + return &Bool{boolToInt(initial)} +} + +// Load atomically loads the Boolean. +func (b *Bool) Load() bool { + return truthy(atomic.LoadUint32(&b.v)) +} + +// CAS is an atomic compare-and-swap. +func (b *Bool) CAS(old, new bool) bool { + return atomic.CompareAndSwapUint32(&b.v, boolToInt(old), boolToInt(new)) +} + +// Store atomically stores the passed value. +func (b *Bool) Store(new bool) { + atomic.StoreUint32(&b.v, boolToInt(new)) +} + +// Swap sets the given value and returns the previous value. +func (b *Bool) Swap(new bool) bool { + return truthy(atomic.SwapUint32(&b.v, boolToInt(new))) +} + +// Toggle atomically negates the Boolean and returns the previous value. +func (b *Bool) Toggle() bool { + return truthy(atomic.AddUint32(&b.v, 1) - 1) +} + +func truthy(n uint32) bool { + return n&1 == 1 +} + +func boolToInt(b bool) uint32 { + if b { + return 1 + } + return 0 +} + +// Float64 is an atomic wrapper around float64. +type Float64 struct { + v uint64 +} + +// NewFloat64 creates a Float64. +func NewFloat64(f float64) *Float64 { + return &Float64{math.Float64bits(f)} +} + +// Load atomically loads the wrapped value. +func (f *Float64) Load() float64 { + return math.Float64frombits(atomic.LoadUint64(&f.v)) +} + +// Store atomically stores the passed value. +func (f *Float64) Store(s float64) { + atomic.StoreUint64(&f.v, math.Float64bits(s)) +} + +// Add atomically adds to the wrapped float64 and returns the new value. +func (f *Float64) Add(s float64) float64 { + for { + old := f.Load() + new := old + s + if f.CAS(old, new) { + return new + } + } +} + +// Sub atomically subtracts from the wrapped float64 and returns the new value. +func (f *Float64) Sub(s float64) float64 { + return f.Add(-s) +} + +// CAS is an atomic compare-and-swap. +func (f *Float64) CAS(old, new float64) bool { + return atomic.CompareAndSwapUint64(&f.v, math.Float64bits(old), math.Float64bits(new)) +} + +// Duration is an atomic wrapper around time.Duration +// https://godoc.org/time#Duration +type Duration struct { + v Int64 +} + +// NewDuration creates a Duration. +func NewDuration(d time.Duration) *Duration { + return &Duration{v: *NewInt64(int64(d))} +} + +// Load atomically loads the wrapped value. +func (d *Duration) Load() time.Duration { + return time.Duration(d.v.Load()) +} + +// Store atomically stores the passed value. +func (d *Duration) Store(n time.Duration) { + d.v.Store(int64(n)) +} + +// Add atomically adds to the wrapped time.Duration and returns the new value. +func (d *Duration) Add(n time.Duration) time.Duration { + return time.Duration(d.v.Add(int64(n))) +} + +// Sub atomically subtracts from the wrapped time.Duration and returns the new value. +func (d *Duration) Sub(n time.Duration) time.Duration { + return time.Duration(d.v.Sub(int64(n))) +} + +// Swap atomically swaps the wrapped time.Duration and returns the old value. +func (d *Duration) Swap(n time.Duration) time.Duration { + return time.Duration(d.v.Swap(int64(n))) +} + +// CAS is an atomic compare-and-swap. +func (d *Duration) CAS(old, new time.Duration) bool { + return d.v.CAS(int64(old), int64(new)) +} + +// Value shadows the type of the same name from sync/atomic +// https://godoc.org/sync/atomic#Value +type Value struct{ atomic.Value } diff --git a/vendor/go.uber.org/atomic/error.go b/vendor/go.uber.org/atomic/error.go new file mode 100644 index 0000000000..0489d19bad --- /dev/null +++ b/vendor/go.uber.org/atomic/error.go @@ -0,0 +1,55 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package atomic + +// Error is an atomic type-safe wrapper around Value for errors +type Error struct{ v Value } + +// errorHolder is non-nil holder for error object. +// atomic.Value panics on saving nil object, so err object needs to be +// wrapped with valid object first. +type errorHolder struct{ err error } + +// NewError creates new atomic error object +func NewError(err error) *Error { + e := &Error{} + if err != nil { + e.Store(err) + } + return e +} + +// Load atomically loads the wrapped error +func (e *Error) Load() error { + v := e.v.Load() + if v == nil { + return nil + } + + eh := v.(errorHolder) + return eh.err +} + +// Store atomically stores error. +// NOTE: a holder object is allocated on each Store call. +func (e *Error) Store(err error) { + e.v.Store(errorHolder{err: err}) +} diff --git a/vendor/go.uber.org/atomic/glide.lock b/vendor/go.uber.org/atomic/glide.lock new file mode 100644 index 0000000000..3c72c59976 --- /dev/null +++ b/vendor/go.uber.org/atomic/glide.lock @@ -0,0 +1,17 @@ +hash: f14d51408e3e0e4f73b34e4039484c78059cd7fc5f4996fdd73db20dc8d24f53 +updated: 2016-10-27T00:10:51.16960137-07:00 +imports: [] +testImports: +- name: github.com/davecgh/go-spew + version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d + subpackages: + - spew +- name: github.com/pmezard/go-difflib + version: d8ed2627bdf02c080bf22230dbb337003b7aba2d + subpackages: + - difflib +- name: github.com/stretchr/testify + version: d77da356e56a7428ad25149ca77381849a6a5232 + subpackages: + - assert + - require diff --git a/vendor/go.uber.org/atomic/glide.yaml b/vendor/go.uber.org/atomic/glide.yaml new file mode 100644 index 0000000000..4cf608ec0f --- /dev/null +++ b/vendor/go.uber.org/atomic/glide.yaml @@ -0,0 +1,6 @@ +package: go.uber.org/atomic +testImport: +- package: github.com/stretchr/testify + subpackages: + - assert + - require diff --git a/vendor/go.uber.org/atomic/string.go b/vendor/go.uber.org/atomic/string.go new file mode 100644 index 0000000000..ede8136fac --- /dev/null +++ b/vendor/go.uber.org/atomic/string.go @@ -0,0 +1,49 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package atomic + +// String is an atomic type-safe wrapper around Value for strings. +type String struct{ v Value } + +// NewString creates a String. +func NewString(str string) *String { + s := &String{} + if str != "" { + s.Store(str) + } + return s +} + +// Load atomically loads the wrapped string. +func (s *String) Load() string { + v := s.v.Load() + if v == nil { + return "" + } + return v.(string) +} + +// Store atomically stores the passed string. +// Note: Converting the string to an interface{} to store in the Value +// requires an allocation. +func (s *String) Store(str string) { + s.v.Store(str) +} diff --git a/vendor/go.uber.org/multierr/.codecov.yml b/vendor/go.uber.org/multierr/.codecov.yml new file mode 100644 index 0000000000..6d4d1be7b5 --- /dev/null +++ b/vendor/go.uber.org/multierr/.codecov.yml @@ -0,0 +1,15 @@ +coverage: + range: 80..100 + round: down + precision: 2 + + status: + project: # measuring the overall project coverage + default: # context, you can create multiple ones with custom titles + enabled: yes # must be yes|true to enable this status + target: 100 # specify the target coverage for each commit status + # option: "auto" (must increase from parent commit or pull request base) + # option: "X%" a static target percentage to hit + if_not_found: success # if parent is not found report status as success, error, or failure + if_ci_failed: error # if ci fails report status as success, error, or failure + diff --git a/vendor/go.uber.org/multierr/.gitignore b/vendor/go.uber.org/multierr/.gitignore new file mode 100644 index 0000000000..61ead86667 --- /dev/null +++ b/vendor/go.uber.org/multierr/.gitignore @@ -0,0 +1 @@ +/vendor diff --git a/vendor/go.uber.org/multierr/.travis.yml b/vendor/go.uber.org/multierr/.travis.yml new file mode 100644 index 0000000000..a6412b7fed --- /dev/null +++ b/vendor/go.uber.org/multierr/.travis.yml @@ -0,0 +1,33 @@ +sudo: false +language: go +go_import_path: go.uber.org/multierr + +env: + global: + - GO15VENDOREXPERIMENT=1 + +go: + - 1.11.x + - 1.12.x + - 1.13.x + +cache: + directories: + - vendor + +before_install: +- go version + +install: +- | + set -e + make install_ci + +script: +- | + set -e + make lint + make test_ci + +after_success: +- bash <(curl -s https://codecov.io/bash) diff --git a/vendor/go.uber.org/multierr/CHANGELOG.md b/vendor/go.uber.org/multierr/CHANGELOG.md new file mode 100644 index 0000000000..f1b852cf3f --- /dev/null +++ b/vendor/go.uber.org/multierr/CHANGELOG.md @@ -0,0 +1,35 @@ +Releases +======== + +v1.2.0 (2019-09-26) +=================== + +- Support extracting and matching against wrapped errors with `errors.As` + and `errors.Is`. + + +v1.1.0 (2017-06-30) +=================== + +- Added an `Errors(error) []error` function to extract the underlying list of + errors for a multierr error. + + +v1.0.0 (2017-05-31) +=================== + +No changes since v0.2.0. This release is committing to making no breaking +changes to the current API in the 1.X series. + + +v0.2.0 (2017-04-11) +=================== + +- Repeatedly appending to the same error is now faster due to fewer + allocations. + + +v0.1.0 (2017-31-03) +=================== + +- Initial release diff --git a/vendor/go.uber.org/multierr/LICENSE.txt b/vendor/go.uber.org/multierr/LICENSE.txt new file mode 100644 index 0000000000..858e02475f --- /dev/null +++ b/vendor/go.uber.org/multierr/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2017 Uber Technologies, Inc. + +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/go.uber.org/multierr/Makefile b/vendor/go.uber.org/multierr/Makefile new file mode 100644 index 0000000000..b4bf73d8c3 --- /dev/null +++ b/vendor/go.uber.org/multierr/Makefile @@ -0,0 +1,74 @@ +export GO15VENDOREXPERIMENT=1 + +PACKAGES := $(shell glide nv) + +GO_FILES := $(shell \ + find . '(' -path '*/.*' -o -path './vendor' ')' -prune \ + -o -name '*.go' -print | cut -b3-) + +.PHONY: install +install: + glide --version || go get github.com/Masterminds/glide + glide install + +.PHONY: build +build: + go build -i $(PACKAGES) + +.PHONY: test +test: + go test -cover -race $(PACKAGES) + +.PHONY: gofmt +gofmt: + $(eval FMT_LOG := $(shell mktemp -t gofmt.XXXXX)) + @gofmt -e -s -l $(GO_FILES) > $(FMT_LOG) || true + @[ ! -s "$(FMT_LOG)" ] || (echo "gofmt failed:" | cat - $(FMT_LOG) && false) + +.PHONY: govet +govet: + $(eval VET_LOG := $(shell mktemp -t govet.XXXXX)) + @go vet $(PACKAGES) 2>&1 \ + | grep -v '^exit status' > $(VET_LOG) || true + @[ ! -s "$(VET_LOG)" ] || (echo "govet failed:" | cat - $(VET_LOG) && false) + +.PHONY: golint +golint: + @go get golang.org/x/lint/golint + $(eval LINT_LOG := $(shell mktemp -t golint.XXXXX)) + @cat /dev/null > $(LINT_LOG) + @$(foreach pkg, $(PACKAGES), golint $(pkg) >> $(LINT_LOG) || true;) + @[ ! -s "$(LINT_LOG)" ] || (echo "golint failed:" | cat - $(LINT_LOG) && false) + +.PHONY: staticcheck +staticcheck: + @go get honnef.co/go/tools/cmd/staticcheck + $(eval STATICCHECK_LOG := $(shell mktemp -t staticcheck.XXXXX)) + @staticcheck $(PACKAGES) 2>&1 > $(STATICCHECK_LOG) || true + @[ ! -s "$(STATICCHECK_LOG)" ] || (echo "staticcheck failed:" | cat - $(STATICCHECK_LOG) && false) + +.PHONY: lint +lint: gofmt govet golint staticcheck + +.PHONY: cover +cover: + ./scripts/cover.sh $(shell go list $(PACKAGES)) + go tool cover -html=cover.out -o cover.html + +update-license: + @go get go.uber.org/tools/update-license + @update-license \ + $(shell go list -json $(PACKAGES) | \ + jq -r '.Dir + "/" + (.GoFiles | .[])') + +############################################################################## + +.PHONY: install_ci +install_ci: install + go get github.com/wadey/gocovmerge + go get github.com/mattn/goveralls + go get golang.org/x/tools/cmd/cover + +.PHONY: test_ci +test_ci: install_ci + ./scripts/cover.sh $(shell go list $(PACKAGES)) diff --git a/vendor/go.uber.org/multierr/README.md b/vendor/go.uber.org/multierr/README.md new file mode 100644 index 0000000000..751bd65e58 --- /dev/null +++ b/vendor/go.uber.org/multierr/README.md @@ -0,0 +1,23 @@ +# multierr [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] + +`multierr` allows combining one or more Go `error`s together. + +## Installation + + go get -u go.uber.org/multierr + +## Status + +Stable: No breaking changes will be made before 2.0. + +------------------------------------------------------------------------------- + +Released under the [MIT License]. + +[MIT License]: LICENSE.txt +[doc-img]: https://godoc.org/go.uber.org/multierr?status.svg +[doc]: https://godoc.org/go.uber.org/multierr +[ci-img]: https://travis-ci.com/uber-go/multierr.svg?branch=master +[cov-img]: https://codecov.io/gh/uber-go/multierr/branch/master/graph/badge.svg +[ci]: https://travis-ci.com/uber-go/multierr +[cov]: https://codecov.io/gh/uber-go/multierr diff --git a/vendor/go.uber.org/multierr/error.go b/vendor/go.uber.org/multierr/error.go new file mode 100644 index 0000000000..d4be183448 --- /dev/null +++ b/vendor/go.uber.org/multierr/error.go @@ -0,0 +1,399 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +// Package multierr allows combining one or more errors together. +// +// Overview +// +// Errors can be combined with the use of the Combine function. +// +// multierr.Combine( +// reader.Close(), +// writer.Close(), +// conn.Close(), +// ) +// +// If only two errors are being combined, the Append function may be used +// instead. +// +// err = multierr.Append(reader.Close(), writer.Close()) +// +// This makes it possible to record resource cleanup failures from deferred +// blocks with the help of named return values. +// +// func sendRequest(req Request) (err error) { +// conn, err := openConnection() +// if err != nil { +// return err +// } +// defer func() { +// err = multierr.Append(err, conn.Close()) +// }() +// // ... +// } +// +// The underlying list of errors for a returned error object may be retrieved +// with the Errors function. +// +// errors := multierr.Errors(err) +// if len(errors) > 0 { +// fmt.Println("The following errors occurred:") +// } +// +// Advanced Usage +// +// Errors returned by Combine and Append MAY implement the following +// interface. +// +// type errorGroup interface { +// // Returns a slice containing the underlying list of errors. +// // +// // This slice MUST NOT be modified by the caller. +// Errors() []error +// } +// +// Note that if you need access to list of errors behind a multierr error, you +// should prefer using the Errors function. That said, if you need cheap +// read-only access to the underlying errors slice, you can attempt to cast +// the error to this interface. You MUST handle the failure case gracefully +// because errors returned by Combine and Append are not guaranteed to +// implement this interface. +// +// var errors []error +// group, ok := err.(errorGroup) +// if ok { +// errors = group.Errors() +// } else { +// errors = []error{err} +// } +package multierr // import "go.uber.org/multierr" + +import ( + "bytes" + "fmt" + "io" + "strings" + "sync" + + "go.uber.org/atomic" +) + +var ( + // Separator for single-line error messages. + _singlelineSeparator = []byte("; ") + + // Prefix for multi-line messages + _multilinePrefix = []byte("the following errors occurred:") + + // Prefix for the first and following lines of an item in a list of + // multi-line error messages. + // + // For example, if a single item is: + // + // foo + // bar + // + // It will become, + // + // - foo + // bar + _multilineSeparator = []byte("\n - ") + _multilineIndent = []byte(" ") +) + +// _bufferPool is a pool of bytes.Buffers. +var _bufferPool = sync.Pool{ + New: func() interface{} { + return &bytes.Buffer{} + }, +} + +type errorGroup interface { + Errors() []error +} + +// Errors returns a slice containing zero or more errors that the supplied +// error is composed of. If the error is nil, the returned slice is empty. +// +// err := multierr.Append(r.Close(), w.Close()) +// errors := multierr.Errors(err) +// +// If the error is not composed of other errors, the returned slice contains +// just the error that was passed in. +// +// Callers of this function are free to modify the returned slice. +func Errors(err error) []error { + if err == nil { + return nil + } + + // Note that we're casting to multiError, not errorGroup. Our contract is + // that returned errors MAY implement errorGroup. Errors, however, only + // has special behavior for multierr-specific error objects. + // + // This behavior can be expanded in the future but I think it's prudent to + // start with as little as possible in terms of contract and possibility + // of misuse. + eg, ok := err.(*multiError) + if !ok { + return []error{err} + } + + errors := eg.Errors() + result := make([]error, len(errors)) + copy(result, errors) + return result +} + +// multiError is an error that holds one or more errors. +// +// An instance of this is guaranteed to be non-empty and flattened. That is, +// none of the errors inside multiError are other multiErrors. +// +// multiError formats to a semi-colon delimited list of error messages with +// %v and with a more readable multi-line format with %+v. +type multiError struct { + copyNeeded atomic.Bool + errors []error +} + +var _ errorGroup = (*multiError)(nil) + +// Errors returns the list of underlying errors. +// +// This slice MUST NOT be modified. +func (merr *multiError) Errors() []error { + if merr == nil { + return nil + } + return merr.errors +} + +func (merr *multiError) Error() string { + if merr == nil { + return "" + } + + buff := _bufferPool.Get().(*bytes.Buffer) + buff.Reset() + + merr.writeSingleline(buff) + + result := buff.String() + _bufferPool.Put(buff) + return result +} + +func (merr *multiError) Format(f fmt.State, c rune) { + if c == 'v' && f.Flag('+') { + merr.writeMultiline(f) + } else { + merr.writeSingleline(f) + } +} + +func (merr *multiError) writeSingleline(w io.Writer) { + first := true + for _, item := range merr.errors { + if first { + first = false + } else { + w.Write(_singlelineSeparator) + } + io.WriteString(w, item.Error()) + } +} + +func (merr *multiError) writeMultiline(w io.Writer) { + w.Write(_multilinePrefix) + for _, item := range merr.errors { + w.Write(_multilineSeparator) + writePrefixLine(w, _multilineIndent, fmt.Sprintf("%+v", item)) + } +} + +// Writes s to the writer with the given prefix added before each line after +// the first. +func writePrefixLine(w io.Writer, prefix []byte, s string) { + first := true + for len(s) > 0 { + if first { + first = false + } else { + w.Write(prefix) + } + + idx := strings.IndexByte(s, '\n') + if idx < 0 { + idx = len(s) - 1 + } + + io.WriteString(w, s[:idx+1]) + s = s[idx+1:] + } +} + +type inspectResult struct { + // Number of top-level non-nil errors + Count int + + // Total number of errors including multiErrors + Capacity int + + // Index of the first non-nil error in the list. Value is meaningless if + // Count is zero. + FirstErrorIdx int + + // Whether the list contains at least one multiError + ContainsMultiError bool +} + +// Inspects the given slice of errors so that we can efficiently allocate +// space for it. +func inspect(errors []error) (res inspectResult) { + first := true + for i, err := range errors { + if err == nil { + continue + } + + res.Count++ + if first { + first = false + res.FirstErrorIdx = i + } + + if merr, ok := err.(*multiError); ok { + res.Capacity += len(merr.errors) + res.ContainsMultiError = true + } else { + res.Capacity++ + } + } + return +} + +// fromSlice converts the given list of errors into a single error. +func fromSlice(errors []error) error { + res := inspect(errors) + switch res.Count { + case 0: + return nil + case 1: + // only one non-nil entry + return errors[res.FirstErrorIdx] + case len(errors): + if !res.ContainsMultiError { + // already flat + return &multiError{errors: errors} + } + } + + nonNilErrs := make([]error, 0, res.Capacity) + for _, err := range errors[res.FirstErrorIdx:] { + if err == nil { + continue + } + + if nested, ok := err.(*multiError); ok { + nonNilErrs = append(nonNilErrs, nested.errors...) + } else { + nonNilErrs = append(nonNilErrs, err) + } + } + + return &multiError{errors: nonNilErrs} +} + +// Combine combines the passed errors into a single error. +// +// If zero arguments were passed or if all items are nil, a nil error is +// returned. +// +// Combine(nil, nil) // == nil +// +// If only a single error was passed, it is returned as-is. +// +// Combine(err) // == err +// +// Combine skips over nil arguments so this function may be used to combine +// together errors from operations that fail independently of each other. +// +// multierr.Combine( +// reader.Close(), +// writer.Close(), +// pipe.Close(), +// ) +// +// If any of the passed errors is a multierr error, it will be flattened along +// with the other errors. +// +// multierr.Combine(multierr.Combine(err1, err2), err3) +// // is the same as +// multierr.Combine(err1, err2, err3) +// +// The returned error formats into a readable multi-line error message if +// formatted with %+v. +// +// fmt.Sprintf("%+v", multierr.Combine(err1, err2)) +func Combine(errors ...error) error { + return fromSlice(errors) +} + +// Append appends the given errors together. Either value may be nil. +// +// This function is a specialization of Combine for the common case where +// there are only two errors. +// +// err = multierr.Append(reader.Close(), writer.Close()) +// +// The following pattern may also be used to record failure of deferred +// operations without losing information about the original error. +// +// func doSomething(..) (err error) { +// f := acquireResource() +// defer func() { +// err = multierr.Append(err, f.Close()) +// }() +func Append(left error, right error) error { + switch { + case left == nil: + return right + case right == nil: + return left + } + + if _, ok := right.(*multiError); !ok { + if l, ok := left.(*multiError); ok && !l.copyNeeded.Swap(true) { + // Common case where the error on the left is constantly being + // appended to. + errs := append(l.errors, right) + return &multiError{errors: errs} + } else if !ok { + // Both errors are single errors. + return &multiError{errors: []error{left, right}} + } + } + + // Either right or both, left and right, are multiErrors. Rely on usual + // expensive logic. + errors := [2]error{left, right} + return fromSlice(errors[0:]) +} diff --git a/vendor/go.uber.org/multierr/glide.lock b/vendor/go.uber.org/multierr/glide.lock new file mode 100644 index 0000000000..f9ea94c334 --- /dev/null +++ b/vendor/go.uber.org/multierr/glide.lock @@ -0,0 +1,19 @@ +hash: b53b5e9a84b9cb3cc4b2d0499e23da2feca1eec318ce9bb717ecf35bf24bf221 +updated: 2017-04-10T13:34:45.671678062-07:00 +imports: +- name: go.uber.org/atomic + version: 3b8db5e93c4c02efbc313e17b2e796b0914a01fb +testImports: +- name: github.com/davecgh/go-spew + version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 + subpackages: + - spew +- name: github.com/pmezard/go-difflib + version: d8ed2627bdf02c080bf22230dbb337003b7aba2d + subpackages: + - difflib +- name: github.com/stretchr/testify + version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 + subpackages: + - assert + - require diff --git a/vendor/go.uber.org/multierr/glide.yaml b/vendor/go.uber.org/multierr/glide.yaml new file mode 100644 index 0000000000..6ef084ec24 --- /dev/null +++ b/vendor/go.uber.org/multierr/glide.yaml @@ -0,0 +1,8 @@ +package: go.uber.org/multierr +import: +- package: go.uber.org/atomic + version: ^1 +testImport: +- package: github.com/stretchr/testify + subpackages: + - assert diff --git a/vendor/go.uber.org/multierr/go113.go b/vendor/go.uber.org/multierr/go113.go new file mode 100644 index 0000000000..264b0eac0d --- /dev/null +++ b/vendor/go.uber.org/multierr/go113.go @@ -0,0 +1,52 @@ +// Copyright (c) 2019 Uber Technologies, Inc. +// +// 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. + +// +build go1.13 + +package multierr + +import "errors" + +// As attempts to find the first error in the error list that matches the type +// of the value that target points to. +// +// This function allows errors.As to traverse the values stored on the +// multierr error. +func (merr *multiError) As(target interface{}) bool { + for _, err := range merr.Errors() { + if errors.As(err, target) { + return true + } + } + return false +} + +// Is attempts to match the provided error against errors in the error list. +// +// This function allows errors.Is to traverse the values stored on the +// multierr error. +func (merr *multiError) Is(target error) bool { + for _, err := range merr.Errors() { + if errors.Is(err, target) { + return true + } + } + return false +} diff --git a/vendor/go.uber.org/zap/.codecov.yml b/vendor/go.uber.org/zap/.codecov.yml new file mode 100644 index 0000000000..8e5ca7d3e2 --- /dev/null +++ b/vendor/go.uber.org/zap/.codecov.yml @@ -0,0 +1,17 @@ +coverage: + range: 80..100 + round: down + precision: 2 + + status: + project: # measuring the overall project coverage + default: # context, you can create multiple ones with custom titles + enabled: yes # must be yes|true to enable this status + target: 95% # specify the target coverage for each commit status + # option: "auto" (must increase from parent commit or pull request base) + # option: "X%" a static target percentage to hit + if_not_found: success # if parent is not found report status as success, error, or failure + if_ci_failed: error # if ci fails report status as success, error, or failure +ignore: + - internal/readme/readme.go + diff --git a/vendor/go.uber.org/zap/.gitignore b/vendor/go.uber.org/zap/.gitignore new file mode 100644 index 0000000000..08fbde6ce2 --- /dev/null +++ b/vendor/go.uber.org/zap/.gitignore @@ -0,0 +1,28 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test +vendor + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof +*.pprof +*.out +*.log diff --git a/vendor/go.uber.org/zap/.readme.tmpl b/vendor/go.uber.org/zap/.readme.tmpl new file mode 100644 index 0000000000..c6440db8eb --- /dev/null +++ b/vendor/go.uber.org/zap/.readme.tmpl @@ -0,0 +1,108 @@ +# :zap: zap [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] + +Blazing fast, structured, leveled logging in Go. + +## Installation + +`go get -u go.uber.org/zap` + +Note that zap only supports the two most recent minor versions of Go. + +## Quick Start + +In contexts where performance is nice, but not critical, use the +`SugaredLogger`. It's 4-10x faster than other structured logging +packages and includes both structured and `printf`-style APIs. + +```go +logger, _ := zap.NewProduction() +defer logger.Sync() // flushes buffer, if any +sugar := logger.Sugar() +sugar.Infow("failed to fetch URL", + // Structured context as loosely typed key-value pairs. + "url", url, + "attempt", 3, + "backoff", time.Second, +) +sugar.Infof("Failed to fetch URL: %s", url) +``` + +When performance and type safety are critical, use the `Logger`. It's even +faster than the `SugaredLogger` and allocates far less, but it only supports +structured logging. + +```go +logger, _ := zap.NewProduction() +defer logger.Sync() +logger.Info("failed to fetch URL", + // Structured context as strongly typed Field values. + zap.String("url", url), + zap.Int("attempt", 3), + zap.Duration("backoff", time.Second), +) +``` + +See the [documentation][doc] and [FAQ](FAQ.md) for more details. + +## Performance + +For applications that log in the hot path, reflection-based serialization and +string formatting are prohibitively expensive — they're CPU-intensive +and make many small allocations. Put differently, using `encoding/json` and +`fmt.Fprintf` to log tons of `interface{}`s makes your application slow. + +Zap takes a different approach. It includes a reflection-free, zero-allocation +JSON encoder, and the base `Logger` strives to avoid serialization overhead +and allocations wherever possible. By building the high-level `SugaredLogger` +on that foundation, zap lets users *choose* when they need to count every +allocation and when they'd prefer a more familiar, loosely typed API. + +As measured by its own [benchmarking suite][], not only is zap more performant +than comparable structured logging packages — it's also faster than the +standard library. Like all benchmarks, take these with a grain of salt.[1](#footnote-versions) + +Log a message and 10 fields: + +{{.BenchmarkAddingFields}} + +Log a message with a logger that already has 10 fields of context: + +{{.BenchmarkAccumulatedContext}} + +Log a static string, without any context or `printf`-style templating: + +{{.BenchmarkWithoutFields}} + +## Development Status: Stable + +All APIs are finalized, and no breaking changes will be made in the 1.x series +of releases. Users of semver-aware dependency management systems should pin +zap to `^1`. + +## Contributing + +We encourage and support an active, healthy community of contributors — +including you! Details are in the [contribution guide](CONTRIBUTING.md) and +the [code of conduct](CODE_OF_CONDUCT.md). The zap maintainers keep an eye on +issues and pull requests, but you can also report any negative conduct to +oss-conduct@uber.com. That email list is a private, safe space; even the zap +maintainers don't have access, so don't hesitate to hold us to a high +standard. + +
+ +Released under the [MIT License](LICENSE.txt). + +1 In particular, keep in mind that we may be +benchmarking against slightly older versions of other packages. Versions are +pinned in zap's [glide.lock][] file. [↩](#anchor-versions) + +[doc-img]: https://godoc.org/go.uber.org/zap?status.svg +[doc]: https://godoc.org/go.uber.org/zap +[ci-img]: https://travis-ci.org/uber-go/zap.svg?branch=master +[ci]: https://travis-ci.org/uber-go/zap +[cov-img]: https://codecov.io/gh/uber-go/zap/branch/master/graph/badge.svg +[cov]: https://codecov.io/gh/uber-go/zap +[benchmarking suite]: https://github.com/uber-go/zap/tree/master/benchmarks +[glide.lock]: https://github.com/uber-go/zap/blob/master/glide.lock diff --git a/vendor/go.uber.org/zap/.travis.yml b/vendor/go.uber.org/zap/.travis.yml new file mode 100644 index 0000000000..ada5ebdcc9 --- /dev/null +++ b/vendor/go.uber.org/zap/.travis.yml @@ -0,0 +1,21 @@ +language: go +sudo: false +go: + - 1.11.x + - 1.12.x +go_import_path: go.uber.org/zap +env: + global: + - TEST_TIMEOUT_SCALE=10 +cache: + directories: + - vendor +install: + - make dependencies +script: + - make lint + - make test + - make bench +after_success: + - make cover + - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/go.uber.org/zap/CHANGELOG.md b/vendor/go.uber.org/zap/CHANGELOG.md new file mode 100644 index 0000000000..28d10677eb --- /dev/null +++ b/vendor/go.uber.org/zap/CHANGELOG.md @@ -0,0 +1,327 @@ +# Changelog + +## 1.10.0 (29 Apr 2019) + +Bugfixes: +* [#657][]: Fix `MapObjectEncoder.AppendByteString` not adding value as a + string. +* [#706][]: Fix incorrect call depth to determine caller in Go 1.12. + +Enhancements: +* [#610][]: Add `zaptest.WrapOptions` to wrap `zap.Option` for creating test + loggers. +* [#675][]: Don't panic when encoding a String field. +* [#704][]: Disable HTML escaping for JSON objects encoded using the + reflect-based encoder. + +Thanks to @iaroslav-ciupin, @lelenanam, @joa, @NWilson for their contributions +to this release. + +## v1.9.1 (06 Aug 2018) + +Bugfixes: + +* [#614][]: MapObjectEncoder should not ignore empty slices. + +## v1.9.0 (19 Jul 2018) + +Enhancements: +* [#602][]: Reduce number of allocations when logging with reflection. +* [#572][], [#606][]: Expose a registry for third-party logging sinks. + +Thanks to @nfarah86, @AlekSi, @JeanMertz, @philippgille, @etsangsplk, and +@dimroc for their contributions to this release. + +## v1.8.0 (13 Apr 2018) + +Enhancements: +* [#508][]: Make log level configurable when redirecting the standard + library's logger. +* [#518][]: Add a logger that writes to a `*testing.TB`. +* [#577][]: Add a top-level alias for `zapcore.Field` to clean up GoDoc. + +Bugfixes: +* [#574][]: Add a missing import comment to `go.uber.org/zap/buffer`. + +Thanks to @DiSiqueira and @djui for their contributions to this release. + +## v1.7.1 (25 Sep 2017) + +Bugfixes: +* [#504][]: Store strings when using AddByteString with the map encoder. + +## v1.7.0 (21 Sep 2017) + +Enhancements: + +* [#487][]: Add `NewStdLogAt`, which extends `NewStdLog` by allowing the user + to specify the level of the logged messages. + +## v1.6.0 (30 Aug 2017) + +Enhancements: + +* [#491][]: Omit zap stack frames from stacktraces. +* [#490][]: Add a `ContextMap` method to observer logs for simpler + field validation in tests. + +## v1.5.0 (22 Jul 2017) + +Enhancements: + +* [#460][] and [#470][]: Support errors produced by `go.uber.org/multierr`. +* [#465][]: Support user-supplied encoders for logger names. + +Bugfixes: + +* [#477][]: Fix a bug that incorrectly truncated deep stacktraces. + +Thanks to @richard-tunein and @pavius for their contributions to this release. + +## v1.4.1 (08 Jun 2017) + +This release fixes two bugs. + +Bugfixes: + +* [#435][]: Support a variety of case conventions when unmarshaling levels. +* [#444][]: Fix a panic in the observer. + +## v1.4.0 (12 May 2017) + +This release adds a few small features and is fully backward-compatible. + +Enhancements: + +* [#424][]: Add a `LineEnding` field to `EncoderConfig`, allowing users to + override the Unix-style default. +* [#425][]: Preserve time zones when logging times. +* [#431][]: Make `zap.AtomicLevel` implement `fmt.Stringer`, which makes a + variety of operations a bit simpler. + +## v1.3.0 (25 Apr 2017) + +This release adds an enhancement to zap's testing helpers as well as the +ability to marshal an AtomicLevel. It is fully backward-compatible. + +Enhancements: + +* [#415][]: Add a substring-filtering helper to zap's observer. This is + particularly useful when testing the `SugaredLogger`. +* [#416][]: Make `AtomicLevel` implement `encoding.TextMarshaler`. + +## v1.2.0 (13 Apr 2017) + +This release adds a gRPC compatibility wrapper. It is fully backward-compatible. + +Enhancements: + +* [#402][]: Add a `zapgrpc` package that wraps zap's Logger and implements + `grpclog.Logger`. + +## v1.1.0 (31 Mar 2017) + +This release fixes two bugs and adds some enhancements to zap's testing helpers. +It is fully backward-compatible. + +Bugfixes: + +* [#385][]: Fix caller path trimming on Windows. +* [#396][]: Fix a panic when attempting to use non-existent directories with + zap's configuration struct. + +Enhancements: + +* [#386][]: Add filtering helpers to zaptest's observing logger. + +Thanks to @moitias for contributing to this release. + +## v1.0.0 (14 Mar 2017) + +This is zap's first stable release. All exported APIs are now final, and no +further breaking changes will be made in the 1.x release series. Anyone using a +semver-aware dependency manager should now pin to `^1`. + +Breaking changes: + +* [#366][]: Add byte-oriented APIs to encoders to log UTF-8 encoded text without + casting from `[]byte` to `string`. +* [#364][]: To support buffering outputs, add `Sync` methods to `zapcore.Core`, + `zap.Logger`, and `zap.SugaredLogger`. +* [#371][]: Rename the `testutils` package to `zaptest`, which is less likely to + clash with other testing helpers. + +Bugfixes: + +* [#362][]: Make the ISO8601 time formatters fixed-width, which is friendlier + for tab-separated console output. +* [#369][]: Remove the automatic locks in `zapcore.NewCore`, which allows zap to + work with concurrency-safe `WriteSyncer` implementations. +* [#347][]: Stop reporting errors when trying to `fsync` standard out on Linux + systems. +* [#373][]: Report the correct caller from zap's standard library + interoperability wrappers. + +Enhancements: + +* [#348][]: Add a registry allowing third-party encodings to work with zap's + built-in `Config`. +* [#327][]: Make the representation of logger callers configurable (like times, + levels, and durations). +* [#376][]: Allow third-party encoders to use their own buffer pools, which + removes the last performance advantage that zap's encoders have over plugins. +* [#346][]: Add `CombineWriteSyncers`, a convenience function to tee multiple + `WriteSyncer`s and lock the result. +* [#365][]: Make zap's stacktraces compatible with mid-stack inlining (coming in + Go 1.9). +* [#372][]: Export zap's observing logger as `zaptest/observer`. This makes it + easier for particularly punctilious users to unit test their application's + logging. + +Thanks to @suyash, @htrendev, @flisky, @Ulexus, and @skipor for their +contributions to this release. + +## v1.0.0-rc.3 (7 Mar 2017) + +This is the third release candidate for zap's stable release. There are no +breaking changes. + +Bugfixes: + +* [#339][]: Byte slices passed to `zap.Any` are now correctly treated as binary blobs + rather than `[]uint8`. + +Enhancements: + +* [#307][]: Users can opt into colored output for log levels. +* [#353][]: In addition to hijacking the output of the standard library's + package-global logging functions, users can now construct a zap-backed + `log.Logger` instance. +* [#311][]: Frames from common runtime functions and some of zap's internal + machinery are now omitted from stacktraces. + +Thanks to @ansel1 and @suyash for their contributions to this release. + +## v1.0.0-rc.2 (21 Feb 2017) + +This is the second release candidate for zap's stable release. It includes two +breaking changes. + +Breaking changes: + +* [#316][]: Zap's global loggers are now fully concurrency-safe + (previously, users had to ensure that `ReplaceGlobals` was called before the + loggers were in use). However, they must now be accessed via the `L()` and + `S()` functions. Users can update their projects with + + ``` + gofmt -r "zap.L -> zap.L()" -w . + gofmt -r "zap.S -> zap.S()" -w . + ``` +* [#309][] and [#317][]: RC1 was mistakenly shipped with invalid + JSON and YAML struct tags on all config structs. This release fixes the tags + and adds static analysis to prevent similar bugs in the future. + +Bugfixes: + +* [#321][]: Redirecting the standard library's `log` output now + correctly reports the logger's caller. + +Enhancements: + +* [#325][] and [#333][]: Zap now transparently supports non-standard, rich + errors like those produced by `github.com/pkg/errors`. +* [#326][]: Though `New(nil)` continues to return a no-op logger, `NewNop()` is + now preferred. Users can update their projects with `gofmt -r 'zap.New(nil) -> + zap.NewNop()' -w .`. +* [#300][]: Incorrectly importing zap as `github.com/uber-go/zap` now returns a + more informative error. + +Thanks to @skipor and @chapsuk for their contributions to this release. + +## v1.0.0-rc.1 (14 Feb 2017) + +This is the first release candidate for zap's stable release. There are multiple +breaking changes and improvements from the pre-release version. Most notably: + +* **Zap's import path is now "go.uber.org/zap"** — all users will + need to update their code. +* User-facing types and functions remain in the `zap` package. Code relevant + largely to extension authors is now in the `zapcore` package. +* The `zapcore.Core` type makes it easy for third-party packages to use zap's + internals but provide a different user-facing API. +* `Logger` is now a concrete type instead of an interface. +* A less verbose (though slower) logging API is included by default. +* Package-global loggers `L` and `S` are included. +* A human-friendly console encoder is included. +* A declarative config struct allows common logger configurations to be managed + as configuration instead of code. +* Sampling is more accurate, and doesn't depend on the standard library's shared + timer heap. + +## v0.1.0-beta.1 (6 Feb 2017) + +This is a minor version, tagged to allow users to pin to the pre-1.0 APIs and +upgrade at their leisure. Since this is the first tagged release, there are no +backward compatibility concerns and all functionality is new. + +Early zap adopters should pin to the 0.1.x minor version until they're ready to +upgrade to the upcoming stable release. + +[#316]: https://github.com/uber-go/zap/pull/316 +[#309]: https://github.com/uber-go/zap/pull/309 +[#317]: https://github.com/uber-go/zap/pull/317 +[#321]: https://github.com/uber-go/zap/pull/321 +[#325]: https://github.com/uber-go/zap/pull/325 +[#333]: https://github.com/uber-go/zap/pull/333 +[#326]: https://github.com/uber-go/zap/pull/326 +[#300]: https://github.com/uber-go/zap/pull/300 +[#339]: https://github.com/uber-go/zap/pull/339 +[#307]: https://github.com/uber-go/zap/pull/307 +[#353]: https://github.com/uber-go/zap/pull/353 +[#311]: https://github.com/uber-go/zap/pull/311 +[#366]: https://github.com/uber-go/zap/pull/366 +[#364]: https://github.com/uber-go/zap/pull/364 +[#371]: https://github.com/uber-go/zap/pull/371 +[#362]: https://github.com/uber-go/zap/pull/362 +[#369]: https://github.com/uber-go/zap/pull/369 +[#347]: https://github.com/uber-go/zap/pull/347 +[#373]: https://github.com/uber-go/zap/pull/373 +[#348]: https://github.com/uber-go/zap/pull/348 +[#327]: https://github.com/uber-go/zap/pull/327 +[#376]: https://github.com/uber-go/zap/pull/376 +[#346]: https://github.com/uber-go/zap/pull/346 +[#365]: https://github.com/uber-go/zap/pull/365 +[#372]: https://github.com/uber-go/zap/pull/372 +[#385]: https://github.com/uber-go/zap/pull/385 +[#396]: https://github.com/uber-go/zap/pull/396 +[#386]: https://github.com/uber-go/zap/pull/386 +[#402]: https://github.com/uber-go/zap/pull/402 +[#415]: https://github.com/uber-go/zap/pull/415 +[#416]: https://github.com/uber-go/zap/pull/416 +[#424]: https://github.com/uber-go/zap/pull/424 +[#425]: https://github.com/uber-go/zap/pull/425 +[#431]: https://github.com/uber-go/zap/pull/431 +[#435]: https://github.com/uber-go/zap/pull/435 +[#444]: https://github.com/uber-go/zap/pull/444 +[#477]: https://github.com/uber-go/zap/pull/477 +[#465]: https://github.com/uber-go/zap/pull/465 +[#460]: https://github.com/uber-go/zap/pull/460 +[#470]: https://github.com/uber-go/zap/pull/470 +[#487]: https://github.com/uber-go/zap/pull/487 +[#490]: https://github.com/uber-go/zap/pull/490 +[#491]: https://github.com/uber-go/zap/pull/491 +[#504]: https://github.com/uber-go/zap/pull/504 +[#508]: https://github.com/uber-go/zap/pull/508 +[#518]: https://github.com/uber-go/zap/pull/518 +[#577]: https://github.com/uber-go/zap/pull/577 +[#574]: https://github.com/uber-go/zap/pull/574 +[#602]: https://github.com/uber-go/zap/pull/602 +[#572]: https://github.com/uber-go/zap/pull/572 +[#606]: https://github.com/uber-go/zap/pull/606 +[#614]: https://github.com/uber-go/zap/pull/614 +[#657]: https://github.com/uber-go/zap/pull/657 +[#706]: https://github.com/uber-go/zap/pull/706 +[#610]: https://github.com/uber-go/zap/pull/610 +[#675]: https://github.com/uber-go/zap/pull/675 +[#704]: https://github.com/uber-go/zap/pull/704 diff --git a/vendor/go.uber.org/zap/CODE_OF_CONDUCT.md b/vendor/go.uber.org/zap/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..e327d9aa5c --- /dev/null +++ b/vendor/go.uber.org/zap/CODE_OF_CONDUCT.md @@ -0,0 +1,75 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, +body size, disability, ethnicity, gender identity and expression, level of +experience, nationality, personal appearance, race, religion, or sexual +identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an +appointed representative at an online or offline event. Representation of a +project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at oss-conduct@uber.com. The project +team will review and investigate all complaints, and will respond in a way +that it deems appropriate to the circumstances. The project team is obligated +to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 1.4, available at +[http://contributor-covenant.org/version/1/4][version]. + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/go.uber.org/zap/CONTRIBUTING.md b/vendor/go.uber.org/zap/CONTRIBUTING.md new file mode 100644 index 0000000000..9454bbaf02 --- /dev/null +++ b/vendor/go.uber.org/zap/CONTRIBUTING.md @@ -0,0 +1,81 @@ +# Contributing + +We'd love your help making zap the very best structured logging library in Go! + +If you'd like to add new exported APIs, please [open an issue][open-issue] +describing your proposal — discussing API changes ahead of time makes +pull request review much smoother. In your issue, pull request, and any other +communications, please remember to treat your fellow contributors with +respect! We take our [code of conduct](CODE_OF_CONDUCT.md) seriously. + +Note that you'll need to sign [Uber's Contributor License Agreement][cla] +before we can accept any of your contributions. If necessary, a bot will remind +you to accept the CLA when you open your pull request. + +## Setup + +[Fork][fork], then clone the repository: + +``` +mkdir -p $GOPATH/src/go.uber.org +cd $GOPATH/src/go.uber.org +git clone git@github.com:your_github_username/zap.git +cd zap +git remote add upstream https://github.com/uber-go/zap.git +git fetch upstream +``` + +Install zap's dependencies: + +``` +make dependencies +``` + +Make sure that the tests and the linters pass: + +``` +make test +make lint +``` + +If you're not using the minor version of Go specified in the Makefile's +`LINTABLE_MINOR_VERSIONS` variable, `make lint` doesn't do anything. This is +fine, but it means that you'll only discover lint failures after you open your +pull request. + +## Making Changes + +Start by creating a new branch for your changes: + +``` +cd $GOPATH/src/go.uber.org/zap +git checkout master +git fetch upstream +git rebase upstream/master +git checkout -b cool_new_feature +``` + +Make your changes, then ensure that `make lint` and `make test` still pass. If +you're satisfied with your changes, push them to your fork. + +``` +git push origin cool_new_feature +``` + +Then use the GitHub UI to open a pull request. + +At this point, you're waiting on us to review your changes. We *try* to respond +to issues and pull requests within a few business days, and we may suggest some +improvements or alternatives. Once your changes are approved, one of the +project maintainers will merge them. + +We're much more likely to approve your changes if you: + +* Add tests for new functionality. +* Write a [good commit message][commit-message]. +* Maintain backward compatibility. + +[fork]: https://github.com/uber-go/zap/fork +[open-issue]: https://github.com/uber-go/zap/issues/new +[cla]: https://cla-assistant.io/uber-go/zap +[commit-message]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html diff --git a/vendor/go.uber.org/zap/FAQ.md b/vendor/go.uber.org/zap/FAQ.md new file mode 100644 index 0000000000..4256d35c76 --- /dev/null +++ b/vendor/go.uber.org/zap/FAQ.md @@ -0,0 +1,155 @@ +# Frequently Asked Questions + +## Design + +### Why spend so much effort on logger performance? + +Of course, most applications won't notice the impact of a slow logger: they +already take tens or hundreds of milliseconds for each operation, so an extra +millisecond doesn't matter. + +On the other hand, why *not* make structured logging fast? The `SugaredLogger` +isn't any harder to use than other logging packages, and the `Logger` makes +structured logging possible in performance-sensitive contexts. Across a fleet +of Go microservices, making each application even slightly more efficient adds +up quickly. + +### Why aren't `Logger` and `SugaredLogger` interfaces? + +Unlike the familiar `io.Writer` and `http.Handler`, `Logger` and +`SugaredLogger` interfaces would include *many* methods. As [Rob Pike points +out][go-proverbs], "The bigger the interface, the weaker the abstraction." +Interfaces are also rigid — *any* change requires releasing a new major +version, since it breaks all third-party implementations. + +Making the `Logger` and `SugaredLogger` concrete types doesn't sacrifice much +abstraction, and it lets us add methods without introducing breaking changes. +Your applications should define and depend upon an interface that includes +just the methods you use. + +### Why sample application logs? + +Applications often experience runs of errors, either because of a bug or +because of a misbehaving user. Logging errors is usually a good idea, but it +can easily make this bad situation worse: not only is your application coping +with a flood of errors, it's also spending extra CPU cycles and I/O logging +those errors. Since writes are typically serialized, logging limits throughput +when you need it most. + +Sampling fixes this problem by dropping repetitive log entries. Under normal +conditions, your application writes out every entry. When similar entries are +logged hundreds or thousands of times each second, though, zap begins dropping +duplicates to preserve throughput. + +### Why do the structured logging APIs take a message in addition to fields? + +Subjectively, we find it helpful to accompany structured context with a brief +description. This isn't critical during development, but it makes debugging +and operating unfamiliar systems much easier. + +More concretely, zap's sampling algorithm uses the message to identify +duplicate entries. In our experience, this is a practical middle ground +between random sampling (which often drops the exact entry that you need while +debugging) and hashing the complete entry (which is prohibitively expensive). + +### Why include package-global loggers? + +Since so many other logging packages include a global logger, many +applications aren't designed to accept loggers as explicit parameters. +Changing function signatures is often a breaking change, so zap includes +global loggers to simplify migration. + +Avoid them where possible. + +### Why include dedicated Panic and Fatal log levels? + +In general, application code should handle errors gracefully instead of using +`panic` or `os.Exit`. However, every rule has exceptions, and it's common to +crash when an error is truly unrecoverable. To avoid losing any information +— especially the reason for the crash — the logger must flush any +buffered entries before the process exits. + +Zap makes this easy by offering `Panic` and `Fatal` logging methods that +automatically flush before exiting. Of course, this doesn't guarantee that +logs will never be lost, but it eliminates a common error. + +See the discussion in uber-go/zap#207 for more details. + +### What's `DPanic`? + +`DPanic` stands for "panic in development." In development, it logs at +`PanicLevel`; otherwise, it logs at `ErrorLevel`. `DPanic` makes it easier to +catch errors that are theoretically possible, but shouldn't actually happen, +*without* crashing in production. + +If you've ever written code like this, you need `DPanic`: + +```go +if err != nil { + panic(fmt.Sprintf("shouldn't ever get here: %v", err)) +} +``` + +## Installation + +### What does the error `expects import "go.uber.org/zap"` mean? + +Either zap was installed incorrectly or you're referencing the wrong package +name in your code. + +Zap's source code happens to be hosted on GitHub, but the [import +path][import-path] is `go.uber.org/zap`. This gives us, the project +maintainers, the freedom to move the source code if necessary. However, it +means that you need to take a little care when installing and using the +package. + +If you follow two simple rules, everything should work: install zap with `go +get -u go.uber.org/zap`, and always import it in your code with `import +"go.uber.org/zap"`. Your code shouldn't contain *any* references to +`github.com/uber-go/zap`. + +## Usage + +### Does zap support log rotation? + +Zap doesn't natively support rotating log files, since we prefer to leave this +to an external program like `logrotate`. + +However, it's easy to integrate a log rotation package like +[`gopkg.in/natefinch/lumberjack.v2`][lumberjack] as a `zapcore.WriteSyncer`. + +```go +// lumberjack.Logger is already safe for concurrent use, so we don't need to +// lock it. +w := zapcore.AddSync(&lumberjack.Logger{ + Filename: "/var/log/myapp/foo.log", + MaxSize: 500, // megabytes + MaxBackups: 3, + MaxAge: 28, // days +}) +core := zapcore.NewCore( + zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), + w, + zap.InfoLevel, +) +logger := zap.New(core) +``` + +## Extensions + +We'd love to support every logging need within zap itself, but we're only +familiar with a handful of log ingestion systems, flag-parsing packages, and +the like. Rather than merging code that we can't effectively debug and +support, we'd rather grow an ecosystem of zap extensions. + +We're aware of the following extensions, but haven't used them ourselves: + +| Package | Integration | +| --- | --- | +| `github.com/tchap/zapext` | Sentry, syslog | +| `github.com/fgrosse/zaptest` | Ginkgo | +| `github.com/blendle/zapdriver` | Stackdriver | + +[go-proverbs]: https://go-proverbs.github.io/ +[import-path]: https://golang.org/cmd/go/#hdr-Remote_import_paths +[lumberjack]: https://godoc.org/gopkg.in/natefinch/lumberjack.v2 diff --git a/vendor/go.uber.org/zap/LICENSE.txt b/vendor/go.uber.org/zap/LICENSE.txt new file mode 100644 index 0000000000..6652bed45f --- /dev/null +++ b/vendor/go.uber.org/zap/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2016-2017 Uber Technologies, Inc. + +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/go.uber.org/zap/Makefile b/vendor/go.uber.org/zap/Makefile new file mode 100644 index 0000000000..073e9aa910 --- /dev/null +++ b/vendor/go.uber.org/zap/Makefile @@ -0,0 +1,76 @@ +export GO15VENDOREXPERIMENT=1 + +BENCH_FLAGS ?= -cpuprofile=cpu.pprof -memprofile=mem.pprof -benchmem +PKGS ?= $(shell glide novendor) +# Many Go tools take file globs or directories as arguments instead of packages. +PKG_FILES ?= *.go zapcore benchmarks buffer zapgrpc zaptest zaptest/observer internal/bufferpool internal/exit internal/color internal/ztest + +# The linting tools evolve with each Go version, so run them only on the latest +# stable release. +GO_VERSION := $(shell go version | cut -d " " -f 3) +GO_MINOR_VERSION := $(word 2,$(subst ., ,$(GO_VERSION))) +LINTABLE_MINOR_VERSIONS := 12 +ifneq ($(filter $(LINTABLE_MINOR_VERSIONS),$(GO_MINOR_VERSION)),) +SHOULD_LINT := true +endif + + +.PHONY: all +all: lint test + +.PHONY: dependencies +dependencies: + @echo "Installing Glide and locked dependencies..." + glide --version || go get -u -f github.com/Masterminds/glide + glide install + @echo "Installing test dependencies..." + go install ./vendor/github.com/axw/gocov/gocov + go install ./vendor/github.com/mattn/goveralls +ifdef SHOULD_LINT + @echo "Installing golint..." + go install ./vendor/github.com/golang/lint/golint +else + @echo "Not installing golint, since we don't expect to lint on" $(GO_VERSION) +endif + +# Disable printf-like invocation checking due to testify.assert.Error() +VET_RULES := -printf=false + +.PHONY: lint +lint: +ifdef SHOULD_LINT + @rm -rf lint.log + @echo "Checking formatting..." + @gofmt -d -s $(PKG_FILES) 2>&1 | tee lint.log + @echo "Installing test dependencies for vet..." + @go test -i $(PKGS) + @echo "Checking vet..." + @go vet $(VET_RULES) $(PKGS) 2>&1 | tee -a lint.log + @echo "Checking lint..." + @$(foreach dir,$(PKGS),golint $(dir) 2>&1 | tee -a lint.log;) + @echo "Checking for unresolved FIXMEs..." + @git grep -i fixme | grep -v -e vendor -e Makefile | tee -a lint.log + @echo "Checking for license headers..." + @./check_license.sh | tee -a lint.log + @[ ! -s lint.log ] +else + @echo "Skipping linters on" $(GO_VERSION) +endif + +.PHONY: test +test: + go test -race $(PKGS) + +.PHONY: cover +cover: + ./scripts/cover.sh $(PKGS) + +.PHONY: bench +BENCH ?= . +bench: + @$(foreach pkg,$(PKGS),go test -bench=$(BENCH) -run="^$$" $(BENCH_FLAGS) $(pkg);) + +.PHONY: updatereadme +updatereadme: + rm -f README.md + cat .readme.tmpl | go run internal/readme/readme.go > README.md diff --git a/vendor/go.uber.org/zap/README.md b/vendor/go.uber.org/zap/README.md new file mode 100644 index 0000000000..f4fd1cb444 --- /dev/null +++ b/vendor/go.uber.org/zap/README.md @@ -0,0 +1,136 @@ +# :zap: zap [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] + +Blazing fast, structured, leveled logging in Go. + +## Installation + +`go get -u go.uber.org/zap` + +Note that zap only supports the two most recent minor versions of Go. + +## Quick Start + +In contexts where performance is nice, but not critical, use the +`SugaredLogger`. It's 4-10x faster than other structured logging +packages and includes both structured and `printf`-style APIs. + +```go +logger, _ := zap.NewProduction() +defer logger.Sync() // flushes buffer, if any +sugar := logger.Sugar() +sugar.Infow("failed to fetch URL", + // Structured context as loosely typed key-value pairs. + "url", url, + "attempt", 3, + "backoff", time.Second, +) +sugar.Infof("Failed to fetch URL: %s", url) +``` + +When performance and type safety are critical, use the `Logger`. It's even +faster than the `SugaredLogger` and allocates far less, but it only supports +structured logging. + +```go +logger, _ := zap.NewProduction() +defer logger.Sync() +logger.Info("failed to fetch URL", + // Structured context as strongly typed Field values. + zap.String("url", url), + zap.Int("attempt", 3), + zap.Duration("backoff", time.Second), +) +``` + +See the [documentation][doc] and [FAQ](FAQ.md) for more details. + +## Performance + +For applications that log in the hot path, reflection-based serialization and +string formatting are prohibitively expensive — they're CPU-intensive +and make many small allocations. Put differently, using `encoding/json` and +`fmt.Fprintf` to log tons of `interface{}`s makes your application slow. + +Zap takes a different approach. It includes a reflection-free, zero-allocation +JSON encoder, and the base `Logger` strives to avoid serialization overhead +and allocations wherever possible. By building the high-level `SugaredLogger` +on that foundation, zap lets users *choose* when they need to count every +allocation and when they'd prefer a more familiar, loosely typed API. + +As measured by its own [benchmarking suite][], not only is zap more performant +than comparable structured logging packages — it's also faster than the +standard library. Like all benchmarks, take these with a grain of salt.[1](#footnote-versions) + +Log a message and 10 fields: + +| Package | Time | Objects Allocated | +| :--- | :---: | :---: | +| :zap: zap | 3131 ns/op | 5 allocs/op | +| :zap: zap (sugared) | 4173 ns/op | 21 allocs/op | +| zerolog | 16154 ns/op | 90 allocs/op | +| lion | 16341 ns/op | 111 allocs/op | +| go-kit | 17049 ns/op | 126 allocs/op | +| logrus | 23662 ns/op | 142 allocs/op | +| log15 | 36351 ns/op | 149 allocs/op | +| apex/log | 42530 ns/op | 126 allocs/op | + +Log a message with a logger that already has 10 fields of context: + +| Package | Time | Objects Allocated | +| :--- | :---: | :---: | +| :zap: zap | 380 ns/op | 0 allocs/op | +| :zap: zap (sugared) | 564 ns/op | 2 allocs/op | +| zerolog | 321 ns/op | 0 allocs/op | +| lion | 7092 ns/op | 39 allocs/op | +| go-kit | 20226 ns/op | 115 allocs/op | +| logrus | 22312 ns/op | 130 allocs/op | +| log15 | 28788 ns/op | 79 allocs/op | +| apex/log | 42063 ns/op | 115 allocs/op | + +Log a static string, without any context or `printf`-style templating: + +| Package | Time | Objects Allocated | +| :--- | :---: | :---: | +| :zap: zap | 361 ns/op | 0 allocs/op | +| :zap: zap (sugared) | 534 ns/op | 2 allocs/op | +| zerolog | 323 ns/op | 0 allocs/op | +| standard library | 575 ns/op | 2 allocs/op | +| go-kit | 922 ns/op | 13 allocs/op | +| lion | 1413 ns/op | 10 allocs/op | +| logrus | 2291 ns/op | 27 allocs/op | +| apex/log | 3690 ns/op | 11 allocs/op | +| log15 | 5954 ns/op | 26 allocs/op | + +## Development Status: Stable + +All APIs are finalized, and no breaking changes will be made in the 1.x series +of releases. Users of semver-aware dependency management systems should pin +zap to `^1`. + +## Contributing + +We encourage and support an active, healthy community of contributors — +including you! Details are in the [contribution guide](CONTRIBUTING.md) and +the [code of conduct](CODE_OF_CONDUCT.md). The zap maintainers keep an eye on +issues and pull requests, but you can also report any negative conduct to +oss-conduct@uber.com. That email list is a private, safe space; even the zap +maintainers don't have access, so don't hesitate to hold us to a high +standard. + +
+ +Released under the [MIT License](LICENSE.txt). + +1 In particular, keep in mind that we may be +benchmarking against slightly older versions of other packages. Versions are +pinned in zap's [glide.lock][] file. [↩](#anchor-versions) + +[doc-img]: https://godoc.org/go.uber.org/zap?status.svg +[doc]: https://godoc.org/go.uber.org/zap +[ci-img]: https://travis-ci.org/uber-go/zap.svg?branch=master +[ci]: https://travis-ci.org/uber-go/zap +[cov-img]: https://codecov.io/gh/uber-go/zap/branch/master/graph/badge.svg +[cov]: https://codecov.io/gh/uber-go/zap +[benchmarking suite]: https://github.com/uber-go/zap/tree/master/benchmarks +[glide.lock]: https://github.com/uber-go/zap/blob/master/glide.lock diff --git a/vendor/go.uber.org/zap/array.go b/vendor/go.uber.org/zap/array.go new file mode 100644 index 0000000000..5be3704a3e --- /dev/null +++ b/vendor/go.uber.org/zap/array.go @@ -0,0 +1,320 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import ( + "time" + + "go.uber.org/zap/zapcore" +) + +// Array constructs a field with the given key and ArrayMarshaler. It provides +// a flexible, but still type-safe and efficient, way to add array-like types +// to the logging context. The struct's MarshalLogArray method is called lazily. +func Array(key string, val zapcore.ArrayMarshaler) Field { + return Field{Key: key, Type: zapcore.ArrayMarshalerType, Interface: val} +} + +// Bools constructs a field that carries a slice of bools. +func Bools(key string, bs []bool) Field { + return Array(key, bools(bs)) +} + +// ByteStrings constructs a field that carries a slice of []byte, each of which +// must be UTF-8 encoded text. +func ByteStrings(key string, bss [][]byte) Field { + return Array(key, byteStringsArray(bss)) +} + +// Complex128s constructs a field that carries a slice of complex numbers. +func Complex128s(key string, nums []complex128) Field { + return Array(key, complex128s(nums)) +} + +// Complex64s constructs a field that carries a slice of complex numbers. +func Complex64s(key string, nums []complex64) Field { + return Array(key, complex64s(nums)) +} + +// Durations constructs a field that carries a slice of time.Durations. +func Durations(key string, ds []time.Duration) Field { + return Array(key, durations(ds)) +} + +// Float64s constructs a field that carries a slice of floats. +func Float64s(key string, nums []float64) Field { + return Array(key, float64s(nums)) +} + +// Float32s constructs a field that carries a slice of floats. +func Float32s(key string, nums []float32) Field { + return Array(key, float32s(nums)) +} + +// Ints constructs a field that carries a slice of integers. +func Ints(key string, nums []int) Field { + return Array(key, ints(nums)) +} + +// Int64s constructs a field that carries a slice of integers. +func Int64s(key string, nums []int64) Field { + return Array(key, int64s(nums)) +} + +// Int32s constructs a field that carries a slice of integers. +func Int32s(key string, nums []int32) Field { + return Array(key, int32s(nums)) +} + +// Int16s constructs a field that carries a slice of integers. +func Int16s(key string, nums []int16) Field { + return Array(key, int16s(nums)) +} + +// Int8s constructs a field that carries a slice of integers. +func Int8s(key string, nums []int8) Field { + return Array(key, int8s(nums)) +} + +// Strings constructs a field that carries a slice of strings. +func Strings(key string, ss []string) Field { + return Array(key, stringArray(ss)) +} + +// Times constructs a field that carries a slice of time.Times. +func Times(key string, ts []time.Time) Field { + return Array(key, times(ts)) +} + +// Uints constructs a field that carries a slice of unsigned integers. +func Uints(key string, nums []uint) Field { + return Array(key, uints(nums)) +} + +// Uint64s constructs a field that carries a slice of unsigned integers. +func Uint64s(key string, nums []uint64) Field { + return Array(key, uint64s(nums)) +} + +// Uint32s constructs a field that carries a slice of unsigned integers. +func Uint32s(key string, nums []uint32) Field { + return Array(key, uint32s(nums)) +} + +// Uint16s constructs a field that carries a slice of unsigned integers. +func Uint16s(key string, nums []uint16) Field { + return Array(key, uint16s(nums)) +} + +// Uint8s constructs a field that carries a slice of unsigned integers. +func Uint8s(key string, nums []uint8) Field { + return Array(key, uint8s(nums)) +} + +// Uintptrs constructs a field that carries a slice of pointer addresses. +func Uintptrs(key string, us []uintptr) Field { + return Array(key, uintptrs(us)) +} + +// Errors constructs a field that carries a slice of errors. +func Errors(key string, errs []error) Field { + return Array(key, errArray(errs)) +} + +type bools []bool + +func (bs bools) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range bs { + arr.AppendBool(bs[i]) + } + return nil +} + +type byteStringsArray [][]byte + +func (bss byteStringsArray) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range bss { + arr.AppendByteString(bss[i]) + } + return nil +} + +type complex128s []complex128 + +func (nums complex128s) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendComplex128(nums[i]) + } + return nil +} + +type complex64s []complex64 + +func (nums complex64s) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendComplex64(nums[i]) + } + return nil +} + +type durations []time.Duration + +func (ds durations) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range ds { + arr.AppendDuration(ds[i]) + } + return nil +} + +type float64s []float64 + +func (nums float64s) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendFloat64(nums[i]) + } + return nil +} + +type float32s []float32 + +func (nums float32s) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendFloat32(nums[i]) + } + return nil +} + +type ints []int + +func (nums ints) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendInt(nums[i]) + } + return nil +} + +type int64s []int64 + +func (nums int64s) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendInt64(nums[i]) + } + return nil +} + +type int32s []int32 + +func (nums int32s) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendInt32(nums[i]) + } + return nil +} + +type int16s []int16 + +func (nums int16s) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendInt16(nums[i]) + } + return nil +} + +type int8s []int8 + +func (nums int8s) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendInt8(nums[i]) + } + return nil +} + +type stringArray []string + +func (ss stringArray) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range ss { + arr.AppendString(ss[i]) + } + return nil +} + +type times []time.Time + +func (ts times) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range ts { + arr.AppendTime(ts[i]) + } + return nil +} + +type uints []uint + +func (nums uints) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendUint(nums[i]) + } + return nil +} + +type uint64s []uint64 + +func (nums uint64s) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendUint64(nums[i]) + } + return nil +} + +type uint32s []uint32 + +func (nums uint32s) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendUint32(nums[i]) + } + return nil +} + +type uint16s []uint16 + +func (nums uint16s) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendUint16(nums[i]) + } + return nil +} + +type uint8s []uint8 + +func (nums uint8s) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendUint8(nums[i]) + } + return nil +} + +type uintptrs []uintptr + +func (nums uintptrs) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range nums { + arr.AppendUintptr(nums[i]) + } + return nil +} diff --git a/vendor/go.uber.org/zap/buffer/buffer.go b/vendor/go.uber.org/zap/buffer/buffer.go new file mode 100644 index 0000000000..7592e8c63f --- /dev/null +++ b/vendor/go.uber.org/zap/buffer/buffer.go @@ -0,0 +1,115 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +// Package buffer provides a thin wrapper around a byte slice. Unlike the +// standard library's bytes.Buffer, it supports a portion of the strconv +// package's zero-allocation formatters. +package buffer // import "go.uber.org/zap/buffer" + +import "strconv" + +const _size = 1024 // by default, create 1 KiB buffers + +// Buffer is a thin wrapper around a byte slice. It's intended to be pooled, so +// the only way to construct one is via a Pool. +type Buffer struct { + bs []byte + pool Pool +} + +// AppendByte writes a single byte to the Buffer. +func (b *Buffer) AppendByte(v byte) { + b.bs = append(b.bs, v) +} + +// AppendString writes a string to the Buffer. +func (b *Buffer) AppendString(s string) { + b.bs = append(b.bs, s...) +} + +// AppendInt appends an integer to the underlying buffer (assuming base 10). +func (b *Buffer) AppendInt(i int64) { + b.bs = strconv.AppendInt(b.bs, i, 10) +} + +// AppendUint appends an unsigned integer to the underlying buffer (assuming +// base 10). +func (b *Buffer) AppendUint(i uint64) { + b.bs = strconv.AppendUint(b.bs, i, 10) +} + +// AppendBool appends a bool to the underlying buffer. +func (b *Buffer) AppendBool(v bool) { + b.bs = strconv.AppendBool(b.bs, v) +} + +// AppendFloat appends a float to the underlying buffer. It doesn't quote NaN +// or +/- Inf. +func (b *Buffer) AppendFloat(f float64, bitSize int) { + b.bs = strconv.AppendFloat(b.bs, f, 'f', -1, bitSize) +} + +// Len returns the length of the underlying byte slice. +func (b *Buffer) Len() int { + return len(b.bs) +} + +// Cap returns the capacity of the underlying byte slice. +func (b *Buffer) Cap() int { + return cap(b.bs) +} + +// Bytes returns a mutable reference to the underlying byte slice. +func (b *Buffer) Bytes() []byte { + return b.bs +} + +// String returns a string copy of the underlying byte slice. +func (b *Buffer) String() string { + return string(b.bs) +} + +// Reset resets the underlying byte slice. Subsequent writes re-use the slice's +// backing array. +func (b *Buffer) Reset() { + b.bs = b.bs[:0] +} + +// Write implements io.Writer. +func (b *Buffer) Write(bs []byte) (int, error) { + b.bs = append(b.bs, bs...) + return len(bs), nil +} + +// TrimNewline trims any final "\n" byte from the end of the buffer. +func (b *Buffer) TrimNewline() { + if i := len(b.bs) - 1; i >= 0 { + if b.bs[i] == '\n' { + b.bs = b.bs[:i] + } + } +} + +// Free returns the Buffer to its Pool. +// +// Callers must not retain references to the Buffer after calling Free. +func (b *Buffer) Free() { + b.pool.put(b) +} diff --git a/vendor/go.uber.org/zap/buffer/pool.go b/vendor/go.uber.org/zap/buffer/pool.go new file mode 100644 index 0000000000..8fb3e202cf --- /dev/null +++ b/vendor/go.uber.org/zap/buffer/pool.go @@ -0,0 +1,49 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package buffer + +import "sync" + +// A Pool is a type-safe wrapper around a sync.Pool. +type Pool struct { + p *sync.Pool +} + +// NewPool constructs a new Pool. +func NewPool() Pool { + return Pool{p: &sync.Pool{ + New: func() interface{} { + return &Buffer{bs: make([]byte, 0, _size)} + }, + }} +} + +// Get retrieves a Buffer from the pool, creating one if necessary. +func (p Pool) Get() *Buffer { + buf := p.p.Get().(*Buffer) + buf.Reset() + buf.pool = p + return buf +} + +func (p Pool) put(buf *Buffer) { + p.p.Put(buf) +} diff --git a/vendor/go.uber.org/zap/check_license.sh b/vendor/go.uber.org/zap/check_license.sh new file mode 100644 index 0000000000..345ac8b89a --- /dev/null +++ b/vendor/go.uber.org/zap/check_license.sh @@ -0,0 +1,17 @@ +#!/bin/bash -e + +ERROR_COUNT=0 +while read -r file +do + case "$(head -1 "${file}")" in + *"Copyright (c) "*" Uber Technologies, Inc.") + # everything's cool + ;; + *) + echo "$file is missing license header." + (( ERROR_COUNT++ )) + ;; + esac +done < <(git ls-files "*\.go") + +exit $ERROR_COUNT diff --git a/vendor/go.uber.org/zap/config.go b/vendor/go.uber.org/zap/config.go new file mode 100644 index 0000000000..6fe17d9e0f --- /dev/null +++ b/vendor/go.uber.org/zap/config.go @@ -0,0 +1,243 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import ( + "sort" + "time" + + "go.uber.org/zap/zapcore" +) + +// SamplingConfig sets a sampling strategy for the logger. Sampling caps the +// global CPU and I/O load that logging puts on your process while attempting +// to preserve a representative subset of your logs. +// +// Values configured here are per-second. See zapcore.NewSampler for details. +type SamplingConfig struct { + Initial int `json:"initial" yaml:"initial"` + Thereafter int `json:"thereafter" yaml:"thereafter"` +} + +// Config offers a declarative way to construct a logger. It doesn't do +// anything that can't be done with New, Options, and the various +// zapcore.WriteSyncer and zapcore.Core wrappers, but it's a simpler way to +// toggle common options. +// +// Note that Config intentionally supports only the most common options. More +// unusual logging setups (logging to network connections or message queues, +// splitting output between multiple files, etc.) are possible, but require +// direct use of the zapcore package. For sample code, see the package-level +// BasicConfiguration and AdvancedConfiguration examples. +// +// For an example showing runtime log level changes, see the documentation for +// AtomicLevel. +type Config struct { + // Level is the minimum enabled logging level. Note that this is a dynamic + // level, so calling Config.Level.SetLevel will atomically change the log + // level of all loggers descended from this config. + Level AtomicLevel `json:"level" yaml:"level"` + // Development puts the logger in development mode, which changes the + // behavior of DPanicLevel and takes stacktraces more liberally. + Development bool `json:"development" yaml:"development"` + // DisableCaller stops annotating logs with the calling function's file + // name and line number. By default, all logs are annotated. + DisableCaller bool `json:"disableCaller" yaml:"disableCaller"` + // DisableStacktrace completely disables automatic stacktrace capturing. By + // default, stacktraces are captured for WarnLevel and above logs in + // development and ErrorLevel and above in production. + DisableStacktrace bool `json:"disableStacktrace" yaml:"disableStacktrace"` + // Sampling sets a sampling policy. A nil SamplingConfig disables sampling. + Sampling *SamplingConfig `json:"sampling" yaml:"sampling"` + // Encoding sets the logger's encoding. Valid values are "json" and + // "console", as well as any third-party encodings registered via + // RegisterEncoder. + Encoding string `json:"encoding" yaml:"encoding"` + // EncoderConfig sets options for the chosen encoder. See + // zapcore.EncoderConfig for details. + EncoderConfig zapcore.EncoderConfig `json:"encoderConfig" yaml:"encoderConfig"` + // OutputPaths is a list of URLs or file paths to write logging output to. + // See Open for details. + OutputPaths []string `json:"outputPaths" yaml:"outputPaths"` + // ErrorOutputPaths is a list of URLs to write internal logger errors to. + // The default is standard error. + // + // Note that this setting only affects internal errors; for sample code that + // sends error-level logs to a different location from info- and debug-level + // logs, see the package-level AdvancedConfiguration example. + ErrorOutputPaths []string `json:"errorOutputPaths" yaml:"errorOutputPaths"` + // InitialFields is a collection of fields to add to the root logger. + InitialFields map[string]interface{} `json:"initialFields" yaml:"initialFields"` +} + +// NewProductionEncoderConfig returns an opinionated EncoderConfig for +// production environments. +func NewProductionEncoderConfig() zapcore.EncoderConfig { + return zapcore.EncoderConfig{ + TimeKey: "ts", + LevelKey: "level", + NameKey: "logger", + CallerKey: "caller", + MessageKey: "msg", + StacktraceKey: "stacktrace", + LineEnding: zapcore.DefaultLineEnding, + EncodeLevel: zapcore.LowercaseLevelEncoder, + EncodeTime: zapcore.EpochTimeEncoder, + EncodeDuration: zapcore.SecondsDurationEncoder, + EncodeCaller: zapcore.ShortCallerEncoder, + } +} + +// NewProductionConfig is a reasonable production logging configuration. +// Logging is enabled at InfoLevel and above. +// +// It uses a JSON encoder, writes to standard error, and enables sampling. +// Stacktraces are automatically included on logs of ErrorLevel and above. +func NewProductionConfig() Config { + return Config{ + Level: NewAtomicLevelAt(InfoLevel), + Development: false, + Sampling: &SamplingConfig{ + Initial: 100, + Thereafter: 100, + }, + Encoding: "json", + EncoderConfig: NewProductionEncoderConfig(), + OutputPaths: []string{"stderr"}, + ErrorOutputPaths: []string{"stderr"}, + } +} + +// NewDevelopmentEncoderConfig returns an opinionated EncoderConfig for +// development environments. +func NewDevelopmentEncoderConfig() zapcore.EncoderConfig { + return zapcore.EncoderConfig{ + // Keys can be anything except the empty string. + TimeKey: "T", + LevelKey: "L", + NameKey: "N", + CallerKey: "C", + MessageKey: "M", + StacktraceKey: "S", + LineEnding: zapcore.DefaultLineEnding, + EncodeLevel: zapcore.CapitalLevelEncoder, + EncodeTime: zapcore.ISO8601TimeEncoder, + EncodeDuration: zapcore.StringDurationEncoder, + EncodeCaller: zapcore.ShortCallerEncoder, + } +} + +// NewDevelopmentConfig is a reasonable development logging configuration. +// Logging is enabled at DebugLevel and above. +// +// It enables development mode (which makes DPanicLevel logs panic), uses a +// console encoder, writes to standard error, and disables sampling. +// Stacktraces are automatically included on logs of WarnLevel and above. +func NewDevelopmentConfig() Config { + return Config{ + Level: NewAtomicLevelAt(DebugLevel), + Development: true, + Encoding: "console", + EncoderConfig: NewDevelopmentEncoderConfig(), + OutputPaths: []string{"stderr"}, + ErrorOutputPaths: []string{"stderr"}, + } +} + +// Build constructs a logger from the Config and Options. +func (cfg Config) Build(opts ...Option) (*Logger, error) { + enc, err := cfg.buildEncoder() + if err != nil { + return nil, err + } + + sink, errSink, err := cfg.openSinks() + if err != nil { + return nil, err + } + + log := New( + zapcore.NewCore(enc, sink, cfg.Level), + cfg.buildOptions(errSink)..., + ) + if len(opts) > 0 { + log = log.WithOptions(opts...) + } + return log, nil +} + +func (cfg Config) buildOptions(errSink zapcore.WriteSyncer) []Option { + opts := []Option{ErrorOutput(errSink)} + + if cfg.Development { + opts = append(opts, Development()) + } + + if !cfg.DisableCaller { + opts = append(opts, AddCaller()) + } + + stackLevel := ErrorLevel + if cfg.Development { + stackLevel = WarnLevel + } + if !cfg.DisableStacktrace { + opts = append(opts, AddStacktrace(stackLevel)) + } + + if cfg.Sampling != nil { + opts = append(opts, WrapCore(func(core zapcore.Core) zapcore.Core { + return zapcore.NewSampler(core, time.Second, int(cfg.Sampling.Initial), int(cfg.Sampling.Thereafter)) + })) + } + + if len(cfg.InitialFields) > 0 { + fs := make([]Field, 0, len(cfg.InitialFields)) + keys := make([]string, 0, len(cfg.InitialFields)) + for k := range cfg.InitialFields { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + fs = append(fs, Any(k, cfg.InitialFields[k])) + } + opts = append(opts, Fields(fs...)) + } + + return opts +} + +func (cfg Config) openSinks() (zapcore.WriteSyncer, zapcore.WriteSyncer, error) { + sink, closeOut, err := Open(cfg.OutputPaths...) + if err != nil { + return nil, nil, err + } + errSink, _, err := Open(cfg.ErrorOutputPaths...) + if err != nil { + closeOut() + return nil, nil, err + } + return sink, errSink, nil +} + +func (cfg Config) buildEncoder() (zapcore.Encoder, error) { + return newEncoder(cfg.Encoding, cfg.EncoderConfig) +} diff --git a/vendor/go.uber.org/zap/doc.go b/vendor/go.uber.org/zap/doc.go new file mode 100644 index 0000000000..8638dd1b96 --- /dev/null +++ b/vendor/go.uber.org/zap/doc.go @@ -0,0 +1,113 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +// Package zap provides fast, structured, leveled logging. +// +// For applications that log in the hot path, reflection-based serialization +// and string formatting are prohibitively expensive - they're CPU-intensive +// and make many small allocations. Put differently, using json.Marshal and +// fmt.Fprintf to log tons of interface{} makes your application slow. +// +// Zap takes a different approach. It includes a reflection-free, +// zero-allocation JSON encoder, and the base Logger strives to avoid +// serialization overhead and allocations wherever possible. By building the +// high-level SugaredLogger on that foundation, zap lets users choose when +// they need to count every allocation and when they'd prefer a more familiar, +// loosely typed API. +// +// Choosing a Logger +// +// In contexts where performance is nice, but not critical, use the +// SugaredLogger. It's 4-10x faster than other structured logging packages and +// supports both structured and printf-style logging. Like log15 and go-kit, +// the SugaredLogger's structured logging APIs are loosely typed and accept a +// variadic number of key-value pairs. (For more advanced use cases, they also +// accept strongly typed fields - see the SugaredLogger.With documentation for +// details.) +// sugar := zap.NewExample().Sugar() +// defer sugar.Sync() +// sugar.Infow("failed to fetch URL", +// "url", "http://example.com", +// "attempt", 3, +// "backoff", time.Second, +// ) +// sugar.Infof("failed to fetch URL: %s", "http://example.com") +// +// By default, loggers are unbuffered. However, since zap's low-level APIs +// allow buffering, calling Sync before letting your process exit is a good +// habit. +// +// In the rare contexts where every microsecond and every allocation matter, +// use the Logger. It's even faster than the SugaredLogger and allocates far +// less, but it only supports strongly-typed, structured logging. +// logger := zap.NewExample() +// defer logger.Sync() +// logger.Info("failed to fetch URL", +// zap.String("url", "http://example.com"), +// zap.Int("attempt", 3), +// zap.Duration("backoff", time.Second), +// ) +// +// Choosing between the Logger and SugaredLogger doesn't need to be an +// application-wide decision: converting between the two is simple and +// inexpensive. +// logger := zap.NewExample() +// defer logger.Sync() +// sugar := logger.Sugar() +// plain := sugar.Desugar() +// +// Configuring Zap +// +// The simplest way to build a Logger is to use zap's opinionated presets: +// NewExample, NewProduction, and NewDevelopment. These presets build a logger +// with a single function call: +// logger, err := zap.NewProduction() +// if err != nil { +// log.Fatalf("can't initialize zap logger: %v", err) +// } +// defer logger.Sync() +// +// Presets are fine for small projects, but larger projects and organizations +// naturally require a bit more customization. For most users, zap's Config +// struct strikes the right balance between flexibility and convenience. See +// the package-level BasicConfiguration example for sample code. +// +// More unusual configurations (splitting output between files, sending logs +// to a message queue, etc.) are possible, but require direct use of +// go.uber.org/zap/zapcore. See the package-level AdvancedConfiguration +// example for sample code. +// +// Extending Zap +// +// The zap package itself is a relatively thin wrapper around the interfaces +// in go.uber.org/zap/zapcore. Extending zap to support a new encoding (e.g., +// BSON), a new log sink (e.g., Kafka), or something more exotic (perhaps an +// exception aggregation service, like Sentry or Rollbar) typically requires +// implementing the zapcore.Encoder, zapcore.WriteSyncer, or zapcore.Core +// interfaces. See the zapcore documentation for details. +// +// Similarly, package authors can use the high-performance Encoder and Core +// implementations in the zapcore package to build their own loggers. +// +// Frequently Asked Questions +// +// An FAQ covering everything from installation errors to design decisions is +// available at https://github.com/uber-go/zap/blob/master/FAQ.md. +package zap // import "go.uber.org/zap" diff --git a/vendor/go.uber.org/zap/encoder.go b/vendor/go.uber.org/zap/encoder.go new file mode 100644 index 0000000000..2e9d3c3415 --- /dev/null +++ b/vendor/go.uber.org/zap/encoder.go @@ -0,0 +1,75 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import ( + "errors" + "fmt" + "sync" + + "go.uber.org/zap/zapcore" +) + +var ( + errNoEncoderNameSpecified = errors.New("no encoder name specified") + + _encoderNameToConstructor = map[string]func(zapcore.EncoderConfig) (zapcore.Encoder, error){ + "console": func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) { + return zapcore.NewConsoleEncoder(encoderConfig), nil + }, + "json": func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) { + return zapcore.NewJSONEncoder(encoderConfig), nil + }, + } + _encoderMutex sync.RWMutex +) + +// RegisterEncoder registers an encoder constructor, which the Config struct +// can then reference. By default, the "json" and "console" encoders are +// registered. +// +// Attempting to register an encoder whose name is already taken returns an +// error. +func RegisterEncoder(name string, constructor func(zapcore.EncoderConfig) (zapcore.Encoder, error)) error { + _encoderMutex.Lock() + defer _encoderMutex.Unlock() + if name == "" { + return errNoEncoderNameSpecified + } + if _, ok := _encoderNameToConstructor[name]; ok { + return fmt.Errorf("encoder already registered for name %q", name) + } + _encoderNameToConstructor[name] = constructor + return nil +} + +func newEncoder(name string, encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) { + _encoderMutex.RLock() + defer _encoderMutex.RUnlock() + if name == "" { + return nil, errNoEncoderNameSpecified + } + constructor, ok := _encoderNameToConstructor[name] + if !ok { + return nil, fmt.Errorf("no encoder registered for name %q", name) + } + return constructor(encoderConfig) +} diff --git a/vendor/go.uber.org/zap/error.go b/vendor/go.uber.org/zap/error.go new file mode 100644 index 0000000000..65982a51e5 --- /dev/null +++ b/vendor/go.uber.org/zap/error.go @@ -0,0 +1,80 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package zap + +import ( + "sync" + + "go.uber.org/zap/zapcore" +) + +var _errArrayElemPool = sync.Pool{New: func() interface{} { + return &errArrayElem{} +}} + +// Error is shorthand for the common idiom NamedError("error", err). +func Error(err error) Field { + return NamedError("error", err) +} + +// NamedError constructs a field that lazily stores err.Error() under the +// provided key. Errors which also implement fmt.Formatter (like those produced +// by github.com/pkg/errors) will also have their verbose representation stored +// under key+"Verbose". If passed a nil error, the field is a no-op. +// +// For the common case in which the key is simply "error", the Error function +// is shorter and less repetitive. +func NamedError(key string, err error) Field { + if err == nil { + return Skip() + } + return Field{Key: key, Type: zapcore.ErrorType, Interface: err} +} + +type errArray []error + +func (errs errArray) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range errs { + if errs[i] == nil { + continue + } + // To represent each error as an object with an "error" attribute and + // potentially an "errorVerbose" attribute, we need to wrap it in a + // type that implements LogObjectMarshaler. To prevent this from + // allocating, pool the wrapper type. + elem := _errArrayElemPool.Get().(*errArrayElem) + elem.error = errs[i] + arr.AppendObject(elem) + elem.error = nil + _errArrayElemPool.Put(elem) + } + return nil +} + +type errArrayElem struct { + error +} + +func (e *errArrayElem) MarshalLogObject(enc zapcore.ObjectEncoder) error { + // Re-use the error field's logic, which supports non-standard error types. + Error(e.error).AddTo(enc) + return nil +} diff --git a/vendor/go.uber.org/zap/field.go b/vendor/go.uber.org/zap/field.go new file mode 100644 index 0000000000..5130e13477 --- /dev/null +++ b/vendor/go.uber.org/zap/field.go @@ -0,0 +1,310 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import ( + "fmt" + "math" + "time" + + "go.uber.org/zap/zapcore" +) + +// Field is an alias for Field. Aliasing this type dramatically +// improves the navigability of this package's API documentation. +type Field = zapcore.Field + +// Skip constructs a no-op field, which is often useful when handling invalid +// inputs in other Field constructors. +func Skip() Field { + return Field{Type: zapcore.SkipType} +} + +// Binary constructs a field that carries an opaque binary blob. +// +// Binary data is serialized in an encoding-appropriate format. For example, +// zap's JSON encoder base64-encodes binary blobs. To log UTF-8 encoded text, +// use ByteString. +func Binary(key string, val []byte) Field { + return Field{Key: key, Type: zapcore.BinaryType, Interface: val} +} + +// Bool constructs a field that carries a bool. +func Bool(key string, val bool) Field { + var ival int64 + if val { + ival = 1 + } + return Field{Key: key, Type: zapcore.BoolType, Integer: ival} +} + +// ByteString constructs a field that carries UTF-8 encoded text as a []byte. +// To log opaque binary blobs (which aren't necessarily valid UTF-8), use +// Binary. +func ByteString(key string, val []byte) Field { + return Field{Key: key, Type: zapcore.ByteStringType, Interface: val} +} + +// Complex128 constructs a field that carries a complex number. Unlike most +// numeric fields, this costs an allocation (to convert the complex128 to +// interface{}). +func Complex128(key string, val complex128) Field { + return Field{Key: key, Type: zapcore.Complex128Type, Interface: val} +} + +// Complex64 constructs a field that carries a complex number. Unlike most +// numeric fields, this costs an allocation (to convert the complex64 to +// interface{}). +func Complex64(key string, val complex64) Field { + return Field{Key: key, Type: zapcore.Complex64Type, Interface: val} +} + +// Float64 constructs a field that carries a float64. The way the +// floating-point value is represented is encoder-dependent, so marshaling is +// necessarily lazy. +func Float64(key string, val float64) Field { + return Field{Key: key, Type: zapcore.Float64Type, Integer: int64(math.Float64bits(val))} +} + +// Float32 constructs a field that carries a float32. The way the +// floating-point value is represented is encoder-dependent, so marshaling is +// necessarily lazy. +func Float32(key string, val float32) Field { + return Field{Key: key, Type: zapcore.Float32Type, Integer: int64(math.Float32bits(val))} +} + +// Int constructs a field with the given key and value. +func Int(key string, val int) Field { + return Int64(key, int64(val)) +} + +// Int64 constructs a field with the given key and value. +func Int64(key string, val int64) Field { + return Field{Key: key, Type: zapcore.Int64Type, Integer: val} +} + +// Int32 constructs a field with the given key and value. +func Int32(key string, val int32) Field { + return Field{Key: key, Type: zapcore.Int32Type, Integer: int64(val)} +} + +// Int16 constructs a field with the given key and value. +func Int16(key string, val int16) Field { + return Field{Key: key, Type: zapcore.Int16Type, Integer: int64(val)} +} + +// Int8 constructs a field with the given key and value. +func Int8(key string, val int8) Field { + return Field{Key: key, Type: zapcore.Int8Type, Integer: int64(val)} +} + +// String constructs a field with the given key and value. +func String(key string, val string) Field { + return Field{Key: key, Type: zapcore.StringType, String: val} +} + +// Uint constructs a field with the given key and value. +func Uint(key string, val uint) Field { + return Uint64(key, uint64(val)) +} + +// Uint64 constructs a field with the given key and value. +func Uint64(key string, val uint64) Field { + return Field{Key: key, Type: zapcore.Uint64Type, Integer: int64(val)} +} + +// Uint32 constructs a field with the given key and value. +func Uint32(key string, val uint32) Field { + return Field{Key: key, Type: zapcore.Uint32Type, Integer: int64(val)} +} + +// Uint16 constructs a field with the given key and value. +func Uint16(key string, val uint16) Field { + return Field{Key: key, Type: zapcore.Uint16Type, Integer: int64(val)} +} + +// Uint8 constructs a field with the given key and value. +func Uint8(key string, val uint8) Field { + return Field{Key: key, Type: zapcore.Uint8Type, Integer: int64(val)} +} + +// Uintptr constructs a field with the given key and value. +func Uintptr(key string, val uintptr) Field { + return Field{Key: key, Type: zapcore.UintptrType, Integer: int64(val)} +} + +// Reflect constructs a field with the given key and an arbitrary object. It uses +// an encoding-appropriate, reflection-based function to lazily serialize nearly +// any object into the logging context, but it's relatively slow and +// allocation-heavy. Outside tests, Any is always a better choice. +// +// If encoding fails (e.g., trying to serialize a map[int]string to JSON), Reflect +// includes the error message in the final log output. +func Reflect(key string, val interface{}) Field { + return Field{Key: key, Type: zapcore.ReflectType, Interface: val} +} + +// Namespace creates a named, isolated scope within the logger's context. All +// subsequent fields will be added to the new namespace. +// +// This helps prevent key collisions when injecting loggers into sub-components +// or third-party libraries. +func Namespace(key string) Field { + return Field{Key: key, Type: zapcore.NamespaceType} +} + +// Stringer constructs a field with the given key and the output of the value's +// String method. The Stringer's String method is called lazily. +func Stringer(key string, val fmt.Stringer) Field { + return Field{Key: key, Type: zapcore.StringerType, Interface: val} +} + +// Time constructs a Field with the given key and value. The encoder +// controls how the time is serialized. +func Time(key string, val time.Time) Field { + return Field{Key: key, Type: zapcore.TimeType, Integer: val.UnixNano(), Interface: val.Location()} +} + +// Stack constructs a field that stores a stacktrace of the current goroutine +// under provided key. Keep in mind that taking a stacktrace is eager and +// expensive (relatively speaking); this function both makes an allocation and +// takes about two microseconds. +func Stack(key string) Field { + // Returning the stacktrace as a string costs an allocation, but saves us + // from expanding the zapcore.Field union struct to include a byte slice. Since + // taking a stacktrace is already so expensive (~10us), the extra allocation + // is okay. + return String(key, takeStacktrace()) +} + +// Duration constructs a field with the given key and value. The encoder +// controls how the duration is serialized. +func Duration(key string, val time.Duration) Field { + return Field{Key: key, Type: zapcore.DurationType, Integer: int64(val)} +} + +// Object constructs a field with the given key and ObjectMarshaler. It +// provides a flexible, but still type-safe and efficient, way to add map- or +// struct-like user-defined types to the logging context. The struct's +// MarshalLogObject method is called lazily. +func Object(key string, val zapcore.ObjectMarshaler) Field { + return Field{Key: key, Type: zapcore.ObjectMarshalerType, Interface: val} +} + +// Any takes a key and an arbitrary value and chooses the best way to represent +// them as a field, falling back to a reflection-based approach only if +// necessary. +// +// Since byte/uint8 and rune/int32 are aliases, Any can't differentiate between +// them. To minimize surprises, []byte values are treated as binary blobs, byte +// values are treated as uint8, and runes are always treated as integers. +func Any(key string, value interface{}) Field { + switch val := value.(type) { + case zapcore.ObjectMarshaler: + return Object(key, val) + case zapcore.ArrayMarshaler: + return Array(key, val) + case bool: + return Bool(key, val) + case []bool: + return Bools(key, val) + case complex128: + return Complex128(key, val) + case []complex128: + return Complex128s(key, val) + case complex64: + return Complex64(key, val) + case []complex64: + return Complex64s(key, val) + case float64: + return Float64(key, val) + case []float64: + return Float64s(key, val) + case float32: + return Float32(key, val) + case []float32: + return Float32s(key, val) + case int: + return Int(key, val) + case []int: + return Ints(key, val) + case int64: + return Int64(key, val) + case []int64: + return Int64s(key, val) + case int32: + return Int32(key, val) + case []int32: + return Int32s(key, val) + case int16: + return Int16(key, val) + case []int16: + return Int16s(key, val) + case int8: + return Int8(key, val) + case []int8: + return Int8s(key, val) + case string: + return String(key, val) + case []string: + return Strings(key, val) + case uint: + return Uint(key, val) + case []uint: + return Uints(key, val) + case uint64: + return Uint64(key, val) + case []uint64: + return Uint64s(key, val) + case uint32: + return Uint32(key, val) + case []uint32: + return Uint32s(key, val) + case uint16: + return Uint16(key, val) + case []uint16: + return Uint16s(key, val) + case uint8: + return Uint8(key, val) + case []byte: + return Binary(key, val) + case uintptr: + return Uintptr(key, val) + case []uintptr: + return Uintptrs(key, val) + case time.Time: + return Time(key, val) + case []time.Time: + return Times(key, val) + case time.Duration: + return Duration(key, val) + case []time.Duration: + return Durations(key, val) + case error: + return NamedError(key, val) + case []error: + return Errors(key, val) + case fmt.Stringer: + return Stringer(key, val) + default: + return Reflect(key, val) + } +} diff --git a/vendor/go.uber.org/zap/flag.go b/vendor/go.uber.org/zap/flag.go new file mode 100644 index 0000000000..1312875072 --- /dev/null +++ b/vendor/go.uber.org/zap/flag.go @@ -0,0 +1,39 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import ( + "flag" + + "go.uber.org/zap/zapcore" +) + +// LevelFlag uses the standard library's flag.Var to declare a global flag +// with the specified name, default, and usage guidance. The returned value is +// a pointer to the value of the flag. +// +// If you don't want to use the flag package's global state, you can use any +// non-nil *Level as a flag.Value with your own *flag.FlagSet. +func LevelFlag(name string, defaultLevel zapcore.Level, usage string) *zapcore.Level { + lvl := defaultLevel + flag.Var(&lvl, name, usage) + return &lvl +} diff --git a/vendor/go.uber.org/zap/glide.lock b/vendor/go.uber.org/zap/glide.lock new file mode 100644 index 0000000000..881b462c0e --- /dev/null +++ b/vendor/go.uber.org/zap/glide.lock @@ -0,0 +1,76 @@ +hash: f073ba522c06c88ea3075bde32a8aaf0969a840a66cab6318a0897d141ffee92 +updated: 2017-07-22T18:06:49.598185334-07:00 +imports: +- name: go.uber.org/atomic + version: 4e336646b2ef9fc6e47be8e21594178f98e5ebcf +- name: go.uber.org/multierr + version: 3c4937480c32f4c13a875a1829af76c98ca3d40a +testImports: +- name: github.com/apex/log + version: d9b960447bfa720077b2da653cc79e533455b499 + subpackages: + - handlers/json +- name: github.com/axw/gocov + version: 3a69a0d2a4ef1f263e2d92b041a69593d6964fe8 + subpackages: + - gocov +- name: github.com/davecgh/go-spew + version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9 + subpackages: + - spew +- name: github.com/fatih/color + version: 62e9147c64a1ed519147b62a56a14e83e2be02c1 +- name: github.com/go-kit/kit + version: e10f5bf035be9af21fd5b2fb4469d5716c6ab07d + subpackages: + - log +- name: github.com/go-logfmt/logfmt + version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 +- name: github.com/go-stack/stack + version: 54be5f394ed2c3e19dac9134a40a95ba5a017f7b +- name: github.com/golang/lint + version: c5fb716d6688a859aae56d26d3e6070808df29f7 + subpackages: + - golint +- name: github.com/kr/logfmt + version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 +- name: github.com/mattn/go-colorable + version: 3fa8c76f9daed4067e4a806fb7e4dc86455c6d6a +- name: github.com/mattn/go-isatty + version: fc9e8d8ef48496124e79ae0df75490096eccf6fe +- name: github.com/mattn/goveralls + version: 6efce81852ad1b7567c17ad71b03aeccc9dd9ae0 +- name: github.com/pborman/uuid + version: e790cca94e6cc75c7064b1332e63811d4aae1a53 +- name: github.com/pkg/errors + version: 645ef00459ed84a119197bfb8d8205042c6df63d +- name: github.com/pmezard/go-difflib + version: d8ed2627bdf02c080bf22230dbb337003b7aba2d + subpackages: + - difflib +- name: github.com/rs/zerolog + version: eed4c2b94d945e0b2456ad6aa518a443986b5f22 +- name: github.com/satori/go.uuid + version: 5bf94b69c6b68ee1b541973bb8e1144db23a194b +- name: github.com/sirupsen/logrus + version: 7dd06bf38e1e13df288d471a57d5adbac106be9e +- name: github.com/stretchr/testify + version: f6abca593680b2315d2075e0f5e2a9751e3f431a + subpackages: + - assert + - require +- name: go.pedge.io/lion + version: 87958e8713f1fa138d993087133b97e976642159 +- name: golang.org/x/sys + version: c4489faa6e5ab84c0ef40d6ee878f7a030281f0f + subpackages: + - unix +- name: golang.org/x/tools + version: 496819729719f9d07692195e0a94d6edd2251389 + subpackages: + - cover +- name: gopkg.in/inconshreveable/log15.v2 + version: b105bd37f74e5d9dc7b6ad7806715c7a2b83fd3f + subpackages: + - stack + - term diff --git a/vendor/go.uber.org/zap/glide.yaml b/vendor/go.uber.org/zap/glide.yaml new file mode 100644 index 0000000000..94412594ca --- /dev/null +++ b/vendor/go.uber.org/zap/glide.yaml @@ -0,0 +1,35 @@ +package: go.uber.org/zap +license: MIT +import: +- package: go.uber.org/atomic + version: ^1 +- package: go.uber.org/multierr + version: ^1 +testImport: +- package: github.com/satori/go.uuid +- package: github.com/sirupsen/logrus +- package: github.com/apex/log + subpackages: + - handlers/json +- package: github.com/go-kit/kit + subpackages: + - log +- package: github.com/stretchr/testify + subpackages: + - assert + - require +- package: gopkg.in/inconshreveable/log15.v2 +- package: github.com/mattn/goveralls +- package: github.com/pborman/uuid +- package: github.com/pkg/errors +- package: go.pedge.io/lion +- package: github.com/rs/zerolog +- package: golang.org/x/tools + subpackages: + - cover +- package: github.com/golang/lint + subpackages: + - golint +- package: github.com/axw/gocov + subpackages: + - gocov diff --git a/vendor/go.uber.org/zap/global.go b/vendor/go.uber.org/zap/global.go new file mode 100644 index 0000000000..c1ac0507cd --- /dev/null +++ b/vendor/go.uber.org/zap/global.go @@ -0,0 +1,168 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import ( + "bytes" + "fmt" + "log" + "os" + "sync" + + "go.uber.org/zap/zapcore" +) + +const ( + _loggerWriterDepth = 2 + _programmerErrorTemplate = "You've found a bug in zap! Please file a bug at " + + "https://github.com/uber-go/zap/issues/new and reference this error: %v" +) + +var ( + _globalMu sync.RWMutex + _globalL = NewNop() + _globalS = _globalL.Sugar() +) + +// L returns the global Logger, which can be reconfigured with ReplaceGlobals. +// It's safe for concurrent use. +func L() *Logger { + _globalMu.RLock() + l := _globalL + _globalMu.RUnlock() + return l +} + +// S returns the global SugaredLogger, which can be reconfigured with +// ReplaceGlobals. It's safe for concurrent use. +func S() *SugaredLogger { + _globalMu.RLock() + s := _globalS + _globalMu.RUnlock() + return s +} + +// ReplaceGlobals replaces the global Logger and SugaredLogger, and returns a +// function to restore the original values. It's safe for concurrent use. +func ReplaceGlobals(logger *Logger) func() { + _globalMu.Lock() + prev := _globalL + _globalL = logger + _globalS = logger.Sugar() + _globalMu.Unlock() + return func() { ReplaceGlobals(prev) } +} + +// NewStdLog returns a *log.Logger which writes to the supplied zap Logger at +// InfoLevel. To redirect the standard library's package-global logging +// functions, use RedirectStdLog instead. +func NewStdLog(l *Logger) *log.Logger { + logger := l.WithOptions(AddCallerSkip(_stdLogDefaultDepth + _loggerWriterDepth)) + f := logger.Info + return log.New(&loggerWriter{f}, "" /* prefix */, 0 /* flags */) +} + +// NewStdLogAt returns *log.Logger which writes to supplied zap logger at +// required level. +func NewStdLogAt(l *Logger, level zapcore.Level) (*log.Logger, error) { + logger := l.WithOptions(AddCallerSkip(_stdLogDefaultDepth + _loggerWriterDepth)) + logFunc, err := levelToFunc(logger, level) + if err != nil { + return nil, err + } + return log.New(&loggerWriter{logFunc}, "" /* prefix */, 0 /* flags */), nil +} + +// RedirectStdLog redirects output from the standard library's package-global +// logger to the supplied logger at InfoLevel. Since zap already handles caller +// annotations, timestamps, etc., it automatically disables the standard +// library's annotations and prefixing. +// +// It returns a function to restore the original prefix and flags and reset the +// standard library's output to os.Stderr. +func RedirectStdLog(l *Logger) func() { + f, err := redirectStdLogAt(l, InfoLevel) + if err != nil { + // Can't get here, since passing InfoLevel to redirectStdLogAt always + // works. + panic(fmt.Sprintf(_programmerErrorTemplate, err)) + } + return f +} + +// RedirectStdLogAt redirects output from the standard library's package-global +// logger to the supplied logger at the specified level. Since zap already +// handles caller annotations, timestamps, etc., it automatically disables the +// standard library's annotations and prefixing. +// +// It returns a function to restore the original prefix and flags and reset the +// standard library's output to os.Stderr. +func RedirectStdLogAt(l *Logger, level zapcore.Level) (func(), error) { + return redirectStdLogAt(l, level) +} + +func redirectStdLogAt(l *Logger, level zapcore.Level) (func(), error) { + flags := log.Flags() + prefix := log.Prefix() + log.SetFlags(0) + log.SetPrefix("") + logger := l.WithOptions(AddCallerSkip(_stdLogDefaultDepth + _loggerWriterDepth)) + logFunc, err := levelToFunc(logger, level) + if err != nil { + return nil, err + } + log.SetOutput(&loggerWriter{logFunc}) + return func() { + log.SetFlags(flags) + log.SetPrefix(prefix) + log.SetOutput(os.Stderr) + }, nil +} + +func levelToFunc(logger *Logger, lvl zapcore.Level) (func(string, ...Field), error) { + switch lvl { + case DebugLevel: + return logger.Debug, nil + case InfoLevel: + return logger.Info, nil + case WarnLevel: + return logger.Warn, nil + case ErrorLevel: + return logger.Error, nil + case DPanicLevel: + return logger.DPanic, nil + case PanicLevel: + return logger.Panic, nil + case FatalLevel: + return logger.Fatal, nil + } + return nil, fmt.Errorf("unrecognized level: %q", lvl) +} + +type loggerWriter struct { + logFunc func(msg string, fields ...Field) +} + +func (l *loggerWriter) Write(p []byte) (int, error) { + p = bytes.TrimSpace(p) + l.logFunc(string(p)) + return len(p), nil +} diff --git a/vendor/go.uber.org/zap/global_go112.go b/vendor/go.uber.org/zap/global_go112.go new file mode 100644 index 0000000000..6b5dbda807 --- /dev/null +++ b/vendor/go.uber.org/zap/global_go112.go @@ -0,0 +1,26 @@ +// Copyright (c) 2019 Uber Technologies, Inc. +// +// 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. + +// See #682 for more information. +// +build go1.12 + +package zap + +const _stdLogDefaultDepth = 1 diff --git a/vendor/go.uber.org/zap/global_prego112.go b/vendor/go.uber.org/zap/global_prego112.go new file mode 100644 index 0000000000..d3ab9af933 --- /dev/null +++ b/vendor/go.uber.org/zap/global_prego112.go @@ -0,0 +1,26 @@ +// Copyright (c) 2019 Uber Technologies, Inc. +// +// 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. + +// See #682 for more information. +// +build !go1.12 + +package zap + +const _stdLogDefaultDepth = 2 diff --git a/vendor/go.uber.org/zap/http_handler.go b/vendor/go.uber.org/zap/http_handler.go new file mode 100644 index 0000000000..1b0ecaca9c --- /dev/null +++ b/vendor/go.uber.org/zap/http_handler.go @@ -0,0 +1,81 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import ( + "encoding/json" + "fmt" + "net/http" + + "go.uber.org/zap/zapcore" +) + +// ServeHTTP is a simple JSON endpoint that can report on or change the current +// logging level. +// +// GET requests return a JSON description of the current logging level. PUT +// requests change the logging level and expect a payload like: +// {"level":"info"} +// +// It's perfectly safe to change the logging level while a program is running. +func (lvl AtomicLevel) ServeHTTP(w http.ResponseWriter, r *http.Request) { + type errorResponse struct { + Error string `json:"error"` + } + type payload struct { + Level *zapcore.Level `json:"level"` + } + + enc := json.NewEncoder(w) + + switch r.Method { + + case http.MethodGet: + current := lvl.Level() + enc.Encode(payload{Level: ¤t}) + + case http.MethodPut: + var req payload + + if errmess := func() string { + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + return fmt.Sprintf("Request body must be well-formed JSON: %v", err) + } + if req.Level == nil { + return "Must specify a logging level." + } + return "" + }(); errmess != "" { + w.WriteHeader(http.StatusBadRequest) + enc.Encode(errorResponse{Error: errmess}) + return + } + + lvl.SetLevel(*req.Level) + enc.Encode(req) + + default: + w.WriteHeader(http.StatusMethodNotAllowed) + enc.Encode(errorResponse{ + Error: "Only GET and PUT are supported.", + }) + } +} diff --git a/vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go b/vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go new file mode 100644 index 0000000000..dad583aaa5 --- /dev/null +++ b/vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go @@ -0,0 +1,31 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +// Package bufferpool houses zap's shared internal buffer pool. Third-party +// packages can recreate the same functionality with buffers.NewPool. +package bufferpool + +import "go.uber.org/zap/buffer" + +var ( + _pool = buffer.NewPool() + // Get retrieves a buffer from the pool, creating one if necessary. + Get = _pool.Get +) diff --git a/vendor/go.uber.org/zap/internal/color/color.go b/vendor/go.uber.org/zap/internal/color/color.go new file mode 100644 index 0000000000..c4d5d02abc --- /dev/null +++ b/vendor/go.uber.org/zap/internal/color/color.go @@ -0,0 +1,44 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +// Package color adds coloring functionality for TTY output. +package color + +import "fmt" + +// Foreground colors. +const ( + Black Color = iota + 30 + Red + Green + Yellow + Blue + Magenta + Cyan + White +) + +// Color represents a text color. +type Color uint8 + +// Add adds the coloring to the given string. +func (c Color) Add(s string) string { + return fmt.Sprintf("\x1b[%dm%s\x1b[0m", uint8(c), s) +} diff --git a/vendor/go.uber.org/zap/internal/exit/exit.go b/vendor/go.uber.org/zap/internal/exit/exit.go new file mode 100644 index 0000000000..dfc5b05feb --- /dev/null +++ b/vendor/go.uber.org/zap/internal/exit/exit.go @@ -0,0 +1,64 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +// Package exit provides stubs so that unit tests can exercise code that calls +// os.Exit(1). +package exit + +import "os" + +var real = func() { os.Exit(1) } + +// Exit normally terminates the process by calling os.Exit(1). If the package +// is stubbed, it instead records a call in the testing spy. +func Exit() { + real() +} + +// A StubbedExit is a testing fake for os.Exit. +type StubbedExit struct { + Exited bool + prev func() +} + +// Stub substitutes a fake for the call to os.Exit(1). +func Stub() *StubbedExit { + s := &StubbedExit{prev: real} + real = s.exit + return s +} + +// WithStub runs the supplied function with Exit stubbed. It returns the stub +// used, so that users can test whether the process would have crashed. +func WithStub(f func()) *StubbedExit { + s := Stub() + defer s.Unstub() + f() + return s +} + +// Unstub restores the previous exit function. +func (se *StubbedExit) Unstub() { + real = se.prev +} + +func (se *StubbedExit) exit() { + se.Exited = true +} diff --git a/vendor/go.uber.org/zap/level.go b/vendor/go.uber.org/zap/level.go new file mode 100644 index 0000000000..3567a9a1e6 --- /dev/null +++ b/vendor/go.uber.org/zap/level.go @@ -0,0 +1,132 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import ( + "go.uber.org/atomic" + "go.uber.org/zap/zapcore" +) + +const ( + // DebugLevel logs are typically voluminous, and are usually disabled in + // production. + DebugLevel = zapcore.DebugLevel + // InfoLevel is the default logging priority. + InfoLevel = zapcore.InfoLevel + // WarnLevel logs are more important than Info, but don't need individual + // human review. + WarnLevel = zapcore.WarnLevel + // ErrorLevel logs are high-priority. If an application is running smoothly, + // it shouldn't generate any error-level logs. + ErrorLevel = zapcore.ErrorLevel + // DPanicLevel logs are particularly important errors. In development the + // logger panics after writing the message. + DPanicLevel = zapcore.DPanicLevel + // PanicLevel logs a message, then panics. + PanicLevel = zapcore.PanicLevel + // FatalLevel logs a message, then calls os.Exit(1). + FatalLevel = zapcore.FatalLevel +) + +// LevelEnablerFunc is a convenient way to implement zapcore.LevelEnabler with +// an anonymous function. +// +// It's particularly useful when splitting log output between different +// outputs (e.g., standard error and standard out). For sample code, see the +// package-level AdvancedConfiguration example. +type LevelEnablerFunc func(zapcore.Level) bool + +// Enabled calls the wrapped function. +func (f LevelEnablerFunc) Enabled(lvl zapcore.Level) bool { return f(lvl) } + +// An AtomicLevel is an atomically changeable, dynamic logging level. It lets +// you safely change the log level of a tree of loggers (the root logger and +// any children created by adding context) at runtime. +// +// The AtomicLevel itself is an http.Handler that serves a JSON endpoint to +// alter its level. +// +// AtomicLevels must be created with the NewAtomicLevel constructor to allocate +// their internal atomic pointer. +type AtomicLevel struct { + l *atomic.Int32 +} + +// NewAtomicLevel creates an AtomicLevel with InfoLevel and above logging +// enabled. +func NewAtomicLevel() AtomicLevel { + return AtomicLevel{ + l: atomic.NewInt32(int32(InfoLevel)), + } +} + +// NewAtomicLevelAt is a convenience function that creates an AtomicLevel +// and then calls SetLevel with the given level. +func NewAtomicLevelAt(l zapcore.Level) AtomicLevel { + a := NewAtomicLevel() + a.SetLevel(l) + return a +} + +// Enabled implements the zapcore.LevelEnabler interface, which allows the +// AtomicLevel to be used in place of traditional static levels. +func (lvl AtomicLevel) Enabled(l zapcore.Level) bool { + return lvl.Level().Enabled(l) +} + +// Level returns the minimum enabled log level. +func (lvl AtomicLevel) Level() zapcore.Level { + return zapcore.Level(int8(lvl.l.Load())) +} + +// SetLevel alters the logging level. +func (lvl AtomicLevel) SetLevel(l zapcore.Level) { + lvl.l.Store(int32(l)) +} + +// String returns the string representation of the underlying Level. +func (lvl AtomicLevel) String() string { + return lvl.Level().String() +} + +// UnmarshalText unmarshals the text to an AtomicLevel. It uses the same text +// representations as the static zapcore.Levels ("debug", "info", "warn", +// "error", "dpanic", "panic", and "fatal"). +func (lvl *AtomicLevel) UnmarshalText(text []byte) error { + if lvl.l == nil { + lvl.l = &atomic.Int32{} + } + + var l zapcore.Level + if err := l.UnmarshalText(text); err != nil { + return err + } + + lvl.SetLevel(l) + return nil +} + +// MarshalText marshals the AtomicLevel to a byte slice. It uses the same +// text representation as the static zapcore.Levels ("debug", "info", "warn", +// "error", "dpanic", "panic", and "fatal"). +func (lvl AtomicLevel) MarshalText() (text []byte, err error) { + return lvl.Level().MarshalText() +} diff --git a/vendor/go.uber.org/zap/logger.go b/vendor/go.uber.org/zap/logger.go new file mode 100644 index 0000000000..dc8f6e3a4b --- /dev/null +++ b/vendor/go.uber.org/zap/logger.go @@ -0,0 +1,305 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import ( + "fmt" + "io/ioutil" + "os" + "runtime" + "strings" + "time" + + "go.uber.org/zap/zapcore" +) + +// A Logger provides fast, leveled, structured logging. All methods are safe +// for concurrent use. +// +// The Logger is designed for contexts in which every microsecond and every +// allocation matters, so its API intentionally favors performance and type +// safety over brevity. For most applications, the SugaredLogger strikes a +// better balance between performance and ergonomics. +type Logger struct { + core zapcore.Core + + development bool + name string + errorOutput zapcore.WriteSyncer + + addCaller bool + addStack zapcore.LevelEnabler + + callerSkip int +} + +// New constructs a new Logger from the provided zapcore.Core and Options. If +// the passed zapcore.Core is nil, it falls back to using a no-op +// implementation. +// +// This is the most flexible way to construct a Logger, but also the most +// verbose. For typical use cases, the highly-opinionated presets +// (NewProduction, NewDevelopment, and NewExample) or the Config struct are +// more convenient. +// +// For sample code, see the package-level AdvancedConfiguration example. +func New(core zapcore.Core, options ...Option) *Logger { + if core == nil { + return NewNop() + } + log := &Logger{ + core: core, + errorOutput: zapcore.Lock(os.Stderr), + addStack: zapcore.FatalLevel + 1, + } + return log.WithOptions(options...) +} + +// NewNop returns a no-op Logger. It never writes out logs or internal errors, +// and it never runs user-defined hooks. +// +// Using WithOptions to replace the Core or error output of a no-op Logger can +// re-enable logging. +func NewNop() *Logger { + return &Logger{ + core: zapcore.NewNopCore(), + errorOutput: zapcore.AddSync(ioutil.Discard), + addStack: zapcore.FatalLevel + 1, + } +} + +// NewProduction builds a sensible production Logger that writes InfoLevel and +// above logs to standard error as JSON. +// +// It's a shortcut for NewProductionConfig().Build(...Option). +func NewProduction(options ...Option) (*Logger, error) { + return NewProductionConfig().Build(options...) +} + +// NewDevelopment builds a development Logger that writes DebugLevel and above +// logs to standard error in a human-friendly format. +// +// It's a shortcut for NewDevelopmentConfig().Build(...Option). +func NewDevelopment(options ...Option) (*Logger, error) { + return NewDevelopmentConfig().Build(options...) +} + +// NewExample builds a Logger that's designed for use in zap's testable +// examples. It writes DebugLevel and above logs to standard out as JSON, but +// omits the timestamp and calling function to keep example output +// short and deterministic. +func NewExample(options ...Option) *Logger { + encoderCfg := zapcore.EncoderConfig{ + MessageKey: "msg", + LevelKey: "level", + NameKey: "logger", + EncodeLevel: zapcore.LowercaseLevelEncoder, + EncodeTime: zapcore.ISO8601TimeEncoder, + EncodeDuration: zapcore.StringDurationEncoder, + } + core := zapcore.NewCore(zapcore.NewJSONEncoder(encoderCfg), os.Stdout, DebugLevel) + return New(core).WithOptions(options...) +} + +// Sugar wraps the Logger to provide a more ergonomic, but slightly slower, +// API. Sugaring a Logger is quite inexpensive, so it's reasonable for a +// single application to use both Loggers and SugaredLoggers, converting +// between them on the boundaries of performance-sensitive code. +func (log *Logger) Sugar() *SugaredLogger { + core := log.clone() + core.callerSkip += 2 + return &SugaredLogger{core} +} + +// Named adds a new path segment to the logger's name. Segments are joined by +// periods. By default, Loggers are unnamed. +func (log *Logger) Named(s string) *Logger { + if s == "" { + return log + } + l := log.clone() + if log.name == "" { + l.name = s + } else { + l.name = strings.Join([]string{l.name, s}, ".") + } + return l +} + +// WithOptions clones the current Logger, applies the supplied Options, and +// returns the resulting Logger. It's safe to use concurrently. +func (log *Logger) WithOptions(opts ...Option) *Logger { + c := log.clone() + for _, opt := range opts { + opt.apply(c) + } + return c +} + +// With creates a child logger and adds structured context to it. Fields added +// to the child don't affect the parent, and vice versa. +func (log *Logger) With(fields ...Field) *Logger { + if len(fields) == 0 { + return log + } + l := log.clone() + l.core = l.core.With(fields) + return l +} + +// Check returns a CheckedEntry if logging a message at the specified level +// is enabled. It's a completely optional optimization; in high-performance +// applications, Check can help avoid allocating a slice to hold fields. +func (log *Logger) Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry { + return log.check(lvl, msg) +} + +// Debug logs a message at DebugLevel. The message includes any fields passed +// at the log site, as well as any fields accumulated on the logger. +func (log *Logger) Debug(msg string, fields ...Field) { + if ce := log.check(DebugLevel, msg); ce != nil { + ce.Write(fields...) + } +} + +// Info logs a message at InfoLevel. The message includes any fields passed +// at the log site, as well as any fields accumulated on the logger. +func (log *Logger) Info(msg string, fields ...Field) { + if ce := log.check(InfoLevel, msg); ce != nil { + ce.Write(fields...) + } +} + +// Warn logs a message at WarnLevel. The message includes any fields passed +// at the log site, as well as any fields accumulated on the logger. +func (log *Logger) Warn(msg string, fields ...Field) { + if ce := log.check(WarnLevel, msg); ce != nil { + ce.Write(fields...) + } +} + +// Error logs a message at ErrorLevel. The message includes any fields passed +// at the log site, as well as any fields accumulated on the logger. +func (log *Logger) Error(msg string, fields ...Field) { + if ce := log.check(ErrorLevel, msg); ce != nil { + ce.Write(fields...) + } +} + +// DPanic logs a message at DPanicLevel. The message includes any fields +// passed at the log site, as well as any fields accumulated on the logger. +// +// If the logger is in development mode, it then panics (DPanic means +// "development panic"). This is useful for catching errors that are +// recoverable, but shouldn't ever happen. +func (log *Logger) DPanic(msg string, fields ...Field) { + if ce := log.check(DPanicLevel, msg); ce != nil { + ce.Write(fields...) + } +} + +// Panic logs a message at PanicLevel. The message includes any fields passed +// at the log site, as well as any fields accumulated on the logger. +// +// The logger then panics, even if logging at PanicLevel is disabled. +func (log *Logger) Panic(msg string, fields ...Field) { + if ce := log.check(PanicLevel, msg); ce != nil { + ce.Write(fields...) + } +} + +// Fatal logs a message at FatalLevel. The message includes any fields passed +// at the log site, as well as any fields accumulated on the logger. +// +// The logger then calls os.Exit(1), even if logging at FatalLevel is +// disabled. +func (log *Logger) Fatal(msg string, fields ...Field) { + if ce := log.check(FatalLevel, msg); ce != nil { + ce.Write(fields...) + } +} + +// Sync calls the underlying Core's Sync method, flushing any buffered log +// entries. Applications should take care to call Sync before exiting. +func (log *Logger) Sync() error { + return log.core.Sync() +} + +// Core returns the Logger's underlying zapcore.Core. +func (log *Logger) Core() zapcore.Core { + return log.core +} + +func (log *Logger) clone() *Logger { + copy := *log + return © +} + +func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry { + // check must always be called directly by a method in the Logger interface + // (e.g., Check, Info, Fatal). + const callerSkipOffset = 2 + + // Create basic checked entry thru the core; this will be non-nil if the + // log message will actually be written somewhere. + ent := zapcore.Entry{ + LoggerName: log.name, + Time: time.Now(), + Level: lvl, + Message: msg, + } + ce := log.core.Check(ent, nil) + willWrite := ce != nil + + // Set up any required terminal behavior. + switch ent.Level { + case zapcore.PanicLevel: + ce = ce.Should(ent, zapcore.WriteThenPanic) + case zapcore.FatalLevel: + ce = ce.Should(ent, zapcore.WriteThenFatal) + case zapcore.DPanicLevel: + if log.development { + ce = ce.Should(ent, zapcore.WriteThenPanic) + } + } + + // Only do further annotation if we're going to write this message; checked + // entries that exist only for terminal behavior don't benefit from + // annotation. + if !willWrite { + return ce + } + + // Thread the error output through to the CheckedEntry. + ce.ErrorOutput = log.errorOutput + if log.addCaller { + ce.Entry.Caller = zapcore.NewEntryCaller(runtime.Caller(log.callerSkip + callerSkipOffset)) + if !ce.Entry.Caller.Defined { + fmt.Fprintf(log.errorOutput, "%v Logger.check error: failed to get caller\n", time.Now().UTC()) + log.errorOutput.Sync() + } + } + if log.addStack.Enabled(ce.Entry.Level) { + ce.Entry.Stack = Stack("").String + } + + return ce +} diff --git a/vendor/go.uber.org/zap/options.go b/vendor/go.uber.org/zap/options.go new file mode 100644 index 0000000000..7a6b0fca1b --- /dev/null +++ b/vendor/go.uber.org/zap/options.go @@ -0,0 +1,109 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import "go.uber.org/zap/zapcore" + +// An Option configures a Logger. +type Option interface { + apply(*Logger) +} + +// optionFunc wraps a func so it satisfies the Option interface. +type optionFunc func(*Logger) + +func (f optionFunc) apply(log *Logger) { + f(log) +} + +// WrapCore wraps or replaces the Logger's underlying zapcore.Core. +func WrapCore(f func(zapcore.Core) zapcore.Core) Option { + return optionFunc(func(log *Logger) { + log.core = f(log.core) + }) +} + +// Hooks registers functions which will be called each time the Logger writes +// out an Entry. Repeated use of Hooks is additive. +// +// Hooks are useful for simple side effects, like capturing metrics for the +// number of emitted logs. More complex side effects, including anything that +// requires access to the Entry's structured fields, should be implemented as +// a zapcore.Core instead. See zapcore.RegisterHooks for details. +func Hooks(hooks ...func(zapcore.Entry) error) Option { + return optionFunc(func(log *Logger) { + log.core = zapcore.RegisterHooks(log.core, hooks...) + }) +} + +// Fields adds fields to the Logger. +func Fields(fs ...Field) Option { + return optionFunc(func(log *Logger) { + log.core = log.core.With(fs) + }) +} + +// ErrorOutput sets the destination for errors generated by the Logger. Note +// that this option only affects internal errors; for sample code that sends +// error-level logs to a different location from info- and debug-level logs, +// see the package-level AdvancedConfiguration example. +// +// The supplied WriteSyncer must be safe for concurrent use. The Open and +// zapcore.Lock functions are the simplest ways to protect files with a mutex. +func ErrorOutput(w zapcore.WriteSyncer) Option { + return optionFunc(func(log *Logger) { + log.errorOutput = w + }) +} + +// Development puts the logger in development mode, which makes DPanic-level +// logs panic instead of simply logging an error. +func Development() Option { + return optionFunc(func(log *Logger) { + log.development = true + }) +} + +// AddCaller configures the Logger to annotate each message with the filename +// and line number of zap's caller. +func AddCaller() Option { + return optionFunc(func(log *Logger) { + log.addCaller = true + }) +} + +// AddCallerSkip increases the number of callers skipped by caller annotation +// (as enabled by the AddCaller option). When building wrappers around the +// Logger and SugaredLogger, supplying this Option prevents zap from always +// reporting the wrapper code as the caller. +func AddCallerSkip(skip int) Option { + return optionFunc(func(log *Logger) { + log.callerSkip += skip + }) +} + +// AddStacktrace configures the Logger to record a stack trace for all messages at +// or above a given level. +func AddStacktrace(lvl zapcore.LevelEnabler) Option { + return optionFunc(func(log *Logger) { + log.addStack = lvl + }) +} diff --git a/vendor/go.uber.org/zap/sink.go b/vendor/go.uber.org/zap/sink.go new file mode 100644 index 0000000000..ff0becfe5d --- /dev/null +++ b/vendor/go.uber.org/zap/sink.go @@ -0,0 +1,161 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import ( + "errors" + "fmt" + "io" + "net/url" + "os" + "strings" + "sync" + + "go.uber.org/zap/zapcore" +) + +const schemeFile = "file" + +var ( + _sinkMutex sync.RWMutex + _sinkFactories map[string]func(*url.URL) (Sink, error) // keyed by scheme +) + +func init() { + resetSinkRegistry() +} + +func resetSinkRegistry() { + _sinkMutex.Lock() + defer _sinkMutex.Unlock() + + _sinkFactories = map[string]func(*url.URL) (Sink, error){ + schemeFile: newFileSink, + } +} + +// Sink defines the interface to write to and close logger destinations. +type Sink interface { + zapcore.WriteSyncer + io.Closer +} + +type nopCloserSink struct{ zapcore.WriteSyncer } + +func (nopCloserSink) Close() error { return nil } + +type errSinkNotFound struct { + scheme string +} + +func (e *errSinkNotFound) Error() string { + return fmt.Sprintf("no sink found for scheme %q", e.scheme) +} + +// RegisterSink registers a user-supplied factory for all sinks with a +// particular scheme. +// +// All schemes must be ASCII, valid under section 3.1 of RFC 3986 +// (https://tools.ietf.org/html/rfc3986#section-3.1), and must not already +// have a factory registered. Zap automatically registers a factory for the +// "file" scheme. +func RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) error { + _sinkMutex.Lock() + defer _sinkMutex.Unlock() + + if scheme == "" { + return errors.New("can't register a sink factory for empty string") + } + normalized, err := normalizeScheme(scheme) + if err != nil { + return fmt.Errorf("%q is not a valid scheme: %v", scheme, err) + } + if _, ok := _sinkFactories[normalized]; ok { + return fmt.Errorf("sink factory already registered for scheme %q", normalized) + } + _sinkFactories[normalized] = factory + return nil +} + +func newSink(rawURL string) (Sink, error) { + u, err := url.Parse(rawURL) + if err != nil { + return nil, fmt.Errorf("can't parse %q as a URL: %v", rawURL, err) + } + if u.Scheme == "" { + u.Scheme = schemeFile + } + + _sinkMutex.RLock() + factory, ok := _sinkFactories[u.Scheme] + _sinkMutex.RUnlock() + if !ok { + return nil, &errSinkNotFound{u.Scheme} + } + return factory(u) +} + +func newFileSink(u *url.URL) (Sink, error) { + if u.User != nil { + return nil, fmt.Errorf("user and password not allowed with file URLs: got %v", u) + } + if u.Fragment != "" { + return nil, fmt.Errorf("fragments not allowed with file URLs: got %v", u) + } + if u.RawQuery != "" { + return nil, fmt.Errorf("query parameters not allowed with file URLs: got %v", u) + } + // Error messages are better if we check hostname and port separately. + if u.Port() != "" { + return nil, fmt.Errorf("ports not allowed with file URLs: got %v", u) + } + if hn := u.Hostname(); hn != "" && hn != "localhost" { + return nil, fmt.Errorf("file URLs must leave host empty or use localhost: got %v", u) + } + switch u.Path { + case "stdout": + return nopCloserSink{os.Stdout}, nil + case "stderr": + return nopCloserSink{os.Stderr}, nil + } + return os.OpenFile(u.Path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) +} + +func normalizeScheme(s string) (string, error) { + // https://tools.ietf.org/html/rfc3986#section-3.1 + s = strings.ToLower(s) + if first := s[0]; 'a' > first || 'z' < first { + return "", errors.New("must start with a letter") + } + for i := 1; i < len(s); i++ { // iterate over bytes, not runes + c := s[i] + switch { + case 'a' <= c && c <= 'z': + continue + case '0' <= c && c <= '9': + continue + case c == '.' || c == '+' || c == '-': + continue + } + return "", fmt.Errorf("may not contain %q", c) + } + return s, nil +} diff --git a/vendor/go.uber.org/zap/stacktrace.go b/vendor/go.uber.org/zap/stacktrace.go new file mode 100644 index 0000000000..100fac2168 --- /dev/null +++ b/vendor/go.uber.org/zap/stacktrace.go @@ -0,0 +1,126 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import ( + "runtime" + "strings" + "sync" + + "go.uber.org/zap/internal/bufferpool" +) + +const _zapPackage = "go.uber.org/zap" + +var ( + _stacktracePool = sync.Pool{ + New: func() interface{} { + return newProgramCounters(64) + }, + } + + // We add "." and "/" suffixes to the package name to ensure we only match + // the exact package and not any package with the same prefix. + _zapStacktracePrefixes = addPrefix(_zapPackage, ".", "/") + _zapStacktraceVendorContains = addPrefix("/vendor/", _zapStacktracePrefixes...) +) + +func takeStacktrace() string { + buffer := bufferpool.Get() + defer buffer.Free() + programCounters := _stacktracePool.Get().(*programCounters) + defer _stacktracePool.Put(programCounters) + + var numFrames int + for { + // Skip the call to runtime.Counters and takeStacktrace so that the + // program counters start at the caller of takeStacktrace. + numFrames = runtime.Callers(2, programCounters.pcs) + if numFrames < len(programCounters.pcs) { + break + } + // Don't put the too-short counter slice back into the pool; this lets + // the pool adjust if we consistently take deep stacktraces. + programCounters = newProgramCounters(len(programCounters.pcs) * 2) + } + + i := 0 + skipZapFrames := true // skip all consecutive zap frames at the beginning. + frames := runtime.CallersFrames(programCounters.pcs[:numFrames]) + + // Note: On the last iteration, frames.Next() returns false, with a valid + // frame, but we ignore this frame. The last frame is a a runtime frame which + // adds noise, since it's only either runtime.main or runtime.goexit. + for frame, more := frames.Next(); more; frame, more = frames.Next() { + if skipZapFrames && isZapFrame(frame.Function) { + continue + } else { + skipZapFrames = false + } + + if i != 0 { + buffer.AppendByte('\n') + } + i++ + buffer.AppendString(frame.Function) + buffer.AppendByte('\n') + buffer.AppendByte('\t') + buffer.AppendString(frame.File) + buffer.AppendByte(':') + buffer.AppendInt(int64(frame.Line)) + } + + return buffer.String() +} + +func isZapFrame(function string) bool { + for _, prefix := range _zapStacktracePrefixes { + if strings.HasPrefix(function, prefix) { + return true + } + } + + // We can't use a prefix match here since the location of the vendor + // directory affects the prefix. Instead we do a contains match. + for _, contains := range _zapStacktraceVendorContains { + if strings.Contains(function, contains) { + return true + } + } + + return false +} + +type programCounters struct { + pcs []uintptr +} + +func newProgramCounters(size int) *programCounters { + return &programCounters{make([]uintptr, size)} +} + +func addPrefix(prefix string, ss ...string) []string { + withPrefix := make([]string, len(ss)) + for i, s := range ss { + withPrefix[i] = prefix + s + } + return withPrefix +} diff --git a/vendor/go.uber.org/zap/sugar.go b/vendor/go.uber.org/zap/sugar.go new file mode 100644 index 0000000000..77ca227f47 --- /dev/null +++ b/vendor/go.uber.org/zap/sugar.go @@ -0,0 +1,304 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import ( + "fmt" + + "go.uber.org/zap/zapcore" + + "go.uber.org/multierr" +) + +const ( + _oddNumberErrMsg = "Ignored key without a value." + _nonStringKeyErrMsg = "Ignored key-value pairs with non-string keys." +) + +// A SugaredLogger wraps the base Logger functionality in a slower, but less +// verbose, API. Any Logger can be converted to a SugaredLogger with its Sugar +// method. +// +// Unlike the Logger, the SugaredLogger doesn't insist on structured logging. +// For each log level, it exposes three methods: one for loosely-typed +// structured logging, one for println-style formatting, and one for +// printf-style formatting. For example, SugaredLoggers can produce InfoLevel +// output with Infow ("info with" structured context), Info, or Infof. +type SugaredLogger struct { + base *Logger +} + +// Desugar unwraps a SugaredLogger, exposing the original Logger. Desugaring +// is quite inexpensive, so it's reasonable for a single application to use +// both Loggers and SugaredLoggers, converting between them on the boundaries +// of performance-sensitive code. +func (s *SugaredLogger) Desugar() *Logger { + base := s.base.clone() + base.callerSkip -= 2 + return base +} + +// Named adds a sub-scope to the logger's name. See Logger.Named for details. +func (s *SugaredLogger) Named(name string) *SugaredLogger { + return &SugaredLogger{base: s.base.Named(name)} +} + +// With adds a variadic number of fields to the logging context. It accepts a +// mix of strongly-typed Field objects and loosely-typed key-value pairs. When +// processing pairs, the first element of the pair is used as the field key +// and the second as the field value. +// +// For example, +// sugaredLogger.With( +// "hello", "world", +// "failure", errors.New("oh no"), +// Stack(), +// "count", 42, +// "user", User{Name: "alice"}, +// ) +// is the equivalent of +// unsugared.With( +// String("hello", "world"), +// String("failure", "oh no"), +// Stack(), +// Int("count", 42), +// Object("user", User{Name: "alice"}), +// ) +// +// Note that the keys in key-value pairs should be strings. In development, +// passing a non-string key panics. In production, the logger is more +// forgiving: a separate error is logged, but the key-value pair is skipped +// and execution continues. Passing an orphaned key triggers similar behavior: +// panics in development and errors in production. +func (s *SugaredLogger) With(args ...interface{}) *SugaredLogger { + return &SugaredLogger{base: s.base.With(s.sweetenFields(args)...)} +} + +// Debug uses fmt.Sprint to construct and log a message. +func (s *SugaredLogger) Debug(args ...interface{}) { + s.log(DebugLevel, "", args, nil) +} + +// Info uses fmt.Sprint to construct and log a message. +func (s *SugaredLogger) Info(args ...interface{}) { + s.log(InfoLevel, "", args, nil) +} + +// Warn uses fmt.Sprint to construct and log a message. +func (s *SugaredLogger) Warn(args ...interface{}) { + s.log(WarnLevel, "", args, nil) +} + +// Error uses fmt.Sprint to construct and log a message. +func (s *SugaredLogger) Error(args ...interface{}) { + s.log(ErrorLevel, "", args, nil) +} + +// DPanic uses fmt.Sprint to construct and log a message. In development, the +// logger then panics. (See DPanicLevel for details.) +func (s *SugaredLogger) DPanic(args ...interface{}) { + s.log(DPanicLevel, "", args, nil) +} + +// Panic uses fmt.Sprint to construct and log a message, then panics. +func (s *SugaredLogger) Panic(args ...interface{}) { + s.log(PanicLevel, "", args, nil) +} + +// Fatal uses fmt.Sprint to construct and log a message, then calls os.Exit. +func (s *SugaredLogger) Fatal(args ...interface{}) { + s.log(FatalLevel, "", args, nil) +} + +// Debugf uses fmt.Sprintf to log a templated message. +func (s *SugaredLogger) Debugf(template string, args ...interface{}) { + s.log(DebugLevel, template, args, nil) +} + +// Infof uses fmt.Sprintf to log a templated message. +func (s *SugaredLogger) Infof(template string, args ...interface{}) { + s.log(InfoLevel, template, args, nil) +} + +// Warnf uses fmt.Sprintf to log a templated message. +func (s *SugaredLogger) Warnf(template string, args ...interface{}) { + s.log(WarnLevel, template, args, nil) +} + +// Errorf uses fmt.Sprintf to log a templated message. +func (s *SugaredLogger) Errorf(template string, args ...interface{}) { + s.log(ErrorLevel, template, args, nil) +} + +// DPanicf uses fmt.Sprintf to log a templated message. In development, the +// logger then panics. (See DPanicLevel for details.) +func (s *SugaredLogger) DPanicf(template string, args ...interface{}) { + s.log(DPanicLevel, template, args, nil) +} + +// Panicf uses fmt.Sprintf to log a templated message, then panics. +func (s *SugaredLogger) Panicf(template string, args ...interface{}) { + s.log(PanicLevel, template, args, nil) +} + +// Fatalf uses fmt.Sprintf to log a templated message, then calls os.Exit. +func (s *SugaredLogger) Fatalf(template string, args ...interface{}) { + s.log(FatalLevel, template, args, nil) +} + +// Debugw logs a message with some additional context. The variadic key-value +// pairs are treated as they are in With. +// +// When debug-level logging is disabled, this is much faster than +// s.With(keysAndValues).Debug(msg) +func (s *SugaredLogger) Debugw(msg string, keysAndValues ...interface{}) { + s.log(DebugLevel, msg, nil, keysAndValues) +} + +// Infow logs a message with some additional context. The variadic key-value +// pairs are treated as they are in With. +func (s *SugaredLogger) Infow(msg string, keysAndValues ...interface{}) { + s.log(InfoLevel, msg, nil, keysAndValues) +} + +// Warnw logs a message with some additional context. The variadic key-value +// pairs are treated as they are in With. +func (s *SugaredLogger) Warnw(msg string, keysAndValues ...interface{}) { + s.log(WarnLevel, msg, nil, keysAndValues) +} + +// Errorw logs a message with some additional context. The variadic key-value +// pairs are treated as they are in With. +func (s *SugaredLogger) Errorw(msg string, keysAndValues ...interface{}) { + s.log(ErrorLevel, msg, nil, keysAndValues) +} + +// DPanicw logs a message with some additional context. In development, the +// logger then panics. (See DPanicLevel for details.) The variadic key-value +// pairs are treated as they are in With. +func (s *SugaredLogger) DPanicw(msg string, keysAndValues ...interface{}) { + s.log(DPanicLevel, msg, nil, keysAndValues) +} + +// Panicw logs a message with some additional context, then panics. The +// variadic key-value pairs are treated as they are in With. +func (s *SugaredLogger) Panicw(msg string, keysAndValues ...interface{}) { + s.log(PanicLevel, msg, nil, keysAndValues) +} + +// Fatalw logs a message with some additional context, then calls os.Exit. The +// variadic key-value pairs are treated as they are in With. +func (s *SugaredLogger) Fatalw(msg string, keysAndValues ...interface{}) { + s.log(FatalLevel, msg, nil, keysAndValues) +} + +// Sync flushes any buffered log entries. +func (s *SugaredLogger) Sync() error { + return s.base.Sync() +} + +func (s *SugaredLogger) log(lvl zapcore.Level, template string, fmtArgs []interface{}, context []interface{}) { + // If logging at this level is completely disabled, skip the overhead of + // string formatting. + if lvl < DPanicLevel && !s.base.Core().Enabled(lvl) { + return + } + + // Format with Sprint, Sprintf, or neither. + msg := template + if msg == "" && len(fmtArgs) > 0 { + msg = fmt.Sprint(fmtArgs...) + } else if msg != "" && len(fmtArgs) > 0 { + msg = fmt.Sprintf(template, fmtArgs...) + } + + if ce := s.base.Check(lvl, msg); ce != nil { + ce.Write(s.sweetenFields(context)...) + } +} + +func (s *SugaredLogger) sweetenFields(args []interface{}) []Field { + if len(args) == 0 { + return nil + } + + // Allocate enough space for the worst case; if users pass only structured + // fields, we shouldn't penalize them with extra allocations. + fields := make([]Field, 0, len(args)) + var invalid invalidPairs + + for i := 0; i < len(args); { + // This is a strongly-typed field. Consume it and move on. + if f, ok := args[i].(Field); ok { + fields = append(fields, f) + i++ + continue + } + + // Make sure this element isn't a dangling key. + if i == len(args)-1 { + s.base.DPanic(_oddNumberErrMsg, Any("ignored", args[i])) + break + } + + // Consume this value and the next, treating them as a key-value pair. If the + // key isn't a string, add this pair to the slice of invalid pairs. + key, val := args[i], args[i+1] + if keyStr, ok := key.(string); !ok { + // Subsequent errors are likely, so allocate once up front. + if cap(invalid) == 0 { + invalid = make(invalidPairs, 0, len(args)/2) + } + invalid = append(invalid, invalidPair{i, key, val}) + } else { + fields = append(fields, Any(keyStr, val)) + } + i += 2 + } + + // If we encountered any invalid key-value pairs, log an error. + if len(invalid) > 0 { + s.base.DPanic(_nonStringKeyErrMsg, Array("invalid", invalid)) + } + return fields +} + +type invalidPair struct { + position int + key, value interface{} +} + +func (p invalidPair) MarshalLogObject(enc zapcore.ObjectEncoder) error { + enc.AddInt64("position", int64(p.position)) + Any("key", p.key).AddTo(enc) + Any("value", p.value).AddTo(enc) + return nil +} + +type invalidPairs []invalidPair + +func (ps invalidPairs) MarshalLogArray(enc zapcore.ArrayEncoder) error { + var err error + for i := range ps { + err = multierr.Append(err, enc.AppendObject(ps[i])) + } + return err +} diff --git a/vendor/go.uber.org/zap/time.go b/vendor/go.uber.org/zap/time.go new file mode 100644 index 0000000000..c5a1f16225 --- /dev/null +++ b/vendor/go.uber.org/zap/time.go @@ -0,0 +1,27 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import "time" + +func timeToMillis(t time.Time) int64 { + return t.UnixNano() / int64(time.Millisecond) +} diff --git a/vendor/go.uber.org/zap/writer.go b/vendor/go.uber.org/zap/writer.go new file mode 100644 index 0000000000..86a709ab0b --- /dev/null +++ b/vendor/go.uber.org/zap/writer.go @@ -0,0 +1,99 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zap + +import ( + "fmt" + "io" + "io/ioutil" + + "go.uber.org/zap/zapcore" + + "go.uber.org/multierr" +) + +// Open is a high-level wrapper that takes a variadic number of URLs, opens or +// creates each of the specified resources, and combines them into a locked +// WriteSyncer. It also returns any error encountered and a function to close +// any opened files. +// +// Passing no URLs returns a no-op WriteSyncer. Zap handles URLs without a +// scheme and URLs with the "file" scheme. Third-party code may register +// factories for other schemes using RegisterSink. +// +// URLs with the "file" scheme must use absolute paths on the local +// filesystem. No user, password, port, fragments, or query parameters are +// allowed, and the hostname must be empty or "localhost". +// +// Since it's common to write logs to the local filesystem, URLs without a +// scheme (e.g., "/var/log/foo.log") are treated as local file paths. Without +// a scheme, the special paths "stdout" and "stderr" are interpreted as +// os.Stdout and os.Stderr. When specified without a scheme, relative file +// paths also work. +func Open(paths ...string) (zapcore.WriteSyncer, func(), error) { + writers, close, err := open(paths) + if err != nil { + return nil, nil, err + } + + writer := CombineWriteSyncers(writers...) + return writer, close, nil +} + +func open(paths []string) ([]zapcore.WriteSyncer, func(), error) { + writers := make([]zapcore.WriteSyncer, 0, len(paths)) + closers := make([]io.Closer, 0, len(paths)) + close := func() { + for _, c := range closers { + c.Close() + } + } + + var openErr error + for _, path := range paths { + sink, err := newSink(path) + if err != nil { + openErr = multierr.Append(openErr, fmt.Errorf("couldn't open sink %q: %v", path, err)) + continue + } + writers = append(writers, sink) + closers = append(closers, sink) + } + if openErr != nil { + close() + return writers, nil, openErr + } + + return writers, close, nil +} + +// CombineWriteSyncers is a utility that combines multiple WriteSyncers into a +// single, locked WriteSyncer. If no inputs are supplied, it returns a no-op +// WriteSyncer. +// +// It's provided purely as a convenience; the result is no different from +// using zapcore.NewMultiWriteSyncer and zapcore.Lock individually. +func CombineWriteSyncers(writers ...zapcore.WriteSyncer) zapcore.WriteSyncer { + if len(writers) == 0 { + return zapcore.AddSync(ioutil.Discard) + } + return zapcore.Lock(zapcore.NewMultiWriteSyncer(writers...)) +} diff --git a/vendor/go.uber.org/zap/zapcore/console_encoder.go b/vendor/go.uber.org/zap/zapcore/console_encoder.go new file mode 100644 index 0000000000..b7875966f4 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/console_encoder.go @@ -0,0 +1,147 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import ( + "fmt" + "sync" + + "go.uber.org/zap/buffer" + "go.uber.org/zap/internal/bufferpool" +) + +var _sliceEncoderPool = sync.Pool{ + New: func() interface{} { + return &sliceArrayEncoder{elems: make([]interface{}, 0, 2)} + }, +} + +func getSliceEncoder() *sliceArrayEncoder { + return _sliceEncoderPool.Get().(*sliceArrayEncoder) +} + +func putSliceEncoder(e *sliceArrayEncoder) { + e.elems = e.elems[:0] + _sliceEncoderPool.Put(e) +} + +type consoleEncoder struct { + *jsonEncoder +} + +// NewConsoleEncoder creates an encoder whose output is designed for human - +// rather than machine - consumption. It serializes the core log entry data +// (message, level, timestamp, etc.) in a plain-text format and leaves the +// structured context as JSON. +// +// Note that although the console encoder doesn't use the keys specified in the +// encoder configuration, it will omit any element whose key is set to the empty +// string. +func NewConsoleEncoder(cfg EncoderConfig) Encoder { + return consoleEncoder{newJSONEncoder(cfg, true)} +} + +func (c consoleEncoder) Clone() Encoder { + return consoleEncoder{c.jsonEncoder.Clone().(*jsonEncoder)} +} + +func (c consoleEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer, error) { + line := bufferpool.Get() + + // We don't want the entry's metadata to be quoted and escaped (if it's + // encoded as strings), which means that we can't use the JSON encoder. The + // simplest option is to use the memory encoder and fmt.Fprint. + // + // If this ever becomes a performance bottleneck, we can implement + // ArrayEncoder for our plain-text format. + arr := getSliceEncoder() + if c.TimeKey != "" && c.EncodeTime != nil { + c.EncodeTime(ent.Time, arr) + } + if c.LevelKey != "" && c.EncodeLevel != nil { + c.EncodeLevel(ent.Level, arr) + } + if ent.LoggerName != "" && c.NameKey != "" { + nameEncoder := c.EncodeName + + if nameEncoder == nil { + // Fall back to FullNameEncoder for backward compatibility. + nameEncoder = FullNameEncoder + } + + nameEncoder(ent.LoggerName, arr) + } + if ent.Caller.Defined && c.CallerKey != "" && c.EncodeCaller != nil { + c.EncodeCaller(ent.Caller, arr) + } + for i := range arr.elems { + if i > 0 { + line.AppendByte('\t') + } + fmt.Fprint(line, arr.elems[i]) + } + putSliceEncoder(arr) + + // Add the message itself. + if c.MessageKey != "" { + c.addTabIfNecessary(line) + line.AppendString(ent.Message) + } + + // Add any structured context. + c.writeContext(line, fields) + + // If there's no stacktrace key, honor that; this allows users to force + // single-line output. + if ent.Stack != "" && c.StacktraceKey != "" { + line.AppendByte('\n') + line.AppendString(ent.Stack) + } + + if c.LineEnding != "" { + line.AppendString(c.LineEnding) + } else { + line.AppendString(DefaultLineEnding) + } + return line, nil +} + +func (c consoleEncoder) writeContext(line *buffer.Buffer, extra []Field) { + context := c.jsonEncoder.Clone().(*jsonEncoder) + defer context.buf.Free() + + addFields(context, extra) + context.closeOpenNamespaces() + if context.buf.Len() == 0 { + return + } + + c.addTabIfNecessary(line) + line.AppendByte('{') + line.Write(context.buf.Bytes()) + line.AppendByte('}') +} + +func (c consoleEncoder) addTabIfNecessary(line *buffer.Buffer) { + if line.Len() > 0 { + line.AppendByte('\t') + } +} diff --git a/vendor/go.uber.org/zap/zapcore/core.go b/vendor/go.uber.org/zap/zapcore/core.go new file mode 100644 index 0000000000..a1ef8b034b --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/core.go @@ -0,0 +1,113 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +// Core is a minimal, fast logger interface. It's designed for library authors +// to wrap in a more user-friendly API. +type Core interface { + LevelEnabler + + // With adds structured context to the Core. + With([]Field) Core + // Check determines whether the supplied Entry should be logged (using the + // embedded LevelEnabler and possibly some extra logic). If the entry + // should be logged, the Core adds itself to the CheckedEntry and returns + // the result. + // + // Callers must use Check before calling Write. + Check(Entry, *CheckedEntry) *CheckedEntry + // Write serializes the Entry and any Fields supplied at the log site and + // writes them to their destination. + // + // If called, Write should always log the Entry and Fields; it should not + // replicate the logic of Check. + Write(Entry, []Field) error + // Sync flushes buffered logs (if any). + Sync() error +} + +type nopCore struct{} + +// NewNopCore returns a no-op Core. +func NewNopCore() Core { return nopCore{} } +func (nopCore) Enabled(Level) bool { return false } +func (n nopCore) With([]Field) Core { return n } +func (nopCore) Check(_ Entry, ce *CheckedEntry) *CheckedEntry { return ce } +func (nopCore) Write(Entry, []Field) error { return nil } +func (nopCore) Sync() error { return nil } + +// NewCore creates a Core that writes logs to a WriteSyncer. +func NewCore(enc Encoder, ws WriteSyncer, enab LevelEnabler) Core { + return &ioCore{ + LevelEnabler: enab, + enc: enc, + out: ws, + } +} + +type ioCore struct { + LevelEnabler + enc Encoder + out WriteSyncer +} + +func (c *ioCore) With(fields []Field) Core { + clone := c.clone() + addFields(clone.enc, fields) + return clone +} + +func (c *ioCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { + if c.Enabled(ent.Level) { + return ce.AddCore(ent, c) + } + return ce +} + +func (c *ioCore) Write(ent Entry, fields []Field) error { + buf, err := c.enc.EncodeEntry(ent, fields) + if err != nil { + return err + } + _, err = c.out.Write(buf.Bytes()) + buf.Free() + if err != nil { + return err + } + if ent.Level > ErrorLevel { + // Since we may be crashing the program, sync the output. Ignore Sync + // errors, pending a clean solution to issue #370. + c.Sync() + } + return nil +} + +func (c *ioCore) Sync() error { + return c.out.Sync() +} + +func (c *ioCore) clone() *ioCore { + return &ioCore{ + LevelEnabler: c.LevelEnabler, + enc: c.enc.Clone(), + out: c.out, + } +} diff --git a/vendor/go.uber.org/zap/zapcore/doc.go b/vendor/go.uber.org/zap/zapcore/doc.go new file mode 100644 index 0000000000..31000e91f7 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/doc.go @@ -0,0 +1,24 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +// Package zapcore defines and implements the low-level interfaces upon which +// zap is built. By providing alternate implementations of these interfaces, +// external packages can extend zap's capabilities. +package zapcore // import "go.uber.org/zap/zapcore" diff --git a/vendor/go.uber.org/zap/zapcore/encoder.go b/vendor/go.uber.org/zap/zapcore/encoder.go new file mode 100644 index 0000000000..f0509522b5 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/encoder.go @@ -0,0 +1,348 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import ( + "time" + + "go.uber.org/zap/buffer" +) + +// DefaultLineEnding defines the default line ending when writing logs. +// Alternate line endings specified in EncoderConfig can override this +// behavior. +const DefaultLineEnding = "\n" + +// A LevelEncoder serializes a Level to a primitive type. +type LevelEncoder func(Level, PrimitiveArrayEncoder) + +// LowercaseLevelEncoder serializes a Level to a lowercase string. For example, +// InfoLevel is serialized to "info". +func LowercaseLevelEncoder(l Level, enc PrimitiveArrayEncoder) { + enc.AppendString(l.String()) +} + +// LowercaseColorLevelEncoder serializes a Level to a lowercase string and adds coloring. +// For example, InfoLevel is serialized to "info" and colored blue. +func LowercaseColorLevelEncoder(l Level, enc PrimitiveArrayEncoder) { + s, ok := _levelToLowercaseColorString[l] + if !ok { + s = _unknownLevelColor.Add(l.String()) + } + enc.AppendString(s) +} + +// CapitalLevelEncoder serializes a Level to an all-caps string. For example, +// InfoLevel is serialized to "INFO". +func CapitalLevelEncoder(l Level, enc PrimitiveArrayEncoder) { + enc.AppendString(l.CapitalString()) +} + +// CapitalColorLevelEncoder serializes a Level to an all-caps string and adds color. +// For example, InfoLevel is serialized to "INFO" and colored blue. +func CapitalColorLevelEncoder(l Level, enc PrimitiveArrayEncoder) { + s, ok := _levelToCapitalColorString[l] + if !ok { + s = _unknownLevelColor.Add(l.CapitalString()) + } + enc.AppendString(s) +} + +// UnmarshalText unmarshals text to a LevelEncoder. "capital" is unmarshaled to +// CapitalLevelEncoder, "coloredCapital" is unmarshaled to CapitalColorLevelEncoder, +// "colored" is unmarshaled to LowercaseColorLevelEncoder, and anything else +// is unmarshaled to LowercaseLevelEncoder. +func (e *LevelEncoder) UnmarshalText(text []byte) error { + switch string(text) { + case "capital": + *e = CapitalLevelEncoder + case "capitalColor": + *e = CapitalColorLevelEncoder + case "color": + *e = LowercaseColorLevelEncoder + default: + *e = LowercaseLevelEncoder + } + return nil +} + +// A TimeEncoder serializes a time.Time to a primitive type. +type TimeEncoder func(time.Time, PrimitiveArrayEncoder) + +// EpochTimeEncoder serializes a time.Time to a floating-point number of seconds +// since the Unix epoch. +func EpochTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) { + nanos := t.UnixNano() + sec := float64(nanos) / float64(time.Second) + enc.AppendFloat64(sec) +} + +// EpochMillisTimeEncoder serializes a time.Time to a floating-point number of +// milliseconds since the Unix epoch. +func EpochMillisTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) { + nanos := t.UnixNano() + millis := float64(nanos) / float64(time.Millisecond) + enc.AppendFloat64(millis) +} + +// EpochNanosTimeEncoder serializes a time.Time to an integer number of +// nanoseconds since the Unix epoch. +func EpochNanosTimeEncoder(t time.Time, enc PrimitiveArrayEncoder) { + enc.AppendInt64(t.UnixNano()) +} + +// ISO8601TimeEncoder serializes a time.Time to an ISO8601-formatted string +// with millisecond precision. +func ISO8601TimeEncoder(t time.Time, enc PrimitiveArrayEncoder) { + enc.AppendString(t.Format("2006-01-02T15:04:05.000Z0700")) +} + +// UnmarshalText unmarshals text to a TimeEncoder. "iso8601" and "ISO8601" are +// unmarshaled to ISO8601TimeEncoder, "millis" is unmarshaled to +// EpochMillisTimeEncoder, and anything else is unmarshaled to EpochTimeEncoder. +func (e *TimeEncoder) UnmarshalText(text []byte) error { + switch string(text) { + case "iso8601", "ISO8601": + *e = ISO8601TimeEncoder + case "millis": + *e = EpochMillisTimeEncoder + case "nanos": + *e = EpochNanosTimeEncoder + default: + *e = EpochTimeEncoder + } + return nil +} + +// A DurationEncoder serializes a time.Duration to a primitive type. +type DurationEncoder func(time.Duration, PrimitiveArrayEncoder) + +// SecondsDurationEncoder serializes a time.Duration to a floating-point number of seconds elapsed. +func SecondsDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) { + enc.AppendFloat64(float64(d) / float64(time.Second)) +} + +// NanosDurationEncoder serializes a time.Duration to an integer number of +// nanoseconds elapsed. +func NanosDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) { + enc.AppendInt64(int64(d)) +} + +// StringDurationEncoder serializes a time.Duration using its built-in String +// method. +func StringDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) { + enc.AppendString(d.String()) +} + +// UnmarshalText unmarshals text to a DurationEncoder. "string" is unmarshaled +// to StringDurationEncoder, and anything else is unmarshaled to +// NanosDurationEncoder. +func (e *DurationEncoder) UnmarshalText(text []byte) error { + switch string(text) { + case "string": + *e = StringDurationEncoder + case "nanos": + *e = NanosDurationEncoder + default: + *e = SecondsDurationEncoder + } + return nil +} + +// A CallerEncoder serializes an EntryCaller to a primitive type. +type CallerEncoder func(EntryCaller, PrimitiveArrayEncoder) + +// FullCallerEncoder serializes a caller in /full/path/to/package/file:line +// format. +func FullCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder) { + // TODO: consider using a byte-oriented API to save an allocation. + enc.AppendString(caller.String()) +} + +// ShortCallerEncoder serializes a caller in package/file:line format, trimming +// all but the final directory from the full path. +func ShortCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder) { + // TODO: consider using a byte-oriented API to save an allocation. + enc.AppendString(caller.TrimmedPath()) +} + +// UnmarshalText unmarshals text to a CallerEncoder. "full" is unmarshaled to +// FullCallerEncoder and anything else is unmarshaled to ShortCallerEncoder. +func (e *CallerEncoder) UnmarshalText(text []byte) error { + switch string(text) { + case "full": + *e = FullCallerEncoder + default: + *e = ShortCallerEncoder + } + return nil +} + +// A NameEncoder serializes a period-separated logger name to a primitive +// type. +type NameEncoder func(string, PrimitiveArrayEncoder) + +// FullNameEncoder serializes the logger name as-is. +func FullNameEncoder(loggerName string, enc PrimitiveArrayEncoder) { + enc.AppendString(loggerName) +} + +// UnmarshalText unmarshals text to a NameEncoder. Currently, everything is +// unmarshaled to FullNameEncoder. +func (e *NameEncoder) UnmarshalText(text []byte) error { + switch string(text) { + case "full": + *e = FullNameEncoder + default: + *e = FullNameEncoder + } + return nil +} + +// An EncoderConfig allows users to configure the concrete encoders supplied by +// zapcore. +type EncoderConfig struct { + // Set the keys used for each log entry. If any key is empty, that portion + // of the entry is omitted. + MessageKey string `json:"messageKey" yaml:"messageKey"` + LevelKey string `json:"levelKey" yaml:"levelKey"` + TimeKey string `json:"timeKey" yaml:"timeKey"` + NameKey string `json:"nameKey" yaml:"nameKey"` + CallerKey string `json:"callerKey" yaml:"callerKey"` + StacktraceKey string `json:"stacktraceKey" yaml:"stacktraceKey"` + LineEnding string `json:"lineEnding" yaml:"lineEnding"` + // Configure the primitive representations of common complex types. For + // example, some users may want all time.Times serialized as floating-point + // seconds since epoch, while others may prefer ISO8601 strings. + EncodeLevel LevelEncoder `json:"levelEncoder" yaml:"levelEncoder"` + EncodeTime TimeEncoder `json:"timeEncoder" yaml:"timeEncoder"` + EncodeDuration DurationEncoder `json:"durationEncoder" yaml:"durationEncoder"` + EncodeCaller CallerEncoder `json:"callerEncoder" yaml:"callerEncoder"` + // Unlike the other primitive type encoders, EncodeName is optional. The + // zero value falls back to FullNameEncoder. + EncodeName NameEncoder `json:"nameEncoder" yaml:"nameEncoder"` +} + +// ObjectEncoder is a strongly-typed, encoding-agnostic interface for adding a +// map- or struct-like object to the logging context. Like maps, ObjectEncoders +// aren't safe for concurrent use (though typical use shouldn't require locks). +type ObjectEncoder interface { + // Logging-specific marshalers. + AddArray(key string, marshaler ArrayMarshaler) error + AddObject(key string, marshaler ObjectMarshaler) error + + // Built-in types. + AddBinary(key string, value []byte) // for arbitrary bytes + AddByteString(key string, value []byte) // for UTF-8 encoded bytes + AddBool(key string, value bool) + AddComplex128(key string, value complex128) + AddComplex64(key string, value complex64) + AddDuration(key string, value time.Duration) + AddFloat64(key string, value float64) + AddFloat32(key string, value float32) + AddInt(key string, value int) + AddInt64(key string, value int64) + AddInt32(key string, value int32) + AddInt16(key string, value int16) + AddInt8(key string, value int8) + AddString(key, value string) + AddTime(key string, value time.Time) + AddUint(key string, value uint) + AddUint64(key string, value uint64) + AddUint32(key string, value uint32) + AddUint16(key string, value uint16) + AddUint8(key string, value uint8) + AddUintptr(key string, value uintptr) + + // AddReflected uses reflection to serialize arbitrary objects, so it's slow + // and allocation-heavy. + AddReflected(key string, value interface{}) error + // OpenNamespace opens an isolated namespace where all subsequent fields will + // be added. Applications can use namespaces to prevent key collisions when + // injecting loggers into sub-components or third-party libraries. + OpenNamespace(key string) +} + +// ArrayEncoder is a strongly-typed, encoding-agnostic interface for adding +// array-like objects to the logging context. Of note, it supports mixed-type +// arrays even though they aren't typical in Go. Like slices, ArrayEncoders +// aren't safe for concurrent use (though typical use shouldn't require locks). +type ArrayEncoder interface { + // Built-in types. + PrimitiveArrayEncoder + + // Time-related types. + AppendDuration(time.Duration) + AppendTime(time.Time) + + // Logging-specific marshalers. + AppendArray(ArrayMarshaler) error + AppendObject(ObjectMarshaler) error + + // AppendReflected uses reflection to serialize arbitrary objects, so it's + // slow and allocation-heavy. + AppendReflected(value interface{}) error +} + +// PrimitiveArrayEncoder is the subset of the ArrayEncoder interface that deals +// only in Go's built-in types. It's included only so that Duration- and +// TimeEncoders cannot trigger infinite recursion. +type PrimitiveArrayEncoder interface { + // Built-in types. + AppendBool(bool) + AppendByteString([]byte) // for UTF-8 encoded bytes + AppendComplex128(complex128) + AppendComplex64(complex64) + AppendFloat64(float64) + AppendFloat32(float32) + AppendInt(int) + AppendInt64(int64) + AppendInt32(int32) + AppendInt16(int16) + AppendInt8(int8) + AppendString(string) + AppendUint(uint) + AppendUint64(uint64) + AppendUint32(uint32) + AppendUint16(uint16) + AppendUint8(uint8) + AppendUintptr(uintptr) +} + +// Encoder is a format-agnostic interface for all log entry marshalers. Since +// log encoders don't need to support the same wide range of use cases as +// general-purpose marshalers, it's possible to make them faster and +// lower-allocation. +// +// Implementations of the ObjectEncoder interface's methods can, of course, +// freely modify the receiver. However, the Clone and EncodeEntry methods will +// be called concurrently and shouldn't modify the receiver. +type Encoder interface { + ObjectEncoder + + // Clone copies the encoder, ensuring that adding fields to the copy doesn't + // affect the original. + Clone() Encoder + + // EncodeEntry encodes an entry and fields, along with any accumulated + // context, into a byte buffer and returns it. + EncodeEntry(Entry, []Field) (*buffer.Buffer, error) +} diff --git a/vendor/go.uber.org/zap/zapcore/entry.go b/vendor/go.uber.org/zap/zapcore/entry.go new file mode 100644 index 0000000000..7d9893f331 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/entry.go @@ -0,0 +1,257 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import ( + "fmt" + "strings" + "sync" + "time" + + "go.uber.org/zap/internal/bufferpool" + "go.uber.org/zap/internal/exit" + + "go.uber.org/multierr" +) + +var ( + _cePool = sync.Pool{New: func() interface{} { + // Pre-allocate some space for cores. + return &CheckedEntry{ + cores: make([]Core, 4), + } + }} +) + +func getCheckedEntry() *CheckedEntry { + ce := _cePool.Get().(*CheckedEntry) + ce.reset() + return ce +} + +func putCheckedEntry(ce *CheckedEntry) { + if ce == nil { + return + } + _cePool.Put(ce) +} + +// NewEntryCaller makes an EntryCaller from the return signature of +// runtime.Caller. +func NewEntryCaller(pc uintptr, file string, line int, ok bool) EntryCaller { + if !ok { + return EntryCaller{} + } + return EntryCaller{ + PC: pc, + File: file, + Line: line, + Defined: true, + } +} + +// EntryCaller represents the caller of a logging function. +type EntryCaller struct { + Defined bool + PC uintptr + File string + Line int +} + +// String returns the full path and line number of the caller. +func (ec EntryCaller) String() string { + return ec.FullPath() +} + +// FullPath returns a /full/path/to/package/file:line description of the +// caller. +func (ec EntryCaller) FullPath() string { + if !ec.Defined { + return "undefined" + } + buf := bufferpool.Get() + buf.AppendString(ec.File) + buf.AppendByte(':') + buf.AppendInt(int64(ec.Line)) + caller := buf.String() + buf.Free() + return caller +} + +// TrimmedPath returns a package/file:line description of the caller, +// preserving only the leaf directory name and file name. +func (ec EntryCaller) TrimmedPath() string { + if !ec.Defined { + return "undefined" + } + // nb. To make sure we trim the path correctly on Windows too, we + // counter-intuitively need to use '/' and *not* os.PathSeparator here, + // because the path given originates from Go stdlib, specifically + // runtime.Caller() which (as of Mar/17) returns forward slashes even on + // Windows. + // + // See https://github.com/golang/go/issues/3335 + // and https://github.com/golang/go/issues/18151 + // + // for discussion on the issue on Go side. + // + // Find the last separator. + // + idx := strings.LastIndexByte(ec.File, '/') + if idx == -1 { + return ec.FullPath() + } + // Find the penultimate separator. + idx = strings.LastIndexByte(ec.File[:idx], '/') + if idx == -1 { + return ec.FullPath() + } + buf := bufferpool.Get() + // Keep everything after the penultimate separator. + buf.AppendString(ec.File[idx+1:]) + buf.AppendByte(':') + buf.AppendInt(int64(ec.Line)) + caller := buf.String() + buf.Free() + return caller +} + +// An Entry represents a complete log message. The entry's structured context +// is already serialized, but the log level, time, message, and call site +// information are available for inspection and modification. +// +// Entries are pooled, so any functions that accept them MUST be careful not to +// retain references to them. +type Entry struct { + Level Level + Time time.Time + LoggerName string + Message string + Caller EntryCaller + Stack string +} + +// CheckWriteAction indicates what action to take after a log entry is +// processed. Actions are ordered in increasing severity. +type CheckWriteAction uint8 + +const ( + // WriteThenNoop indicates that nothing special needs to be done. It's the + // default behavior. + WriteThenNoop CheckWriteAction = iota + // WriteThenPanic causes a panic after Write. + WriteThenPanic + // WriteThenFatal causes a fatal os.Exit after Write. + WriteThenFatal +) + +// CheckedEntry is an Entry together with a collection of Cores that have +// already agreed to log it. +// +// CheckedEntry references should be created by calling AddCore or Should on a +// nil *CheckedEntry. References are returned to a pool after Write, and MUST +// NOT be retained after calling their Write method. +type CheckedEntry struct { + Entry + ErrorOutput WriteSyncer + dirty bool // best-effort detection of pool misuse + should CheckWriteAction + cores []Core +} + +func (ce *CheckedEntry) reset() { + ce.Entry = Entry{} + ce.ErrorOutput = nil + ce.dirty = false + ce.should = WriteThenNoop + for i := range ce.cores { + // don't keep references to cores + ce.cores[i] = nil + } + ce.cores = ce.cores[:0] +} + +// Write writes the entry to the stored Cores, returns any errors, and returns +// the CheckedEntry reference to a pool for immediate re-use. Finally, it +// executes any required CheckWriteAction. +func (ce *CheckedEntry) Write(fields ...Field) { + if ce == nil { + return + } + + if ce.dirty { + if ce.ErrorOutput != nil { + // Make a best effort to detect unsafe re-use of this CheckedEntry. + // If the entry is dirty, log an internal error; because the + // CheckedEntry is being used after it was returned to the pool, + // the message may be an amalgamation from multiple call sites. + fmt.Fprintf(ce.ErrorOutput, "%v Unsafe CheckedEntry re-use near Entry %+v.\n", time.Now(), ce.Entry) + ce.ErrorOutput.Sync() + } + return + } + ce.dirty = true + + var err error + for i := range ce.cores { + err = multierr.Append(err, ce.cores[i].Write(ce.Entry, fields)) + } + if ce.ErrorOutput != nil { + if err != nil { + fmt.Fprintf(ce.ErrorOutput, "%v write error: %v\n", time.Now(), err) + ce.ErrorOutput.Sync() + } + } + + should, msg := ce.should, ce.Message + putCheckedEntry(ce) + + switch should { + case WriteThenPanic: + panic(msg) + case WriteThenFatal: + exit.Exit() + } +} + +// AddCore adds a Core that has agreed to log this CheckedEntry. It's intended to be +// used by Core.Check implementations, and is safe to call on nil CheckedEntry +// references. +func (ce *CheckedEntry) AddCore(ent Entry, core Core) *CheckedEntry { + if ce == nil { + ce = getCheckedEntry() + ce.Entry = ent + } + ce.cores = append(ce.cores, core) + return ce +} + +// Should sets this CheckedEntry's CheckWriteAction, which controls whether a +// Core will panic or fatal after writing this log entry. Like AddCore, it's +// safe to call on nil CheckedEntry references. +func (ce *CheckedEntry) Should(ent Entry, should CheckWriteAction) *CheckedEntry { + if ce == nil { + ce = getCheckedEntry() + ce.Entry = ent + } + ce.should = should + return ce +} diff --git a/vendor/go.uber.org/zap/zapcore/error.go b/vendor/go.uber.org/zap/zapcore/error.go new file mode 100644 index 0000000000..a67c7bacc9 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/error.go @@ -0,0 +1,120 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import ( + "fmt" + "sync" +) + +// Encodes the given error into fields of an object. A field with the given +// name is added for the error message. +// +// If the error implements fmt.Formatter, a field with the name ${key}Verbose +// is also added with the full verbose error message. +// +// Finally, if the error implements errorGroup (from go.uber.org/multierr) or +// causer (from github.com/pkg/errors), a ${key}Causes field is added with an +// array of objects containing the errors this error was comprised of. +// +// { +// "error": err.Error(), +// "errorVerbose": fmt.Sprintf("%+v", err), +// "errorCauses": [ +// ... +// ], +// } +func encodeError(key string, err error, enc ObjectEncoder) error { + basic := err.Error() + enc.AddString(key, basic) + + switch e := err.(type) { + case errorGroup: + return enc.AddArray(key+"Causes", errArray(e.Errors())) + case fmt.Formatter: + verbose := fmt.Sprintf("%+v", e) + if verbose != basic { + // This is a rich error type, like those produced by + // github.com/pkg/errors. + enc.AddString(key+"Verbose", verbose) + } + } + return nil +} + +type errorGroup interface { + // Provides read-only access to the underlying list of errors, preferably + // without causing any allocs. + Errors() []error +} + +type causer interface { + // Provides access to the error that caused this error. + Cause() error +} + +// Note that errArry and errArrayElem are very similar to the version +// implemented in the top-level error.go file. We can't re-use this because +// that would require exporting errArray as part of the zapcore API. + +// Encodes a list of errors using the standard error encoding logic. +type errArray []error + +func (errs errArray) MarshalLogArray(arr ArrayEncoder) error { + for i := range errs { + if errs[i] == nil { + continue + } + + el := newErrArrayElem(errs[i]) + arr.AppendObject(el) + el.Free() + } + return nil +} + +var _errArrayElemPool = sync.Pool{New: func() interface{} { + return &errArrayElem{} +}} + +// Encodes any error into a {"error": ...} re-using the same errors logic. +// +// May be passed in place of an array to build a single-element array. +type errArrayElem struct{ err error } + +func newErrArrayElem(err error) *errArrayElem { + e := _errArrayElemPool.Get().(*errArrayElem) + e.err = err + return e +} + +func (e *errArrayElem) MarshalLogArray(arr ArrayEncoder) error { + return arr.AppendObject(e) +} + +func (e *errArrayElem) MarshalLogObject(enc ObjectEncoder) error { + return encodeError("error", e.err, enc) +} + +func (e *errArrayElem) Free() { + e.err = nil + _errArrayElemPool.Put(e) +} diff --git a/vendor/go.uber.org/zap/zapcore/field.go b/vendor/go.uber.org/zap/zapcore/field.go new file mode 100644 index 0000000000..ae772e4a17 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/field.go @@ -0,0 +1,212 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import ( + "bytes" + "fmt" + "math" + "reflect" + "time" +) + +// A FieldType indicates which member of the Field union struct should be used +// and how it should be serialized. +type FieldType uint8 + +const ( + // UnknownType is the default field type. Attempting to add it to an encoder will panic. + UnknownType FieldType = iota + // ArrayMarshalerType indicates that the field carries an ArrayMarshaler. + ArrayMarshalerType + // ObjectMarshalerType indicates that the field carries an ObjectMarshaler. + ObjectMarshalerType + // BinaryType indicates that the field carries an opaque binary blob. + BinaryType + // BoolType indicates that the field carries a bool. + BoolType + // ByteStringType indicates that the field carries UTF-8 encoded bytes. + ByteStringType + // Complex128Type indicates that the field carries a complex128. + Complex128Type + // Complex64Type indicates that the field carries a complex128. + Complex64Type + // DurationType indicates that the field carries a time.Duration. + DurationType + // Float64Type indicates that the field carries a float64. + Float64Type + // Float32Type indicates that the field carries a float32. + Float32Type + // Int64Type indicates that the field carries an int64. + Int64Type + // Int32Type indicates that the field carries an int32. + Int32Type + // Int16Type indicates that the field carries an int16. + Int16Type + // Int8Type indicates that the field carries an int8. + Int8Type + // StringType indicates that the field carries a string. + StringType + // TimeType indicates that the field carries a time.Time. + TimeType + // Uint64Type indicates that the field carries a uint64. + Uint64Type + // Uint32Type indicates that the field carries a uint32. + Uint32Type + // Uint16Type indicates that the field carries a uint16. + Uint16Type + // Uint8Type indicates that the field carries a uint8. + Uint8Type + // UintptrType indicates that the field carries a uintptr. + UintptrType + // ReflectType indicates that the field carries an interface{}, which should + // be serialized using reflection. + ReflectType + // NamespaceType signals the beginning of an isolated namespace. All + // subsequent fields should be added to the new namespace. + NamespaceType + // StringerType indicates that the field carries a fmt.Stringer. + StringerType + // ErrorType indicates that the field carries an error. + ErrorType + // SkipType indicates that the field is a no-op. + SkipType +) + +// A Field is a marshaling operation used to add a key-value pair to a logger's +// context. Most fields are lazily marshaled, so it's inexpensive to add fields +// to disabled debug-level log statements. +type Field struct { + Key string + Type FieldType + Integer int64 + String string + Interface interface{} +} + +// AddTo exports a field through the ObjectEncoder interface. It's primarily +// useful to library authors, and shouldn't be necessary in most applications. +func (f Field) AddTo(enc ObjectEncoder) { + var err error + + switch f.Type { + case ArrayMarshalerType: + err = enc.AddArray(f.Key, f.Interface.(ArrayMarshaler)) + case ObjectMarshalerType: + err = enc.AddObject(f.Key, f.Interface.(ObjectMarshaler)) + case BinaryType: + enc.AddBinary(f.Key, f.Interface.([]byte)) + case BoolType: + enc.AddBool(f.Key, f.Integer == 1) + case ByteStringType: + enc.AddByteString(f.Key, f.Interface.([]byte)) + case Complex128Type: + enc.AddComplex128(f.Key, f.Interface.(complex128)) + case Complex64Type: + enc.AddComplex64(f.Key, f.Interface.(complex64)) + case DurationType: + enc.AddDuration(f.Key, time.Duration(f.Integer)) + case Float64Type: + enc.AddFloat64(f.Key, math.Float64frombits(uint64(f.Integer))) + case Float32Type: + enc.AddFloat32(f.Key, math.Float32frombits(uint32(f.Integer))) + case Int64Type: + enc.AddInt64(f.Key, f.Integer) + case Int32Type: + enc.AddInt32(f.Key, int32(f.Integer)) + case Int16Type: + enc.AddInt16(f.Key, int16(f.Integer)) + case Int8Type: + enc.AddInt8(f.Key, int8(f.Integer)) + case StringType: + enc.AddString(f.Key, f.String) + case TimeType: + if f.Interface != nil { + enc.AddTime(f.Key, time.Unix(0, f.Integer).In(f.Interface.(*time.Location))) + } else { + // Fall back to UTC if location is nil. + enc.AddTime(f.Key, time.Unix(0, f.Integer)) + } + case Uint64Type: + enc.AddUint64(f.Key, uint64(f.Integer)) + case Uint32Type: + enc.AddUint32(f.Key, uint32(f.Integer)) + case Uint16Type: + enc.AddUint16(f.Key, uint16(f.Integer)) + case Uint8Type: + enc.AddUint8(f.Key, uint8(f.Integer)) + case UintptrType: + enc.AddUintptr(f.Key, uintptr(f.Integer)) + case ReflectType: + err = enc.AddReflected(f.Key, f.Interface) + case NamespaceType: + enc.OpenNamespace(f.Key) + case StringerType: + err = encodeStringer(f.Key, f.Interface, enc) + case ErrorType: + encodeError(f.Key, f.Interface.(error), enc) + case SkipType: + break + default: + panic(fmt.Sprintf("unknown field type: %v", f)) + } + + if err != nil { + enc.AddString(fmt.Sprintf("%sError", f.Key), err.Error()) + } +} + +// Equals returns whether two fields are equal. For non-primitive types such as +// errors, marshalers, or reflect types, it uses reflect.DeepEqual. +func (f Field) Equals(other Field) bool { + if f.Type != other.Type { + return false + } + if f.Key != other.Key { + return false + } + + switch f.Type { + case BinaryType, ByteStringType: + return bytes.Equal(f.Interface.([]byte), other.Interface.([]byte)) + case ArrayMarshalerType, ObjectMarshalerType, ErrorType, ReflectType: + return reflect.DeepEqual(f.Interface, other.Interface) + default: + return f == other + } +} + +func addFields(enc ObjectEncoder, fields []Field) { + for i := range fields { + fields[i].AddTo(enc) + } +} + +func encodeStringer(key string, stringer interface{}, enc ObjectEncoder) (err error) { + defer func() { + if v := recover(); v != nil { + err = fmt.Errorf("PANIC=%v", v) + } + }() + + enc.AddString(key, stringer.(fmt.Stringer).String()) + return +} diff --git a/vendor/go.uber.org/zap/zapcore/hook.go b/vendor/go.uber.org/zap/zapcore/hook.go new file mode 100644 index 0000000000..5db4afb302 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/hook.go @@ -0,0 +1,68 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import "go.uber.org/multierr" + +type hooked struct { + Core + funcs []func(Entry) error +} + +// RegisterHooks wraps a Core and runs a collection of user-defined callback +// hooks each time a message is logged. Execution of the callbacks is blocking. +// +// This offers users an easy way to register simple callbacks (e.g., metrics +// collection) without implementing the full Core interface. +func RegisterHooks(core Core, hooks ...func(Entry) error) Core { + funcs := append([]func(Entry) error{}, hooks...) + return &hooked{ + Core: core, + funcs: funcs, + } +} + +func (h *hooked) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { + // Let the wrapped Core decide whether to log this message or not. This + // also gives the downstream a chance to register itself directly with the + // CheckedEntry. + if downstream := h.Core.Check(ent, ce); downstream != nil { + return downstream.AddCore(ent, h) + } + return ce +} + +func (h *hooked) With(fields []Field) Core { + return &hooked{ + Core: h.Core.With(fields), + funcs: h.funcs, + } +} + +func (h *hooked) Write(ent Entry, _ []Field) error { + // Since our downstream had a chance to register itself directly with the + // CheckedMessage, we don't need to call it here. + var err error + for i := range h.funcs { + err = multierr.Append(err, h.funcs[i](ent)) + } + return err +} diff --git a/vendor/go.uber.org/zap/zapcore/json_encoder.go b/vendor/go.uber.org/zap/zapcore/json_encoder.go new file mode 100644 index 0000000000..9aec4eada3 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/json_encoder.go @@ -0,0 +1,505 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import ( + "encoding/base64" + "encoding/json" + "math" + "sync" + "time" + "unicode/utf8" + + "go.uber.org/zap/buffer" + "go.uber.org/zap/internal/bufferpool" +) + +// For JSON-escaping; see jsonEncoder.safeAddString below. +const _hex = "0123456789abcdef" + +var _jsonPool = sync.Pool{New: func() interface{} { + return &jsonEncoder{} +}} + +func getJSONEncoder() *jsonEncoder { + return _jsonPool.Get().(*jsonEncoder) +} + +func putJSONEncoder(enc *jsonEncoder) { + if enc.reflectBuf != nil { + enc.reflectBuf.Free() + } + enc.EncoderConfig = nil + enc.buf = nil + enc.spaced = false + enc.openNamespaces = 0 + enc.reflectBuf = nil + enc.reflectEnc = nil + _jsonPool.Put(enc) +} + +type jsonEncoder struct { + *EncoderConfig + buf *buffer.Buffer + spaced bool // include spaces after colons and commas + openNamespaces int + + // for encoding generic values by reflection + reflectBuf *buffer.Buffer + reflectEnc *json.Encoder +} + +// NewJSONEncoder creates a fast, low-allocation JSON encoder. The encoder +// appropriately escapes all field keys and values. +// +// Note that the encoder doesn't deduplicate keys, so it's possible to produce +// a message like +// {"foo":"bar","foo":"baz"} +// This is permitted by the JSON specification, but not encouraged. Many +// libraries will ignore duplicate key-value pairs (typically keeping the last +// pair) when unmarshaling, but users should attempt to avoid adding duplicate +// keys. +func NewJSONEncoder(cfg EncoderConfig) Encoder { + return newJSONEncoder(cfg, false) +} + +func newJSONEncoder(cfg EncoderConfig, spaced bool) *jsonEncoder { + return &jsonEncoder{ + EncoderConfig: &cfg, + buf: bufferpool.Get(), + spaced: spaced, + } +} + +func (enc *jsonEncoder) AddArray(key string, arr ArrayMarshaler) error { + enc.addKey(key) + return enc.AppendArray(arr) +} + +func (enc *jsonEncoder) AddObject(key string, obj ObjectMarshaler) error { + enc.addKey(key) + return enc.AppendObject(obj) +} + +func (enc *jsonEncoder) AddBinary(key string, val []byte) { + enc.AddString(key, base64.StdEncoding.EncodeToString(val)) +} + +func (enc *jsonEncoder) AddByteString(key string, val []byte) { + enc.addKey(key) + enc.AppendByteString(val) +} + +func (enc *jsonEncoder) AddBool(key string, val bool) { + enc.addKey(key) + enc.AppendBool(val) +} + +func (enc *jsonEncoder) AddComplex128(key string, val complex128) { + enc.addKey(key) + enc.AppendComplex128(val) +} + +func (enc *jsonEncoder) AddDuration(key string, val time.Duration) { + enc.addKey(key) + enc.AppendDuration(val) +} + +func (enc *jsonEncoder) AddFloat64(key string, val float64) { + enc.addKey(key) + enc.AppendFloat64(val) +} + +func (enc *jsonEncoder) AddInt64(key string, val int64) { + enc.addKey(key) + enc.AppendInt64(val) +} + +func (enc *jsonEncoder) resetReflectBuf() { + if enc.reflectBuf == nil { + enc.reflectBuf = bufferpool.Get() + enc.reflectEnc = json.NewEncoder(enc.reflectBuf) + + // For consistency with our custom JSON encoder. + enc.reflectEnc.SetEscapeHTML(false) + } else { + enc.reflectBuf.Reset() + } +} + +func (enc *jsonEncoder) AddReflected(key string, obj interface{}) error { + enc.resetReflectBuf() + err := enc.reflectEnc.Encode(obj) + if err != nil { + return err + } + enc.reflectBuf.TrimNewline() + enc.addKey(key) + _, err = enc.buf.Write(enc.reflectBuf.Bytes()) + return err +} + +func (enc *jsonEncoder) OpenNamespace(key string) { + enc.addKey(key) + enc.buf.AppendByte('{') + enc.openNamespaces++ +} + +func (enc *jsonEncoder) AddString(key, val string) { + enc.addKey(key) + enc.AppendString(val) +} + +func (enc *jsonEncoder) AddTime(key string, val time.Time) { + enc.addKey(key) + enc.AppendTime(val) +} + +func (enc *jsonEncoder) AddUint64(key string, val uint64) { + enc.addKey(key) + enc.AppendUint64(val) +} + +func (enc *jsonEncoder) AppendArray(arr ArrayMarshaler) error { + enc.addElementSeparator() + enc.buf.AppendByte('[') + err := arr.MarshalLogArray(enc) + enc.buf.AppendByte(']') + return err +} + +func (enc *jsonEncoder) AppendObject(obj ObjectMarshaler) error { + enc.addElementSeparator() + enc.buf.AppendByte('{') + err := obj.MarshalLogObject(enc) + enc.buf.AppendByte('}') + return err +} + +func (enc *jsonEncoder) AppendBool(val bool) { + enc.addElementSeparator() + enc.buf.AppendBool(val) +} + +func (enc *jsonEncoder) AppendByteString(val []byte) { + enc.addElementSeparator() + enc.buf.AppendByte('"') + enc.safeAddByteString(val) + enc.buf.AppendByte('"') +} + +func (enc *jsonEncoder) AppendComplex128(val complex128) { + enc.addElementSeparator() + // Cast to a platform-independent, fixed-size type. + r, i := float64(real(val)), float64(imag(val)) + enc.buf.AppendByte('"') + // Because we're always in a quoted string, we can use strconv without + // special-casing NaN and +/-Inf. + enc.buf.AppendFloat(r, 64) + enc.buf.AppendByte('+') + enc.buf.AppendFloat(i, 64) + enc.buf.AppendByte('i') + enc.buf.AppendByte('"') +} + +func (enc *jsonEncoder) AppendDuration(val time.Duration) { + cur := enc.buf.Len() + enc.EncodeDuration(val, enc) + if cur == enc.buf.Len() { + // User-supplied EncodeDuration is a no-op. Fall back to nanoseconds to keep + // JSON valid. + enc.AppendInt64(int64(val)) + } +} + +func (enc *jsonEncoder) AppendInt64(val int64) { + enc.addElementSeparator() + enc.buf.AppendInt(val) +} + +func (enc *jsonEncoder) AppendReflected(val interface{}) error { + enc.resetReflectBuf() + err := enc.reflectEnc.Encode(val) + if err != nil { + return err + } + enc.reflectBuf.TrimNewline() + enc.addElementSeparator() + _, err = enc.buf.Write(enc.reflectBuf.Bytes()) + return err +} + +func (enc *jsonEncoder) AppendString(val string) { + enc.addElementSeparator() + enc.buf.AppendByte('"') + enc.safeAddString(val) + enc.buf.AppendByte('"') +} + +func (enc *jsonEncoder) AppendTime(val time.Time) { + cur := enc.buf.Len() + enc.EncodeTime(val, enc) + if cur == enc.buf.Len() { + // User-supplied EncodeTime is a no-op. Fall back to nanos since epoch to keep + // output JSON valid. + enc.AppendInt64(val.UnixNano()) + } +} + +func (enc *jsonEncoder) AppendUint64(val uint64) { + enc.addElementSeparator() + enc.buf.AppendUint(val) +} + +func (enc *jsonEncoder) AddComplex64(k string, v complex64) { enc.AddComplex128(k, complex128(v)) } +func (enc *jsonEncoder) AddFloat32(k string, v float32) { enc.AddFloat64(k, float64(v)) } +func (enc *jsonEncoder) AddInt(k string, v int) { enc.AddInt64(k, int64(v)) } +func (enc *jsonEncoder) AddInt32(k string, v int32) { enc.AddInt64(k, int64(v)) } +func (enc *jsonEncoder) AddInt16(k string, v int16) { enc.AddInt64(k, int64(v)) } +func (enc *jsonEncoder) AddInt8(k string, v int8) { enc.AddInt64(k, int64(v)) } +func (enc *jsonEncoder) AddUint(k string, v uint) { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AddUint32(k string, v uint32) { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AddUint16(k string, v uint16) { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AddUint8(k string, v uint8) { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AddUintptr(k string, v uintptr) { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AppendComplex64(v complex64) { enc.AppendComplex128(complex128(v)) } +func (enc *jsonEncoder) AppendFloat64(v float64) { enc.appendFloat(v, 64) } +func (enc *jsonEncoder) AppendFloat32(v float32) { enc.appendFloat(float64(v), 32) } +func (enc *jsonEncoder) AppendInt(v int) { enc.AppendInt64(int64(v)) } +func (enc *jsonEncoder) AppendInt32(v int32) { enc.AppendInt64(int64(v)) } +func (enc *jsonEncoder) AppendInt16(v int16) { enc.AppendInt64(int64(v)) } +func (enc *jsonEncoder) AppendInt8(v int8) { enc.AppendInt64(int64(v)) } +func (enc *jsonEncoder) AppendUint(v uint) { enc.AppendUint64(uint64(v)) } +func (enc *jsonEncoder) AppendUint32(v uint32) { enc.AppendUint64(uint64(v)) } +func (enc *jsonEncoder) AppendUint16(v uint16) { enc.AppendUint64(uint64(v)) } +func (enc *jsonEncoder) AppendUint8(v uint8) { enc.AppendUint64(uint64(v)) } +func (enc *jsonEncoder) AppendUintptr(v uintptr) { enc.AppendUint64(uint64(v)) } + +func (enc *jsonEncoder) Clone() Encoder { + clone := enc.clone() + clone.buf.Write(enc.buf.Bytes()) + return clone +} + +func (enc *jsonEncoder) clone() *jsonEncoder { + clone := getJSONEncoder() + clone.EncoderConfig = enc.EncoderConfig + clone.spaced = enc.spaced + clone.openNamespaces = enc.openNamespaces + clone.buf = bufferpool.Get() + return clone +} + +func (enc *jsonEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer, error) { + final := enc.clone() + final.buf.AppendByte('{') + + if final.LevelKey != "" { + final.addKey(final.LevelKey) + cur := final.buf.Len() + final.EncodeLevel(ent.Level, final) + if cur == final.buf.Len() { + // User-supplied EncodeLevel was a no-op. Fall back to strings to keep + // output JSON valid. + final.AppendString(ent.Level.String()) + } + } + if final.TimeKey != "" { + final.AddTime(final.TimeKey, ent.Time) + } + if ent.LoggerName != "" && final.NameKey != "" { + final.addKey(final.NameKey) + cur := final.buf.Len() + nameEncoder := final.EncodeName + + // if no name encoder provided, fall back to FullNameEncoder for backwards + // compatibility + if nameEncoder == nil { + nameEncoder = FullNameEncoder + } + + nameEncoder(ent.LoggerName, final) + if cur == final.buf.Len() { + // User-supplied EncodeName was a no-op. Fall back to strings to + // keep output JSON valid. + final.AppendString(ent.LoggerName) + } + } + if ent.Caller.Defined && final.CallerKey != "" { + final.addKey(final.CallerKey) + cur := final.buf.Len() + final.EncodeCaller(ent.Caller, final) + if cur == final.buf.Len() { + // User-supplied EncodeCaller was a no-op. Fall back to strings to + // keep output JSON valid. + final.AppendString(ent.Caller.String()) + } + } + if final.MessageKey != "" { + final.addKey(enc.MessageKey) + final.AppendString(ent.Message) + } + if enc.buf.Len() > 0 { + final.addElementSeparator() + final.buf.Write(enc.buf.Bytes()) + } + addFields(final, fields) + final.closeOpenNamespaces() + if ent.Stack != "" && final.StacktraceKey != "" { + final.AddString(final.StacktraceKey, ent.Stack) + } + final.buf.AppendByte('}') + if final.LineEnding != "" { + final.buf.AppendString(final.LineEnding) + } else { + final.buf.AppendString(DefaultLineEnding) + } + + ret := final.buf + putJSONEncoder(final) + return ret, nil +} + +func (enc *jsonEncoder) truncate() { + enc.buf.Reset() +} + +func (enc *jsonEncoder) closeOpenNamespaces() { + for i := 0; i < enc.openNamespaces; i++ { + enc.buf.AppendByte('}') + } +} + +func (enc *jsonEncoder) addKey(key string) { + enc.addElementSeparator() + enc.buf.AppendByte('"') + enc.safeAddString(key) + enc.buf.AppendByte('"') + enc.buf.AppendByte(':') + if enc.spaced { + enc.buf.AppendByte(' ') + } +} + +func (enc *jsonEncoder) addElementSeparator() { + last := enc.buf.Len() - 1 + if last < 0 { + return + } + switch enc.buf.Bytes()[last] { + case '{', '[', ':', ',', ' ': + return + default: + enc.buf.AppendByte(',') + if enc.spaced { + enc.buf.AppendByte(' ') + } + } +} + +func (enc *jsonEncoder) appendFloat(val float64, bitSize int) { + enc.addElementSeparator() + switch { + case math.IsNaN(val): + enc.buf.AppendString(`"NaN"`) + case math.IsInf(val, 1): + enc.buf.AppendString(`"+Inf"`) + case math.IsInf(val, -1): + enc.buf.AppendString(`"-Inf"`) + default: + enc.buf.AppendFloat(val, bitSize) + } +} + +// safeAddString JSON-escapes a string and appends it to the internal buffer. +// Unlike the standard library's encoder, it doesn't attempt to protect the +// user from browser vulnerabilities or JSONP-related problems. +func (enc *jsonEncoder) safeAddString(s string) { + for i := 0; i < len(s); { + if enc.tryAddRuneSelf(s[i]) { + i++ + continue + } + r, size := utf8.DecodeRuneInString(s[i:]) + if enc.tryAddRuneError(r, size) { + i++ + continue + } + enc.buf.AppendString(s[i : i+size]) + i += size + } +} + +// safeAddByteString is no-alloc equivalent of safeAddString(string(s)) for s []byte. +func (enc *jsonEncoder) safeAddByteString(s []byte) { + for i := 0; i < len(s); { + if enc.tryAddRuneSelf(s[i]) { + i++ + continue + } + r, size := utf8.DecodeRune(s[i:]) + if enc.tryAddRuneError(r, size) { + i++ + continue + } + enc.buf.Write(s[i : i+size]) + i += size + } +} + +// tryAddRuneSelf appends b if it is valid UTF-8 character represented in a single byte. +func (enc *jsonEncoder) tryAddRuneSelf(b byte) bool { + if b >= utf8.RuneSelf { + return false + } + if 0x20 <= b && b != '\\' && b != '"' { + enc.buf.AppendByte(b) + return true + } + switch b { + case '\\', '"': + enc.buf.AppendByte('\\') + enc.buf.AppendByte(b) + case '\n': + enc.buf.AppendByte('\\') + enc.buf.AppendByte('n') + case '\r': + enc.buf.AppendByte('\\') + enc.buf.AppendByte('r') + case '\t': + enc.buf.AppendByte('\\') + enc.buf.AppendByte('t') + default: + // Encode bytes < 0x20, except for the escape sequences above. + enc.buf.AppendString(`\u00`) + enc.buf.AppendByte(_hex[b>>4]) + enc.buf.AppendByte(_hex[b&0xF]) + } + return true +} + +func (enc *jsonEncoder) tryAddRuneError(r rune, size int) bool { + if r == utf8.RuneError && size == 1 { + enc.buf.AppendString(`\ufffd`) + return true + } + return false +} diff --git a/vendor/go.uber.org/zap/zapcore/level.go b/vendor/go.uber.org/zap/zapcore/level.go new file mode 100644 index 0000000000..e575c9f432 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/level.go @@ -0,0 +1,175 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import ( + "bytes" + "errors" + "fmt" +) + +var errUnmarshalNilLevel = errors.New("can't unmarshal a nil *Level") + +// A Level is a logging priority. Higher levels are more important. +type Level int8 + +const ( + // DebugLevel logs are typically voluminous, and are usually disabled in + // production. + DebugLevel Level = iota - 1 + // InfoLevel is the default logging priority. + InfoLevel + // WarnLevel logs are more important than Info, but don't need individual + // human review. + WarnLevel + // ErrorLevel logs are high-priority. If an application is running smoothly, + // it shouldn't generate any error-level logs. + ErrorLevel + // DPanicLevel logs are particularly important errors. In development the + // logger panics after writing the message. + DPanicLevel + // PanicLevel logs a message, then panics. + PanicLevel + // FatalLevel logs a message, then calls os.Exit(1). + FatalLevel + + _minLevel = DebugLevel + _maxLevel = FatalLevel +) + +// String returns a lower-case ASCII representation of the log level. +func (l Level) String() string { + switch l { + case DebugLevel: + return "debug" + case InfoLevel: + return "info" + case WarnLevel: + return "warn" + case ErrorLevel: + return "error" + case DPanicLevel: + return "dpanic" + case PanicLevel: + return "panic" + case FatalLevel: + return "fatal" + default: + return fmt.Sprintf("Level(%d)", l) + } +} + +// CapitalString returns an all-caps ASCII representation of the log level. +func (l Level) CapitalString() string { + // Printing levels in all-caps is common enough that we should export this + // functionality. + switch l { + case DebugLevel: + return "DEBUG" + case InfoLevel: + return "INFO" + case WarnLevel: + return "WARN" + case ErrorLevel: + return "ERROR" + case DPanicLevel: + return "DPANIC" + case PanicLevel: + return "PANIC" + case FatalLevel: + return "FATAL" + default: + return fmt.Sprintf("LEVEL(%d)", l) + } +} + +// MarshalText marshals the Level to text. Note that the text representation +// drops the -Level suffix (see example). +func (l Level) MarshalText() ([]byte, error) { + return []byte(l.String()), nil +} + +// UnmarshalText unmarshals text to a level. Like MarshalText, UnmarshalText +// expects the text representation of a Level to drop the -Level suffix (see +// example). +// +// In particular, this makes it easy to configure logging levels using YAML, +// TOML, or JSON files. +func (l *Level) UnmarshalText(text []byte) error { + if l == nil { + return errUnmarshalNilLevel + } + if !l.unmarshalText(text) && !l.unmarshalText(bytes.ToLower(text)) { + return fmt.Errorf("unrecognized level: %q", text) + } + return nil +} + +func (l *Level) unmarshalText(text []byte) bool { + switch string(text) { + case "debug", "DEBUG": + *l = DebugLevel + case "info", "INFO", "": // make the zero value useful + *l = InfoLevel + case "warn", "WARN": + *l = WarnLevel + case "error", "ERROR": + *l = ErrorLevel + case "dpanic", "DPANIC": + *l = DPanicLevel + case "panic", "PANIC": + *l = PanicLevel + case "fatal", "FATAL": + *l = FatalLevel + default: + return false + } + return true +} + +// Set sets the level for the flag.Value interface. +func (l *Level) Set(s string) error { + return l.UnmarshalText([]byte(s)) +} + +// Get gets the level for the flag.Getter interface. +func (l *Level) Get() interface{} { + return *l +} + +// Enabled returns true if the given level is at or above this level. +func (l Level) Enabled(lvl Level) bool { + return lvl >= l +} + +// LevelEnabler decides whether a given logging level is enabled when logging a +// message. +// +// Enablers are intended to be used to implement deterministic filters; +// concerns like sampling are better implemented as a Core. +// +// Each concrete Level value implements a static LevelEnabler which returns +// true for itself and all higher logging levels. For example WarnLevel.Enabled() +// will return true for WarnLevel, ErrorLevel, DPanicLevel, PanicLevel, and +// FatalLevel, but return false for InfoLevel and DebugLevel. +type LevelEnabler interface { + Enabled(Level) bool +} diff --git a/vendor/go.uber.org/zap/zapcore/level_strings.go b/vendor/go.uber.org/zap/zapcore/level_strings.go new file mode 100644 index 0000000000..7af8dadcb3 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/level_strings.go @@ -0,0 +1,46 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import "go.uber.org/zap/internal/color" + +var ( + _levelToColor = map[Level]color.Color{ + DebugLevel: color.Magenta, + InfoLevel: color.Blue, + WarnLevel: color.Yellow, + ErrorLevel: color.Red, + DPanicLevel: color.Red, + PanicLevel: color.Red, + FatalLevel: color.Red, + } + _unknownLevelColor = color.Red + + _levelToLowercaseColorString = make(map[Level]string, len(_levelToColor)) + _levelToCapitalColorString = make(map[Level]string, len(_levelToColor)) +) + +func init() { + for level, color := range _levelToColor { + _levelToLowercaseColorString[level] = color.Add(level.String()) + _levelToCapitalColorString[level] = color.Add(level.CapitalString()) + } +} diff --git a/vendor/go.uber.org/zap/zapcore/marshaler.go b/vendor/go.uber.org/zap/zapcore/marshaler.go new file mode 100644 index 0000000000..2627a653df --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/marshaler.go @@ -0,0 +1,53 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +// ObjectMarshaler allows user-defined types to efficiently add themselves to the +// logging context, and to selectively omit information which shouldn't be +// included in logs (e.g., passwords). +type ObjectMarshaler interface { + MarshalLogObject(ObjectEncoder) error +} + +// ObjectMarshalerFunc is a type adapter that turns a function into an +// ObjectMarshaler. +type ObjectMarshalerFunc func(ObjectEncoder) error + +// MarshalLogObject calls the underlying function. +func (f ObjectMarshalerFunc) MarshalLogObject(enc ObjectEncoder) error { + return f(enc) +} + +// ArrayMarshaler allows user-defined types to efficiently add themselves to the +// logging context, and to selectively omit information which shouldn't be +// included in logs (e.g., passwords). +type ArrayMarshaler interface { + MarshalLogArray(ArrayEncoder) error +} + +// ArrayMarshalerFunc is a type adapter that turns a function into an +// ArrayMarshaler. +type ArrayMarshalerFunc func(ArrayEncoder) error + +// MarshalLogArray calls the underlying function. +func (f ArrayMarshalerFunc) MarshalLogArray(enc ArrayEncoder) error { + return f(enc) +} diff --git a/vendor/go.uber.org/zap/zapcore/memory_encoder.go b/vendor/go.uber.org/zap/zapcore/memory_encoder.go new file mode 100644 index 0000000000..dfead0829d --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/memory_encoder.go @@ -0,0 +1,179 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import "time" + +// MapObjectEncoder is an ObjectEncoder backed by a simple +// map[string]interface{}. It's not fast enough for production use, but it's +// helpful in tests. +type MapObjectEncoder struct { + // Fields contains the entire encoded log context. + Fields map[string]interface{} + // cur is a pointer to the namespace we're currently writing to. + cur map[string]interface{} +} + +// NewMapObjectEncoder creates a new map-backed ObjectEncoder. +func NewMapObjectEncoder() *MapObjectEncoder { + m := make(map[string]interface{}) + return &MapObjectEncoder{ + Fields: m, + cur: m, + } +} + +// AddArray implements ObjectEncoder. +func (m *MapObjectEncoder) AddArray(key string, v ArrayMarshaler) error { + arr := &sliceArrayEncoder{elems: make([]interface{}, 0)} + err := v.MarshalLogArray(arr) + m.cur[key] = arr.elems + return err +} + +// AddObject implements ObjectEncoder. +func (m *MapObjectEncoder) AddObject(k string, v ObjectMarshaler) error { + newMap := NewMapObjectEncoder() + m.cur[k] = newMap.Fields + return v.MarshalLogObject(newMap) +} + +// AddBinary implements ObjectEncoder. +func (m *MapObjectEncoder) AddBinary(k string, v []byte) { m.cur[k] = v } + +// AddByteString implements ObjectEncoder. +func (m *MapObjectEncoder) AddByteString(k string, v []byte) { m.cur[k] = string(v) } + +// AddBool implements ObjectEncoder. +func (m *MapObjectEncoder) AddBool(k string, v bool) { m.cur[k] = v } + +// AddDuration implements ObjectEncoder. +func (m MapObjectEncoder) AddDuration(k string, v time.Duration) { m.cur[k] = v } + +// AddComplex128 implements ObjectEncoder. +func (m *MapObjectEncoder) AddComplex128(k string, v complex128) { m.cur[k] = v } + +// AddComplex64 implements ObjectEncoder. +func (m *MapObjectEncoder) AddComplex64(k string, v complex64) { m.cur[k] = v } + +// AddFloat64 implements ObjectEncoder. +func (m *MapObjectEncoder) AddFloat64(k string, v float64) { m.cur[k] = v } + +// AddFloat32 implements ObjectEncoder. +func (m *MapObjectEncoder) AddFloat32(k string, v float32) { m.cur[k] = v } + +// AddInt implements ObjectEncoder. +func (m *MapObjectEncoder) AddInt(k string, v int) { m.cur[k] = v } + +// AddInt64 implements ObjectEncoder. +func (m *MapObjectEncoder) AddInt64(k string, v int64) { m.cur[k] = v } + +// AddInt32 implements ObjectEncoder. +func (m *MapObjectEncoder) AddInt32(k string, v int32) { m.cur[k] = v } + +// AddInt16 implements ObjectEncoder. +func (m *MapObjectEncoder) AddInt16(k string, v int16) { m.cur[k] = v } + +// AddInt8 implements ObjectEncoder. +func (m *MapObjectEncoder) AddInt8(k string, v int8) { m.cur[k] = v } + +// AddString implements ObjectEncoder. +func (m *MapObjectEncoder) AddString(k string, v string) { m.cur[k] = v } + +// AddTime implements ObjectEncoder. +func (m MapObjectEncoder) AddTime(k string, v time.Time) { m.cur[k] = v } + +// AddUint implements ObjectEncoder. +func (m *MapObjectEncoder) AddUint(k string, v uint) { m.cur[k] = v } + +// AddUint64 implements ObjectEncoder. +func (m *MapObjectEncoder) AddUint64(k string, v uint64) { m.cur[k] = v } + +// AddUint32 implements ObjectEncoder. +func (m *MapObjectEncoder) AddUint32(k string, v uint32) { m.cur[k] = v } + +// AddUint16 implements ObjectEncoder. +func (m *MapObjectEncoder) AddUint16(k string, v uint16) { m.cur[k] = v } + +// AddUint8 implements ObjectEncoder. +func (m *MapObjectEncoder) AddUint8(k string, v uint8) { m.cur[k] = v } + +// AddUintptr implements ObjectEncoder. +func (m *MapObjectEncoder) AddUintptr(k string, v uintptr) { m.cur[k] = v } + +// AddReflected implements ObjectEncoder. +func (m *MapObjectEncoder) AddReflected(k string, v interface{}) error { + m.cur[k] = v + return nil +} + +// OpenNamespace implements ObjectEncoder. +func (m *MapObjectEncoder) OpenNamespace(k string) { + ns := make(map[string]interface{}) + m.cur[k] = ns + m.cur = ns +} + +// sliceArrayEncoder is an ArrayEncoder backed by a simple []interface{}. Like +// the MapObjectEncoder, it's not designed for production use. +type sliceArrayEncoder struct { + elems []interface{} +} + +func (s *sliceArrayEncoder) AppendArray(v ArrayMarshaler) error { + enc := &sliceArrayEncoder{} + err := v.MarshalLogArray(enc) + s.elems = append(s.elems, enc.elems) + return err +} + +func (s *sliceArrayEncoder) AppendObject(v ObjectMarshaler) error { + m := NewMapObjectEncoder() + err := v.MarshalLogObject(m) + s.elems = append(s.elems, m.Fields) + return err +} + +func (s *sliceArrayEncoder) AppendReflected(v interface{}) error { + s.elems = append(s.elems, v) + return nil +} + +func (s *sliceArrayEncoder) AppendBool(v bool) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendByteString(v []byte) { s.elems = append(s.elems, string(v)) } +func (s *sliceArrayEncoder) AppendComplex128(v complex128) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendComplex64(v complex64) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendDuration(v time.Duration) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendFloat64(v float64) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendFloat32(v float32) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt(v int) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt64(v int64) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt32(v int32) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt16(v int16) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendInt8(v int8) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendString(v string) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendTime(v time.Time) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint(v uint) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint64(v uint64) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint32(v uint32) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint16(v uint16) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUint8(v uint8) { s.elems = append(s.elems, v) } +func (s *sliceArrayEncoder) AppendUintptr(v uintptr) { s.elems = append(s.elems, v) } diff --git a/vendor/go.uber.org/zap/zapcore/sampler.go b/vendor/go.uber.org/zap/zapcore/sampler.go new file mode 100644 index 0000000000..e316418636 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/sampler.go @@ -0,0 +1,134 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import ( + "time" + + "go.uber.org/atomic" +) + +const ( + _numLevels = _maxLevel - _minLevel + 1 + _countersPerLevel = 4096 +) + +type counter struct { + resetAt atomic.Int64 + counter atomic.Uint64 +} + +type counters [_numLevels][_countersPerLevel]counter + +func newCounters() *counters { + return &counters{} +} + +func (cs *counters) get(lvl Level, key string) *counter { + i := lvl - _minLevel + j := fnv32a(key) % _countersPerLevel + return &cs[i][j] +} + +// fnv32a, adapted from "hash/fnv", but without a []byte(string) alloc +func fnv32a(s string) uint32 { + const ( + offset32 = 2166136261 + prime32 = 16777619 + ) + hash := uint32(offset32) + for i := 0; i < len(s); i++ { + hash ^= uint32(s[i]) + hash *= prime32 + } + return hash +} + +func (c *counter) IncCheckReset(t time.Time, tick time.Duration) uint64 { + tn := t.UnixNano() + resetAfter := c.resetAt.Load() + if resetAfter > tn { + return c.counter.Inc() + } + + c.counter.Store(1) + + newResetAfter := tn + tick.Nanoseconds() + if !c.resetAt.CAS(resetAfter, newResetAfter) { + // We raced with another goroutine trying to reset, and it also reset + // the counter to 1, so we need to reincrement the counter. + return c.counter.Inc() + } + + return 1 +} + +type sampler struct { + Core + + counts *counters + tick time.Duration + first, thereafter uint64 +} + +// NewSampler creates a Core that samples incoming entries, which caps the CPU +// and I/O load of logging while attempting to preserve a representative subset +// of your logs. +// +// Zap samples by logging the first N entries with a given level and message +// each tick. If more Entries with the same level and message are seen during +// the same interval, every Mth message is logged and the rest are dropped. +// +// Keep in mind that zap's sampling implementation is optimized for speed over +// absolute precision; under load, each tick may be slightly over- or +// under-sampled. +func NewSampler(core Core, tick time.Duration, first, thereafter int) Core { + return &sampler{ + Core: core, + tick: tick, + counts: newCounters(), + first: uint64(first), + thereafter: uint64(thereafter), + } +} + +func (s *sampler) With(fields []Field) Core { + return &sampler{ + Core: s.Core.With(fields), + tick: s.tick, + counts: s.counts, + first: s.first, + thereafter: s.thereafter, + } +} + +func (s *sampler) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { + if !s.Enabled(ent.Level) { + return ce + } + + counter := s.counts.get(ent.Level, ent.Message) + n := counter.IncCheckReset(ent.Time, s.tick) + if n > s.first && (n-s.first)%s.thereafter != 0 { + return ce + } + return s.Core.Check(ent, ce) +} diff --git a/vendor/go.uber.org/zap/zapcore/tee.go b/vendor/go.uber.org/zap/zapcore/tee.go new file mode 100644 index 0000000000..07a32eef9a --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/tee.go @@ -0,0 +1,81 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import "go.uber.org/multierr" + +type multiCore []Core + +// NewTee creates a Core that duplicates log entries into two or more +// underlying Cores. +// +// Calling it with a single Core returns the input unchanged, and calling +// it with no input returns a no-op Core. +func NewTee(cores ...Core) Core { + switch len(cores) { + case 0: + return NewNopCore() + case 1: + return cores[0] + default: + return multiCore(cores) + } +} + +func (mc multiCore) With(fields []Field) Core { + clone := make(multiCore, len(mc)) + for i := range mc { + clone[i] = mc[i].With(fields) + } + return clone +} + +func (mc multiCore) Enabled(lvl Level) bool { + for i := range mc { + if mc[i].Enabled(lvl) { + return true + } + } + return false +} + +func (mc multiCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { + for i := range mc { + ce = mc[i].Check(ent, ce) + } + return ce +} + +func (mc multiCore) Write(ent Entry, fields []Field) error { + var err error + for i := range mc { + err = multierr.Append(err, mc[i].Write(ent, fields)) + } + return err +} + +func (mc multiCore) Sync() error { + var err error + for i := range mc { + err = multierr.Append(err, mc[i].Sync()) + } + return err +} diff --git a/vendor/go.uber.org/zap/zapcore/write_syncer.go b/vendor/go.uber.org/zap/zapcore/write_syncer.go new file mode 100644 index 0000000000..209e25fe22 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/write_syncer.go @@ -0,0 +1,123 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import ( + "io" + "sync" + + "go.uber.org/multierr" +) + +// A WriteSyncer is an io.Writer that can also flush any buffered data. Note +// that *os.File (and thus, os.Stderr and os.Stdout) implement WriteSyncer. +type WriteSyncer interface { + io.Writer + Sync() error +} + +// AddSync converts an io.Writer to a WriteSyncer. It attempts to be +// intelligent: if the concrete type of the io.Writer implements WriteSyncer, +// we'll use the existing Sync method. If it doesn't, we'll add a no-op Sync. +func AddSync(w io.Writer) WriteSyncer { + switch w := w.(type) { + case WriteSyncer: + return w + default: + return writerWrapper{w} + } +} + +type lockedWriteSyncer struct { + sync.Mutex + ws WriteSyncer +} + +// Lock wraps a WriteSyncer in a mutex to make it safe for concurrent use. In +// particular, *os.Files must be locked before use. +func Lock(ws WriteSyncer) WriteSyncer { + if _, ok := ws.(*lockedWriteSyncer); ok { + // no need to layer on another lock + return ws + } + return &lockedWriteSyncer{ws: ws} +} + +func (s *lockedWriteSyncer) Write(bs []byte) (int, error) { + s.Lock() + n, err := s.ws.Write(bs) + s.Unlock() + return n, err +} + +func (s *lockedWriteSyncer) Sync() error { + s.Lock() + err := s.ws.Sync() + s.Unlock() + return err +} + +type writerWrapper struct { + io.Writer +} + +func (w writerWrapper) Sync() error { + return nil +} + +type multiWriteSyncer []WriteSyncer + +// NewMultiWriteSyncer creates a WriteSyncer that duplicates its writes +// and sync calls, much like io.MultiWriter. +func NewMultiWriteSyncer(ws ...WriteSyncer) WriteSyncer { + if len(ws) == 1 { + return ws[0] + } + // Copy to protect against https://github.com/golang/go/issues/7809 + return multiWriteSyncer(append([]WriteSyncer(nil), ws...)) +} + +// See https://golang.org/src/io/multi.go +// When not all underlying syncers write the same number of bytes, +// the smallest number is returned even though Write() is called on +// all of them. +func (ws multiWriteSyncer) Write(p []byte) (int, error) { + var writeErr error + nWritten := 0 + for _, w := range ws { + n, err := w.Write(p) + writeErr = multierr.Append(writeErr, err) + if nWritten == 0 && n != 0 { + nWritten = n + } else if n < nWritten { + nWritten = n + } + } + return nWritten, writeErr +} + +func (ws multiWriteSyncer) Sync() error { + var err error + for _, w := range ws { + err = multierr.Append(err, w.Sync()) + } + return err +} diff --git a/vendor/knative.dev/pkg/apis/condition_types.go b/vendor/knative.dev/pkg/apis/condition_types.go index 31c566807f..c90438648b 100644 --- a/vendor/knative.dev/pkg/apis/condition_types.go +++ b/vendor/knative.dev/pkg/apis/condition_types.go @@ -53,7 +53,7 @@ const ( ) // Conditions defines a readiness condition for a Knative resource. -// See: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#typical-status-properties +// See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties // +k8s:deepcopy-gen=true // +k8s:openapi-gen=true type Condition struct { diff --git a/vendor/knative.dev/pkg/apis/duck/patch.go b/vendor/knative.dev/pkg/apis/duck/patch.go index 386aa1f32e..d4a01d1aab 100644 --- a/vendor/knative.dev/pkg/apis/duck/patch.go +++ b/vendor/knative.dev/pkg/apis/duck/patch.go @@ -37,6 +37,8 @@ func marshallBeforeAfter(before, after interface{}) ([]byte, []byte, error) { return rawBefore, rawAfter, nil } +// CreateMergePatch creates a json merge patch as specified in +// http://tools.ietf.org/html/draft-ietf-appsawg-json-merge-patch-07 func CreateMergePatch(before, after interface{}) ([]byte, error) { rawBefore, rawAfter, err := marshallBeforeAfter(before, after) if err != nil { @@ -45,6 +47,17 @@ func CreateMergePatch(before, after interface{}) ([]byte, error) { return jsonmergepatch.CreateMergePatch(rawBefore, rawAfter) } +// CreateBytePatch is a helper function that creates the same content as +// CreatePatch, but returns in []byte format instead of JSONPatch. +func CreateBytePatch(before, after interface{}) ([]byte, error) { + patch, err := CreatePatch(before, after) + if err != nil { + return nil, err + } + return patch.MarshalJSON() +} + +// CreatePatch creates a patch as specified in http://jsonpatch.com/ func CreatePatch(before, after interface{}) (JSONPatch, error) { rawBefore, rawAfter, err := marshallBeforeAfter(before, after) if err != nil { diff --git a/vendor/knative.dev/pkg/apis/duck/v1/addressable_types.go b/vendor/knative.dev/pkg/apis/duck/v1/addressable_types.go new file mode 100644 index 0000000000..7d804ea885 --- /dev/null +++ b/vendor/knative.dev/pkg/apis/duck/v1/addressable_types.go @@ -0,0 +1,114 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + "knative.dev/pkg/apis" + "knative.dev/pkg/apis/duck" +) + +// Addressable provides a generic mechanism for a custom resource +// definition to indicate a destination for message delivery. + +// Addressable is the schema for the destination information. This is +// typically stored in the object's `status`, as this information may +// be generated by the controller. +type Addressable struct { + URL *apis.URL `json:"url,omitempty"` +} + +var ( + // Addressable is an Implementable "duck type". + _ duck.Implementable = (*Addressable)(nil) + // Addressable is a Convertible type. + _ apis.Convertible = (*Addressable)(nil) +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// AddressableType is a skeleton type wrapping Addressable in the manner we expect +// resource writers defining compatible resources to embed it. We will +// typically use this type to deserialize Addressable ObjectReferences and +// access the Addressable data. This is not a real resource. +type AddressableType struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Status AddressStatus `json:"status"` +} + +// AddressStatus shows how we expect folks to embed Addressable in +// their Status field. +type AddressStatus struct { + Address *Addressable `json:"address,omitempty"` +} + +var ( + // Verify AddressableType resources meet duck contracts. + _ duck.Populatable = (*AddressableType)(nil) + _ apis.Listable = (*AddressableType)(nil) +) + +// GetFullType implements duck.Implementable +func (*Addressable) GetFullType() duck.Populatable { + return &AddressableType{} +} + +// ConvertUp implements apis.Convertible +func (a *Addressable) ConvertUp(ctx context.Context, to apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", to) +} + +// ConvertDown implements apis.Convertible +func (a *Addressable) ConvertDown(ctx context.Context, from apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", from) +} + +// Populate implements duck.Populatable +func (t *AddressableType) Populate() { + t.Status = AddressStatus{ + &Addressable{ + // Populate ALL fields + URL: &apis.URL{ + Scheme: "http", + Host: "foo.com", + }, + }, + } +} + +// GetListType implements apis.Listable +func (*AddressableType) GetListType() runtime.Object { + return &AddressableTypeList{} +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// AddressableTypeList is a list of AddressableType resources +type AddressableTypeList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []AddressableType `json:"items"` +} diff --git a/vendor/knative.dev/pkg/apis/duck/v1/doc.go b/vendor/knative.dev/pkg/apis/duck/v1/doc.go new file mode 100644 index 0000000000..161005b080 --- /dev/null +++ b/vendor/knative.dev/pkg/apis/duck/v1/doc.go @@ -0,0 +1,23 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Api versions allow the api contract for a resource to be changed while keeping +// backward compatibility by support multiple concurrent versions +// of the same resource + +// +k8s:deepcopy-gen=package +// +groupName=duck.knative.dev +package v1 diff --git a/vendor/knative.dev/pkg/apis/duck/v1/register.go b/vendor/knative.dev/pkg/apis/duck/v1/register.go new file mode 100644 index 0000000000..43f5e89ad2 --- /dev/null +++ b/vendor/knative.dev/pkg/apis/duck/v1/register.go @@ -0,0 +1,55 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "knative.dev/pkg/apis/duck" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: duck.GroupName, Version: "v1"} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes( + SchemeGroupVersion, + &KResource{}, + (&KResource{}).GetListType(), + &AddressableType{}, + (&AddressableType{}).GetListType(), + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/knative.dev/pkg/apis/duck/v1/source_types.go b/vendor/knative.dev/pkg/apis/duck/v1/source_types.go new file mode 100644 index 0000000000..da217c59c7 --- /dev/null +++ b/vendor/knative.dev/pkg/apis/duck/v1/source_types.go @@ -0,0 +1,157 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + "knative.dev/pkg/apis" + "knative.dev/pkg/apis/duck" + apisv1alpha1 "knative.dev/pkg/apis/v1alpha1" +) + +// Source is an Implementable "duck type". +var _ duck.Implementable = (*Source)(nil) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Source is the minimum resource shape to adhere to the Source Specification. +// This duck type is intended to allow implementors of Sources and +// Importers to verify their own resources meet the expectations. +// This is not a real resource. +// NOTE: The Source Specification is in progress and the shape and names could +// be modified until it has been accepted. +type Source struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec SourceSpec `json:"spec"` + Status SourceStatus `json:"status"` +} + +type SourceSpec struct { + // Sink is a reference to an object that will resolve to a domain name or a + // URI directly to use as the sink. + Sink apisv1alpha1.Destination `json:"sink,omitempty"` + + // CloudEventOverrides defines overrides to control the output format and + // modifications of the event sent to the sink. + // +optional + CloudEventOverrides *CloudEventOverrides `json:"ceOverrides,omitempty"` +} + +// CloudEventOverrides defines arguments for a Source that control the output +// format of the CloudEvents produced by the Source. +type CloudEventOverrides struct { + // Extensions specify what attribute are added or overridden on the + // outbound event. Each `Extensions` key-value pair are set on the event as + // an attribute extension independently. + // +optional + Extensions map[string]string `json:"extensions,omitempty"` +} + +// SourceStatus shows how we expect folks to embed Addressable in +// their Status field. +type SourceStatus struct { + // inherits duck/v1beta1 Status, which currently provides: + // * ObservedGeneration - the 'Generation' of the Service that was last + // processed by the controller. + // * Conditions - the latest available observations of a resource's current + // state. + Status `json:",inline"` + + // SinkURI is the current active sink URI that has been configured for the + // Source. + // +optional + SinkURI *apis.URL `json:"sinkUri,omitempty"` +} + +// IsReady returns true if the resource is ready overall. +func (ss *SourceStatus) IsReady() bool { + for _, c := range ss.Conditions { + switch c.Type { + // Look for the "happy" condition, which is the only condition that + // we can reliably understand to be the overall state of the resource. + case apis.ConditionReady, apis.ConditionSucceeded: + return c.IsTrue() + } + } + return false +} + +var ( + // Verify Source resources meet duck contracts. + _ duck.Populatable = (*Source)(nil) + _ apis.Listable = (*Source)(nil) +) + +const ( + // SourceConditionSinkProvided has status True when the Source + // has been configured with a sink target that is resolvable. + SourceConditionSinkProvided apis.ConditionType = "SinkProvided" +) + +// GetFullType implements duck.Implementable +func (*Source) GetFullType() duck.Populatable { + return &Source{} +} + +// Populate implements duck.Populatable +func (s *Source) Populate() { + s.Spec.Sink = apisv1alpha1.Destination{ + URI: &apis.URL{ + Scheme: "https", + Host: "tableflip.dev", + RawQuery: "flip=mattmoor", + }, + } + s.Spec.CloudEventOverrides = &CloudEventOverrides{ + Extensions: map[string]string{"boosh": "kakow"}, + } + s.Status.ObservedGeneration = 42 + s.Status.Conditions = Conditions{{ + // Populate ALL fields + Type: SourceConditionSinkProvided, + Status: corev1.ConditionTrue, + LastTransitionTime: apis.VolatileTime{Inner: metav1.NewTime(time.Date(1984, 02, 28, 18, 52, 00, 00, time.UTC))}, + }} + s.Status.SinkURI = &apis.URL{ + Scheme: "https", + Host: "tableflip.dev", + RawQuery: "flip=mattmoor", + } +} + +// GetListType implements apis.Listable +func (*Source) GetListType() runtime.Object { + return &SourceList{} +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// SourceList is a list of Source resources +type SourceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []Source `json:"items"` +} diff --git a/vendor/knative.dev/pkg/apis/duck/v1/status_types.go b/vendor/knative.dev/pkg/apis/duck/v1/status_types.go new file mode 100644 index 0000000000..68a6b47693 --- /dev/null +++ b/vendor/knative.dev/pkg/apis/duck/v1/status_types.go @@ -0,0 +1,141 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + + "knative.dev/pkg/apis" + "knative.dev/pkg/apis/duck" +) + +// Conditions is a simple wrapper around apis.Conditions to implement duck.Implementable. +type Conditions apis.Conditions + +// Conditions is an Implementable "duck type". +var _ duck.Implementable = (*Conditions)(nil) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:openapi-gen=true + +// KResource is a skeleton type wrapping Conditions in the manner we expect +// resource writers defining compatible resources to embed it. We will +// typically use this type to deserialize Conditions ObjectReferences and +// access the Conditions data. This is not a real resource. +type KResource struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Status Status `json:"status"` +} + +// Status shows how we expect folks to embed Conditions in +// their Status field. +// WARNING: Adding fields to this struct will add them to all Knative resources. +type Status struct { + // ObservedGeneration is the 'Generation' of the Service that + // was last processed by the controller. + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + + // Conditions the latest available observations of a resource's current state. + // +optional + // +patchMergeKey=type + // +patchStrategy=merge + Conditions Conditions `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` +} + +var _ apis.ConditionsAccessor = (*Status)(nil) + +// GetConditions implements apis.ConditionsAccessor +func (s *Status) GetConditions() apis.Conditions { + return apis.Conditions(s.Conditions) +} + +// SetConditions implements apis.ConditionsAccessor +func (s *Status) SetConditions(c apis.Conditions) { + s.Conditions = Conditions(c) +} + +// In order for Conditions to be Implementable, KResource must be Populatable. +var _ duck.Populatable = (*KResource)(nil) + +// Ensure KResource satisfies apis.Listable +var _ apis.Listable = (*KResource)(nil) + +// GetFullType implements duck.Implementable +func (*Conditions) GetFullType() duck.Populatable { + return &KResource{} +} + +// GetCondition fetches the condition of the specified type. +func (s *Status) GetCondition(t apis.ConditionType) *apis.Condition { + for _, cond := range s.Conditions { + if cond.Type == t { + return &cond + } + } + return nil +} + +// ConvertTo helps implement apis.Convertible for types embedding this Status. +func (source *Status) ConvertTo(ctx context.Context, sink *Status) { + sink.ObservedGeneration = source.ObservedGeneration + for _, c := range source.Conditions { + switch c.Type { + // Copy over the "happy" condition, which is the only condition that + // we can reliably transfer. + case apis.ConditionReady, apis.ConditionSucceeded: + sink.SetConditions(apis.Conditions{c}) + return + } + } +} + +// Populate implements duck.Populatable +func (t *KResource) Populate() { + t.Status.ObservedGeneration = 42 + t.Status.Conditions = Conditions{{ + // Populate ALL fields + Type: "Birthday", + Status: corev1.ConditionTrue, + LastTransitionTime: apis.VolatileTime{Inner: metav1.NewTime(time.Date(1984, 02, 28, 18, 52, 00, 00, time.UTC))}, + Reason: "Celebrate", + Message: "n3wScott, find your party hat :tada:", + }} +} + +// GetListType implements apis.Listable +func (*KResource) GetListType() runtime.Object { + return &KResourceList{} +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// KResourceList is a list of KResource resources +type KResourceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []KResource `json:"items"` +} diff --git a/vendor/knative.dev/pkg/apis/duck/v1/zz_generated.deepcopy.go b/vendor/knative.dev/pkg/apis/duck/v1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..6be6207a3a --- /dev/null +++ b/vendor/knative.dev/pkg/apis/duck/v1/zz_generated.deepcopy.go @@ -0,0 +1,361 @@ +// +build !ignore_autogenerated + +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" + apis "knative.dev/pkg/apis" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddressStatus) DeepCopyInto(out *AddressStatus) { + *out = *in + if in.Address != nil { + in, out := &in.Address, &out.Address + *out = new(Addressable) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressStatus. +func (in *AddressStatus) DeepCopy() *AddressStatus { + if in == nil { + return nil + } + out := new(AddressStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Addressable) DeepCopyInto(out *Addressable) { + *out = *in + if in.URL != nil { + in, out := &in.URL, &out.URL + *out = new(apis.URL) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Addressable. +func (in *Addressable) DeepCopy() *Addressable { + if in == nil { + return nil + } + out := new(Addressable) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddressableType) DeepCopyInto(out *AddressableType) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressableType. +func (in *AddressableType) DeepCopy() *AddressableType { + if in == nil { + return nil + } + out := new(AddressableType) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AddressableType) 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 *AddressableTypeList) DeepCopyInto(out *AddressableTypeList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]AddressableType, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressableTypeList. +func (in *AddressableTypeList) DeepCopy() *AddressableTypeList { + if in == nil { + return nil + } + out := new(AddressableTypeList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AddressableTypeList) 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 *CloudEventOverrides) DeepCopyInto(out *CloudEventOverrides) { + *out = *in + if in.Extensions != nil { + in, out := &in.Extensions, &out.Extensions + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudEventOverrides. +func (in *CloudEventOverrides) DeepCopy() *CloudEventOverrides { + if in == nil { + return nil + } + out := new(CloudEventOverrides) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in Conditions) DeepCopyInto(out *Conditions) { + { + in := &in + *out = make(Conditions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + return + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Conditions. +func (in Conditions) DeepCopy() Conditions { + if in == nil { + return nil + } + out := new(Conditions) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KResource) DeepCopyInto(out *KResource) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KResource. +func (in *KResource) DeepCopy() *KResource { + if in == nil { + return nil + } + out := new(KResource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KResource) 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 *KResourceList) DeepCopyInto(out *KResourceList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KResource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KResourceList. +func (in *KResourceList) DeepCopy() *KResourceList { + if in == nil { + return nil + } + out := new(KResourceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KResourceList) 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 *Source) DeepCopyInto(out *Source) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Source. +func (in *Source) DeepCopy() *Source { + if in == nil { + return nil + } + out := new(Source) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Source) 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 *SourceList) DeepCopyInto(out *SourceList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Source, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SourceList. +func (in *SourceList) DeepCopy() *SourceList { + if in == nil { + return nil + } + out := new(SourceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *SourceList) 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 *SourceSpec) DeepCopyInto(out *SourceSpec) { + *out = *in + in.Sink.DeepCopyInto(&out.Sink) + if in.CloudEventOverrides != nil { + in, out := &in.CloudEventOverrides, &out.CloudEventOverrides + *out = new(CloudEventOverrides) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SourceSpec. +func (in *SourceSpec) DeepCopy() *SourceSpec { + if in == nil { + return nil + } + out := new(SourceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SourceStatus) DeepCopyInto(out *SourceStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + if in.SinkURI != nil { + in, out := &in.SinkURI, &out.SinkURI + *out = new(apis.URL) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SourceStatus. +func (in *SourceStatus) DeepCopy() *SourceStatus { + if in == nil { + return nil + } + out := new(SourceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Status) DeepCopyInto(out *Status) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make(Conditions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status. +func (in *Status) DeepCopy() *Status { + if in == nil { + return nil + } + out := new(Status) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/knative.dev/pkg/apis/duck/v1alpha1/addressable_types.go b/vendor/knative.dev/pkg/apis/duck/v1alpha1/addressable_types.go index 2b5fcbd9e2..e0b3300111 100644 --- a/vendor/knative.dev/pkg/apis/duck/v1alpha1/addressable_types.go +++ b/vendor/knative.dev/pkg/apis/duck/v1alpha1/addressable_types.go @@ -17,11 +17,15 @@ limitations under the License. package v1alpha1 import ( + "context" + "fmt" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "knative.dev/pkg/apis" "knative.dev/pkg/apis/duck" + v1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/apis/duck/v1beta1" ) @@ -37,8 +41,12 @@ type Addressable struct { Hostname string `json:"hostname,omitempty"` } -// Addressable is an Implementable "duck type". -var _ duck.Implementable = (*Addressable)(nil) +var ( + // Addressable is an Implementable "duck type". + _ duck.Implementable = (*Addressable)(nil) + // Addressable is a Convertible type. + _ apis.Convertible = (*Addressable)(nil) +) // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -71,6 +79,35 @@ func (*Addressable) GetFullType() duck.Populatable { return &AddressableType{} } +// ConvertUp implements apis.Convertible +func (a *Addressable) ConvertUp(ctx context.Context, to apis.Convertible) error { + url := a.GetURL() + switch sink := to.(type) { + case *v1.Addressable: + sink.URL = url.DeepCopy() + return nil + case *v1beta1.Addressable: + sink.URL = url.DeepCopy() + return nil + default: + return fmt.Errorf("unknown version, got: %T", to) + } +} + +// ConvertDown implements apis.Convertible +func (a *Addressable) ConvertDown(ctx context.Context, from apis.Convertible) error { + switch source := from.(type) { + case *v1.Addressable: + a.URL = source.URL.DeepCopy() + return nil + case *v1beta1.Addressable: + a.URL = source.URL.DeepCopy() + return nil + default: + return fmt.Errorf("unknown version, got: %T", from) + } +} + // Populate implements duck.Populatable func (t *AddressableType) Populate() { t.Status = AddressStatus{ @@ -87,6 +124,7 @@ func (t *AddressableType) Populate() { } } +// GetURL returns the URL type for the Addressable. func (a Addressable) GetURL() apis.URL { if a.URL != nil { return *a.URL diff --git a/vendor/knative.dev/pkg/apis/duck/v1alpha1/conditions_types.go b/vendor/knative.dev/pkg/apis/duck/v1alpha1/conditions_types.go index 12003a5863..043ad5e8a6 100644 --- a/vendor/knative.dev/pkg/apis/duck/v1alpha1/conditions_types.go +++ b/vendor/knative.dev/pkg/apis/duck/v1alpha1/conditions_types.go @@ -60,7 +60,7 @@ const ( ) // Conditions defines a readiness condition for a Knative resource. -// See: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#typical-status-properties +// See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties // +k8s:deepcopy-gen=true type Condition struct { // Type of condition. diff --git a/vendor/knative.dev/pkg/apis/duck/v1alpha1/zz_generated.deepcopy.go b/vendor/knative.dev/pkg/apis/duck/v1alpha1/zz_generated.deepcopy.go index a59e67ce3f..bdae1b58cf 100644 --- a/vendor/knative.dev/pkg/apis/duck/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/knative.dev/pkg/apis/duck/v1alpha1/zz_generated.deepcopy.go @@ -93,7 +93,7 @@ func (in *AddressableType) DeepCopyObject() runtime.Object { func (in *AddressableTypeList) DeepCopyInto(out *AddressableTypeList) { *out = *in out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]AddressableType, len(*in)) @@ -192,7 +192,7 @@ func (in *KResource) DeepCopyObject() runtime.Object { func (in *KResourceList) DeepCopyInto(out *KResourceList) { *out = *in out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]KResource, len(*in)) @@ -275,7 +275,7 @@ func (in *LegacyTarget) DeepCopyObject() runtime.Object { func (in *LegacyTargetList) DeepCopyInto(out *LegacyTargetList) { *out = *in out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]LegacyTarget, len(*in)) @@ -374,7 +374,7 @@ func (in *Target) DeepCopyObject() runtime.Object { func (in *TargetList) DeepCopyInto(out *TargetList) { *out = *in out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]Target, len(*in)) diff --git a/vendor/knative.dev/pkg/apis/duck/v1beta1/addressable_types.go b/vendor/knative.dev/pkg/apis/duck/v1beta1/addressable_types.go index 817585a3b3..2aa9de0d2e 100644 --- a/vendor/knative.dev/pkg/apis/duck/v1beta1/addressable_types.go +++ b/vendor/knative.dev/pkg/apis/duck/v1beta1/addressable_types.go @@ -17,11 +17,15 @@ limitations under the License. package v1beta1 import ( + "context" + "fmt" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "knative.dev/pkg/apis" "knative.dev/pkg/apis/duck" + v1 "knative.dev/pkg/apis/duck/v1" ) // Addressable provides a generic mechanism for a custom resource @@ -34,8 +38,12 @@ type Addressable struct { URL *apis.URL `json:"url,omitempty"` } -// Addressable is an Implementable "duck type". -var _ duck.Implementable = (*Addressable)(nil) +var ( + // Addressable is an Implementable "duck type". + _ duck.Implementable = (*Addressable)(nil) + // Addressable is a Convertible type. + _ apis.Convertible = (*Addressable)(nil) +) // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -68,6 +76,28 @@ func (*Addressable) GetFullType() duck.Populatable { return &AddressableType{} } +// ConvertUp implements apis.Convertible +func (a *Addressable) ConvertUp(ctx context.Context, to apis.Convertible) error { + switch sink := to.(type) { + case *v1.Addressable: + sink.URL = a.URL.DeepCopy() + return nil + default: + return fmt.Errorf("unknown version, got: %T", to) + } +} + +// ConvertDown implements apis.Convertible +func (a *Addressable) ConvertDown(ctx context.Context, from apis.Convertible) error { + switch source := from.(type) { + case *v1.Addressable: + a.URL = source.URL.DeepCopy() + return nil + default: + return fmt.Errorf("unknown version, got: %T", from) + } +} + // Populate implements duck.Populatable func (t *AddressableType) Populate() { t.Status = AddressStatus{ diff --git a/vendor/knative.dev/pkg/apis/duck/v1beta1/zz_generated.deepcopy.go b/vendor/knative.dev/pkg/apis/duck/v1beta1/zz_generated.deepcopy.go index da817c52b1..79e359d884 100644 --- a/vendor/knative.dev/pkg/apis/duck/v1beta1/zz_generated.deepcopy.go +++ b/vendor/knative.dev/pkg/apis/duck/v1beta1/zz_generated.deepcopy.go @@ -98,7 +98,7 @@ func (in *AddressableType) DeepCopyObject() runtime.Object { func (in *AddressableTypeList) DeepCopyInto(out *AddressableTypeList) { *out = *in out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]AddressableType, len(*in)) @@ -203,7 +203,7 @@ func (in *KResource) DeepCopyObject() runtime.Object { func (in *KResourceList) DeepCopyInto(out *KResourceList) { *out = *in out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]KResource, len(*in)) @@ -264,7 +264,7 @@ func (in *Source) DeepCopyObject() runtime.Object { func (in *SourceList) DeepCopyInto(out *SourceList) { *out = *in out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]Source, len(*in)) diff --git a/vendor/knative.dev/pkg/apis/field_error.go b/vendor/knative.dev/pkg/apis/field_error.go index 59b281d6ee..c3bb68bf2d 100644 --- a/vendor/knative.dev/pkg/apis/field_error.go +++ b/vendor/knative.dev/pkg/apis/field_error.go @@ -312,13 +312,13 @@ func ErrDisallowedUpdateDeprecatedFields(fieldPaths ...string) *FieldError { } // ErrInvalidArrayValue constructs a FieldError for a repetetive `field` -// at `index` that has received an invalid string value. +// at `index` that has received an invalid value. func ErrInvalidArrayValue(value interface{}, field string, index int) *FieldError { return ErrInvalidValue(value, CurrentField).ViaFieldIndex(field, index) } // ErrInvalidValue constructs a FieldError for a field that has received an -// invalid string value. +// invalid value. func ErrInvalidValue(value interface{}, fieldPath string) *FieldError { return &FieldError{ Message: fmt.Sprintf("invalid value: %v", value), @@ -326,6 +326,15 @@ func ErrInvalidValue(value interface{}, fieldPath string) *FieldError { } } +// ErrGeneric constructs a FieldError to allow for the different error strings for the +// the different cases. +func ErrGeneric(diagnostic string, fieldPaths ...string) *FieldError { + return &FieldError{ + Message: diagnostic, + Paths: fieldPaths, + } +} + // ErrMissingOneOf is a variadic helper method for constructing a FieldError for // not having at least one field in a mutually exclusive field group. func ErrMissingOneOf(fieldPaths ...string) *FieldError { diff --git a/vendor/knative.dev/pkg/apis/url.go b/vendor/knative.dev/pkg/apis/url.go index 0ff8ea0538..b059907568 100644 --- a/vendor/knative.dev/pkg/apis/url.go +++ b/vendor/knative.dev/pkg/apis/url.go @@ -41,6 +41,30 @@ func ParseURL(u string) (*URL, error) { return (*URL)(pu), nil } +// HTTP creates an http:// URL pointing to a known domain. +func HTTP(domain string) *URL { + return &URL{ + Scheme: "http", + Host: domain, + } +} + +// HTTPS creates an https:// URL pointing to a known domain. +func HTTPS(domain string) *URL { + return &URL{ + Scheme: "https", + Host: domain, + } +} + +// IsEmpty returns true if the URL is `nil` or represents an empty URL. +func (u *URL) IsEmpty() bool { + if u == nil { + return true + } + return *u == URL{} +} + // MarshalJSON implements a custom json marshal method used when this type is // marshaled using json.Marshal. // json.Marshaler impl @@ -57,11 +81,14 @@ func (u *URL) UnmarshalJSON(b []byte) error { if err := json.Unmarshal(b, &ref); err != nil { return err } - r, err := ParseURL(ref) - if err != nil { + if r, err := ParseURL(ref); err != nil { return err + } else if r != nil { + *u = *r + } else { + *u = URL{} } - *u = *r + return nil } @@ -73,3 +100,12 @@ func (u *URL) String() string { uu := url.URL(*u) return uu.String() } + +// URL returns the URL as a url.URL. +func (u *URL) URL() *url.URL { + if u == nil { + return &url.URL{} + } + url := url.URL(*u) + return &url +} diff --git a/vendor/knative.dev/pkg/apis/v1alpha1/destination.go b/vendor/knative.dev/pkg/apis/v1alpha1/destination.go index 0f9ee409c9..dae152dec1 100644 --- a/vendor/knative.dev/pkg/apis/v1alpha1/destination.go +++ b/vendor/knative.dev/pkg/apis/v1alpha1/destination.go @@ -18,133 +18,47 @@ package v1alpha1 import ( "context" - "net/url" - "path" - "strings" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/equality" - "knative.dev/pkg/apis" ) // Destination represents a target of an invocation over HTTP. type Destination struct { - // ObjectReference points to an Addressable. - *corev1.ObjectReference `json:",inline"` + // Ref points to an Addressable. + // +optional + Ref *corev1.ObjectReference `json:"ref,omitempty"` - // URI is for direct URI Designations. + // URI can be an absolute URL(non-empty scheme and non-empty host) pointing to the target or a relative URI. Relative URIs will be resolved using the base URI retrieved from Ref. + // +optional URI *apis.URL `json:"uri,omitempty"` - - // Path is used with the resulting URL from Addressable ObjectReference or URI. Must start - // with `/`. An empty path should be represented as the nil value, not `` or `/`. Will be - // appended to the path of the resulting URL from the Addressable, or URI. - Path *string `json:"path,omitempty"` -} - -// NewDestination constructs a Destination from an object reference as a convenience. -func NewDestination(obj *corev1.ObjectReference, paths ...string) (*Destination, error) { - dest := &Destination{ - ObjectReference: obj, - } - err := dest.AppendPath(paths...) - if err != nil { - return nil, err - } - return dest, nil -} - -// NewDestinationURI constructs a Destination from a URI. -func NewDestinationURI(uri *apis.URL, paths ...string) (*Destination, error) { - dest := &Destination{ - URI: uri, - } - err := dest.AppendPath(paths...) - if err != nil { - return nil, err - } - return dest, nil -} - -// AppendPath iteratively appends paths to the Destination. -// The path will always begin with "/" unless it is empty. -// An empty path ("" or "/") will always resolve to nil. -func (current *Destination) AppendPath(paths ...string) error { - // Start with empty string or existing path - var fullpath string - if current.Path != nil { - fullpath = *current.Path - } - - // Intelligently join all the paths provided - fullpath = path.Join("/", fullpath, path.Join(paths...)) - - // Parse the URL to trim garbage - urlpath, err := apis.ParseURL(fullpath) - if err != nil { - return err - } - - // apis.ParseURL returns nil if our path was empty, then our path - // should reflect that it is not set. - if urlpath == nil { - current.Path = nil - return nil - } - - // A path of "/" adds no information, just toss it - // Note that urlpath.Path == "" is always false here (joined with "/" above). - if urlpath.Path == "/" { - current.Path = nil - return nil - } - - // Only use the plain path from the URL - current.Path = &urlpath.Path - return nil } func (current *Destination) Validate(ctx context.Context) *apis.FieldError { if current != nil { - errs := validateDestination(*current).ViaField(apis.CurrentField) - if current.Path != nil { - errs = errs.Also(validateDestinationPath(*current.Path).ViaField("path")) - } - return errs + return ValidateDestination(*current).ViaField(apis.CurrentField) } else { return nil } } -func validateDestination(dest Destination) *apis.FieldError { - if dest.URI != nil { - if dest.ObjectReference != nil { - return apis.ErrMultipleOneOf("uri", "[apiVersion, kind, name]") - } - if dest.URI.Host == "" || dest.URI.Scheme == "" { - return apis.ErrInvalidValue(dest.URI.String(), "uri") - } - } else if dest.ObjectReference == nil { - return apis.ErrMissingOneOf("uri", "[apiVersion, kind, name]") - } else { - return validateDestinationRef(*dest.ObjectReference) +func ValidateDestination(dest Destination) *apis.FieldError { + if dest.Ref == nil && dest.URI == nil { + return apis.ErrGeneric("expected at least one, got neither", "ref", "uri") } - return nil -} - -func validateDestinationPath(path string) *apis.FieldError { - if strings.HasPrefix(path, "/") { - if pu, err := url.Parse(path); err != nil { - return apis.ErrInvalidValue(path, apis.CurrentField) - } else if !equality.Semantic.DeepEqual(pu, &url.URL{Path: pu.Path}) { - return apis.ErrInvalidValue(path, apis.CurrentField) + if dest.Ref != nil && dest.URI != nil && dest.URI.URL().IsAbs() { + return apis.ErrGeneric("Absolute URI is not allowed when Ref is present", "ref", "uri") + } + // IsAbs() check whether the URL has a non-empty scheme. Besides the non-empty scheme, we also require dest.URI has a non-empty host + if dest.Ref == nil && dest.URI != nil && (!dest.URI.URL().IsAbs() || dest.URI.Host == "") { + return apis.ErrInvalidValue("Relative URI is not allowed when Ref is absent", "uri") } - } else { - return apis.ErrInvalidValue(path, apis.CurrentField) + if dest.Ref != nil && dest.URI == nil{ + return validateDestinationRef(*dest.Ref).ViaField("ref") } return nil } + func validateDestinationRef(ref corev1.ObjectReference) *apis.FieldError { // Check the object. var errs *apis.FieldError diff --git a/vendor/knative.dev/pkg/apis/v1alpha1/zz_generated.deepcopy.go b/vendor/knative.dev/pkg/apis/v1alpha1/zz_generated.deepcopy.go index a54dcace80..5640bf0a81 100644 --- a/vendor/knative.dev/pkg/apis/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/knative.dev/pkg/apis/v1alpha1/zz_generated.deepcopy.go @@ -28,8 +28,8 @@ import ( // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Destination) DeepCopyInto(out *Destination) { *out = *in - if in.ObjectReference != nil { - in, out := &in.ObjectReference, &out.ObjectReference + if in.Ref != nil { + in, out := &in.Ref, &out.Ref *out = new(v1.ObjectReference) **out = **in } @@ -38,11 +38,6 @@ func (in *Destination) DeepCopyInto(out *Destination) { *out = new(apis.URL) (*in).DeepCopyInto(*out) } - if in.Path != nil { - in, out := &in.Path, &out.Path - *out = new(string) - **out = **in - } return } diff --git a/vendor/knative.dev/pkg/configmap/filter.go b/vendor/knative.dev/pkg/configmap/filter.go index 27bf13df98..ed1040e27b 100644 --- a/vendor/knative.dev/pkg/configmap/filter.go +++ b/vendor/knative.dev/pkg/configmap/filter.go @@ -16,7 +16,12 @@ limitations under the License. package configmap -import "reflect" +import ( + "fmt" + "reflect" + + corev1 "k8s.io/api/core/v1" +) // TypeFilter accepts instances of types to check against and returns a function transformer that would only let // the call to f through if value is assignable to any one of types of ts. Example: @@ -42,3 +47,28 @@ func TypeFilter(ts ...interface{}) func(func(string, interface{})) func(string, } } } + +// ValidateConstructor checks the type of the constructor it evaluates +// the constructor to be a function with correct signature. +// +// The expectation is for the constructor to receive a single input +// parameter of type corev1.ConfigMap as the input and return two +// values with the second value being of type error +func ValidateConstructor(constructor interface{}) error { + cType := reflect.TypeOf(constructor) + + if cType.Kind() != reflect.Func { + return fmt.Errorf("config constructor must be a function") + } + + if cType.NumIn() != 1 || cType.In(0) != reflect.TypeOf(&corev1.ConfigMap{}) { + return fmt.Errorf("config constructor must be of the type func(*k8s.io/api/core/v1/ConfigMap) (..., error)") + } + + errorType := reflect.TypeOf((*error)(nil)).Elem() + + if cType.NumOut() != 2 || !cType.Out(1).Implements(errorType) { + return fmt.Errorf("config constructor must be of the type func(*k8s.io/api/core/v1/ConfigMap) (..., error)") + } + return nil +} diff --git a/vendor/knative.dev/pkg/configmap/informed_watcher.go b/vendor/knative.dev/pkg/configmap/informed_watcher.go index 5903d59d7e..0189a9a235 100644 --- a/vendor/knative.dev/pkg/configmap/informed_watcher.go +++ b/vendor/knative.dev/pkg/configmap/informed_watcher.go @@ -18,9 +18,9 @@ package configmap import ( "errors" - "time" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" k8serrors "k8s.io/apimachinery/pkg/api/errors" informers "k8s.io/client-go/informers" corev1informers "k8s.io/client-go/informers/core/v1" @@ -51,8 +51,9 @@ func NewInformedWatcherFromFactory(sif informers.SharedInformerFactory, namespac func NewInformedWatcher(kc kubernetes.Interface, namespace string) *InformedWatcher { return NewInformedWatcherFromFactory(informers.NewSharedInformerFactoryWithOptions( kc, - // This is the default resync period from controller-runtime. - 10*time.Hour, + // We noticed that we're getting updates all the time anyway, due to the + // watches being terminated and re-spawned. + 0, informers.WithNamespace(namespace), ), namespace) } @@ -79,7 +80,7 @@ var _ Watcher = (*InformedWatcher)(nil) var _ DefaultingWatcher = (*InformedWatcher)(nil) // WatchWithDefault implements DefaultingWatcher. -func (i *InformedWatcher) WatchWithDefault(cm corev1.ConfigMap, o Observer) { +func (i *InformedWatcher) WatchWithDefault(cm corev1.ConfigMap, o ...Observer) { i.defaults[cm.Name] = &cm i.m.Lock() @@ -94,7 +95,7 @@ func (i *InformedWatcher) WatchWithDefault(cm corev1.ConfigMap, o Observer) { panic("cannot WatchWithDefault after the InformedWatcher has started") } - i.Watch(cm.Name, o) + i.Watch(cm.Name, o...) } // Start implements Watcher. @@ -140,17 +141,14 @@ func (i *InformedWatcher) registerCallbackAndStartInformer(stopCh <-chan struct{ } func (i *InformedWatcher) checkObservedResourcesExist() error { - i.m.Lock() - defer i.m.Unlock() + i.m.RLock() + defer i.m.RUnlock() // Check that all objects with Observers exist in our informers. for k := range i.observers { - _, err := i.informer.Lister().ConfigMaps(i.Namespace).Get(k) - if err != nil { - if k8serrors.IsNotFound(err) { - if _, ok := i.defaults[k]; ok { - // It is defaulted, so it is OK that it doesn't exist. - continue - } + if _, err := i.informer.Lister().ConfigMaps(i.Namespace).Get(k); err != nil { + if _, ok := i.defaults[k]; ok && k8serrors.IsNotFound(err) { + // It is defaulted, so it is OK that it doesn't exist. + continue } return err } @@ -163,8 +161,13 @@ func (i *InformedWatcher) addConfigMapEvent(obj interface{}) { i.OnChange(configMap) } -func (i *InformedWatcher) updateConfigMapEvent(old, new interface{}) { - configMap := new.(*corev1.ConfigMap) +func (i *InformedWatcher) updateConfigMapEvent(o, n interface{}) { + // Ignore updates that are idempotent. We are seeing those + // periodically. + if equality.Semantic.DeepEqual(o, n) { + return + } + configMap := n.(*corev1.ConfigMap) i.OnChange(configMap) } diff --git a/vendor/knative.dev/pkg/configmap/manual_watcher.go b/vendor/knative.dev/pkg/configmap/manual_watcher.go index ad243de55d..4774e5227f 100644 --- a/vendor/knative.dev/pkg/configmap/manual_watcher.go +++ b/vendor/knative.dev/pkg/configmap/manual_watcher.go @@ -27,7 +27,7 @@ type ManualWatcher struct { Namespace string // Guards mutations to defaultImpl fields - m sync.Mutex + m sync.RWMutex observers map[string][]Observer } @@ -35,14 +35,14 @@ type ManualWatcher struct { var _ Watcher = (*ManualWatcher)(nil) // Watch implements Watcher -func (w *ManualWatcher) Watch(name string, o Observer) { +func (w *ManualWatcher) Watch(name string, o ...Observer) { w.m.Lock() defer w.m.Unlock() if w.observers == nil { w.observers = make(map[string][]Observer, 1) } - w.observers[name] = append(w.observers[name], o) + w.observers[name] = append(w.observers[name], o...) } func (w *ManualWatcher) Start(<-chan struct{}) error { @@ -54,8 +54,8 @@ func (w *ManualWatcher) OnChange(configMap *corev1.ConfigMap) { return } // Within our namespace, take the lock and see if there are any registered observers. - w.m.Lock() - defer w.m.Unlock() + w.m.RLock() + defer w.m.RUnlock() observers, ok := w.observers[configMap.Name] if !ok { return // No observers. diff --git a/vendor/knative.dev/pkg/configmap/static_watcher.go b/vendor/knative.dev/pkg/configmap/static_watcher.go index 96a01140db..2ce7c866bf 100644 --- a/vendor/knative.dev/pkg/configmap/static_watcher.go +++ b/vendor/knative.dev/pkg/configmap/static_watcher.go @@ -22,13 +22,6 @@ import ( corev1 "k8s.io/api/core/v1" ) -// NewFixedWatcher returns a StaticWatcher that exposes a collection of ConfigMaps. -// -// Deprecated: Use NewStaticWatcher -func NewFixedWatcher(cms ...*corev1.ConfigMap) *StaticWatcher { - return NewStaticWatcher(cms...) -} - // NewStaticWatcher returns an StaticWatcher that exposes a collection of ConfigMaps. func NewStaticWatcher(cms ...*corev1.ConfigMap) *StaticWatcher { cmm := make(map[string]*corev1.ConfigMap) @@ -48,10 +41,12 @@ type StaticWatcher struct { var _ Watcher = (*StaticWatcher)(nil) // Watch implements Watcher -func (di *StaticWatcher) Watch(name string, o Observer) { +func (di *StaticWatcher) Watch(name string, o ...Observer) { cm, ok := di.cfgs[name] if ok { - o(cm) + for _, observer := range o { + observer(cm) + } } else { panic(fmt.Sprintf("Tried to watch unknown config with name %q", name)) } diff --git a/vendor/knative.dev/pkg/configmap/store.go b/vendor/knative.dev/pkg/configmap/store.go index 012d35de9d..825803c254 100644 --- a/vendor/knative.dev/pkg/configmap/store.go +++ b/vendor/knative.dev/pkg/configmap/store.go @@ -101,20 +101,8 @@ func NewUntypedStore( } func (s *UntypedStore) registerConfig(name string, constructor interface{}) { - cType := reflect.TypeOf(constructor) - - if cType.Kind() != reflect.Func { - panic("config constructor must be a function") - } - - if cType.NumIn() != 1 || cType.In(0) != reflect.TypeOf(&corev1.ConfigMap{}) { - panic("config constructor must be of the type func(*k8s.io/api/core/v1/ConfigMap) (..., error)") - } - - errorType := reflect.TypeOf((*error)(nil)).Elem() - - if cType.NumOut() != 2 || !cType.Out(1).Implements(errorType) { - panic("config constructor must be of the type func(*k8s.io/api/core/v1/ConfigMap) (..., error)") + if err := ValidateConstructor(constructor); err != nil { + panic(err) } s.storages[name] = &atomic.Value{} diff --git a/vendor/knative.dev/pkg/configmap/watcher.go b/vendor/knative.dev/pkg/configmap/watcher.go index 71a18f4953..ff703dbc75 100644 --- a/vendor/knative.dev/pkg/configmap/watcher.go +++ b/vendor/knative.dev/pkg/configmap/watcher.go @@ -28,8 +28,8 @@ type Observer func(*corev1.ConfigMap) // Watcher defines the interface that a configmap implementation must implement. type Watcher interface { - // Watch is called to register a callback to be notified when a named ConfigMap changes. - Watch(string, Observer) + // Watch is called to register callbacks to be notified when a named ConfigMap changes. + Watch(string, ...Observer) // Start is called to initiate the watches and provide a channel to signal when we should // stop watching. When Start returns, all registered Observers will be called with the @@ -42,8 +42,8 @@ type Watcher interface { type DefaultingWatcher interface { Watcher - // WatchWithDefault is called to register a callback to be notified when a named ConfigMap + // WatchWithDefault is called to register callbacks to be notified when a named ConfigMap // changes. The provided default value is always observed before any real ConfigMap with that // name is. If the real ConfigMap with that name is deleted, then the default value is observed. - WatchWithDefault(cm corev1.ConfigMap, o Observer) + WatchWithDefault(cm corev1.ConfigMap, o ...Observer) } diff --git a/vendor/knative.dev/pkg/kmeta/accessor.go b/vendor/knative.dev/pkg/kmeta/accessor.go index 3cf58350df..e43aaf0e15 100644 --- a/vendor/knative.dev/pkg/kmeta/accessor.go +++ b/vendor/knative.dev/pkg/kmeta/accessor.go @@ -19,10 +19,10 @@ package kmeta import ( "fmt" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/cache" ) @@ -30,6 +30,8 @@ import ( // runtime.Object and metav1.Object that Kubernetes API types // registered with runtime.Scheme must support. type Accessor interface { + metav1.Object + // Interfaces for metav1.TypeMeta GroupVersionKind() schema.GroupVersionKind SetGroupVersionKind(gvk schema.GroupVersionKind) @@ -37,40 +39,6 @@ type Accessor interface { // Interfaces for runtime.Object GetObjectKind() schema.ObjectKind DeepCopyObject() runtime.Object - - // Interfaces for metav1.Object - GetNamespace() string - SetNamespace(namespace string) - GetName() string - SetName(name string) - GetGenerateName() string - SetGenerateName(name string) - GetUID() types.UID - SetUID(uid types.UID) - GetResourceVersion() string - SetResourceVersion(version string) - GetGeneration() int64 - SetGeneration(generation int64) - GetSelfLink() string - SetSelfLink(selfLink string) - GetCreationTimestamp() metav1.Time - SetCreationTimestamp(timestamp metav1.Time) - GetDeletionTimestamp() *metav1.Time - SetDeletionTimestamp(timestamp *metav1.Time) - GetDeletionGracePeriodSeconds() *int64 - SetDeletionGracePeriodSeconds(*int64) - GetLabels() map[string]string - SetLabels(labels map[string]string) - GetAnnotations() map[string]string - SetAnnotations(annotations map[string]string) - GetInitializers() *metav1.Initializers - SetInitializers(initializers *metav1.Initializers) - GetFinalizers() []string - SetFinalizers(finalizers []string) - GetOwnerReferences() []metav1.OwnerReference - SetOwnerReferences([]metav1.OwnerReference) - GetClusterName() string - SetClusterName(clusterName string) } // DeletionHandlingAccessor tries to convert given interface into Accessor first; @@ -92,3 +60,16 @@ func DeletionHandlingAccessor(obj interface{}) (Accessor, error) { return accessor, nil } + +// ObjectReference returns an core/v1.ObjectReference for the given object +func ObjectReference(obj Accessor) corev1.ObjectReference { + gvk := obj.GroupVersionKind() + apiVersion, kind := gvk.ToAPIVersionAndKind() + + return corev1.ObjectReference{ + APIVersion: apiVersion, + Kind: kind, + Namespace: obj.GetNamespace(), + Name: obj.GetName(), + } +} diff --git a/vendor/knative.dev/pkg/network/OWNERS b/vendor/knative.dev/pkg/network/OWNERS new file mode 100644 index 0000000000..5fa3f1016d --- /dev/null +++ b/vendor/knative.dev/pkg/network/OWNERS @@ -0,0 +1,4 @@ +# The OWNERS file is used by prow to automatically merge approved PRs. + +approvers: +- tcnghia diff --git a/vendor/knative.dev/pkg/network/doc.go b/vendor/knative.dev/pkg/network/doc.go new file mode 100644 index 0000000000..133ce55ea8 --- /dev/null +++ b/vendor/knative.dev/pkg/network/doc.go @@ -0,0 +1,19 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package network holds the typed objects that define the schemas for +// configuring the knative networking layer. +package network diff --git a/vendor/knative.dev/serving/pkg/network/domain.go b/vendor/knative.dev/pkg/network/domain.go similarity index 100% rename from vendor/knative.dev/serving/pkg/network/domain.go rename to vendor/knative.dev/pkg/network/domain.go diff --git a/vendor/knative.dev/serving/pkg/apis/autoscaling/annotation_validation.go b/vendor/knative.dev/serving/pkg/apis/autoscaling/annotation_validation.go index b7d18518c0..db573d343d 100644 --- a/vendor/knative.dev/serving/pkg/apis/autoscaling/annotation_validation.go +++ b/vendor/knative.dev/serving/pkg/apis/autoscaling/annotation_validation.go @@ -41,7 +41,7 @@ func ValidateAnnotations(anns map[string]string) *apis.FieldError { if len(anns) == 0 { return nil } - return validateMinMaxScale(anns).Also(validateFloats(anns)).Also(validateWindows(anns)) + return validateMinMaxScale(anns).Also(validateFloats(anns)).Also(validateWindows(anns).Also(validateMetric(anns))) } func validateFloats(annotations map[string]string) *apis.FieldError { @@ -115,3 +115,29 @@ func validateMinMaxScale(annotations map[string]string) *apis.FieldError { } return errs } + +func validateMetric(annotations map[string]string) *apis.FieldError { + if metric, ok := annotations[MetricAnnotationKey]; ok { + classValue := KPA + if c, ok := annotations[ClassAnnotationKey]; ok { + classValue = c + } + switch classValue { + case KPA: + switch metric { + case Concurrency, RPS: + return nil + } + case HPA: + switch metric { + case CPU, Concurrency, RPS: + return nil + } + default: + // Leave other classes of PodAutoscaler alone. + return nil + } + return apis.ErrInvalidValue(metric, MetricAnnotationKey) + } + return nil +} diff --git a/vendor/knative.dev/serving/pkg/apis/autoscaling/register.go b/vendor/knative.dev/serving/pkg/apis/autoscaling/register.go index a9bbce8665..88526ce583 100644 --- a/vendor/knative.dev/serving/pkg/apis/autoscaling/register.go +++ b/vendor/knative.dev/serving/pkg/apis/autoscaling/register.go @@ -19,8 +19,10 @@ package autoscaling import "time" const ( + // The internal autoscaling group name. This is used for CRDs. InternalGroupName = "autoscaling.internal.knative.dev" + // The publuc autoscaling group name. This is used for annotations, labels, etc. GroupName = "autoscaling.knative.dev" // ClassAnnotationKey is the annotation for the explicit class of autoscaler @@ -50,6 +52,8 @@ const ( Concurrency = "concurrency" // CPU is the amount of the requested cpu actually being consumed by the Pod. CPU = "cpu" + // RPS is the requests per second reaching the Pod. + RPS = "rps" // TargetAnnotationKey is the annotation to specify what metric value the // PodAutoscaler should attempt to maintain. For example, diff --git a/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/metric_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/metric_lifecycle.go index e785084716..838577a5b9 100644 --- a/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/metric_lifecycle.go +++ b/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/metric_lifecycle.go @@ -18,9 +18,56 @@ package v1alpha1 import ( "k8s.io/apimachinery/pkg/runtime/schema" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +const ( + // MetricConditionReady is set when the Metric's latest + // underlying revision has reported readiness. + MetricConditionReady = apis.ConditionReady +) + +var condSet = apis.NewLivingConditionSet( + MetricConditionReady, ) // GetGroupVersionKind implements OwnerRefable. func (m *Metric) GetGroupVersionKind() schema.GroupVersionKind { return SchemeGroupVersion.WithKind("Metric") } + +// GetCondition gets the condition `t`. +func (ms *MetricStatus) GetCondition(t apis.ConditionType) *apis.Condition { + return condSet.Manage(ms).GetCondition(t) +} + +// InitializeConditions initializes the conditions of the Metric. +func (ms *MetricStatus) InitializeConditions() { + condSet.Manage(ms).InitializeConditions() +} + +// MarkMetricReady marks the metric status as ready +func (ms *MetricStatus) MarkMetricReady() { + condSet.Manage(ms).MarkTrue(MetricConditionReady) +} + +// MarkMetricNotReady marks the metric status as ready == Unknown +func (ms *MetricStatus) MarkMetricNotReady(reason, message string) { + condSet.Manage(ms).MarkUnknown(MetricConditionReady, reason, message) +} + +// MarkMetricFailed marks the metric status as failed +func (ms *MetricStatus) MarkMetricFailed(reason, message string) { + condSet.Manage(ms).MarkFalse(MetricConditionReady, reason, message) +} + +// IsReady looks at the conditions and if the condition MetricConditionReady +// is true +func (ms *MetricStatus) IsReady() bool { + return condSet.Manage(ms.duck()).IsHappy() +} + +func (ms *MetricStatus) duck() *duckv1.Status { + return (*duckv1.Status)(&ms.Status) +} diff --git a/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/metric_types.go b/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/metric_types.go index b2592481b9..dca3e6d7c7 100644 --- a/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/metric_types.go +++ b/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/metric_types.go @@ -21,6 +21,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/kmeta" ) @@ -63,7 +64,9 @@ type MetricSpec struct { } // MetricStatus reflects the status of metric collection for this specific entity. -type MetricStatus struct{} +type MetricStatus struct { + duckv1.Status `json:",inline"` +} // MetricList is a list of Metric resources // diff --git a/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/pa_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/pa_lifecycle.go index 30c90430be..53203e56fb 100644 --- a/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/pa_lifecycle.go +++ b/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/pa_lifecycle.go @@ -25,7 +25,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/serving/pkg/apis/autoscaling" ) @@ -76,10 +76,15 @@ func (pa *PodAutoscaler) annotationFloat64(key string) (float64, bool) { // ScaleBounds returns scale bounds annotations values as a tuple: // `(min, max int32)`. The value of 0 for any of min or max means the bound is -// not set +// not set. +// Note: min will be ignored if the PA is not reachable func (pa *PodAutoscaler) ScaleBounds() (min, max int32) { - return pa.annotationInt32(autoscaling.MinScaleAnnotationKey), - pa.annotationInt32(autoscaling.MaxScaleAnnotationKey) + if pa.Spec.Reachability != ReachabilityUnreachable { + min = pa.annotationInt32(autoscaling.MinScaleAnnotationKey) + } + max = pa.annotationInt32(autoscaling.MaxScaleAnnotationKey) + + return } // Target returns the target annotation value or false if not present, or invalid. @@ -185,32 +190,48 @@ func (pas *PodAutoscalerStatus) MarkResourceFailedCreation(kind, name string) { // CanScaleToZero checks whether the pod autoscaler has been in an inactive state // for at least the specified grace period. -func (pas *PodAutoscalerStatus) CanScaleToZero(gracePeriod time.Duration) bool { - return pas.inStatusFor(corev1.ConditionFalse, gracePeriod) > 0 +func (pas *PodAutoscalerStatus) CanScaleToZero(now time.Time, gracePeriod time.Duration) bool { + return pas.inStatusFor(corev1.ConditionFalse, now, gracePeriod) > 0 } // ActiveFor returns the time PA spent being active. -func (pas *PodAutoscalerStatus) ActiveFor() time.Duration { - return pas.inStatusFor(corev1.ConditionTrue, 0) +func (pas *PodAutoscalerStatus) ActiveFor(now time.Time) time.Duration { + return pas.inStatusFor(corev1.ConditionTrue, now, 0) } // CanFailActivation checks whether the pod autoscaler has been activating // for at least the specified idle period. -func (pas *PodAutoscalerStatus) CanFailActivation(idlePeriod time.Duration) bool { - return pas.inStatusFor(corev1.ConditionUnknown, idlePeriod) > 0 +func (pas *PodAutoscalerStatus) CanFailActivation(now time.Time, idlePeriod time.Duration) bool { + return pas.inStatusFor(corev1.ConditionUnknown, now, idlePeriod) > 0 } // inStatusFor returns positive duration if the PodAutoscalerStatus's Active condition has stayed in // the specified status for at least the specified duration. Otherwise it returns negative duration, // including when the status is undetermined (Active condition is not found.) -func (pas *PodAutoscalerStatus) inStatusFor(status corev1.ConditionStatus, dur time.Duration) time.Duration { +func (pas *PodAutoscalerStatus) inStatusFor(status corev1.ConditionStatus, now time.Time, dur time.Duration) time.Duration { cond := pas.GetCondition(PodAutoscalerConditionActive) if cond == nil || cond.Status != status { return -1 } - return time.Since(cond.LastTransitionTime.Inner.Add(dur)) + return now.Sub(cond.LastTransitionTime.Inner.Add(dur)) +} + +func (pas *PodAutoscalerStatus) duck() *duckv1.Status { + return (*duckv1.Status)(&pas.Status) +} + +// GetDesiredScale returns the desired scale if ever set, or -1. +func (pas *PodAutoscalerStatus) GetDesiredScale() int32 { + if pas.DesiredScale != nil { + return *pas.DesiredScale + } + return -1 } -func (pas *PodAutoscalerStatus) duck() *duckv1beta1.Status { - return (*duckv1beta1.Status)(&pas.Status) +// GetActualScale returns the desired scale if ever set, or -1. +func (pas *PodAutoscalerStatus) GetActualScale() int32 { + if pas.ActualScale != nil { + return *pas.ActualScale + } + return -1 } diff --git a/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/pa_types.go b/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/pa_types.go index ac27c3ea0d..7cda594f12 100644 --- a/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/pa_types.go +++ b/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/pa_types.go @@ -20,10 +20,9 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/kmeta" net "knative.dev/serving/pkg/apis/networking" - servingv1beta1 "knative.dev/serving/pkg/apis/serving/v1beta1" ) // +genclient @@ -57,6 +56,22 @@ var ( _ kmeta.OwnerRefable = (*PodAutoscaler)(nil) ) +// ReachabilityType is the enumeration type for the different states of reachability +// to the `ScaleTarget` of a `PodAutoscaler` +type ReachabilityType string + +const ( + // ReachabilityUnknown means the reachability of the `ScaleTarget` is unknown. + // Used when the reachability cannot be determined, eg. during activation. + ReachabilityUnknown ReachabilityType = "" + + // ReachabilityReachable means the `ScaleTarget` is reachable, ie. it has an active route. + ReachabilityReachable ReachabilityType = "Reachable" + + // ReachabilityReachable means the `ScaleTarget` is not reachable, ie. it does not have an active route. + ReachabilityUnreachable ReachabilityType = "Unreachable" +) + // PodAutoscalerSpec holds the desired state of the PodAutoscaler (from the client). type PodAutoscalerSpec struct { // DeprecatedGeneration was used prior in Kubernetes versions <1.11 @@ -74,18 +89,23 @@ type PodAutoscalerSpec struct { // in-flight (concurrent) requests per container of the Revision. // Defaults to `0` which means unlimited concurrency. // +optional - ContainerConcurrency servingv1beta1.RevisionContainerConcurrencyType `json:"containerConcurrency,omitempty"` + ContainerConcurrency int64 `json:"containerConcurrency,omitempty"` // ScaleTargetRef defines the /scale-able resource that this PodAutoscaler // is responsible for quickly right-sizing. ScaleTargetRef corev1.ObjectReference `json:"scaleTargetRef"` + // Reachable specifies whether or not the `ScaleTargetRef` can be reached (ie. has a route). + // Defaults to `ReachabilityUnknown` + // +optional + Reachability ReachabilityType `json:"reachability,omitempty"` + // DeprecatedServiceName holds the name of a core Kubernetes Service resource that // load balances over the pods referenced by the ScaleTargetRef. DeprecatedServiceName string `json:"serviceName"` // The application-layer protocol. Matches `ProtocolType` inferred from the revision spec. - ProtocolType net.ProtocolType + ProtocolType net.ProtocolType `json:"protocolType"` } const ( @@ -98,7 +118,7 @@ const ( // PodAutoscalerStatus communicates the observed state of the PodAutoscaler (from the controller). type PodAutoscalerStatus struct { - duckv1beta1.Status + duckv1.Status `json:",inline"` // ServiceName is the K8s Service name that serves the revision, scaled by this PA. // The service is created and owned by the ServerlessService object owned by this PA. @@ -107,6 +127,12 @@ type PodAutoscalerStatus struct { // MetricsServiceName is the K8s Service name that provides revision metrics. // The service is managed by the PA object. MetricsServiceName string `json:"metricsServiceName"` + + // DesiredScale shows the current desired number of replicas for the revision. + DesiredScale *int32 `json:"desiredScale,omitempty"` + + // ActualScale shows the actual number of replicas for the revision. + ActualScale *int32 `json:"actualScale,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/pa_validation.go b/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/pa_validation.go index f1b1be9773..31b2bb957a 100644 --- a/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/pa_validation.go +++ b/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/pa_validation.go @@ -18,58 +18,25 @@ package v1alpha1 import ( "context" - "fmt" "k8s.io/apimachinery/pkg/api/equality" "knative.dev/pkg/apis" - "knative.dev/serving/pkg/apis/autoscaling" "knative.dev/serving/pkg/apis/serving" ) func (pa *PodAutoscaler) Validate(ctx context.Context) *apis.FieldError { errs := serving.ValidateObjectMetadata(pa.GetObjectMeta()).ViaField("metadata") - errs = errs.Also(pa.validateMetric()) return errs.Also(pa.Spec.Validate(apis.WithinSpec(ctx)).ViaField("spec")) } // Validate validates PodAutoscaler Spec. -func (rs *PodAutoscalerSpec) Validate(ctx context.Context) *apis.FieldError { - if equality.Semantic.DeepEqual(rs, &PodAutoscalerSpec{}) { +func (pa *PodAutoscalerSpec) Validate(ctx context.Context) *apis.FieldError { + if equality.Semantic.DeepEqual(pa, &PodAutoscalerSpec{}) { return apis.ErrMissingField(apis.CurrentField) } - errs := serving.ValidateNamespacedObjectReference(&rs.ScaleTargetRef).ViaField("scaleTargetRef") - errs = errs.Also(rs.ContainerConcurrency.Validate(ctx). - ViaField("containerConcurrency")) - return errs.Also(validateSKSFields(ctx, rs)) + return serving.ValidateNamespacedObjectReference(&pa.ScaleTargetRef).ViaField("scaleTargetRef").Also(serving.ValidateContainerConcurrency(&pa.ContainerConcurrency).ViaField("containerConcurrency")).Also(validateSKSFields(ctx, pa)) } func validateSKSFields(ctx context.Context, rs *PodAutoscalerSpec) (errs *apis.FieldError) { return errs.Also(rs.ProtocolType.Validate(ctx)).ViaField("protocolType") } - -func (pa *PodAutoscaler) validateMetric() *apis.FieldError { - if metric, ok := pa.Annotations[autoscaling.MetricAnnotationKey]; ok { - switch pa.Class() { - case autoscaling.KPA: - switch metric { - case autoscaling.Concurrency: - return nil - } - case autoscaling.HPA: - switch metric { - case autoscaling.CPU, autoscaling.Concurrency: - return nil - } - // TODO: implement OPS autoscaling. - default: - // Leave other classes of PodAutoscaler alone. - return nil - } - return &apis.FieldError{ - Message: fmt.Sprintf("Unsupported metric %q for PodAutoscaler class %q", - metric, pa.Class()), - Paths: []string{"annotations[autoscaling.knative.dev/metric]"}, - } - } - return nil -} diff --git a/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/zz_generated.deepcopy.go b/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/zz_generated.deepcopy.go index 0356e40d40..435a5a8642 100644 --- a/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/knative.dev/serving/pkg/apis/autoscaling/v1alpha1/zz_generated.deepcopy.go @@ -31,7 +31,7 @@ func (in *Metric) DeepCopyInto(out *Metric) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec - out.Status = in.Status + in.Status.DeepCopyInto(&out.Status) return } @@ -105,6 +105,7 @@ func (in *MetricSpec) DeepCopy() *MetricSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MetricStatus) DeepCopyInto(out *MetricStatus) { *out = *in + in.Status.DeepCopyInto(&out.Status) return } @@ -200,6 +201,16 @@ func (in *PodAutoscalerSpec) DeepCopy() *PodAutoscalerSpec { func (in *PodAutoscalerStatus) DeepCopyInto(out *PodAutoscalerStatus) { *out = *in in.Status.DeepCopyInto(&out.Status) + if in.DesiredScale != nil { + in, out := &in.DesiredScale, &out.DesiredScale + *out = new(int32) + **out = **in + } + if in.ActualScale != nil { + in, out := &in.ActualScale, &out.ActualScale + *out = new(int32) + **out = **in + } return } diff --git a/vendor/knative.dev/serving/pkg/apis/config/defaults.go b/vendor/knative.dev/serving/pkg/apis/config/defaults.go index 5799eb62e4..df27f9aed0 100644 --- a/vendor/knative.dev/serving/pkg/apis/config/defaults.go +++ b/vendor/knative.dev/serving/pkg/apis/config/defaults.go @@ -44,6 +44,13 @@ const ( // DefaultUserContainerName is the default name we give to the container // specified by the user, if `name:` is omitted. DefaultUserContainerName = "user-container" + + // DefaultContainerConcurrency is the default container concurrency. It will be set if ContainerConcurrency is not specified. + DefaultContainerConcurrency int64 = 0 + + // DefaultMaxRevisionContainerConcurrency is the maximum configurable + // container concurrency. + DefaultMaxRevisionContainerConcurrency int64 = 1000 ) // NewDefaultsConfigFromMap creates a Defaults from the supplied Map @@ -64,6 +71,10 @@ func NewDefaultsConfigFromMap(data map[string]string) (*Defaults, error) { key: "max-revision-timeout-seconds", field: &nc.MaxRevisionTimeoutSeconds, defaultValue: DefaultMaxRevisionTimeoutSeconds, + }, { + key: "container-concurrency", + field: &nc.ContainerConcurrency, + defaultValue: DefaultContainerConcurrency, }} { if raw, ok := data[i64.key]; !ok { *i64.field = i64.defaultValue @@ -78,6 +89,10 @@ func NewDefaultsConfigFromMap(data map[string]string) (*Defaults, error) { return nil, fmt.Errorf("revision-timeout-seconds (%d) cannot be greater than max-revision-timeout-seconds (%d)", nc.RevisionTimeoutSeconds, nc.MaxRevisionTimeoutSeconds) } + if nc.ContainerConcurrency < 0 || nc.ContainerConcurrency > DefaultMaxRevisionContainerConcurrency { + return nil, apis.ErrOutOfBoundsValue(nc.ContainerConcurrency, 0, DefaultMaxRevisionContainerConcurrency, "containerConcurrency") + } + // Process resource quantity fields for _, rsrc := range []struct { key string @@ -137,6 +152,8 @@ type Defaults struct { UserContainerNameTemplate string + ContainerConcurrency int64 + RevisionCPURequest *resource.Quantity RevisionCPULimit *resource.Quantity RevisionMemoryRequest *resource.Quantity diff --git a/vendor/knative.dev/serving/pkg/apis/networking/register.go b/vendor/knative.dev/serving/pkg/apis/networking/register.go index f255f88c86..11ded7d685 100644 --- a/vendor/knative.dev/serving/pkg/apis/networking/register.go +++ b/vendor/knative.dev/serving/pkg/apis/networking/register.go @@ -73,6 +73,17 @@ const ( // value a different reconciliation logic may be used (for examples, // Cert-Manager-based Certificate will reconcile into a Cert-Manager Certificate). CertificateClassAnnotationKey = GroupName + "/certificate.class" + + // ActivatorServiceName is the name of the activator Kubernetes service. + ActivatorServiceName = "activator-service" + + // DisableWildcardCertLabelKey is the label key attached to a namespace to indicate that + // a wildcard certificate should be not created for it. + DisableWildcardCertLabelKey = GroupName + "/disableWildcardCert" + + // WildcardCertDomainLabelKey is the label key attached to a certificate to indicate the + // domain for which it was issued. + WildcardCertDomainLabelKey = "networking.knative.dev/wildcardDomain" ) // ServiceType is the enumeration type for the Kubernetes services diff --git a/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/certificate_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/certificate_lifecycle.go index 2a734b597e..38b77a9615 100644 --- a/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/certificate_lifecycle.go +++ b/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/certificate_lifecycle.go @@ -20,9 +20,8 @@ import ( "fmt" "k8s.io/apimachinery/pkg/runtime/schema" - "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" ) // InitializeConditions initializes the certificate conditions. @@ -35,13 +34,13 @@ func (cs *CertificateStatus) MarkReady() { certificateCondSet.Manage(cs).MarkTrue(CertificateConditionReady) } -// MarkUnknown marks the certificate status as unknown. -func (cs *CertificateStatus) MarkUnknown(reason, message string) { +// MarkNotReady marks the certificate status as unknown. +func (cs *CertificateStatus) MarkNotReady(reason, message string) { certificateCondSet.Manage(cs).MarkUnknown(CertificateConditionReady, reason, message) } -// MarkNotReady marks the certificate as not ready. -func (cs *CertificateStatus) MarkNotReady(reason, message string) { +// MarkFailed marks the certificate as not ready. +func (cs *CertificateStatus) MarkFailed(reason, message string) { certificateCondSet.Manage(cs).MarkFalse(CertificateConditionReady, reason, message) } @@ -76,6 +75,6 @@ func (c *Certificate) GetGroupVersionKind() schema.GroupVersionKind { return SchemeGroupVersion.WithKind("Certificate") } -func (cs *CertificateStatus) duck() *duckv1beta1.Status { +func (cs *CertificateStatus) duck() *duckv1.Status { return &cs.Status } diff --git a/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/certificate_types.go b/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/certificate_types.go index 9738faf016..9bf98cce46 100644 --- a/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/certificate_types.go +++ b/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/certificate_types.go @@ -20,7 +20,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/kmeta" ) @@ -88,7 +88,7 @@ type CertificateStatus struct { // - The target secret exists // - The target secret contains a certificate that has not expired // - The target secret contains a private key valid for the certificate - duckv1beta1.Status `json:",inline"` + duckv1.Status `json:",inline"` // The expiration time of the TLS certificate stored in the secret named // by this resource in spec.secretName. diff --git a/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/ingress_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/ingress_lifecycle.go index 22a2255c2f..f227e75afe 100644 --- a/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/ingress_lifecycle.go +++ b/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/ingress_lifecycle.go @@ -21,7 +21,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" ) var ingressCondSet = apis.NewLivingConditionSet( @@ -78,12 +78,17 @@ func (is *IngressStatus) MarkLoadBalancerPending() { "Waiting for VirtualService to be ready") } +// MarkIngressNotReady marks the "IngressConditionReady" condition to unknown. +func (is *IngressStatus) MarkIngressNotReady(reason, message string) { + ingressCondSet.Manage(is).MarkUnknown(IngressConditionReady, reason, message) +} + // IsReady looks at the conditions and if the Status has a condition // IngressConditionReady returns true if ConditionStatus is True func (is *IngressStatus) IsReady() bool { return ingressCondSet.Manage(is).IsHappy() } -func (is *IngressStatus) duck() *duckv1beta1.Status { +func (is *IngressStatus) duck() *duckv1.Status { return &is.Status } diff --git a/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/ingress_types.go b/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/ingress_types.go index 68cc25e1a3..8b9e8425ab 100644 --- a/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/ingress_types.go +++ b/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/ingress_types.go @@ -20,7 +20,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/kmeta" ) @@ -276,7 +276,7 @@ type HTTPRetry struct { // IngressStatus describe the current state of the Ingress. type IngressStatus struct { - duckv1beta1.Status `json:",inline"` + duckv1.Status `json:",inline"` // LoadBalancer contains the current status of the load-balancer. // This is to be superseded by the combination of `PublicLoadBalancer` and `PrivateLoadBalancer` diff --git a/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/serverlessservice_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/serverlessservice_lifecycle.go index b9dcd2eea7..e8ad84fdc5 100644 --- a/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/serverlessservice_lifecycle.go +++ b/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/serverlessservice_lifecycle.go @@ -23,7 +23,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" ) var serverlessServiceCondSet = apis.NewLivingConditionSet( @@ -91,7 +91,7 @@ func (sss *ServerlessServiceStatus) IsReady() bool { return serverlessServiceCondSet.Manage(sss).IsHappy() } -func (sss *ServerlessServiceStatus) duck() *duckv1beta1.Status { +func (sss *ServerlessServiceStatus) duck() *duckv1.Status { return &sss.Status } diff --git a/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/serverlessservice_types.go b/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/serverlessservice_types.go index 80ae00675f..689bf43146 100644 --- a/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/serverlessservice_types.go +++ b/vendor/knative.dev/serving/pkg/apis/networking/v1alpha1/serverlessservice_types.go @@ -20,7 +20,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/kmeta" networking "knative.dev/serving/pkg/apis/networking" ) @@ -104,7 +104,7 @@ type ServerlessServiceSpec struct { // ServerlessServiceStatus describes the current state of the ServerlessService. type ServerlessServiceStatus struct { - duckv1beta1.Status `json:",inline"` + duckv1.Status `json:",inline"` // ServiceName holds the name of a core K8s Service resource that // load balances over the pods backing this Revision (activator or revision). diff --git a/vendor/knative.dev/serving/pkg/apis/serving/k8s_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/k8s_lifecycle.go new file mode 100644 index 0000000000..f40bfbf9fd --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/k8s_lifecycle.go @@ -0,0 +1,78 @@ +/* +Copyright 2019 The Knative Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package serving + +import ( + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +var depCondSet = apis.NewLivingConditionSet( + DeploymentConditionProgressing, + DeploymentConditionReplicaSetReady, +) + +const ( + // DeploymentConditionReady means the underlying deployment is ready. + DeploymentConditionReady = apis.ConditionReady + // DeploymentConditionReplicaSetready inverts the underlying deployment's + // ReplicaSetFailure condition. + DeploymentConditionReplicaSetReady apis.ConditionType = "ReplicaSetReady" + // DeploymentConditionProgressing reflects the underlying deployment's + // Progressing condition. + DeploymentConditionProgressing apis.ConditionType = "Progressing" +) + +// transformDeploymentStatus transforms the kubernetes DeploymentStatus into a +// duckv1.Status that uses ConditionSets to propagate failures and expose +// a top-level happy state, per our condition conventions. +func TransformDeploymentStatus(ds *appsv1.DeploymentStatus) *duckv1.Status { + s := &duckv1.Status{} + + depCondSet.Manage(s).InitializeConditions() + // The absence of this condition means no failure has occurred. If we find it + // below, we'll ovewrwrite this. + depCondSet.Manage(s).MarkTrue(DeploymentConditionReplicaSetReady) + + for _, cond := range ds.Conditions { + // TODO(jonjohnsonjr): Should we care about appsv1.DeploymentAvailable here? + switch cond.Type { + case appsv1.DeploymentProgressing: + switch cond.Status { + case corev1.ConditionUnknown: + depCondSet.Manage(s).MarkUnknown(DeploymentConditionProgressing, cond.Reason, cond.Message) + case corev1.ConditionTrue: + depCondSet.Manage(s).MarkTrue(DeploymentConditionProgressing) + case corev1.ConditionFalse: + depCondSet.Manage(s).MarkFalse(DeploymentConditionProgressing, cond.Reason, cond.Message) + } + case appsv1.DeploymentReplicaFailure: + switch cond.Status { + case corev1.ConditionUnknown: + depCondSet.Manage(s).MarkUnknown(DeploymentConditionReplicaSetReady, cond.Reason, cond.Message) + case corev1.ConditionTrue: + depCondSet.Manage(s).MarkFalse(DeploymentConditionReplicaSetReady, cond.Reason, cond.Message) + case corev1.ConditionFalse: + depCondSet.Manage(s).MarkTrue(DeploymentConditionReplicaSetReady) + } + } + } + return s +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/k8s_validation.go b/vendor/knative.dev/serving/pkg/apis/serving/k8s_validation.go index b55cd9e04e..4ad5443330 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/k8s_validation.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/k8s_validation.go @@ -97,9 +97,15 @@ func validateVolume(volume corev1.Volume) *apis.FieldError { specified := []string{} if vs.Secret != nil { specified = append(specified, "secret") + for i, item := range vs.Secret.Items { + errs = errs.Also(validateKeyToPath(item).ViaFieldIndex("items", i)) + } } if vs.ConfigMap != nil { specified = append(specified, "configMap") + for i, item := range vs.ConfigMap.Items { + errs = errs.Also(validateKeyToPath(item).ViaFieldIndex("items", i)) + } } if vs.Projected != nil { specified = append(specified, "projected") @@ -143,7 +149,7 @@ func validateConfigMapProjection(cmp *corev1.ConfigMapProjection) *apis.FieldErr errs = errs.Also(apis.ErrMissingField("name")) } for i, item := range cmp.Items { - errs = errs.Also(apis.CheckDisallowedFields(item, *KeyToPathMask(&item)).ViaIndex(i)) + errs = errs.Also(validateKeyToPath(item).ViaFieldIndex("items", i)) } return errs } @@ -156,7 +162,18 @@ func validateSecretProjection(sp *corev1.SecretProjection) *apis.FieldError { errs = errs.Also(apis.ErrMissingField("name")) } for i, item := range sp.Items { - errs = errs.Also(apis.CheckDisallowedFields(item, *KeyToPathMask(&item)).ViaIndex(i)) + errs = errs.Also(validateKeyToPath(item).ViaFieldIndex("items", i)) + } + return errs +} + +func validateKeyToPath(k2p corev1.KeyToPath) *apis.FieldError { + errs := apis.CheckDisallowedFields(k2p, *KeyToPathMask(&k2p)) + if k2p.Key == "" { + errs = errs.Also(apis.ErrMissingField("key")) + } + if k2p.Path == "" { + errs = errs.Also(apis.ErrMissingField("path")) } return errs } @@ -439,11 +456,17 @@ func validateReadinessProbe(p *corev1.Probe) *apis.FieldError { // PeriodSeconds == 0 indicates Knative's special probe with aggressive retries if p.PeriodSeconds == 0 { if p.FailureThreshold != 0 { - errs = errs.Also(apis.ErrDisallowedFields("failureThreshold")) + errs = errs.Also(&apis.FieldError{ + Message: "failureThreshold is disallowed when periodSeconds is zero", + Paths: []string{"failureThreshold"}, + }) } if p.TimeoutSeconds != 0 { - errs = errs.Also(apis.ErrDisallowedFields("timeoutSeconds")) + errs = errs.Also(&apis.FieldError{ + Message: "timeoutSeconds is disallowed when periodSeconds is zero", + Paths: []string{"timeoutSeconds"}, + }) } } else { if p.TimeoutSeconds < 1 { diff --git a/vendor/knative.dev/serving/pkg/apis/serving/metadata_validation.go b/vendor/knative.dev/serving/pkg/apis/serving/metadata_validation.go index c569babc2c..96c8b453ea 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/metadata_validation.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/metadata_validation.go @@ -19,18 +19,40 @@ package serving import ( "context" "strconv" + "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" "knative.dev/serving/pkg/apis/autoscaling" "knative.dev/serving/pkg/apis/config" + routeconfig "knative.dev/serving/pkg/reconciler/route/config" +) + +var ( + allowedAnnotations = map[string]struct{}{ + UpdaterAnnotation: {}, + CreatorAnnotation: {}, + RevisionLastPinnedAnnotationKey: {}, + GroupNamePrefix + "forceUpgrade": {}, + } ) // ValidateObjectMetadata validates that `metadata` stanza of the // resources is correct. func ValidateObjectMetadata(meta metav1.Object) *apis.FieldError { return apis.ValidateObjectMetadata(meta). - Also(autoscaling.ValidateAnnotations(meta.GetAnnotations()).ViaField("annotations")) + Also(autoscaling.ValidateAnnotations(meta.GetAnnotations()). + Also(validateKnativeAnnotations(meta.GetAnnotations())). + ViaField("annotations")) +} + +func validateKnativeAnnotations(annotations map[string]string) (errs *apis.FieldError) { + for key := range annotations { + if _, ok := allowedAnnotations[key]; !ok && strings.HasPrefix(key, GroupNamePrefix) { + errs = errs.Also(apis.ErrInvalidKeyName(key, apis.CurrentField)) + } + } + return } // ValidateQueueSidecarAnnotation validates QueueSideCarResourcePercentageAnnotation @@ -64,3 +86,23 @@ func ValidateTimeoutSeconds(ctx context.Context, timeoutSeconds int64) *apis.Fie } return nil } + +// ValidateContainerConcurrency function validates the ContainerConcurrency field +// TODO(#5007): Move this to autoscaling. +func ValidateContainerConcurrency(containerConcurrency *int64) *apis.FieldError { + if containerConcurrency != nil { + if *containerConcurrency < 0 || *containerConcurrency > config.DefaultMaxRevisionContainerConcurrency { + return apis.ErrOutOfBoundsValue( + *containerConcurrency, 0, config.DefaultMaxRevisionContainerConcurrency, apis.CurrentField) + } + } + return nil +} + +// ValidateClusterVisibilityLabel function validates the visibility label on a Route +func ValidateClusterVisibilityLabel(label string) (errs *apis.FieldError) { + if label != routeconfig.VisibilityClusterLocal { + errs = apis.ErrInvalidValue(label, routeconfig.VisibilityLabelKey) + } + return +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/register.go b/vendor/knative.dev/serving/pkg/apis/serving/register.go index 35c8677e87..ba8264063c 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/register.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/register.go @@ -20,6 +20,9 @@ const ( // GroupName is the group name for knative labels and annotations GroupName = "serving.knative.dev" + // GroupNamePrefix is the prefix for label key and annotation key + GroupNamePrefix = GroupName + "/" + // ConfigurationLabelKey is the label key attached to a Revision indicating by // which Configuration it is created. ConfigurationLabelKey = GroupName + "/configuration" diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_conversion.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_conversion.go new file mode 100644 index 0000000000..05d012ce55 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_conversion.go @@ -0,0 +1,34 @@ +/* +Copyright 2019 The Knative Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + "fmt" + + "knative.dev/pkg/apis" +) + +// ConvertUp implements apis.Convertible +func (source *Configuration) ConvertUp(ctx context.Context, sink apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", sink) +} + +// ConvertDown implements apis.Convertible +func (sink *Configuration) ConvertDown(ctx context.Context, source apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", source) +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_defaults.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_defaults.go new file mode 100644 index 0000000000..db1170d3fb --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_defaults.go @@ -0,0 +1,34 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + + "knative.dev/pkg/apis" +) + +// SetDefaults implements apis.Defaultable +func (c *Configuration) SetDefaults(ctx context.Context) { + ctx = apis.WithinParent(ctx, c.ObjectMeta) + c.Spec.SetDefaults(apis.WithinSpec(ctx)) +} + +// SetDefaults implements apis.Defaultable +func (cs *ConfigurationSpec) SetDefaults(ctx context.Context) { + cs.Template.SetDefaults(ctx) +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_lifecycle.go new file mode 100644 index 0000000000..93057dacf5 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_lifecycle.go @@ -0,0 +1,35 @@ +/* +Copyright 2019 The Knative Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + + "knative.dev/pkg/apis" +) + +var configurationCondSet = apis.NewLivingConditionSet() + +// GetGroupVersionKind returns the GroupVersionKind. +func (r *Configuration) GetGroupVersionKind() schema.GroupVersionKind { + return SchemeGroupVersion.WithKind("Configuration") +} + +// IsReady returns if the configuration is ready to serve the requested configuration. +func (cs *ConfigurationStatus) IsReady() bool { + return configurationCondSet.Manage(cs).IsHappy() +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_types.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_types.go new file mode 100644 index 0000000000..7c2c4a2bf2 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_types.go @@ -0,0 +1,102 @@ +/* +Copyright 2019 The Knative Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/kmeta" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Configuration represents the "floating HEAD" of a linear history of Revisions. +// Users create new Revisions by updating the Configuration's spec. +// The "latest created" revision's name is available under status, as is the +// "latest ready" revision's name. +// See also: https://knative.dev/serving/blob/master/docs/spec/overview.md#configuration +type Configuration struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // +optional + Spec ConfigurationSpec `json:"spec,omitempty"` + + // +optional + Status ConfigurationStatus `json:"status,omitempty"` +} + +// Verify that Configuration adheres to the appropriate interfaces. +var ( + // Check that Configuration may be validated and defaulted. + _ apis.Validatable = (*Configuration)(nil) + _ apis.Defaultable = (*Configuration)(nil) + + // Check that Configuration can be converted to higher versions. + _ apis.Convertible = (*Configuration)(nil) + + // Check that we can create OwnerReferences to a Configuration. + _ kmeta.OwnerRefable = (*Configuration)(nil) +) + +// ConfigurationSpec holds the desired state of the Configuration (from the client). +type ConfigurationSpec struct { + // Template holds the latest specification for the Revision to be stamped out. + // +optional + Template RevisionTemplateSpec `json:"template"` +} + +const ( + // ConfigurationConditionReady is set when the configuration's latest + // underlying revision has reported readiness. + ConfigurationConditionReady = apis.ConditionReady +) + +// ConfigurationStatusFields holds the fields of Configuration's status that +// are not generally shared. This is defined separately and inlined so that +// other types can readily consume these fields via duck typing. +type ConfigurationStatusFields struct { + // LatestReadyRevisionName holds the name of the latest Revision stamped out + // from this Configuration that has had its "Ready" condition become "True". + // +optional + LatestReadyRevisionName string `json:"latestReadyRevisionName,omitempty"` + + // LatestCreatedRevisionName is the last revision that was created from this + // Configuration. It might not be ready yet, for that use LatestReadyRevisionName. + // +optional + LatestCreatedRevisionName string `json:"latestCreatedRevisionName,omitempty"` +} + +// ConfigurationStatus communicates the observed state of the Configuration (from the controller). +type ConfigurationStatus struct { + duckv1.Status `json:",inline"` + + ConfigurationStatusFields `json:",inline"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ConfigurationList is a list of Configuration resources +type ConfigurationList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []Configuration `json:"items"` +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_validation.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_validation.go new file mode 100644 index 0000000000..8e3f56d388 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/configuration_validation.go @@ -0,0 +1,93 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" + "knative.dev/serving/pkg/apis/serving" + "knative.dev/serving/pkg/reconciler/route/config" +) + +// Validate makes sure that Configuration is properly configured. +func (c *Configuration) Validate(ctx context.Context) (errs *apis.FieldError) { + // If we are in a status sub resource update, the metadata and spec cannot change. + // So, to avoid rejecting controller status updates due to validations that may + // have changed (i.e. due to config-defaults changes), we elide the metadata and + // spec validation. + if !apis.IsInStatusUpdate(ctx) { + errs = errs.Also(serving.ValidateObjectMetadata(c.GetObjectMeta()).Also( + c.validateLabels().ViaField("labels")).ViaField("metadata")) + ctx = apis.WithinParent(ctx, c.ObjectMeta) + errs = errs.Also(c.Spec.Validate(apis.WithinSpec(ctx)).ViaField("spec")) + } + + errs = errs.Also(c.Status.Validate(apis.WithinStatus(ctx)).ViaField("status")) + + if apis.IsInUpdate(ctx) { + original := apis.GetBaseline(ctx).(*Configuration) + + err := c.Spec.Template.VerifyNameChange(ctx, original.Spec.Template) + errs = errs.Also(err.ViaField("spec.template")) + } + + return errs +} + +// Validate implements apis.Validatable +func (cs *ConfigurationSpec) Validate(ctx context.Context) *apis.FieldError { + return cs.Template.Validate(ctx).ViaField("template") +} + +// Validate implements apis.Validatable +func (cs *ConfigurationStatus) Validate(ctx context.Context) *apis.FieldError { + return cs.ConfigurationStatusFields.Validate(ctx) +} + +// Validate implements apis.Validatable +func (csf *ConfigurationStatusFields) Validate(ctx context.Context) *apis.FieldError { + return nil +} + +// validateLabels function validates configuration labels +func (c *Configuration) validateLabels() (errs *apis.FieldError) { + for key, val := range c.GetLabels() { + switch { + case key == config.VisibilityLabelKey: + errs = errs.Also(validateClusterVisibilityLabel(val)) + case key == serving.RouteLabelKey: + case key == serving.ServiceLabelKey: + errs = errs.Also(verifyLabelOwnerRef(val, serving.ServiceLabelKey, "Service", c.GetOwnerReferences())) + case strings.HasPrefix(key, serving.GroupNamePrefix): + errs = errs.Also(apis.ErrInvalidKeyName(key, apis.CurrentField)) + } + } + return +} + +// verifyLabelOwnerRef function verifies the owner references of resource with label key has val value. +func verifyLabelOwnerRef(val, label, resource string, ownerRefs []metav1.OwnerReference) (errs *apis.FieldError) { + for _, ref := range ownerRefs { + if ref.Kind == resource && val == ref.Name { + return + } + } + return errs.Also(apis.ErrMissingField(label)) +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/contexts.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/contexts.go similarity index 96% rename from vendor/knative.dev/serving/pkg/apis/serving/v1beta1/contexts.go rename to vendor/knative.dev/serving/pkg/apis/serving/v1/contexts.go index 9cc23937ad..2b1076cf33 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/contexts.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/contexts.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1beta1 +package v1 import "context" @@ -40,13 +40,13 @@ func HasDefaultConfigurationName(ctx context.Context) bool { type lemonadeKey struct{} // WithUpgradeViaDefaulting notes on the context that we want defaulting to rewrite -// from v1alpha1 to v1beta1. +// from v1alpha1 to v1. func WithUpgradeViaDefaulting(ctx context.Context) context.Context { return context.WithValue(ctx, lemonadeKey{}, struct{}{}) } // IsUpgradeViaDefaulting checks whether we should be "defaulting" from v1alpha1 to -// the v1beta1 subset. +// the v1 subset. func IsUpgradeViaDefaulting(ctx context.Context) bool { return ctx.Value(lemonadeKey{}) != nil } diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/doc.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/doc.go new file mode 100644 index 0000000000..fab9a24e65 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1 contains the Serving v1 API types. + +// +k8s:deepcopy-gen=package +// +groupName=serving.knative.dev +package v1 diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/register.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/register.go new file mode 100644 index 0000000000..479507d511 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/register.go @@ -0,0 +1,61 @@ +/* +Copyright 2019 The Knative Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "knative.dev/serving/pkg/apis/serving" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// SchemeGroupVersion is group version used to register these objects. +var SchemeGroupVersion = schema.GroupVersion{Group: serving.GroupName, Version: "v1"} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind. +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource. +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // SchemeBuilder registers the addKnownTypes function. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // AddToScheme applies all the stored functions to the scheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &Revision{}, + &RevisionList{}, + &Configuration{}, + &ConfigurationList{}, + &Route{}, + &RouteList{}, + &Service{}, + &ServiceList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_conversion.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_conversion.go new file mode 100644 index 0000000000..89ed8e5a04 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_conversion.go @@ -0,0 +1,34 @@ +/* +Copyright 2019 The Knative Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + "fmt" + + "knative.dev/pkg/apis" +) + +// ConvertUp implements apis.Convertible +func (source *Revision) ConvertUp(ctx context.Context, sink apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", sink) +} + +// ConvertDown implements apis.Convertible +func (sink *Revision) ConvertDown(ctx context.Context, source apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", source) +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_defaults.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_defaults.go new file mode 100644 index 0000000000..01df5b6262 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_defaults.go @@ -0,0 +1,102 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + + corev1 "k8s.io/api/core/v1" + "knative.dev/pkg/apis" + "knative.dev/pkg/ptr" + "knative.dev/serving/pkg/apis/config" +) + +// SetDefaults implements apis.Defaultable +func (r *Revision) SetDefaults(ctx context.Context) { + r.Spec.SetDefaults(apis.WithinSpec(ctx)) +} + +// SetDefaults implements apis.Defaultable +func (rts *RevisionTemplateSpec) SetDefaults(ctx context.Context) { + rts.Spec.SetDefaults(apis.WithinSpec(ctx)) +} + +// SetDefaults implements apis.Defaultable +func (rs *RevisionSpec) SetDefaults(ctx context.Context) { + cfg := config.FromContextOrDefaults(ctx) + + // Default TimeoutSeconds based on our configmap + if rs.TimeoutSeconds == nil || *rs.TimeoutSeconds == 0 { + rs.TimeoutSeconds = ptr.Int64(cfg.Defaults.RevisionTimeoutSeconds) + } + + // Default ContainerConcurrency based on our configmap + if rs.ContainerConcurrency == nil { + rs.ContainerConcurrency = ptr.Int64(cfg.Defaults.ContainerConcurrency) + } + + for idx := range rs.PodSpec.Containers { + if rs.PodSpec.Containers[idx].Name == "" { + rs.PodSpec.Containers[idx].Name = cfg.Defaults.UserContainerName(ctx) + } + + if rs.PodSpec.Containers[idx].Resources.Requests == nil { + rs.PodSpec.Containers[idx].Resources.Requests = corev1.ResourceList{} + } + if _, ok := rs.PodSpec.Containers[idx].Resources.Requests[corev1.ResourceCPU]; !ok { + if rsrc := cfg.Defaults.RevisionCPURequest; rsrc != nil { + rs.PodSpec.Containers[idx].Resources.Requests[corev1.ResourceCPU] = *rsrc + } + } + if _, ok := rs.PodSpec.Containers[idx].Resources.Requests[corev1.ResourceMemory]; !ok { + if rsrc := cfg.Defaults.RevisionMemoryRequest; rsrc != nil { + rs.PodSpec.Containers[idx].Resources.Requests[corev1.ResourceMemory] = *rsrc + } + } + + if rs.PodSpec.Containers[idx].Resources.Limits == nil { + rs.PodSpec.Containers[idx].Resources.Limits = corev1.ResourceList{} + } + if _, ok := rs.PodSpec.Containers[idx].Resources.Limits[corev1.ResourceCPU]; !ok { + if rsrc := cfg.Defaults.RevisionCPULimit; rsrc != nil { + rs.PodSpec.Containers[idx].Resources.Limits[corev1.ResourceCPU] = *rsrc + } + } + if _, ok := rs.PodSpec.Containers[idx].Resources.Limits[corev1.ResourceMemory]; !ok { + if rsrc := cfg.Defaults.RevisionMemoryLimit; rsrc != nil { + rs.PodSpec.Containers[idx].Resources.Limits[corev1.ResourceMemory] = *rsrc + } + } + if rs.PodSpec.Containers[idx].ReadinessProbe == nil { + rs.PodSpec.Containers[idx].ReadinessProbe = &corev1.Probe{} + } + if rs.PodSpec.Containers[idx].ReadinessProbe.TCPSocket == nil && + rs.PodSpec.Containers[idx].ReadinessProbe.HTTPGet == nil && + rs.PodSpec.Containers[idx].ReadinessProbe.Exec == nil { + rs.PodSpec.Containers[idx].ReadinessProbe.TCPSocket = &corev1.TCPSocketAction{} + } + + if rs.PodSpec.Containers[idx].ReadinessProbe.SuccessThreshold == 0 { + rs.PodSpec.Containers[idx].ReadinessProbe.SuccessThreshold = 1 + } + + vms := rs.PodSpec.Containers[idx].VolumeMounts + for i := range vms { + vms[i].ReadOnly = true + } + } +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_lifecycle.go new file mode 100644 index 0000000000..a178edf353 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_lifecycle.go @@ -0,0 +1,55 @@ +/* +Copyright 2019 The Knative Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + + "knative.dev/pkg/apis" + "knative.dev/serving/pkg/apis/config" +) + +const ( + // DefaultUserPort is the system default port value exposed on the user-container. + DefaultUserPort = 8080 +) + +var revisionCondSet = apis.NewLivingConditionSet() + +// GetGroupVersionKind returns the GroupVersionKind. +func (r *Revision) GetGroupVersionKind() schema.GroupVersionKind { + return SchemeGroupVersion.WithKind("Revision") +} + +// IsReady returns if the revision is ready to serve the requested configuration. +func (rs *RevisionStatus) IsReady() bool { + return revisionCondSet.Manage(rs).IsHappy() +} + +// GetContainerConcurrency returns the container concurrency. If +// container concurrency is not set, the default value will be returned. +// We use the original default (0) here for backwards compatibility. +// Previous versions of Knative equated unspecified and zero, so to avoid +// changing the value used by Revisions with unspecified values when a different +// default is configured, we use the original default instead of the configured +// default to remain safe across upgrades. +func (rs *RevisionSpec) GetContainerConcurrency() int64 { + if rs.ContainerConcurrency == nil { + return config.DefaultContainerConcurrency + } + return *rs.ContainerConcurrency +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_types.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_types.go new file mode 100644 index 0000000000..8eb83f7b2a --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_types.go @@ -0,0 +1,125 @@ +/* +Copyright 2019 The Knative Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/kmeta" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Revision is an immutable snapshot of code and configuration. A revision +// references a container image. Revisions are created by updates to a +// Configuration. +// +// See also: https://knative.dev/serving/blob/master/docs/spec/overview.md#revision +type Revision struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // +optional + Spec RevisionSpec `json:"spec,omitempty"` + + // +optional + Status RevisionStatus `json:"status,omitempty"` +} + +// Verify that Revision adheres to the appropriate interfaces. +var ( + // Check that Revision can be validated, can be defaulted, and has immutable fields. + _ apis.Validatable = (*Revision)(nil) + _ apis.Defaultable = (*Revision)(nil) + + // Check that Revision can be converted to higher versions. + _ apis.Convertible = (*Revision)(nil) + + // Check that we can create OwnerReferences to a Revision. + _ kmeta.OwnerRefable = (*Revision)(nil) +) + +// RevisionTemplateSpec describes the data a revision should have when created from a template. +// Based on: https://github.com/kubernetes/api/blob/e771f807/core/v1/types.go#L3179-L3190 +type RevisionTemplateSpec struct { + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // +optional + Spec RevisionSpec `json:"spec,omitempty"` +} + +// RevisionSpec holds the desired state of the Revision (from the client). +type RevisionSpec struct { + corev1.PodSpec `json:",inline"` + + // ContainerConcurrency specifies the maximum allowed in-flight (concurrent) + // requests per container of the Revision. Defaults to `0` which means + // concurrency to the application is not limited, and the system decides the + // target concurrency for the autoscaler. + // +optional + ContainerConcurrency *int64 `json:"containerConcurrency,omitempty"` + + // TimeoutSeconds holds the max duration the instance is allowed for + // responding to a request. If unspecified, a system default will + // be provided. + // +optional + TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty"` +} + +const ( + // RevisionConditionReady is set when the revision is starting to materialize + // runtime resources, and becomes true when those resources are ready. + RevisionConditionReady = apis.ConditionReady +) + +// RevisionStatus communicates the observed state of the Revision (from the controller). +type RevisionStatus struct { + duckv1.Status `json:",inline"` + + // ServiceName holds the name of a core Kubernetes Service resource that + // load balances over the pods backing this Revision. + // +optional + ServiceName string `json:"serviceName,omitempty"` + + // LogURL specifies the generated logging url for this particular revision + // based on the revision url template specified in the controller's config. + // +optional + LogURL string `json:"logUrl,omitempty"` + + // ImageDigest holds the resolved digest for the image specified + // within .Spec.Container.Image. The digest is resolved during the creation + // of Revision. This field holds the digest value regardless of whether + // a tag or digest was originally specified in the Container object. It + // may be empty if the image comes from a registry listed to skip resolution. + // +optional + ImageDigest string `json:"imageDigest,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// RevisionList is a list of Revision resources +type RevisionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []Revision `json:"items"` +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_validation.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_validation.go new file mode 100644 index 0000000000..4662c595a7 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/revision_validation.go @@ -0,0 +1,144 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + "fmt" + "strings" + + "knative.dev/pkg/apis" + "knative.dev/pkg/kmp" + "knative.dev/serving/pkg/apis/autoscaling" + "knative.dev/serving/pkg/apis/serving" +) + +// Validate ensures Revision is properly configured. +func (r *Revision) Validate(ctx context.Context) *apis.FieldError { + errs := serving.ValidateObjectMetadata(r.GetObjectMeta()).Also( + r.ValidateLabels().ViaField("labels")).ViaField("metadata") + errs = errs.Also(r.Status.Validate(apis.WithinStatus(ctx)).ViaField("status")) + + if apis.IsInUpdate(ctx) { + original := apis.GetBaseline(ctx).(*Revision) + if diff, err := kmp.ShortDiff(original.Spec, r.Spec); err != nil { + return &apis.FieldError{ + Message: "Failed to diff Revision", + Paths: []string{"spec"}, + Details: err.Error(), + } + } else if diff != "" { + return &apis.FieldError{ + Message: "Immutable fields changed (-old +new)", + Paths: []string{"spec"}, + Details: diff, + } + } + } else { + errs = errs.Also(r.Spec.Validate(apis.WithinSpec(ctx)).ViaField("spec")) + } + + return errs +} + +// Validate implements apis.Validatable +func (rts *RevisionTemplateSpec) Validate(ctx context.Context) *apis.FieldError { + errs := rts.Spec.Validate(apis.WithinSpec(ctx)).ViaField("spec") + errs = errs.Also(autoscaling.ValidateAnnotations(rts.GetAnnotations()).ViaField("metadata.annotations")) + + // If the RevisionTemplateSpec has a name specified, then check that + // it follows the requirements on the name. + if rts.Name != "" { + var prefix string + if om := apis.ParentMeta(ctx); om.Name == "" { + prefix = om.GenerateName + } else { + prefix = om.Name + "-" + } + + if !strings.HasPrefix(rts.Name, prefix) { + errs = errs.Also(apis.ErrInvalidValue( + fmt.Sprintf("%q must have prefix %q", rts.Name, prefix), + "metadata.name")) + } + } + + errs = errs.Also(serving.ValidateQueueSidecarAnnotation(rts.Annotations).ViaField("metadata.annotations")) + return errs +} + +// VerifyNameChange checks that if a user brought their own name previously that it +// changes at the appropriate times. +func (current *RevisionTemplateSpec) VerifyNameChange(ctx context.Context, og RevisionTemplateSpec) *apis.FieldError { + if current.Name == "" { + // We only check that Name changes when the RevisionTemplate changes. + return nil + } + if current.Name != og.Name { + // The name changed, so we're good. + return nil + } + + if diff, err := kmp.ShortDiff(&og, current); err != nil { + return &apis.FieldError{ + Message: "Failed to diff RevisionTemplate", + Paths: []string{apis.CurrentField}, + Details: err.Error(), + } + } else if diff != "" { + return &apis.FieldError{ + Message: "Saw the following changes without a name change (-old +new)", + Paths: []string{apis.CurrentField}, + Details: diff, + } + } + return nil +} + +// Validate implements apis.Validatable +func (rs *RevisionSpec) Validate(ctx context.Context) *apis.FieldError { + errs := serving.ValidatePodSpec(rs.PodSpec) + + if rs.TimeoutSeconds != nil { + errs = errs.Also(serving.ValidateTimeoutSeconds(ctx, *rs.TimeoutSeconds)) + } + + if rs.ContainerConcurrency != nil { + errs = errs.Also(serving.ValidateContainerConcurrency(rs.ContainerConcurrency).ViaField("containerConcurrency")) + } + + return errs +} + +// Validate implements apis.Validatable +func (rs *RevisionStatus) Validate(ctx context.Context) *apis.FieldError { + return nil +} + +// ValidateLabels function validates service labels +func (r *Revision) ValidateLabels() (errs *apis.FieldError) { + for key, val := range r.GetLabels() { + switch { + case key == serving.RouteLabelKey || key == serving.ServiceLabelKey || key == serving.ConfigurationGenerationLabelKey: + case key == serving.ConfigurationLabelKey: + errs = errs.Also(verifyLabelOwnerRef(val, serving.ConfigurationLabelKey, "Configuration", r.GetOwnerReferences())) + case strings.HasPrefix(key, serving.GroupNamePrefix): + errs = errs.Also(apis.ErrInvalidKeyName(key, "")) + } + } + return +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/route_conversion.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/route_conversion.go new file mode 100644 index 0000000000..7ef3cb1ae5 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/route_conversion.go @@ -0,0 +1,34 @@ +/* +Copyright 2019 The Knative Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + "fmt" + + "knative.dev/pkg/apis" +) + +// ConvertUp implements apis.Convertible +func (source *Route) ConvertUp(ctx context.Context, sink apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", sink) +} + +// ConvertDown implements apis.Convertible +func (sink *Route) ConvertDown(ctx context.Context, source apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", source) +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/route_defaults.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/route_defaults.go new file mode 100644 index 0000000000..327281fa6e --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/route_defaults.go @@ -0,0 +1,50 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + + "knative.dev/pkg/apis" + "knative.dev/pkg/ptr" +) + +// SetDefaults implements apis.Defaultable +func (r *Route) SetDefaults(ctx context.Context) { + r.Spec.SetDefaults(apis.WithinSpec(ctx)) +} + +// SetDefaults implements apis.Defaultable +func (rs *RouteSpec) SetDefaults(ctx context.Context) { + if len(rs.Traffic) == 0 && HasDefaultConfigurationName(ctx) { + rs.Traffic = []TrafficTarget{{ + Percent: ptr.Int64(100), + LatestRevision: ptr.Bool(true), + }} + } + + for idx := range rs.Traffic { + rs.Traffic[idx].SetDefaults(ctx) + } +} + +// SetDefaults implements apis.Defaultable +func (tt *TrafficTarget) SetDefaults(ctx context.Context) { + if tt.LatestRevision == nil { + tt.LatestRevision = ptr.Bool(tt.RevisionName == "") + } +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/route_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/route_lifecycle.go new file mode 100644 index 0000000000..7b4094b12f --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/route_lifecycle.go @@ -0,0 +1,35 @@ +/* +Copyright 2019 The Knative Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + + "knative.dev/pkg/apis" +) + +var routeCondSet = apis.NewLivingConditionSet() + +// GetGroupVersionKind returns the GroupVersionKind. +func (r *Route) GetGroupVersionKind() schema.GroupVersionKind { + return SchemeGroupVersion.WithKind("Route") +} + +// IsReady returns if the route is ready to serve the requested configuration. +func (rs *RouteStatus) IsReady() bool { + return routeCondSet.Manage(rs).IsHappy() +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/route_types.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/route_types.go new file mode 100644 index 0000000000..0d470ea5b1 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/route_types.go @@ -0,0 +1,159 @@ +/* +Copyright 2019 The Knative Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/kmeta" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Route is responsible for configuring ingress over a collection of Revisions. +// Some of the Revisions a Route distributes traffic over may be specified by +// referencing the Configuration responsible for creating them; in these cases +// the Route is additionally responsible for monitoring the Configuration for +// "latest ready revision" changes, and smoothly rolling out latest revisions. +// See also: https://knative.dev/serving/blob/master/docs/spec/overview.md#route +type Route struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec holds the desired state of the Route (from the client). + // +optional + Spec RouteSpec `json:"spec,omitempty"` + + // Status communicates the observed state of the Route (from the controller). + // +optional + Status RouteStatus `json:"status,omitempty"` +} + +// Verify that Route adheres to the appropriate interfaces. +var ( + // Check that Route may be validated and defaulted. + _ apis.Validatable = (*Route)(nil) + _ apis.Defaultable = (*Route)(nil) + + // Check that Route can be converted to higher versions. + _ apis.Convertible = (*Route)(nil) + + // Check that we can create OwnerReferences to a Route. + _ kmeta.OwnerRefable = (*Route)(nil) +) + +// TrafficTarget holds a single entry of the routing table for a Route. +type TrafficTarget struct { + // Tag is optionally used to expose a dedicated url for referencing + // this target exclusively. + // +optional + Tag string `json:"tag,omitempty"` + + // RevisionName of a specific revision to which to send this portion of + // traffic. This is mutually exclusive with ConfigurationName. + // +optional + RevisionName string `json:"revisionName,omitempty"` + + // ConfigurationName of a configuration to whose latest revision we will send + // this portion of traffic. When the "status.latestReadyRevisionName" of the + // referenced configuration changes, we will automatically migrate traffic + // from the prior "latest ready" revision to the new one. This field is never + // set in Route's status, only its spec. This is mutually exclusive with + // RevisionName. + // +optional + ConfigurationName string `json:"configurationName,omitempty"` + + // LatestRevision may be optionally provided to indicate that the latest + // ready Revision of the Configuration should be used for this traffic + // target. When provided LatestRevision must be true if RevisionName is + // empty; it must be false when RevisionName is non-empty. + // +optional + LatestRevision *bool `json:"latestRevision,omitempty"` + + // Percent indicates that percentage based routing should be used and + // the value indicates the percent of traffic that is be routed to this + // Revision or Configuration. `0` (zero) mean no traffic, `100` means all + // traffic. + // When percentage based routing is being used the follow rules apply: + // - the sum of all percent values must equal 100 + // - when not specified, the implied value for `percent` is zero for + // that particular Revision or Configuration + // +optional + Percent *int64 `json:"percent,omitempty"` + + // URL displays the URL for accessing named traffic targets. URL is displayed in + // status, and is disallowed on spec. URL must contain a scheme (e.g. http://) and + // a hostname, but may not contain anything else (e.g. basic auth, url path, etc.) + // +optional + URL *apis.URL `json:"url,omitempty"` +} + +// RouteSpec holds the desired state of the Route (from the client). +type RouteSpec struct { + // Traffic specifies how to distribute traffic over a collection of + // revisions and configurations. + // +optional + Traffic []TrafficTarget `json:"traffic,omitempty"` +} + +const ( + // RouteConditionReady is set when the service is configured + // and has available backends ready to receive traffic. + RouteConditionReady = apis.ConditionReady +) + +// RouteStatusFields holds the fields of Route's status that +// are not generally shared. This is defined separately and inlined so that +// other types can readily consume these fields via duck typing. +type RouteStatusFields struct { + // URL holds the url that will distribute traffic over the provided traffic targets. + // It generally has the form http[s]://{route-name}.{route-namespace}.{cluster-level-suffix} + // +optional + URL *apis.URL `json:"url,omitempty"` + + // Address holds the information needed for a Route to be the target of an event. + // +optional + Address *duckv1.Addressable `json:"address,omitempty"` + + // Traffic holds the configured traffic distribution. + // These entries will always contain RevisionName references. + // When ConfigurationName appears in the spec, this will hold the + // LatestReadyRevisionName that we last observed. + // +optional + Traffic []TrafficTarget `json:"traffic,omitempty"` +} + +// RouteStatus communicates the observed state of the Route (from the controller). +type RouteStatus struct { + duckv1.Status `json:",inline"` + + RouteStatusFields `json:",inline"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// RouteList is a list of Route resources +type RouteList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []Route `json:"items"` +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/route_validation.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/route_validation.go new file mode 100644 index 0000000000..e79c740cd1 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/route_validation.go @@ -0,0 +1,211 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + "fmt" + "strings" + + "k8s.io/apimachinery/pkg/util/validation" + "knative.dev/pkg/apis" + "knative.dev/serving/pkg/apis/serving" + "knative.dev/serving/pkg/reconciler/route/config" +) + +// Validate makes sure that Route is properly configured. +func (r *Route) Validate(ctx context.Context) *apis.FieldError { + errs := serving.ValidateObjectMetadata(r.GetObjectMeta()).Also( + r.validateLabels().ViaField("labels")).ViaField("metadata") + errs = errs.Also(r.Spec.Validate(apis.WithinSpec(ctx)).ViaField("spec")) + errs = errs.Also(r.Status.Validate(apis.WithinStatus(ctx)).ViaField("status")) + return errs +} + +func validateTrafficList(ctx context.Context, traffic []TrafficTarget) *apis.FieldError { + var errs *apis.FieldError + + // Track the targets of named TrafficTarget entries (to detect duplicates). + trafficMap := make(map[string]int) + + sum := int64(0) + for i, tt := range traffic { + errs = errs.Also(tt.Validate(ctx).ViaIndex(i)) + + if idx, ok := trafficMap[tt.Tag]; ok { + // We want only single definition of the route, even if it points + // to the same config or revision. + errs = errs.Also(&apis.FieldError{ + Message: fmt.Sprintf("Multiple definitions for %q", tt.Tag), + Paths: []string{ + fmt.Sprintf("[%d].tag", i), + fmt.Sprintf("[%d].tag", idx), + }, + }) + } else { + trafficMap[tt.Tag] = i + } + if tt.Percent != nil { + sum += *tt.Percent + } + } + + if sum != 100 { + errs = errs.Also(&apis.FieldError{ + Message: fmt.Sprintf("Traffic targets sum to %d, want 100", sum), + Paths: []string{apis.CurrentField}, + }) + } + return errs +} + +// Validate implements apis.Validatable +func (rs *RouteSpec) Validate(ctx context.Context) *apis.FieldError { + return validateTrafficList(ctx, rs.Traffic).ViaField("traffic") +} + +// Validate verifies that TrafficTarget is properly configured. +func (tt *TrafficTarget) Validate(ctx context.Context) *apis.FieldError { + errs := tt.validateLatestRevision(ctx) + errs = tt.validateRevisionAndConfiguration(ctx, errs) + errs = tt.validateTrafficPercentage(errs) + return tt.validateURL(ctx, errs) +} + +func (tt *TrafficTarget) validateRevisionAndConfiguration(ctx context.Context, errs *apis.FieldError) *apis.FieldError { + // We only validate the sense of latestRevision in the context of a Spec, + // and only when it is specified. + switch { + // When we have a default configurationName, we don't + // allow one to be specified. + case HasDefaultConfigurationName(ctx) && tt.ConfigurationName != "": + errs = errs.Also(apis.ErrDisallowedFields("configurationName")) + + // Both revisionName and configurationName are never allowed to + // appear concurrently. + case tt.RevisionName != "" && tt.ConfigurationName != "": + errs = errs.Also(apis.ErrMultipleOneOf( + "revisionName", "configurationName")) + + // When a revisionName appears, we must check that the name is valid. + case tt.RevisionName != "": + if el := validation.IsQualifiedName(tt.RevisionName); len(el) > 0 { + errs = errs.Also(apis.ErrInvalidKeyName( + tt.RevisionName, "revisionName", el...)) + } + + // When revisionName is missing in Status report an error. + case apis.IsInStatus(ctx): + errs = errs.Also(apis.ErrMissingField("revisionName")) + + // When configurationName is specified, we must check that the name is valid. + case tt.ConfigurationName != "": + if el := validation.IsQualifiedName(tt.ConfigurationName); len(el) > 0 { + errs = errs.Also(apis.ErrInvalidKeyName( + tt.ConfigurationName, "configurationName", el...)) + } + + // When we are using a default configurationName, it must be a valid name already. + case HasDefaultConfigurationName(ctx): + + // All other cases are missing one of revisionName or configurationName. + default: + errs = errs.Also(apis.ErrMissingOneOf( + "revisionName", "configurationName")) + } + return errs +} + +func (tt *TrafficTarget) validateTrafficPercentage(errs *apis.FieldError) *apis.FieldError { + // Check that the traffic Percentage is within bounds. + if tt.Percent != nil && (*tt.Percent < 0 || *tt.Percent > 100) { + errs = errs.Also(apis.ErrOutOfBoundsValue( + *tt.Percent, 0, 100, "percent")) + } + return errs +} + +func (tt *TrafficTarget) validateLatestRevision(ctx context.Context) *apis.FieldError { + if apis.IsInSpec(ctx) && tt.LatestRevision != nil { + lr := *tt.LatestRevision + pinned := tt.RevisionName != "" + if pinned == lr { + // The senses for whether to pin to a particular revision or + // float forward to the latest revision must match. + return apis.ErrInvalidValue(lr, "latestRevision") + } + } + return nil +} + +func (tt *TrafficTarget) validateURL(ctx context.Context, errs *apis.FieldError) *apis.FieldError { + // Check that we set the URL appropriately. + if tt.URL.String() != "" { + // URL is not allowed in traffic under spec. + if apis.IsInSpec(ctx) { + errs = errs.Also(apis.ErrDisallowedFields("url")) + } + + // URL is not allowed in any traffic target without a name. + if tt.Tag == "" { + errs = errs.Also(apis.ErrDisallowedFields("url")) + } + } else if tt.Tag != "" { + // URL must be specified in status when name is specified. + if apis.IsInStatus(ctx) { + errs = errs.Also(apis.ErrMissingField("url")) + } + } + return errs +} + +// Validate implements apis.Validatable. +func (rs *RouteStatus) Validate(ctx context.Context) *apis.FieldError { + return rs.RouteStatusFields.Validate(ctx) +} + +// Validate implements apis.Validatable. +func (rsf *RouteStatusFields) Validate(ctx context.Context) *apis.FieldError { + // TODO(mattmoor): Validate other status fields. + + if len(rsf.Traffic) != 0 { + return validateTrafficList(ctx, rsf.Traffic).ViaField("traffic") + } + return nil +} + +func validateClusterVisibilityLabel(label string) (errs *apis.FieldError) { + if label != config.VisibilityClusterLocal { + errs = apis.ErrInvalidValue(label, config.VisibilityLabelKey) + } + return +} + +// validateLabels function validates route labels. +func (r *Route) validateLabels() (errs *apis.FieldError) { + for key, val := range r.GetLabels() { + switch { + case key == config.VisibilityLabelKey: + errs = errs.Also(validateClusterVisibilityLabel(val)) + case key == serving.ServiceLabelKey: + errs = errs.Also(verifyLabelOwnerRef(val, serving.ServiceLabelKey, "Service", r.GetOwnerReferences())) + case strings.HasPrefix(key, serving.GroupNamePrefix): + errs = errs.Also(apis.ErrInvalidKeyName(key, apis.CurrentField)) + } + } + return +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/service_conversion.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/service_conversion.go new file mode 100644 index 0000000000..efb6605f33 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/service_conversion.go @@ -0,0 +1,34 @@ +/* +Copyright 2019 The Knative Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + "fmt" + + "knative.dev/pkg/apis" +) + +// ConvertUp implements apis.Convertible +func (source *Service) ConvertUp(ctx context.Context, sink apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", sink) +} + +// ConvertDown implements apis.Convertible +func (sink *Service) ConvertDown(ctx context.Context, source apis.Convertible) error { + return fmt.Errorf("v1 is the highest known version, got: %T", source) +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/service_defaults.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/service_defaults.go new file mode 100644 index 0000000000..72468790a7 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/service_defaults.go @@ -0,0 +1,57 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + + "k8s.io/apimachinery/pkg/api/equality" + + "knative.dev/pkg/apis" + "knative.dev/serving/pkg/apis/serving" +) + +// SetDefaults implements apis.Defaultable +func (s *Service) SetDefaults(ctx context.Context) { + ctx = apis.WithinParent(ctx, s.ObjectMeta) + s.Spec.SetDefaults(apis.WithinSpec(ctx)) + + if ui := apis.GetUserInfo(ctx); ui != nil { + ans := s.GetAnnotations() + if ans == nil { + ans = map[string]string{} + s.SetAnnotations(ans) + } + + if apis.IsInUpdate(ctx) { + old := apis.GetBaseline(ctx).(*Service) + if equality.Semantic.DeepEqual(old.Spec, s.Spec) { + return + } + ans[serving.UpdaterAnnotation] = ui.Username + } else { + ans[serving.CreatorAnnotation] = ui.Username + ans[serving.UpdaterAnnotation] = ui.Username + } + } +} + +// SetDefaults implements apis.Defaultable +func (ss *ServiceSpec) SetDefaults(ctx context.Context) { + ss.ConfigurationSpec.SetDefaults(ctx) + ss.RouteSpec.SetDefaults(WithDefaultConfigurationName(ctx)) +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/service_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/service_lifecycle.go new file mode 100644 index 0000000000..f842245478 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/service_lifecycle.go @@ -0,0 +1,35 @@ +/* +Copyright 2019 The Knative Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + + "knative.dev/pkg/apis" +) + +var serviceCondSet = apis.NewLivingConditionSet() + +// GetGroupVersionKind returns the GroupVersionKind. +func (s *Service) GetGroupVersionKind() schema.GroupVersionKind { + return SchemeGroupVersion.WithKind("Service") +} + +// IsReady returns if the service is ready to serve the requested configuration. +func (ss *ServiceStatus) IsReady() bool { + return serviceCondSet.Manage(ss).IsHappy() +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/service_types.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/service_types.go new file mode 100644 index 0000000000..19c4758ac4 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/service_types.go @@ -0,0 +1,113 @@ +/* +Copyright 2019 The Knative Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" + "knative.dev/pkg/kmeta" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Service acts as a top-level container that manages a Route and Configuration +// which implement a network service. Service exists to provide a singular +// abstraction which can be access controlled, reasoned about, and which +// encapsulates software lifecycle decisions such as rollout policy and +// team resource ownership. Service acts only as an orchestrator of the +// underlying Routes and Configurations (much as a kubernetes Deployment +// orchestrates ReplicaSets), and its usage is optional but recommended. +// +// The Service's controller will track the statuses of its owned Configuration +// and Route, reflecting their statuses and conditions as its own. +// +// See also: https://knative.dev/serving/blob/master/docs/spec/overview.md#service +type Service struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // +optional + Spec ServiceSpec `json:"spec,omitempty"` + + // +optional + Status ServiceStatus `json:"status,omitempty"` +} + +// Verify that Service adheres to the appropriate interfaces. +var ( + // Check that Service may be validated and defaulted. + _ apis.Validatable = (*Service)(nil) + _ apis.Defaultable = (*Service)(nil) + + // Check that Service can be converted to higher versions. + _ apis.Convertible = (*Service)(nil) + + // Check that we can create OwnerReferences to a Service. + _ kmeta.OwnerRefable = (*Service)(nil) +) + +// ServiceSpec represents the configuration for the Service object. +// A Service's specification is the union of the specifications for a Route +// and Configuration. The Service restricts what can be expressed in these +// fields, e.g. the Route must reference the provided Configuration; +// however, these limitations also enable friendlier defaulting, +// e.g. Route never needs a Configuration name, and may be defaulted to +// the appropriate "run latest" spec. +type ServiceSpec struct { + // ServiceSpec inlines an unrestricted ConfigurationSpec. + ConfigurationSpec `json:",inline"` + + // ServiceSpec inlines RouteSpec and restricts/defaults its fields + // via webhook. In particular, this spec can only reference this + // Service's configuration and revisions (which also influences + // defaults). + RouteSpec `json:",inline"` +} + +// ConditionType represents a Service condition value +const ( + // ServiceConditionReady is set when the service is configured + // and has available backends ready to receive traffic. + ServiceConditionReady = apis.ConditionReady +) + +// ServiceStatus represents the Status stanza of the Service resource. +type ServiceStatus struct { + duckv1.Status `json:",inline"` + + // In addition to inlining ConfigurationSpec, we also inline the fields + // specific to ConfigurationStatus. + ConfigurationStatusFields `json:",inline"` + + // In addition to inlining RouteSpec, we also inline the fields + // specific to RouteStatus. + RouteStatusFields `json:",inline"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceList is a list of Service resources +type ServiceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []Service `json:"items"` +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/service_validation.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/service_validation.go new file mode 100644 index 0000000000..bbe5477bc8 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/service_validation.go @@ -0,0 +1,79 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + "strings" + + "knative.dev/pkg/apis" + "knative.dev/serving/pkg/apis/serving" + "knative.dev/serving/pkg/reconciler/route/config" +) + +// Validate makes sure that Service is properly configured. +func (s *Service) Validate(ctx context.Context) (errs *apis.FieldError) { + // If we are in a status sub resource update, the metadata and spec cannot change. + // So, to avoid rejecting controller status updates due to validations that may + // have changed (i.e. due to config-defaults changes), we elide the metadata and + // spec validation. + if !apis.IsInStatusUpdate(ctx) { + errs = errs.Also(serving.ValidateObjectMetadata(s.GetObjectMeta()).Also( + s.validateLabels().ViaField("labels")).ViaField("metadata")) + ctx = apis.WithinParent(ctx, s.ObjectMeta) + errs = errs.Also(s.Spec.Validate(apis.WithinSpec(ctx)).ViaField("spec")) + } + + errs = errs.Also(s.Status.Validate(apis.WithinStatus(ctx)).ViaField("status")) + + if apis.IsInUpdate(ctx) { + original := apis.GetBaseline(ctx).(*Service) + errs = errs.Also(apis.ValidateCreatorAndModifier(original.Spec, s.Spec, original.GetAnnotations(), + s.GetAnnotations(), serving.GroupName).ViaField("metadata.annotations")) + err := s.Spec.ConfigurationSpec.Template.VerifyNameChange(ctx, + original.Spec.ConfigurationSpec.Template) + errs = errs.Also(err.ViaField("spec.template")) + } + return errs +} + +// Validate implements apis.Validatable +func (ss *ServiceSpec) Validate(ctx context.Context) *apis.FieldError { + return ss.ConfigurationSpec.Validate(ctx).Also( + // Within the context of Service, the RouteSpec has a default + // configurationName. + ss.RouteSpec.Validate(WithDefaultConfigurationName(ctx))) +} + +// Validate implements apis.Validatable +func (ss *ServiceStatus) Validate(ctx context.Context) *apis.FieldError { + return ss.ConfigurationStatusFields.Validate(ctx).Also( + ss.RouteStatusFields.Validate(ctx)) +} + +// validateLabels function validates service labels +func (s *Service) validateLabels() (errs *apis.FieldError) { + for key, val := range s.GetLabels() { + switch { + case key == config.VisibilityLabelKey: + errs = errs.Also(validateClusterVisibilityLabel(val)) + case strings.HasPrefix(key, serving.GroupNamePrefix): + errs = errs.Also(apis.ErrInvalidKeyName(key, apis.CurrentField)) + } + } + return +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1/zz_generated.deepcopy.go b/vendor/knative.dev/serving/pkg/apis/serving/v1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..efdd513f96 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1/zz_generated.deepcopy.go @@ -0,0 +1,526 @@ +// +build !ignore_autogenerated + +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" + apis "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Configuration) DeepCopyInto(out *Configuration) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Configuration. +func (in *Configuration) DeepCopy() *Configuration { + if in == nil { + return nil + } + out := new(Configuration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Configuration) 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 *ConfigurationList) DeepCopyInto(out *ConfigurationList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Configuration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigurationList. +func (in *ConfigurationList) DeepCopy() *ConfigurationList { + if in == nil { + return nil + } + out := new(ConfigurationList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ConfigurationList) 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 *ConfigurationSpec) DeepCopyInto(out *ConfigurationSpec) { + *out = *in + in.Template.DeepCopyInto(&out.Template) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigurationSpec. +func (in *ConfigurationSpec) DeepCopy() *ConfigurationSpec { + if in == nil { + return nil + } + out := new(ConfigurationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigurationStatus) DeepCopyInto(out *ConfigurationStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + out.ConfigurationStatusFields = in.ConfigurationStatusFields + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigurationStatus. +func (in *ConfigurationStatus) DeepCopy() *ConfigurationStatus { + if in == nil { + return nil + } + out := new(ConfigurationStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigurationStatusFields) DeepCopyInto(out *ConfigurationStatusFields) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigurationStatusFields. +func (in *ConfigurationStatusFields) DeepCopy() *ConfigurationStatusFields { + if in == nil { + return nil + } + out := new(ConfigurationStatusFields) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Revision) DeepCopyInto(out *Revision) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Revision. +func (in *Revision) DeepCopy() *Revision { + if in == nil { + return nil + } + out := new(Revision) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Revision) 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 *RevisionList) DeepCopyInto(out *RevisionList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Revision, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RevisionList. +func (in *RevisionList) DeepCopy() *RevisionList { + if in == nil { + return nil + } + out := new(RevisionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RevisionList) 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 *RevisionSpec) DeepCopyInto(out *RevisionSpec) { + *out = *in + in.PodSpec.DeepCopyInto(&out.PodSpec) + if in.ContainerConcurrency != nil { + in, out := &in.ContainerConcurrency, &out.ContainerConcurrency + *out = new(int64) + **out = **in + } + if in.TimeoutSeconds != nil { + in, out := &in.TimeoutSeconds, &out.TimeoutSeconds + *out = new(int64) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RevisionSpec. +func (in *RevisionSpec) DeepCopy() *RevisionSpec { + if in == nil { + return nil + } + out := new(RevisionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RevisionStatus) DeepCopyInto(out *RevisionStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RevisionStatus. +func (in *RevisionStatus) DeepCopy() *RevisionStatus { + if in == nil { + return nil + } + out := new(RevisionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RevisionTemplateSpec) DeepCopyInto(out *RevisionTemplateSpec) { + *out = *in + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RevisionTemplateSpec. +func (in *RevisionTemplateSpec) DeepCopy() *RevisionTemplateSpec { + if in == nil { + return nil + } + out := new(RevisionTemplateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Route) DeepCopyInto(out *Route) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Route. +func (in *Route) DeepCopy() *Route { + if in == nil { + return nil + } + out := new(Route) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Route) 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 *RouteList) DeepCopyInto(out *RouteList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Route, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteList. +func (in *RouteList) DeepCopy() *RouteList { + if in == nil { + return nil + } + out := new(RouteList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RouteList) 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 *RouteSpec) DeepCopyInto(out *RouteSpec) { + *out = *in + if in.Traffic != nil { + in, out := &in.Traffic, &out.Traffic + *out = make([]TrafficTarget, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteSpec. +func (in *RouteSpec) DeepCopy() *RouteSpec { + if in == nil { + return nil + } + out := new(RouteSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteStatus) DeepCopyInto(out *RouteStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + in.RouteStatusFields.DeepCopyInto(&out.RouteStatusFields) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteStatus. +func (in *RouteStatus) DeepCopy() *RouteStatus { + if in == nil { + return nil + } + out := new(RouteStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteStatusFields) DeepCopyInto(out *RouteStatusFields) { + *out = *in + if in.URL != nil { + in, out := &in.URL, &out.URL + *out = new(apis.URL) + (*in).DeepCopyInto(*out) + } + if in.Address != nil { + in, out := &in.Address, &out.Address + *out = new(duckv1.Addressable) + (*in).DeepCopyInto(*out) + } + if in.Traffic != nil { + in, out := &in.Traffic, &out.Traffic + *out = make([]TrafficTarget, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteStatusFields. +func (in *RouteStatusFields) DeepCopy() *RouteStatusFields { + if in == nil { + return nil + } + out := new(RouteStatusFields) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Service) DeepCopyInto(out *Service) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Service. +func (in *Service) DeepCopy() *Service { + if in == nil { + return nil + } + out := new(Service) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Service) 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 *ServiceList) DeepCopyInto(out *ServiceList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Service, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceList. +func (in *ServiceList) DeepCopy() *ServiceList { + if in == nil { + return nil + } + out := new(ServiceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceList) 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 *ServiceSpec) DeepCopyInto(out *ServiceSpec) { + *out = *in + in.ConfigurationSpec.DeepCopyInto(&out.ConfigurationSpec) + in.RouteSpec.DeepCopyInto(&out.RouteSpec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceSpec. +func (in *ServiceSpec) DeepCopy() *ServiceSpec { + if in == nil { + return nil + } + out := new(ServiceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceStatus) DeepCopyInto(out *ServiceStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + out.ConfigurationStatusFields = in.ConfigurationStatusFields + in.RouteStatusFields.DeepCopyInto(&out.RouteStatusFields) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceStatus. +func (in *ServiceStatus) DeepCopy() *ServiceStatus { + if in == nil { + return nil + } + out := new(ServiceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficTarget) DeepCopyInto(out *TrafficTarget) { + *out = *in + if in.LatestRevision != nil { + in, out := &in.LatestRevision, &out.LatestRevision + *out = new(bool) + **out = **in + } + if in.Percent != nil { + in, out := &in.Percent, &out.Percent + *out = new(int64) + **out = **in + } + if in.URL != nil { + in, out := &in.URL, &out.URL + *out = new(apis.URL) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficTarget. +func (in *TrafficTarget) DeepCopy() *TrafficTarget { + if in == nil { + return nil + } + out := new(TrafficTarget) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_conversion.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_conversion.go index e9b4279313..a7d804a293 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_conversion.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_conversion.go @@ -21,6 +21,7 @@ import ( "fmt" "knative.dev/pkg/apis" + v1 "knative.dev/serving/pkg/apis/serving/v1" "knative.dev/serving/pkg/apis/serving/v1beta1" ) @@ -33,13 +34,19 @@ func (source *Configuration) ConvertUp(ctx context.Context, obj apis.Convertible return err } return source.Status.ConvertUp(ctx, &sink.Status) + case *v1.Configuration: + sink.ObjectMeta = source.ObjectMeta + if err := source.Spec.ConvertUp(ctx, &sink.Spec); err != nil { + return err + } + return source.Status.ConvertUp(ctx, &sink.Status) default: return fmt.Errorf("unknown version, got: %T", sink) } } // ConvertUp helps implement apis.Convertible -func (source *ConfigurationSpec) ConvertUp(ctx context.Context, sink *v1beta1.ConfigurationSpec) error { +func (source *ConfigurationSpec) ConvertUp(ctx context.Context, sink *v1.ConfigurationSpec) error { if source.DeprecatedBuild != nil { return ConvertErrorf("build", "build cannot be migrated forward.") } @@ -56,14 +63,14 @@ func (source *ConfigurationSpec) ConvertUp(ctx context.Context, sink *v1beta1.Co } // ConvertUp helps implement apis.Convertible -func (source *ConfigurationStatus) ConvertUp(ctx context.Context, sink *v1beta1.ConfigurationStatus) error { +func (source *ConfigurationStatus) ConvertUp(ctx context.Context, sink *v1.ConfigurationStatus) error { source.Status.ConvertTo(ctx, &sink.Status) return source.ConfigurationStatusFields.ConvertUp(ctx, &sink.ConfigurationStatusFields) } // ConvertUp helps implement apis.Convertible -func (source *ConfigurationStatusFields) ConvertUp(ctx context.Context, sink *v1beta1.ConfigurationStatusFields) error { +func (source *ConfigurationStatusFields) ConvertUp(ctx context.Context, sink *v1.ConfigurationStatusFields) error { sink.LatestReadyRevisionName = source.LatestReadyRevisionName sink.LatestCreatedRevisionName = source.LatestCreatedRevisionName return nil @@ -78,26 +85,32 @@ func (sink *Configuration) ConvertDown(ctx context.Context, obj apis.Convertible return err } return sink.Status.ConvertDown(ctx, source.Status) + case *v1.Configuration: + sink.ObjectMeta = source.ObjectMeta + if err := sink.Spec.ConvertDown(ctx, source.Spec); err != nil { + return err + } + return sink.Status.ConvertDown(ctx, source.Status) default: return fmt.Errorf("unknown version, got: %T", source) } } // ConvertDown helps implement apis.Convertible -func (sink *ConfigurationSpec) ConvertDown(ctx context.Context, source v1beta1.ConfigurationSpec) error { +func (sink *ConfigurationSpec) ConvertDown(ctx context.Context, source v1.ConfigurationSpec) error { sink.Template = &RevisionTemplateSpec{} return sink.Template.ConvertDown(ctx, source.Template) } // ConvertDown helps implement apis.Convertible -func (sink *ConfigurationStatus) ConvertDown(ctx context.Context, source v1beta1.ConfigurationStatus) error { +func (sink *ConfigurationStatus) ConvertDown(ctx context.Context, source v1.ConfigurationStatus) error { source.Status.ConvertTo(ctx, &sink.Status) return sink.ConfigurationStatusFields.ConvertDown(ctx, source.ConfigurationStatusFields) } // ConvertDown helps implement apis.Convertible -func (sink *ConfigurationStatusFields) ConvertDown(ctx context.Context, source v1beta1.ConfigurationStatusFields) error { +func (sink *ConfigurationStatusFields) ConvertDown(ctx context.Context, source v1.ConfigurationStatusFields) error { sink.LatestReadyRevisionName = source.LatestReadyRevisionName sink.LatestCreatedRevisionName = source.LatestCreatedRevisionName return nil diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_defaults.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_defaults.go index 0e6795def1..48e5ac2ff8 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_defaults.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_defaults.go @@ -21,7 +21,7 @@ import ( "knative.dev/pkg/apis" - "knative.dev/serving/pkg/apis/serving/v1beta1" + v1 "knative.dev/serving/pkg/apis/serving/v1" ) func (c *Configuration) SetDefaults(ctx context.Context) { @@ -30,11 +30,11 @@ func (c *Configuration) SetDefaults(ctx context.Context) { } func (cs *ConfigurationSpec) SetDefaults(ctx context.Context) { - if v1beta1.IsUpgradeViaDefaulting(ctx) { - beta := v1beta1.ConfigurationSpec{} - if cs.ConvertUp(ctx, &beta) == nil { + if v1.IsUpgradeViaDefaulting(ctx) { + v1 := v1.ConfigurationSpec{} + if cs.ConvertUp(ctx, &v1) == nil { alpha := ConfigurationSpec{} - if alpha.ConvertDown(ctx, beta) == nil { + if alpha.ConvertDown(ctx, v1) == nil { *cs = alpha } } diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_lifecycle.go index 338022a687..c0b4a66535 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_lifecycle.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_lifecycle.go @@ -20,7 +20,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime/schema" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" ) var confCondSet = apis.NewLivingConditionSet() @@ -112,6 +112,6 @@ func (cs *ConfigurationStatus) MarkLatestReadyDeleted() { "Revision %q was deleted.", cs.LatestReadyRevisionName) } -func (cs *ConfigurationStatus) duck() *duckv1beta1.Status { +func (cs *ConfigurationStatus) duck() *duckv1.Status { return &cs.Status } diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_types.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_types.go index 3d55854454..87addf0d52 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_types.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/configuration_types.go @@ -20,7 +20,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/kmeta" ) @@ -98,7 +98,7 @@ const ( ConfigurationConditionReady = apis.ConditionReady ) -// ConfigurationStatusFields holds all of the non-duckv1beta1.Status status fields of a Route. +// ConfigurationStatusFields holds all of the non-duckv1.Status status fields of a Route. // These are defined outline so that we can also inline them into Service, and more easily // copy them. type ConfigurationStatusFields struct { @@ -115,7 +115,7 @@ type ConfigurationStatusFields struct { // ConfigurationStatus communicates the observed state of the Configuration (from the controller). type ConfigurationStatus struct { - duckv1beta1.Status `json:",inline"` + duckv1.Status `json:",inline"` ConfigurationStatusFields `json:",inline"` } diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_conversion.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_conversion.go index 7851d8a75d..5c127e3016 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_conversion.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_conversion.go @@ -23,6 +23,7 @@ import ( corev1 "k8s.io/api/core/v1" "knative.dev/pkg/apis" "knative.dev/pkg/ptr" + v1 "knative.dev/serving/pkg/apis/serving/v1" "knative.dev/serving/pkg/apis/serving/v1beta1" ) @@ -39,18 +40,19 @@ func (source *Revision) ConvertUp(ctx context.Context, obj apis.Convertible) err } // ConvertUp helps implement apis.Convertible -func (source *RevisionTemplateSpec) ConvertUp(ctx context.Context, sink *v1beta1.RevisionTemplateSpec) error { +func (source *RevisionTemplateSpec) ConvertUp(ctx context.Context, sink *v1.RevisionTemplateSpec) error { sink.ObjectMeta = source.ObjectMeta return source.Spec.ConvertUp(ctx, &sink.Spec) } // ConvertUp helps implement apis.Convertible -func (source *RevisionSpec) ConvertUp(ctx context.Context, sink *v1beta1.RevisionSpec) error { - sink.ContainerConcurrency = v1beta1.RevisionContainerConcurrencyType( - source.ContainerConcurrency) +func (source *RevisionSpec) ConvertUp(ctx context.Context, sink *v1.RevisionSpec) error { if source.TimeoutSeconds != nil { sink.TimeoutSeconds = ptr.Int64(*source.TimeoutSeconds) } + if source.ContainerConcurrency != nil { + sink.ContainerConcurrency = ptr.Int64(*source.ContainerConcurrency) + } switch { case source.DeprecatedContainer != nil && len(source.Containers) > 0: return apis.ErrMultipleOneOf("container", "containers") @@ -75,7 +77,7 @@ func (source *RevisionSpec) ConvertUp(ctx context.Context, sink *v1beta1.Revisio } // ConvertUp helps implement apis.Convertible -func (source *RevisionStatus) ConvertUp(ctx context.Context, sink *v1beta1.RevisionStatus) { +func (source *RevisionStatus) ConvertUp(ctx context.Context, sink *v1.RevisionStatus) { source.Status.ConvertTo(ctx, &sink.Status) sink.ServiceName = source.ServiceName @@ -96,19 +98,19 @@ func (sink *Revision) ConvertDown(ctx context.Context, obj apis.Convertible) err } // ConvertDown helps implement apis.Convertible -func (sink *RevisionTemplateSpec) ConvertDown(ctx context.Context, source v1beta1.RevisionTemplateSpec) error { +func (sink *RevisionTemplateSpec) ConvertDown(ctx context.Context, source v1.RevisionTemplateSpec) error { sink.ObjectMeta = source.ObjectMeta return sink.Spec.ConvertDown(ctx, source.Spec) } // ConvertDown helps implement apis.Convertible -func (sink *RevisionSpec) ConvertDown(ctx context.Context, source v1beta1.RevisionSpec) error { +func (sink *RevisionSpec) ConvertDown(ctx context.Context, source v1.RevisionSpec) error { sink.RevisionSpec = *source.DeepCopy() return nil } // ConvertDown helps implement apis.Convertible -func (sink *RevisionStatus) ConvertDown(ctx context.Context, source v1beta1.RevisionStatus) { +func (sink *RevisionStatus) ConvertDown(ctx context.Context, source v1.RevisionStatus) { source.Status.ConvertTo(ctx, &sink.Status) sink.ServiceName = source.ServiceName diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_defaults.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_defaults.go index 035012306c..904abd8c2f 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_defaults.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_defaults.go @@ -21,8 +21,8 @@ import ( corev1 "k8s.io/api/core/v1" "knative.dev/pkg/apis" - - "knative.dev/serving/pkg/apis/serving/v1beta1" + "knative.dev/pkg/ptr" + v1 "knative.dev/serving/pkg/apis/serving/v1" ) func (r *Revision) SetDefaults(ctx context.Context) { @@ -30,20 +30,20 @@ func (r *Revision) SetDefaults(ctx context.Context) { } func (rs *RevisionSpec) SetDefaults(ctx context.Context) { - if v1beta1.IsUpgradeViaDefaulting(ctx) { - beta := v1beta1.RevisionSpec{} - if rs.ConvertUp(ctx, &beta) == nil { + if v1.IsUpgradeViaDefaulting(ctx) { + v1 := v1.RevisionSpec{} + if rs.ConvertUp(ctx, &v1) == nil { alpha := RevisionSpec{} - if alpha.ConvertDown(ctx, beta) == nil { + if alpha.ConvertDown(ctx, v1) == nil { *rs = alpha } } } // When ConcurrencyModel is specified but ContainerConcurrency - // is not (0), use the ConcurrencyModel value. - if rs.DeprecatedConcurrencyModel == DeprecatedRevisionRequestConcurrencyModelSingle && rs.ContainerConcurrency == 0 { - rs.ContainerConcurrency = 1 + // is not (`nil`), use the ConcurrencyModel value. + if rs.DeprecatedConcurrencyModel == DeprecatedRevisionRequestConcurrencyModelSingle && rs.ContainerConcurrency == nil { + rs.ContainerConcurrency = ptr.Int64(1) } // When the PodSpec has no containers, move the single Container diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_lifecycle.go index 2f84a5da95..13c26c5466 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_lifecycle.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_lifecycle.go @@ -21,10 +21,13 @@ import ( "strconv" "time" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime/schema" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" + av1alpha1 "knative.dev/serving/pkg/apis/autoscaling/v1alpha1" + "knative.dev/serving/pkg/apis/config" net "knative.dev/serving/pkg/apis/networking" "knative.dev/serving/pkg/apis/serving" ) @@ -79,6 +82,20 @@ func (rs *RevisionSpec) GetContainer() *corev1.Container { return &corev1.Container{} } +// GetContainerConcurrency returns the container concurrency. If +// container concurrency is not set, the default value will be returned. +// We use the original default (0) here for backwards compatibility. +// Previous versions of Knative equated unspecified and zero, so to avoid +// changing the value used by Revisions with unspecified values when a different +// default is configured, we use the original default instead of the configured +// default to remain safe across upgrades. +func (rs *RevisionSpec) GetContainerConcurrency() int64 { + if rs.ContainerConcurrency == nil { + return config.DefaultContainerConcurrency + } + return *rs.ContainerConcurrency +} + func (r *Revision) DeprecatedBuildRef() *corev1.ObjectReference { if r.Spec.DeprecatedBuildRef != nil { buildRef := r.Spec.DeprecatedBuildRef.DeepCopy() @@ -195,6 +212,33 @@ func (rs *RevisionStatus) MarkContainerMissing(message string) { revCondSet.Manage(rs).MarkFalse(RevisionConditionContainerHealthy, "ContainerMissing", message) } +// PropagateAutoscalerStatus propagates autoscaler's status to the revision's status. +func (rs *RevisionStatus) PropagateAutoscalerStatus(ps *av1alpha1.PodAutoscalerStatus) { + // Propagate the service name from the PA. + rs.ServiceName = ps.ServiceName + + // Reflect the PA status in our own. + cond := ps.GetCondition(av1alpha1.PodAutoscalerConditionReady) + if cond == nil { + rs.MarkActivating("Deploying", "") + return + } + + switch cond.Status { + case corev1.ConditionUnknown: + rs.MarkActivating(cond.Reason, cond.Message) + case corev1.ConditionFalse: + rs.MarkInactive(cond.Reason, cond.Message) + case corev1.ConditionTrue: + rs.MarkActive() + + // Precondition for PA being active is SKS being active and + // that entices that |service.endpoints| > 0. + rs.MarkResourcesAvailable() + rs.MarkContainerHealthy() + } +} + // RevisionContainerMissingMessage constructs the status message if a given image // cannot be pulled correctly. func RevisionContainerMissingMessage(image string, message string) string { @@ -267,6 +311,30 @@ func (r *Revision) GetLastPinned() (time.Time, error) { return time.Unix(secs, 0), nil } -func (rs *RevisionStatus) duck() *duckv1beta1.Status { +// IsReachable returns whether or not the revision can be reached by a route. +func (r *Revision) IsReachable() bool { + return r.ObjectMeta.Labels[serving.RouteLabelKey] != "" +} + +func (rs *RevisionStatus) duck() *duckv1.Status { return &rs.Status } + +// PropagateDeploymentStatus takes the Deployment status and applies its values +// to the Revision status. +func (rs *RevisionStatus) PropagateDeploymentStatus(original *appsv1.DeploymentStatus) { + ds := serving.TransformDeploymentStatus(original) + cond := ds.GetCondition(serving.DeploymentConditionReady) + if cond == nil { + return + } + + switch cond.Status { + case corev1.ConditionUnknown: + revCondSet.Manage(rs).MarkUnknown(RevisionConditionResourcesAvailable, cond.Reason, cond.Message) + case corev1.ConditionTrue: + revCondSet.Manage(rs).MarkTrue(RevisionConditionResourcesAvailable) + case corev1.ConditionFalse: + revCondSet.Manage(rs).MarkFalse(RevisionConditionResourcesAvailable, cond.Reason, cond.Message) + } +} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_types.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_types.go index cc1cc1c697..99704e971d 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_types.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_types.go @@ -20,10 +20,10 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/kmeta" - "knative.dev/serving/pkg/apis/serving/v1beta1" + v1 "knative.dev/serving/pkg/apis/serving/v1" ) // +genclient @@ -93,7 +93,7 @@ const ( // DeprecatedRevisionRequestConcurrencyModelType is an enumeration of the // concurrency models supported by a Revision. -// DEPRECATED in favor of RevisionContainerConcurrencyType. +// DEPRECATED in favor of an integer based ContainerConcurrency setting. // TODO(vagababov): retire completely in 0.9. type DeprecatedRevisionRequestConcurrencyModelType string @@ -110,7 +110,7 @@ const ( // RevisionSpec holds the desired state of the Revision (from the client). type RevisionSpec struct { - v1beta1.RevisionSpec `json:",inline"` + v1.RevisionSpec `json:",inline"` // DeprecatedGeneration was used prior in Kubernetes versions <1.11 // when metadata.generation was not being incremented by the api server @@ -173,7 +173,7 @@ const ( // RevisionStatus communicates the observed state of the Revision (from the controller). type RevisionStatus struct { - duckv1beta1.Status `json:",inline"` + duckv1.Status `json:",inline"` // ServiceName holds the name of a core Kubernetes Service resource that // load balances over the pods backing this Revision. diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_validation.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_validation.go index 8d6224d9b6..765ad15b7f 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_validation.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/revision_validation.go @@ -146,7 +146,9 @@ func (rs *RevisionSpec) Validate(ctx context.Context) *apis.FieldError { if err := rs.DeprecatedConcurrencyModel.Validate(ctx).ViaField("concurrencyModel"); err != nil { errs = errs.Also(err) } else { - errs = errs.Also(rs.ContainerConcurrency.Validate(ctx).ViaField("containerConcurrency")) + if rs.ContainerConcurrency != nil { + errs = errs.Also(serving.ValidateContainerConcurrency(rs.ContainerConcurrency).ViaField("containerConcurrency")) + } } if rs.TimeoutSeconds != nil { diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_conversion.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_conversion.go index 699fe79656..f7fa0ba319 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_conversion.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_conversion.go @@ -21,7 +21,9 @@ import ( "fmt" "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" duckv1alpha1 "knative.dev/pkg/apis/duck/v1alpha1" + v1 "knative.dev/serving/pkg/apis/serving/v1" "knative.dev/serving/pkg/apis/serving/v1beta1" ) @@ -38,8 +40,8 @@ func (source *Route) ConvertUp(ctx context.Context, obj apis.Convertible) error } // ConvertUp helps implement apis.Convertible -func (source *RouteSpec) ConvertUp(ctx context.Context, sink *v1beta1.RouteSpec) error { - sink.Traffic = make([]v1beta1.TrafficTarget, len(source.Traffic)) +func (source *RouteSpec) ConvertUp(ctx context.Context, sink *v1.RouteSpec) error { + sink.Traffic = make([]v1.TrafficTarget, len(source.Traffic)) for i := range source.Traffic { if err := source.Traffic[i].ConvertUp(ctx, &sink.Traffic[i]); err != nil { return err @@ -49,7 +51,7 @@ func (source *RouteSpec) ConvertUp(ctx context.Context, sink *v1beta1.RouteSpec) } // ConvertUp helps implement apis.Convertible -func (source *TrafficTarget) ConvertUp(ctx context.Context, sink *v1beta1.TrafficTarget) error { +func (source *TrafficTarget) ConvertUp(ctx context.Context, sink *v1.TrafficTarget) error { *sink = source.TrafficTarget switch { case source.Tag != "" && source.DeprecatedName != "": @@ -63,23 +65,26 @@ func (source *TrafficTarget) ConvertUp(ctx context.Context, sink *v1beta1.Traffi } // ConvertUp helps implement apis.Convertible -func (source *RouteStatus) ConvertUp(ctx context.Context, sink *v1beta1.RouteStatus) { +func (source *RouteStatus) ConvertUp(ctx context.Context, sink *v1.RouteStatus) { source.Status.ConvertTo(ctx, &sink.Status) source.RouteStatusFields.ConvertUp(ctx, &sink.RouteStatusFields) } // ConvertUp helps implement apis.Convertible -func (source *RouteStatusFields) ConvertUp(ctx context.Context, sink *v1beta1.RouteStatusFields) { +func (source *RouteStatusFields) ConvertUp(ctx context.Context, sink *v1.RouteStatusFields) { if source.URL != nil { sink.URL = source.URL.DeepCopy() } if source.Address != nil { - sink.Address = source.Address.Addressable.DeepCopy() + if sink.Address == nil { + sink.Address = &duckv1.Addressable{} + } + source.Address.ConvertUp(ctx, sink.Address) } - sink.Traffic = make([]v1beta1.TrafficTarget, len(source.Traffic)) + sink.Traffic = make([]v1.TrafficTarget, len(source.Traffic)) for i := range source.Traffic { source.Traffic[i].ConvertUp(ctx, &sink.Traffic[i]) } @@ -99,7 +104,7 @@ func (sink *Route) ConvertDown(ctx context.Context, obj apis.Convertible) error } // ConvertDown helps implement apis.Convertible -func (sink *RouteSpec) ConvertDown(ctx context.Context, source v1beta1.RouteSpec) { +func (sink *RouteSpec) ConvertDown(ctx context.Context, source v1.RouteSpec) { sink.Traffic = make([]TrafficTarget, len(source.Traffic)) for i := range source.Traffic { sink.Traffic[i].ConvertDown(ctx, source.Traffic[i]) @@ -107,27 +112,28 @@ func (sink *RouteSpec) ConvertDown(ctx context.Context, source v1beta1.RouteSpec } // ConvertDown helps implement apis.Convertible -func (sink *TrafficTarget) ConvertDown(ctx context.Context, source v1beta1.TrafficTarget) { +func (sink *TrafficTarget) ConvertDown(ctx context.Context, source v1.TrafficTarget) { sink.TrafficTarget = source } // ConvertDown helps implement apis.Convertible -func (sink *RouteStatus) ConvertDown(ctx context.Context, source v1beta1.RouteStatus) { +func (sink *RouteStatus) ConvertDown(ctx context.Context, source v1.RouteStatus) { source.Status.ConvertTo(ctx, &sink.Status) sink.RouteStatusFields.ConvertDown(ctx, source.RouteStatusFields) } // ConvertDown helps implement apis.Convertible -func (sink *RouteStatusFields) ConvertDown(ctx context.Context, source v1beta1.RouteStatusFields) { +func (sink *RouteStatusFields) ConvertDown(ctx context.Context, source v1.RouteStatusFields) { if source.URL != nil { sink.URL = source.URL.DeepCopy() } if source.Address != nil { - sink.Address = &duckv1alpha1.Addressable{ - Addressable: *source.Address, + if sink.Address == nil { + sink.Address = &duckv1alpha1.Addressable{} } + sink.Address.ConvertDown(ctx, source.Address) } sink.Traffic = make([]TrafficTarget, len(source.Traffic)) diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_defaults.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_defaults.go index ab089b2528..e4a5ddbd29 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_defaults.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_defaults.go @@ -21,7 +21,7 @@ import ( "knative.dev/pkg/apis" "knative.dev/pkg/ptr" - "knative.dev/serving/pkg/apis/serving/v1beta1" + v1 "knative.dev/serving/pkg/apis/serving/v1" ) func (r *Route) SetDefaults(ctx context.Context) { @@ -29,19 +29,19 @@ func (r *Route) SetDefaults(ctx context.Context) { } func (rs *RouteSpec) SetDefaults(ctx context.Context) { - if v1beta1.IsUpgradeViaDefaulting(ctx) { - beta := v1beta1.RouteSpec{} - if rs.ConvertUp(ctx, &beta) == nil { + if v1.IsUpgradeViaDefaulting(ctx) { + v1 := v1.RouteSpec{} + if rs.ConvertUp(ctx, &v1) == nil { alpha := RouteSpec{} - alpha.ConvertDown(ctx, beta) + alpha.ConvertDown(ctx, v1) *rs = alpha } } - if len(rs.Traffic) == 0 && v1beta1.HasDefaultConfigurationName(ctx) { + if len(rs.Traffic) == 0 && v1.HasDefaultConfigurationName(ctx) { rs.Traffic = []TrafficTarget{{ - TrafficTarget: v1beta1.TrafficTarget{ - Percent: 100, + TrafficTarget: v1.TrafficTarget{ + Percent: ptr.Int64(100), LatestRevision: ptr.Bool(true), }, }} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_lifecycle.go index a38828f886..401e18791f 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_lifecycle.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_lifecycle.go @@ -23,7 +23,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/serving/pkg/apis/networking/v1alpha1" ) @@ -170,6 +170,6 @@ func (rs *RouteStatus) PropagateIngressStatus(cs v1alpha1.IngressStatus) { } } -func (rs *RouteStatus) duck() *duckv1beta1.Status { +func (rs *RouteStatus) duck() *duckv1.Status { return &rs.Status } diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_types.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_types.go index b7495e9741..3dad80e7cc 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_types.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_types.go @@ -20,11 +20,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" duckv1alpha1 "knative.dev/pkg/apis/duck/v1alpha1" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" "knative.dev/pkg/kmeta" - "knative.dev/serving/pkg/apis/serving/v1beta1" + v1 "knative.dev/serving/pkg/apis/serving/v1" ) // +genclient @@ -70,9 +70,9 @@ type TrafficTarget struct { // +optional DeprecatedName string `json:"name,omitempty"` - // We inherit most of our fields by inlining the v1beta1 type. - // Ultimately all non-v1beta1 fields will be deprecated. - v1beta1.TrafficTarget `json:",inline"` + // We inherit most of our fields by inlining the v1 type. + // Ultimately all non-v1 fields will be deprecated. + v1.TrafficTarget `json:",inline"` } // RouteSpec holds the desired state of the Route (from the client). @@ -112,7 +112,7 @@ const ( RouteConditionCertificateProvisioned apis.ConditionType = "CertificateProvisioned" ) -// RouteStatusFields holds all of the non-duckv1beta1.Status status fields of a Route. +// RouteStatusFields holds all of the non-duckv1.Status status fields of a Route. // These are defined outline so that we can also inline them into Service, and more easily // copy them. type RouteStatusFields struct { @@ -147,7 +147,7 @@ type RouteStatusFields struct { // RouteStatus communicates the observed state of the Route (from the controller). type RouteStatus struct { - duckv1beta1.Status `json:",inline"` + duckv1.Status `json:",inline"` RouteStatusFields `json:",inline"` } diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_validation.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_validation.go index 685c7f77c7..83cf3aa8d3 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_validation.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/route_validation.go @@ -45,12 +45,14 @@ func (rs *RouteSpec) Validate(ctx context.Context) *apis.FieldError { // Track the targets of named TrafficTarget entries (to detect duplicates). trafficMap := make(map[string]diagnostic) - percentSum := 0 + percentSum := int64(0) for i, tt := range rs.Traffic { - // Delegate to the v1beta1 validation. + // Delegate to the v1 validation. errs = errs.Also(tt.TrafficTarget.Validate(ctx).ViaFieldIndex("traffic", i)) - percentSum += tt.Percent + if tt.Percent != nil { + percentSum += *tt.Percent + } if tt.DeprecatedName != "" && tt.Tag != "" { errs = errs.Also(apis.ErrMultipleOneOf("name", "tag"). diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_conversion.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_conversion.go index d4d42aafeb..c4a799a18e 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_conversion.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_conversion.go @@ -22,6 +22,7 @@ import ( "knative.dev/pkg/apis" "knative.dev/pkg/ptr" + v1 "knative.dev/serving/pkg/apis/serving/v1" "knative.dev/serving/pkg/apis/serving/v1beta1" ) @@ -34,18 +35,24 @@ func (source *Service) ConvertUp(ctx context.Context, obj apis.Convertible) erro return err } return source.Status.ConvertUp(ctx, &sink.Status) + case *v1.Service: + sink.ObjectMeta = source.ObjectMeta + if err := source.Spec.ConvertUp(ctx, &sink.Spec); err != nil { + return err + } + return source.Status.ConvertUp(ctx, &sink.Status) default: return fmt.Errorf("unknown version, got: %T", sink) } } // ConvertUp helps implement apis.Convertible -func (source *ServiceSpec) ConvertUp(ctx context.Context, sink *v1beta1.ServiceSpec) error { +func (source *ServiceSpec) ConvertUp(ctx context.Context, sink *v1.ServiceSpec) error { switch { case source.DeprecatedRunLatest != nil: - sink.RouteSpec = v1beta1.RouteSpec{ - Traffic: []v1beta1.TrafficTarget{{ - Percent: 100, + sink.RouteSpec = v1.RouteSpec{ + Traffic: []v1.TrafficTarget{{ + Percent: ptr.Int64(100), LatestRevision: ptr.Bool(true), }}, } @@ -53,29 +60,29 @@ func (source *ServiceSpec) ConvertUp(ctx context.Context, sink *v1beta1.ServiceS case source.DeprecatedRelease != nil: if len(source.DeprecatedRelease.Revisions) == 2 { - sink.RouteSpec = v1beta1.RouteSpec{ - Traffic: []v1beta1.TrafficTarget{{ + sink.RouteSpec = v1.RouteSpec{ + Traffic: []v1.TrafficTarget{{ RevisionName: source.DeprecatedRelease.Revisions[0], - Percent: 100 - source.DeprecatedRelease.RolloutPercent, + Percent: ptr.Int64(int64(100 - source.DeprecatedRelease.RolloutPercent)), Tag: "current", }, { RevisionName: source.DeprecatedRelease.Revisions[1], - Percent: source.DeprecatedRelease.RolloutPercent, + Percent: ptr.Int64(int64(source.DeprecatedRelease.RolloutPercent)), Tag: "candidate", }, { - Percent: 0, + Percent: nil, Tag: "latest", LatestRevision: ptr.Bool(true), }}, } } else { - sink.RouteSpec = v1beta1.RouteSpec{ - Traffic: []v1beta1.TrafficTarget{{ + sink.RouteSpec = v1.RouteSpec{ + Traffic: []v1.TrafficTarget{{ RevisionName: source.DeprecatedRelease.Revisions[0], - Percent: 100, + Percent: ptr.Int64(100), Tag: "current", }, { - Percent: 0, + Percent: nil, Tag: "latest", LatestRevision: ptr.Bool(true), }}, @@ -90,10 +97,10 @@ func (source *ServiceSpec) ConvertUp(ctx context.Context, sink *v1beta1.ServiceS return source.DeprecatedRelease.Configuration.ConvertUp(ctx, &sink.ConfigurationSpec) case source.DeprecatedPinned != nil: - sink.RouteSpec = v1beta1.RouteSpec{ - Traffic: []v1beta1.TrafficTarget{{ + sink.RouteSpec = v1.RouteSpec{ + Traffic: []v1.TrafficTarget{{ RevisionName: source.DeprecatedPinned.RevisionName, - Percent: 100, + Percent: ptr.Int64(100), }}, } return source.DeprecatedPinned.Configuration.ConvertUp(ctx, &sink.ConfigurationSpec) @@ -108,7 +115,7 @@ func (source *ServiceSpec) ConvertUp(ctx context.Context, sink *v1beta1.ServiceS } // ConvertUp helps implement apis.Convertible -func (source *ServiceStatus) ConvertUp(ctx context.Context, sink *v1beta1.ServiceStatus) error { +func (source *ServiceStatus) ConvertUp(ctx context.Context, sink *v1.ServiceStatus) error { source.Status.ConvertTo(ctx, &sink.Status) source.RouteStatusFields.ConvertUp(ctx, &sink.RouteStatusFields) @@ -124,19 +131,25 @@ func (sink *Service) ConvertDown(ctx context.Context, obj apis.Convertible) erro return err } return sink.Status.ConvertDown(ctx, source.Status) + case *v1.Service: + sink.ObjectMeta = source.ObjectMeta + if err := sink.Spec.ConvertDown(ctx, source.Spec); err != nil { + return err + } + return sink.Status.ConvertDown(ctx, source.Status) default: return fmt.Errorf("unknown version, got: %T", source) } } // ConvertDown helps implement apis.Convertible -func (sink *ServiceSpec) ConvertDown(ctx context.Context, source v1beta1.ServiceSpec) error { +func (sink *ServiceSpec) ConvertDown(ctx context.Context, source v1.ServiceSpec) error { sink.RouteSpec.ConvertDown(ctx, source.RouteSpec) return sink.ConfigurationSpec.ConvertDown(ctx, source.ConfigurationSpec) } // ConvertDown helps implement apis.Convertible -func (sink *ServiceStatus) ConvertDown(ctx context.Context, source v1beta1.ServiceStatus) error { +func (sink *ServiceStatus) ConvertDown(ctx context.Context, source v1.ServiceStatus) error { source.Status.ConvertTo(ctx, &sink.Status) sink.RouteStatusFields.ConvertDown(ctx, source.RouteStatusFields) diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_defaults.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_defaults.go index 484b45c1e5..5346bfab75 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_defaults.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_defaults.go @@ -23,7 +23,7 @@ import ( "knative.dev/pkg/apis" "knative.dev/serving/pkg/apis/serving" - "knative.dev/serving/pkg/apis/serving/v1beta1" + v1 "knative.dev/serving/pkg/apis/serving/v1" ) func (s *Service) SetDefaults(ctx context.Context) { @@ -51,11 +51,11 @@ func (s *Service) SetDefaults(ctx context.Context) { } func (ss *ServiceSpec) SetDefaults(ctx context.Context) { - if v1beta1.IsUpgradeViaDefaulting(ctx) { - beta := v1beta1.ServiceSpec{} - if ss.ConvertUp(ctx, &beta) == nil { + if v1.IsUpgradeViaDefaulting(ctx) { + v1 := v1.ServiceSpec{} + if ss.ConvertUp(ctx, &v1) == nil { alpha := ServiceSpec{} - if alpha.ConvertDown(ctx, beta) == nil { + if alpha.ConvertDown(ctx, v1) == nil { *ss = alpha } } @@ -70,6 +70,6 @@ func (ss *ServiceSpec) SetDefaults(ctx context.Context) { } else if ss.DeprecatedManual != nil { } else { ss.ConfigurationSpec.SetDefaults(ctx) - ss.RouteSpec.SetDefaults(v1beta1.WithDefaultConfigurationName(ctx)) + ss.RouteSpec.SetDefaults(v1.WithDefaultConfigurationName(ctx)) } } diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_lifecycle.go index 76402e6d93..168b5fb4cc 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_lifecycle.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_lifecycle.go @@ -23,7 +23,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" ) var serviceCondSet = apis.NewLivingConditionSet( @@ -156,6 +156,6 @@ func (ss *ServiceStatus) PropagateRouteStatus(rs *RouteStatus) { } } -func (ss *ServiceStatus) duck() *duckv1beta1.Status { +func (ss *ServiceStatus) duck() *duckv1.Status { return &ss.Status } diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_types.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_types.go index 8f21ff6120..ece0c5f9c6 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_types.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_types.go @@ -20,7 +20,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/pkg/kmeta" ) @@ -176,7 +176,7 @@ const ( // ServiceStatus represents the Status stanza of the Service resource. type ServiceStatus struct { - duckv1beta1.Status `json:",inline"` + duckv1.Status `json:",inline"` RouteStatusFields `json:",inline"` diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_validation.go b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_validation.go index f9a0352b43..af4f4c74ab 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_validation.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1alpha1/service_validation.go @@ -25,7 +25,7 @@ import ( "knative.dev/pkg/apis" "knative.dev/serving/pkg/apis/serving" - "knative.dev/serving/pkg/apis/serving/v1beta1" + v1 "knative.dev/serving/pkg/apis/serving/v1" ) // Validate validates the fields belonging to Service @@ -121,7 +121,7 @@ func (ss *ServiceSpec) Validate(ctx context.Context) *apis.FieldError { errs = errs.Also(ss.RouteSpec.Validate( // Within the context of Service, the RouteSpec has a default // configurationName. - v1beta1.WithDefaultConfigurationName(ctx))) + v1.WithDefaultConfigurationName(ctx))) } if len(set) > 1 { diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_defaults.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_defaults.go index 926e3c09dd..5c9808a379 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_defaults.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_defaults.go @@ -27,8 +27,3 @@ func (c *Configuration) SetDefaults(ctx context.Context) { ctx = apis.WithinParent(ctx, c.ObjectMeta) c.Spec.SetDefaults(apis.WithinSpec(ctx)) } - -// SetDefaults implements apis.Defaultable -func (cs *ConfigurationSpec) SetDefaults(ctx context.Context) { - cs.Template.SetDefaults(ctx) -} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_lifecycle.go index 2a937bfc0a..b2b1297b82 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_lifecycle.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_lifecycle.go @@ -16,20 +16,9 @@ limitations under the License. package v1beta1 -import ( - "k8s.io/apimachinery/pkg/runtime/schema" - - "knative.dev/pkg/apis" -) - -var configurationCondSet = apis.NewLivingConditionSet() +import "k8s.io/apimachinery/pkg/runtime/schema" // GetGroupVersionKind returns the GroupVersionKind. func (r *Configuration) GetGroupVersionKind() schema.GroupVersionKind { return SchemeGroupVersion.WithKind("Configuration") } - -// IsReady returns if the configuration is ready to serve the requested configuration. -func (cs *ConfigurationStatus) IsReady() bool { - return configurationCondSet.Manage(cs).IsHappy() -} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_types.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_types.go index accf0ec6a2..344e43286a 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_types.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_types.go @@ -19,8 +19,8 @@ package v1beta1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" "knative.dev/pkg/kmeta" + v1 "knative.dev/serving/pkg/apis/serving/v1" ) // +genclient @@ -37,10 +37,10 @@ type Configuration struct { metav1.ObjectMeta `json:"metadata,omitempty"` // +optional - Spec ConfigurationSpec `json:"spec,omitempty"` + Spec v1.ConfigurationSpec `json:"spec,omitempty"` // +optional - Status ConfigurationStatus `json:"status,omitempty"` + Status v1.ConfigurationStatus `json:"status,omitempty"` } // Verify that Configuration adheres to the appropriate interfaces. @@ -56,41 +56,12 @@ var ( _ kmeta.OwnerRefable = (*Configuration)(nil) ) -// ConfigurationSpec holds the desired state of the Configuration (from the client). -type ConfigurationSpec struct { - // Template holds the latest specification for the Revision to be stamped out. - // +optional - Template RevisionTemplateSpec `json:"template"` -} - const ( // ConfigurationConditionReady is set when the configuration's latest // underlying revision has reported readiness. ConfigurationConditionReady = apis.ConditionReady ) -// ConfigurationStatusFields holds the fields of Configuration's status that -// are not generally shared. This is defined separately and inlined so that -// other types can readily consume these fields via duck typing. -type ConfigurationStatusFields struct { - // LatestReadyRevisionName holds the name of the latest Revision stamped out - // from this Configuration that has had its "Ready" condition become "True". - // +optional - LatestReadyRevisionName string `json:"latestReadyRevisionName,omitempty"` - - // LatestCreatedRevisionName is the last revision that was created from this - // Configuration. It might not be ready yet, for that use LatestReadyRevisionName. - // +optional - LatestCreatedRevisionName string `json:"latestCreatedRevisionName,omitempty"` -} - -// ConfigurationStatus communicates the observed state of the Configuration (from the controller). -type ConfigurationStatus struct { - duckv1beta1.Status `json:",inline"` - - ConfigurationStatusFields `json:",inline"` -} - // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // ConfigurationList is a list of Configuration resources diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_validation.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_validation.go index ff7b62c9c9..98ed1129dd 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_validation.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/configuration_validation.go @@ -51,31 +51,16 @@ func (c *Configuration) Validate(ctx context.Context) (errs *apis.FieldError) { return errs } -// Validate implements apis.Validatable -func (cs *ConfigurationSpec) Validate(ctx context.Context) *apis.FieldError { - return cs.Template.Validate(ctx).ViaField("template") -} - -// Validate implements apis.Validatable -func (cs *ConfigurationStatus) Validate(ctx context.Context) *apis.FieldError { - return cs.ConfigurationStatusFields.Validate(ctx) -} - -// Validate implements apis.Validatable -func (csf *ConfigurationStatusFields) Validate(ctx context.Context) *apis.FieldError { - return nil -} - // validateLabels function validates configuration labels func (c *Configuration) validateLabels() (errs *apis.FieldError) { for key, val := range c.GetLabels() { switch { case key == config.VisibilityLabelKey: - errs = errs.Also(validateClusterVisibilityLabel(val)) + errs = errs.Also(serving.ValidateClusterVisibilityLabel(val)) case key == serving.RouteLabelKey: case key == serving.ServiceLabelKey: errs = errs.Also(verifyLabelOwnerRef(val, serving.ServiceLabelKey, "Service", c.GetOwnerReferences())) - case strings.HasPrefix(key, groupNamePrefix): + case strings.HasPrefix(key, serving.GroupNamePrefix): errs = errs.Also(apis.ErrInvalidKeyName(key, apis.CurrentField)) } } diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/register.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/register.go index 7e7b4297d8..1e8d182282 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/register.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/register.go @@ -24,9 +24,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" ) -// GroupNamePrefix is the prefix for label key and annotation key -const groupNamePrefix = serving.GroupName + "/" - // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: serving.GroupName, Version: "v1beta1"} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_defaults.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_defaults.go index 714a5fc61a..4a00953945 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_defaults.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_defaults.go @@ -18,80 +18,9 @@ package v1beta1 import ( "context" - - corev1 "k8s.io/api/core/v1" - - "knative.dev/serving/pkg/apis/config" ) // SetDefaults implements apis.Defaultable func (r *Revision) SetDefaults(ctx context.Context) { r.Spec.SetDefaults(ctx) } - -// SetDefaults implements apis.Defaultable -func (rts *RevisionTemplateSpec) SetDefaults(ctx context.Context) { - rts.Spec.SetDefaults(ctx) -} - -// SetDefaults implements apis.Defaultable -func (rs *RevisionSpec) SetDefaults(ctx context.Context) { - cfg := config.FromContextOrDefaults(ctx) - - // Default TimeoutSeconds based on our configmap - if rs.TimeoutSeconds == nil { - ts := cfg.Defaults.RevisionTimeoutSeconds - rs.TimeoutSeconds = &ts - } - - for idx := range rs.PodSpec.Containers { - if rs.PodSpec.Containers[idx].Name == "" { - rs.PodSpec.Containers[idx].Name = cfg.Defaults.UserContainerName(ctx) - } - - if rs.PodSpec.Containers[idx].Resources.Requests == nil { - rs.PodSpec.Containers[idx].Resources.Requests = corev1.ResourceList{} - } - if _, ok := rs.PodSpec.Containers[idx].Resources.Requests[corev1.ResourceCPU]; !ok { - if rsrc := cfg.Defaults.RevisionCPURequest; rsrc != nil { - rs.PodSpec.Containers[idx].Resources.Requests[corev1.ResourceCPU] = *rsrc - } - } - if _, ok := rs.PodSpec.Containers[idx].Resources.Requests[corev1.ResourceMemory]; !ok { - if rsrc := cfg.Defaults.RevisionMemoryRequest; rsrc != nil { - rs.PodSpec.Containers[idx].Resources.Requests[corev1.ResourceMemory] = *rsrc - } - } - - if rs.PodSpec.Containers[idx].Resources.Limits == nil { - rs.PodSpec.Containers[idx].Resources.Limits = corev1.ResourceList{} - } - if _, ok := rs.PodSpec.Containers[idx].Resources.Limits[corev1.ResourceCPU]; !ok { - if rsrc := cfg.Defaults.RevisionCPULimit; rsrc != nil { - rs.PodSpec.Containers[idx].Resources.Limits[corev1.ResourceCPU] = *rsrc - } - } - if _, ok := rs.PodSpec.Containers[idx].Resources.Limits[corev1.ResourceMemory]; !ok { - if rsrc := cfg.Defaults.RevisionMemoryLimit; rsrc != nil { - rs.PodSpec.Containers[idx].Resources.Limits[corev1.ResourceMemory] = *rsrc - } - } - if rs.PodSpec.Containers[idx].ReadinessProbe == nil { - rs.PodSpec.Containers[idx].ReadinessProbe = &corev1.Probe{} - } - if rs.PodSpec.Containers[idx].ReadinessProbe.TCPSocket == nil && - rs.PodSpec.Containers[idx].ReadinessProbe.HTTPGet == nil && - rs.PodSpec.Containers[idx].ReadinessProbe.Exec == nil { - rs.PodSpec.Containers[idx].ReadinessProbe.TCPSocket = &corev1.TCPSocketAction{} - } - - if rs.PodSpec.Containers[idx].ReadinessProbe.SuccessThreshold == 0 { - rs.PodSpec.Containers[idx].ReadinessProbe.SuccessThreshold = 1 - } - - vms := rs.PodSpec.Containers[idx].VolumeMounts - for i := range vms { - vms[i].ReadOnly = true - } - } -} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_lifecycle.go index 27672d5930..24f994bccf 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_lifecycle.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_lifecycle.go @@ -33,8 +33,3 @@ var revisionCondSet = apis.NewLivingConditionSet() func (r *Revision) GetGroupVersionKind() schema.GroupVersionKind { return SchemeGroupVersion.WithKind("Revision") } - -// IsReady returns if the revision is ready to serve the requested configuration. -func (rs *RevisionStatus) IsReady() bool { - return revisionCondSet.Manage(rs).IsHappy() -} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_types.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_types.go index d6365a4f41..fe72a4471d 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_types.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_types.go @@ -17,11 +17,10 @@ limitations under the License. package v1beta1 import ( - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" "knative.dev/pkg/kmeta" + v1 "knative.dev/serving/pkg/apis/serving/v1" ) // +genclient @@ -38,10 +37,10 @@ type Revision struct { metav1.ObjectMeta `json:"metadata,omitempty"` // +optional - Spec RevisionSpec `json:"spec,omitempty"` + Spec v1.RevisionSpec `json:"spec,omitempty"` // +optional - Status RevisionStatus `json:"status,omitempty"` + Status v1.RevisionStatus `json:"status,omitempty"` } // Verify that Revision adheres to the appropriate interfaces. @@ -57,73 +56,12 @@ var ( _ kmeta.OwnerRefable = (*Revision)(nil) ) -// RevisionTemplateSpec describes the data a revision should have when created from a template. -// Based on: https://github.com/kubernetes/api/blob/e771f807/core/v1/types.go#L3179-L3190 -type RevisionTemplateSpec struct { - // +optional - metav1.ObjectMeta `json:"metadata,omitempty"` - - // +optional - Spec RevisionSpec `json:"spec,omitempty"` -} - -// RevisionContainerConcurrencyType is an integer expressing the maximum number of -// in-flight (concurrent) requests. -type RevisionContainerConcurrencyType int64 - -const ( - // RevisionContainerConcurrencyMax is the maximum configurable - // container concurrency. - RevisionContainerConcurrencyMax RevisionContainerConcurrencyType = 1000 -) - -// RevisionSpec holds the desired state of the Revision (from the client). -type RevisionSpec struct { - corev1.PodSpec `json:",inline"` - - // ContainerConcurrency specifies the maximum allowed in-flight (concurrent) - // requests per container of the Revision. Defaults to `0` which means - // concurrency to the application is not limited, and the system decides the - // target concurrency for the autoscaler. - // +optional - ContainerConcurrency RevisionContainerConcurrencyType `json:"containerConcurrency,omitempty"` - - // TimeoutSeconds holds the max duration the instance is allowed for - // responding to a request. If unspecified, a system default will - // be provided. - // +optional - TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty"` -} - const ( // RevisionConditionReady is set when the revision is starting to materialize // runtime resources, and becomes true when those resources are ready. RevisionConditionReady = apis.ConditionReady ) -// RevisionStatus communicates the observed state of the Revision (from the controller). -type RevisionStatus struct { - duckv1beta1.Status `json:",inline"` - - // ServiceName holds the name of a core Kubernetes Service resource that - // load balances over the pods backing this Revision. - // +optional - ServiceName string `json:"serviceName,omitempty"` - - // LogURL specifies the generated logging url for this particular revision - // based on the revision url template specified in the controller's config. - // +optional - LogURL string `json:"logUrl,omitempty"` - - // ImageDigest holds the resolved digest for the image specified - // within .Spec.Container.Image. The digest is resolved during the creation - // of Revision. This field holds the digest value regardless of whether - // a tag or digest was originally specified in the Container object. It - // may be empty if the image comes from a registry listed to skip resolution. - // +optional - ImageDigest string `json:"imageDigest,omitempty"` -} - // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // RevisionList is a list of Revision resources diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_validation.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_validation.go index 56056f2225..43fe2f6f26 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_validation.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/revision_validation.go @@ -18,12 +18,10 @@ package v1beta1 import ( "context" - "fmt" "strings" "knative.dev/pkg/apis" "knative.dev/pkg/kmp" - "knative.dev/serving/pkg/apis/autoscaling" "knative.dev/serving/pkg/apis/serving" ) @@ -55,87 +53,6 @@ func (r *Revision) Validate(ctx context.Context) *apis.FieldError { return errs } -// Validate implements apis.Validatable -func (rts *RevisionTemplateSpec) Validate(ctx context.Context) *apis.FieldError { - errs := rts.Spec.Validate(apis.WithinSpec(ctx)).ViaField("spec") - errs = errs.Also(autoscaling.ValidateAnnotations(rts.GetAnnotations()).ViaField("metadata.annotations")) - - // If the RevisionTemplateSpec has a name specified, then check that - // it follows the requirements on the name. - if rts.Name != "" { - var prefix string - if om := apis.ParentMeta(ctx); om.Name == "" { - prefix = om.GenerateName - } else { - prefix = om.Name + "-" - } - - if !strings.HasPrefix(rts.Name, prefix) { - errs = errs.Also(apis.ErrInvalidValue( - fmt.Sprintf("%q must have prefix %q", rts.Name, prefix), - "metadata.name")) - } - } - - errs = errs.Also(serving.ValidateQueueSidecarAnnotation(rts.Annotations).ViaField("metadata.annotations")) - return errs -} - -// VerifyNameChange checks that if a user brought their own name previously that it -// changes at the appropriate times. -func (current *RevisionTemplateSpec) VerifyNameChange(ctx context.Context, og RevisionTemplateSpec) *apis.FieldError { - if current.Name == "" { - // We only check that Name changes when the RevisionTemplate changes. - return nil - } - if current.Name != og.Name { - // The name changed, so we're good. - return nil - } - - if diff, err := kmp.ShortDiff(&og, current); err != nil { - return &apis.FieldError{ - Message: "Failed to diff RevisionTemplate", - Paths: []string{apis.CurrentField}, - Details: err.Error(), - } - } else if diff != "" { - return &apis.FieldError{ - Message: "Saw the following changes without a name change (-old +new)", - Paths: []string{apis.CurrentField}, - Details: diff, - } - } - return nil -} - -// Validate implements apis.Validatable -func (rs *RevisionSpec) Validate(ctx context.Context) *apis.FieldError { - errs := rs.ContainerConcurrency.Validate(ctx).ViaField("containerConcurrency") - - errs = errs.Also(serving.ValidatePodSpec(rs.PodSpec)) - - if rs.TimeoutSeconds != nil { - errs = errs.Also(serving.ValidateTimeoutSeconds(ctx, *rs.TimeoutSeconds)) - } - - return errs -} - -// Validate implements apis.Validatable. -func (cc RevisionContainerConcurrencyType) Validate(ctx context.Context) *apis.FieldError { - if cc < 0 || cc > RevisionContainerConcurrencyMax { - return apis.ErrOutOfBoundsValue( - cc, 0, RevisionContainerConcurrencyMax, apis.CurrentField) - } - return nil -} - -// Validate implements apis.Validatable -func (rs *RevisionStatus) Validate(ctx context.Context) *apis.FieldError { - return nil -} - // ValidateLabels function validates service labels func (r *Revision) ValidateLabels() (errs *apis.FieldError) { for key, val := range r.GetLabels() { @@ -143,7 +60,7 @@ func (r *Revision) ValidateLabels() (errs *apis.FieldError) { case key == serving.RouteLabelKey || key == serving.ServiceLabelKey || key == serving.ConfigurationGenerationLabelKey: case key == serving.ConfigurationLabelKey: errs = errs.Also(verifyLabelOwnerRef(val, serving.ConfigurationLabelKey, "Configuration", r.GetOwnerReferences())) - case strings.HasPrefix(key, groupNamePrefix): + case strings.HasPrefix(key, serving.GroupNamePrefix): errs = errs.Also(apis.ErrInvalidKeyName(key, "")) } } diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_defaults.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_defaults.go index abb58c74e5..8f793619f4 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_defaults.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_defaults.go @@ -20,32 +20,9 @@ import ( "context" "knative.dev/pkg/apis" - "knative.dev/pkg/ptr" ) // SetDefaults implements apis.Defaultable func (r *Route) SetDefaults(ctx context.Context) { r.Spec.SetDefaults(apis.WithinSpec(ctx)) } - -// SetDefaults implements apis.Defaultable -func (rs *RouteSpec) SetDefaults(ctx context.Context) { - if len(rs.Traffic) == 0 && HasDefaultConfigurationName(ctx) { - rs.Traffic = []TrafficTarget{{ - Percent: 100, - LatestRevision: ptr.Bool(true), - }} - } - - for idx := range rs.Traffic { - rs.Traffic[idx].SetDefaults(ctx) - } -} - -// SetDefaults implements apis.Defaultable -func (tt *TrafficTarget) SetDefaults(ctx context.Context) { - if tt.LatestRevision == nil { - sense := (tt.RevisionName == "") - tt.LatestRevision = &sense - } -} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_lifecycle.go index ff50561113..f4b93117da 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_lifecycle.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_lifecycle.go @@ -16,20 +16,9 @@ limitations under the License. package v1beta1 -import ( - "k8s.io/apimachinery/pkg/runtime/schema" - - "knative.dev/pkg/apis" -) - -var routeCondSet = apis.NewLivingConditionSet() +import "k8s.io/apimachinery/pkg/runtime/schema" // GetGroupVersionKind returns the GroupVersionKind. func (r *Route) GetGroupVersionKind() schema.GroupVersionKind { return SchemeGroupVersion.WithKind("Route") } - -// IsReady returns if the route is ready to serve the requested configuration. -func (rs *RouteStatus) IsReady() bool { - return routeCondSet.Manage(rs).IsHappy() -} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_types.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_types.go index c988fbaa71..800ed30e51 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_types.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_types.go @@ -20,8 +20,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" "knative.dev/pkg/kmeta" + v1 "knative.dev/serving/pkg/apis/serving/v1" ) // +genclient @@ -40,11 +40,11 @@ type Route struct { // Spec holds the desired state of the Route (from the client). // +optional - Spec RouteSpec `json:"spec,omitempty"` + Spec v1.RouteSpec `json:"spec,omitempty"` // Status communicates the observed state of the Route (from the controller). // +optional - Status RouteStatus `json:"status,omitempty"` + Status v1.RouteStatus `json:"status,omitempty"` } // Verify that Route adheres to the appropriate interfaces. @@ -60,89 +60,12 @@ var ( _ kmeta.OwnerRefable = (*Route)(nil) ) -// TrafficTarget holds a single entry of the routing table for a Route. -type TrafficTarget struct { - // Tag is optionally used to expose a dedicated url for referencing - // this target exclusively. - // +optional - // TODO(mattmoor): Discuss alternative naming options. - Tag string `json:"tag,omitempty"` - - // RevisionName of a specific revision to which to send this portion of - // traffic. This is mutually exclusive with ConfigurationName. - // +optional - RevisionName string `json:"revisionName,omitempty"` - - // ConfigurationName of a configuration to whose latest revision we will send - // this portion of traffic. When the "status.latestReadyRevisionName" of the - // referenced configuration changes, we will automatically migrate traffic - // from the prior "latest ready" revision to the new one. This field is never - // set in Route's status, only its spec. This is mutually exclusive with - // RevisionName. - // +optional - ConfigurationName string `json:"configurationName,omitempty"` - - // LatestRevision may be optionally provided to indicate that the latest - // ready Revision of the Configuration should be used for this traffic - // target. When provided LatestRevision must be true if RevisionName is - // empty; it must be false when RevisionName is non-empty. - // +optional - LatestRevision *bool `json:"latestRevision,omitempty"` - - // Percent specifies percent of the traffic to this Revision or Configuration. - // This defaults to zero if unspecified. - // +optional - Percent int `json:"percent"` - - // URL displays the URL for accessing named traffic targets. URL is displayed in - // status, and is disallowed on spec. URL must contain a scheme (e.g. http://) and - // a hostname, but may not contain anything else (e.g. basic auth, url path, etc.) - // +optional - URL *apis.URL `json:"url,omitempty"` -} - -// RouteSpec holds the desired state of the Route (from the client). -type RouteSpec struct { - // Traffic specifies how to distribute traffic over a collection of - // revisions and configurations. - // +optional - Traffic []TrafficTarget `json:"traffic,omitempty"` -} - const ( // RouteConditionReady is set when the service is configured // and has available backends ready to receive traffic. RouteConditionReady = apis.ConditionReady ) -// RouteStatusFields holds the fields of Route's status that -// are not generally shared. This is defined separately and inlined so that -// other types can readily consume these fields via duck typing. -type RouteStatusFields struct { - // URL holds the url that will distribute traffic over the provided traffic targets. - // It generally has the form http[s]://{route-name}.{route-namespace}.{cluster-level-suffix} - // +optional - URL *apis.URL `json:"url,omitempty"` - - // Address holds the information needed for a Route to be the target of an event. - // +optional - Address *duckv1beta1.Addressable `json:"address,omitempty"` - - // Traffic holds the configured traffic distribution. - // These entries will always contain RevisionName references. - // When ConfigurationName appears in the spec, this will hold the - // LatestReadyRevisionName that we last observed. - // +optional - Traffic []TrafficTarget `json:"traffic,omitempty"` -} - -// RouteStatus communicates the observed state of the Route (from the controller). -type RouteStatus struct { - duckv1beta1.Status `json:",inline"` - - RouteStatusFields `json:",inline"` -} - // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // RouteList is a list of Route resources diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_validation.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_validation.go index 72da2fab86..2dde0fc8b4 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_validation.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/route_validation.go @@ -18,10 +18,8 @@ package v1beta1 import ( "context" - "fmt" "strings" - "k8s.io/apimachinery/pkg/util/validation" "knative.dev/pkg/apis" "knative.dev/serving/pkg/apis/serving" "knative.dev/serving/pkg/reconciler/route/config" @@ -36,172 +34,15 @@ func (r *Route) Validate(ctx context.Context) *apis.FieldError { return errs } -func validateTrafficList(ctx context.Context, traffic []TrafficTarget) *apis.FieldError { - var errs *apis.FieldError - - // Track the targets of named TrafficTarget entries (to detect duplicates). - trafficMap := make(map[string]int) - - sum := 0 - for i, tt := range traffic { - errs = errs.Also(tt.Validate(ctx).ViaIndex(i)) - - if idx, ok := trafficMap[tt.Tag]; ok { - // We want only single definition of the route, even if it points - // to the same config or revision. - errs = errs.Also(&apis.FieldError{ - Message: fmt.Sprintf("Multiple definitions for %q", tt.Tag), - Paths: []string{ - fmt.Sprintf("[%d].tag", i), - fmt.Sprintf("[%d].tag", idx), - }, - }) - } else { - trafficMap[tt.Tag] = i - } - sum += tt.Percent - } - - if sum != 100 { - errs = errs.Also(&apis.FieldError{ - Message: fmt.Sprintf("Traffic targets sum to %d, want 100", sum), - Paths: []string{apis.CurrentField}, - }) - } - return errs -} - -// Validate implements apis.Validatable -func (rs *RouteSpec) Validate(ctx context.Context) *apis.FieldError { - return validateTrafficList(ctx, rs.Traffic).ViaField("traffic") -} - -// Validate verifies that TrafficTarget is properly configured. -func (tt *TrafficTarget) Validate(ctx context.Context) *apis.FieldError { - errs := tt.validateLatestRevision(ctx) - errs = tt.validateRevisionAndConfiguration(ctx, errs) - errs = tt.validateTrafficPercentage(errs) - return tt.validateUrl(ctx, errs) -} - -func (tt *TrafficTarget) validateRevisionAndConfiguration(ctx context.Context, errs *apis.FieldError) *apis.FieldError { - // We only validate the sense of latestRevision in the context of a Spec, - // and only when it is specified. - switch { - // When we have a default configurationName, we don't - // allow one to be specified. - case HasDefaultConfigurationName(ctx) && tt.ConfigurationName != "": - errs = errs.Also(apis.ErrDisallowedFields("configurationName")) - - // Both revisionName and configurationName are never allowed to - // appear concurrently. - case tt.RevisionName != "" && tt.ConfigurationName != "": - errs = errs.Also(apis.ErrMultipleOneOf( - "revisionName", "configurationName")) - - // When a revisionName appears, we must check that the name is valid. - case tt.RevisionName != "": - if el := validation.IsQualifiedName(tt.RevisionName); len(el) > 0 { - errs = errs.Also(apis.ErrInvalidKeyName( - tt.RevisionName, "revisionName", el...)) - } - - // When revisionName is missing in Status report an error. - case apis.IsInStatus(ctx): - errs = errs.Also(apis.ErrMissingField("revisionName")) - - // When configurationName is specified, we must check that the name is valid. - case tt.ConfigurationName != "": - if el := validation.IsQualifiedName(tt.ConfigurationName); len(el) > 0 { - errs = errs.Also(apis.ErrInvalidKeyName( - tt.ConfigurationName, "configurationName", el...)) - } - - // When we are using a default configurationName, it must be a valid name already. - case HasDefaultConfigurationName(ctx): - - // All other cases are missing one of revisionName or configurationName. - default: - errs = errs.Also(apis.ErrMissingOneOf( - "revisionName", "configurationName")) - } - return errs -} - -func (tt *TrafficTarget) validateTrafficPercentage(errs *apis.FieldError) *apis.FieldError { - // Check that the traffic Percentage is within bounds. - if tt.Percent < 0 || tt.Percent > 100 { - errs = errs.Also(apis.ErrOutOfBoundsValue( - tt.Percent, 0, 100, "percent")) - } - return errs -} - -func (tt *TrafficTarget) validateLatestRevision(ctx context.Context) *apis.FieldError { - if apis.IsInSpec(ctx) && tt.LatestRevision != nil { - lr := *tt.LatestRevision - pinned := tt.RevisionName != "" - if pinned == lr { - // The senses for whether to pin to a particular revision or - // float forward to the latest revision must match. - return apis.ErrInvalidValue(lr, "latestRevision") - } - } - return nil -} - -func (tt *TrafficTarget) validateUrl(ctx context.Context, errs *apis.FieldError) *apis.FieldError { - // Check that we set the URL appropriately. - if tt.URL.String() != "" { - // URL is not allowed in traffic under spec. - if apis.IsInSpec(ctx) { - errs = errs.Also(apis.ErrDisallowedFields("url")) - } - - // URL is not allowed in any traffic target without a name. - if tt.Tag == "" { - errs = errs.Also(apis.ErrDisallowedFields("url")) - } - } else if tt.Tag != "" { - // URL must be specified in status when name is specified. - if apis.IsInStatus(ctx) { - errs = errs.Also(apis.ErrMissingField("url")) - } - } - return errs -} - -// Validate implements apis.Validatable. -func (rs *RouteStatus) Validate(ctx context.Context) *apis.FieldError { - return rs.RouteStatusFields.Validate(ctx) -} - -// Validate implements apis.Validatable. -func (rsf *RouteStatusFields) Validate(ctx context.Context) *apis.FieldError { - // TODO(mattmoor): Validate other status fields. - - if len(rsf.Traffic) != 0 { - return validateTrafficList(ctx, rsf.Traffic).ViaField("traffic") - } - return nil -} - -func validateClusterVisibilityLabel(label string) (errs *apis.FieldError) { - if label != config.VisibilityClusterLocal { - errs = apis.ErrInvalidValue(label, config.VisibilityLabelKey) - } - return -} - // validateLabels function validates route labels. func (r *Route) validateLabels() (errs *apis.FieldError) { for key, val := range r.GetLabels() { switch { case key == config.VisibilityLabelKey: - errs = errs.Also(validateClusterVisibilityLabel(val)) + errs = errs.Also(serving.ValidateClusterVisibilityLabel(val)) case key == serving.ServiceLabelKey: errs = errs.Also(verifyLabelOwnerRef(val, serving.ServiceLabelKey, "Service", r.GetOwnerReferences())) - case strings.HasPrefix(key, groupNamePrefix): + case strings.HasPrefix(key, serving.GroupNamePrefix): errs = errs.Also(apis.ErrInvalidKeyName(key, apis.CurrentField)) } } diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_defaults.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_defaults.go index 09af86568f..e05d1ca814 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_defaults.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_defaults.go @@ -49,9 +49,3 @@ func (s *Service) SetDefaults(ctx context.Context) { } } } - -// SetDefaults implements apis.Defaultable -func (ss *ServiceSpec) SetDefaults(ctx context.Context) { - ss.ConfigurationSpec.SetDefaults(ctx) - ss.RouteSpec.SetDefaults(WithDefaultConfigurationName(ctx)) -} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_lifecycle.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_lifecycle.go index 5168d91116..ad59308fcd 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_lifecycle.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_lifecycle.go @@ -16,20 +16,9 @@ limitations under the License. package v1beta1 -import ( - "k8s.io/apimachinery/pkg/runtime/schema" - - "knative.dev/pkg/apis" -) - -var serviceCondSet = apis.NewLivingConditionSet() +import "k8s.io/apimachinery/pkg/runtime/schema" // GetGroupVersionKind returns the GroupVersionKind. func (s *Service) GetGroupVersionKind() schema.GroupVersionKind { return SchemeGroupVersion.WithKind("Service") } - -// IsReady returns if the service is ready to serve the requested configuration. -func (ss *ServiceStatus) IsReady() bool { - return serviceCondSet.Manage(ss).IsHappy() -} diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_types.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_types.go index ba6d2248bb..332ee83b36 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_types.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_types.go @@ -20,8 +20,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" "knative.dev/pkg/kmeta" + v1 "knative.dev/serving/pkg/apis/serving/v1" ) // +genclient @@ -45,10 +45,10 @@ type Service struct { metav1.ObjectMeta `json:"metadata,omitempty"` // +optional - Spec ServiceSpec `json:"spec,omitempty"` + Spec v1.ServiceSpec `json:"spec,omitempty"` // +optional - Status ServiceStatus `json:"status,omitempty"` + Status v1.ServiceStatus `json:"status,omitempty"` } // Verify that Service adheres to the appropriate interfaces. @@ -64,24 +64,6 @@ var ( _ kmeta.OwnerRefable = (*Service)(nil) ) -// ServiceSpec represents the configuration for the Service object. -// A Service's specification is the union of the specifications for a Route -// and Configuration. The Service restricts what can be expressed in these -// fields, e.g. the Route must reference the provided Configuration; -// however, these limitations also enable friendlier defaulting, -// e.g. Route never needs a Configuration name, and may be defaulted to -// the appropriate "run latest" spec. -type ServiceSpec struct { - // ServiceSpec inlines an unrestricted ConfigurationSpec. - ConfigurationSpec `json:",inline"` - - // ServiceSpec inlines RouteSpec and restricts/defaults its fields - // via webhook. In particular, this spec can only reference this - // Service's configuration and revisions (which also influences - // defaults). - RouteSpec `json:",inline"` -} - // ConditionType represents a Service condition value const ( // ServiceConditionReady is set when the service is configured @@ -89,19 +71,6 @@ const ( ServiceConditionReady = apis.ConditionReady ) -// ServiceStatus represents the Status stanza of the Service resource. -type ServiceStatus struct { - duckv1beta1.Status `json:",inline"` - - // In addition to inlining ConfigurationSpec, we also inline the fields - // specific to ConfigurationStatus. - ConfigurationStatusFields `json:",inline"` - - // In addition to inlining RouteSpec, we also inline the fields - // specific to RouteStatus. - RouteStatusFields `json:",inline"` -} - // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // ServiceList is a list of Service resources diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_validation.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_validation.go index 8b103e5cd0..6daced418c 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_validation.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/service_validation.go @@ -51,27 +51,13 @@ func (s *Service) Validate(ctx context.Context) (errs *apis.FieldError) { return errs } -// Validate implements apis.Validatable -func (ss *ServiceSpec) Validate(ctx context.Context) *apis.FieldError { - return ss.ConfigurationSpec.Validate(ctx).Also( - // Within the context of Service, the RouteSpec has a default - // configurationName. - ss.RouteSpec.Validate(WithDefaultConfigurationName(ctx))) -} - -// Validate implements apis.Validatable -func (ss *ServiceStatus) Validate(ctx context.Context) *apis.FieldError { - return ss.ConfigurationStatusFields.Validate(ctx).Also( - ss.RouteStatusFields.Validate(ctx)) -} - // validateLabels function validates service labels func (s *Service) validateLabels() (errs *apis.FieldError) { for key, val := range s.GetLabels() { switch { case key == config.VisibilityLabelKey: - errs = errs.Also(validateClusterVisibilityLabel(val)) - case strings.HasPrefix(key, groupNamePrefix): + errs = errs.Also(serving.ValidateClusterVisibilityLabel(val)) + case strings.HasPrefix(key, serving.GroupNamePrefix): errs = errs.Also(apis.ErrInvalidKeyName(key, apis.CurrentField)) } } diff --git a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/zz_generated.deepcopy.go b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/zz_generated.deepcopy.go index c07bd927fb..4c6ac4637d 100644 --- a/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/zz_generated.deepcopy.go +++ b/vendor/knative.dev/serving/pkg/apis/serving/v1beta1/zz_generated.deepcopy.go @@ -22,8 +22,6 @@ package v1beta1 import ( runtime "k8s.io/apimachinery/pkg/runtime" - apis "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -87,57 +85,6 @@ func (in *ConfigurationList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigurationSpec) DeepCopyInto(out *ConfigurationSpec) { - *out = *in - in.Template.DeepCopyInto(&out.Template) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigurationSpec. -func (in *ConfigurationSpec) DeepCopy() *ConfigurationSpec { - if in == nil { - return nil - } - out := new(ConfigurationSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigurationStatus) DeepCopyInto(out *ConfigurationStatus) { - *out = *in - in.Status.DeepCopyInto(&out.Status) - out.ConfigurationStatusFields = in.ConfigurationStatusFields - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigurationStatus. -func (in *ConfigurationStatus) DeepCopy() *ConfigurationStatus { - if in == nil { - return nil - } - out := new(ConfigurationStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ConfigurationStatusFields) DeepCopyInto(out *ConfigurationStatusFields) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigurationStatusFields. -func (in *ConfigurationStatusFields) DeepCopy() *ConfigurationStatusFields { - if in == nil { - return nil - } - out := new(ConfigurationStatusFields) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Revision) DeepCopyInto(out *Revision) { *out = *in @@ -199,63 +146,6 @@ func (in *RevisionList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RevisionSpec) DeepCopyInto(out *RevisionSpec) { - *out = *in - in.PodSpec.DeepCopyInto(&out.PodSpec) - if in.TimeoutSeconds != nil { - in, out := &in.TimeoutSeconds, &out.TimeoutSeconds - *out = new(int64) - **out = **in - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RevisionSpec. -func (in *RevisionSpec) DeepCopy() *RevisionSpec { - if in == nil { - return nil - } - out := new(RevisionSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RevisionStatus) DeepCopyInto(out *RevisionStatus) { - *out = *in - in.Status.DeepCopyInto(&out.Status) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RevisionStatus. -func (in *RevisionStatus) DeepCopy() *RevisionStatus { - if in == nil { - return nil - } - out := new(RevisionStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RevisionTemplateSpec) DeepCopyInto(out *RevisionTemplateSpec) { - *out = *in - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RevisionTemplateSpec. -func (in *RevisionTemplateSpec) DeepCopy() *RevisionTemplateSpec { - if in == nil { - return nil - } - out := new(RevisionTemplateSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Route) DeepCopyInto(out *Route) { *out = *in @@ -317,80 +207,6 @@ func (in *RouteList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RouteSpec) DeepCopyInto(out *RouteSpec) { - *out = *in - if in.Traffic != nil { - in, out := &in.Traffic, &out.Traffic - *out = make([]TrafficTarget, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteSpec. -func (in *RouteSpec) DeepCopy() *RouteSpec { - if in == nil { - return nil - } - out := new(RouteSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RouteStatus) DeepCopyInto(out *RouteStatus) { - *out = *in - in.Status.DeepCopyInto(&out.Status) - in.RouteStatusFields.DeepCopyInto(&out.RouteStatusFields) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteStatus. -func (in *RouteStatus) DeepCopy() *RouteStatus { - if in == nil { - return nil - } - out := new(RouteStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *RouteStatusFields) DeepCopyInto(out *RouteStatusFields) { - *out = *in - if in.URL != nil { - in, out := &in.URL, &out.URL - *out = new(apis.URL) - (*in).DeepCopyInto(*out) - } - if in.Address != nil { - in, out := &in.Address, &out.Address - *out = new(duckv1beta1.Addressable) - (*in).DeepCopyInto(*out) - } - if in.Traffic != nil { - in, out := &in.Traffic, &out.Traffic - *out = make([]TrafficTarget, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteStatusFields. -func (in *RouteStatusFields) DeepCopy() *RouteStatusFields { - if in == nil { - return nil - } - out := new(RouteStatusFields) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Service) DeepCopyInto(out *Service) { *out = *in @@ -451,66 +267,3 @@ func (in *ServiceList) DeepCopyObject() runtime.Object { } return nil } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) { - *out = *in - in.ConfigurationSpec.DeepCopyInto(&out.ConfigurationSpec) - in.RouteSpec.DeepCopyInto(&out.RouteSpec) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceSpec. -func (in *ServiceSpec) DeepCopy() *ServiceSpec { - if in == nil { - return nil - } - out := new(ServiceSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceStatus) DeepCopyInto(out *ServiceStatus) { - *out = *in - in.Status.DeepCopyInto(&out.Status) - out.ConfigurationStatusFields = in.ConfigurationStatusFields - in.RouteStatusFields.DeepCopyInto(&out.RouteStatusFields) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceStatus. -func (in *ServiceStatus) DeepCopy() *ServiceStatus { - if in == nil { - return nil - } - out := new(ServiceStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TrafficTarget) DeepCopyInto(out *TrafficTarget) { - *out = *in - if in.LatestRevision != nil { - in, out := &in.LatestRevision, &out.LatestRevision - *out = new(bool) - **out = **in - } - if in.URL != nil { - in, out := &in.URL, &out.URL - *out = new(apis.URL) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficTarget. -func (in *TrafficTarget) DeepCopy() *TrafficTarget { - if in == nil { - return nil - } - out := new(TrafficTarget) - in.DeepCopyInto(out) - return out -} diff --git a/vendor/knative.dev/serving/pkg/client/clientset/versioned/scheme/register.go b/vendor/knative.dev/serving/pkg/client/clientset/versioned/scheme/register.go index ea2dfd93e0..b9049aef87 100644 --- a/vendor/knative.dev/serving/pkg/client/clientset/versioned/scheme/register.go +++ b/vendor/knative.dev/serving/pkg/client/clientset/versioned/scheme/register.go @@ -26,6 +26,7 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" autoscalingv1alpha1 "knative.dev/serving/pkg/apis/autoscaling/v1alpha1" networkingv1alpha1 "knative.dev/serving/pkg/apis/networking/v1alpha1" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" servingv1alpha1 "knative.dev/serving/pkg/apis/serving/v1alpha1" servingv1beta1 "knative.dev/serving/pkg/apis/serving/v1beta1" ) @@ -38,6 +39,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{ networkingv1alpha1.AddToScheme, servingv1alpha1.AddToScheme, servingv1beta1.AddToScheme, + servingv1.AddToScheme, } // AddToScheme adds all types of this clientset into the given scheme. This allows composition diff --git a/vendor/knative.dev/serving/pkg/network/error_handler.go b/vendor/knative.dev/serving/pkg/network/error_handler.go new file mode 100644 index 0000000000..486518b966 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/network/error_handler.go @@ -0,0 +1,43 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package network + +import ( + "io/ioutil" + "net/http" + + "go.uber.org/zap" +) + +// ErrorHandler sets up a handler suitable for use with the ErrorHandler field on +// httputil's reverse proxy. +func ErrorHandler(logger *zap.SugaredLogger) func(http.ResponseWriter, *http.Request, error) { + return func(w http.ResponseWriter, req *http.Request, err error) { + ss := readSockStat(logger) + logger.Errorw("error reverse proxying request; sockstat: "+ss, zap.Error(err)) + http.Error(w, err.Error(), http.StatusBadGateway) + } +} + +func readSockStat(logger *zap.SugaredLogger) string { + b, err := ioutil.ReadFile("/proc/net/sockstat") + if err != nil { + logger.Errorw("Unable to read sockstat", zap.Error(err)) + return "" + } + return string(b) +} diff --git a/vendor/knative.dev/serving/pkg/network/network.go b/vendor/knative.dev/serving/pkg/network/network.go index 05fa4fe0ed..3e8d24e8f7 100644 --- a/vendor/knative.dev/serving/pkg/network/network.go +++ b/vendor/knative.dev/serving/pkg/network/network.go @@ -42,6 +42,10 @@ const ( // uses to mark requests going through it. ProxyHeaderName = "K-Proxy-Request" + // HashHeaderName is the name of an internal header that Ingress controller + // uses to find out which version of the networking config is deployed. + HashHeaderName = "K-Network-Hash" + // OriginalHostHeader is used to avoid Istio host based routing rules // in Activator. // The header contains the original Host value that can be rewritten diff --git a/vendor/knative.dev/serving/pkg/network/probe_handler.go b/vendor/knative.dev/serving/pkg/network/probe_handler.go new file mode 100644 index 0000000000..be88b57486 --- /dev/null +++ b/vendor/knative.dev/serving/pkg/network/probe_handler.go @@ -0,0 +1,52 @@ +/* +Copyright 2019 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package network + +import ( + "fmt" + "net/http" +) + +// ProbeHeaderValue is the value used in 'K-Network-Probe' +var ProbeHeaderValue = "probe" + +type handler struct { + next http.Handler +} + +// NewProbeHandler wraps a HTTP handler handling probing requests around the provided HTTP handler +func NewProbeHandler(next http.Handler) http.Handler { + return &handler{next: next} +} + +// ServeHTTP handles probing requests +func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if ph := r.Header.Get(ProbeHeaderName); ph != ProbeHeaderValue { + r.Header.Del(HashHeaderName) + h.next.ServeHTTP(w, r) + return + } + + hh := r.Header.Get(HashHeaderName) + if hh == "" { + http.Error(w, fmt.Sprintf("a probe request must contain a non-empty %q header", HashHeaderName), http.StatusBadRequest) + return + } + + w.Header().Set(HashHeaderName, hh) + w.WriteHeader(200) +} diff --git a/vendor/knative.dev/serving/pkg/network/transports.go b/vendor/knative.dev/serving/pkg/network/transports.go index 88d1f142d5..791cdf913a 100644 --- a/vendor/knative.dev/serving/pkg/network/transports.go +++ b/vendor/knative.dev/serving/pkg/network/transports.go @@ -104,13 +104,17 @@ func newHTTPTransport(connTimeout time.Duration, disableKeepAlives bool) http.Ro // NewProberTransport creates a RoundTripper that is useful for probing, // since it will not cache connections. func NewProberTransport() http.RoundTripper { - return newAutoTransport(newHTTPTransport(DefaultConnTimeout, true /*disable keep-alives*/), NewH2CTransport()) + return newAutoTransport( + newHTTPTransport(DefaultConnTimeout, true /*disable keep-alives*/), + NewH2CTransport()) } // NewAutoTransport creates a RoundTripper that can use appropriate transport // based on the request's HTTP version. func NewAutoTransport() http.RoundTripper { - return newAutoTransport(newHTTPTransport(DefaultConnTimeout, false /*disable keep-alives*/), NewH2CTransport()) + return newAutoTransport( + newHTTPTransport(DefaultConnTimeout, false /*disable keep-alives*/), + NewH2CTransport()) } // AutoTransport uses h2c for HTTP2 requests and falls back to `http.DefaultTransport` for all others diff --git a/vendor/knative.dev/serving/pkg/reconciler/route/config/domain.go b/vendor/knative.dev/serving/pkg/reconciler/route/config/domain.go index a7d5cd1d77..3863a1311f 100644 --- a/vendor/knative.dev/serving/pkg/reconciler/route/config/domain.go +++ b/vendor/knative.dev/serving/pkg/reconciler/route/config/domain.go @@ -22,7 +22,7 @@ import ( "github.com/ghodss/yaml" corev1 "k8s.io/api/core/v1" "knative.dev/pkg/configmap" - "knative.dev/serving/pkg/network" + "knative.dev/pkg/network" ) const ( diff --git a/vendor/modules.txt b/vendor/modules.txt index 399d08598a..ff05eea495 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -94,6 +94,17 @@ github.com/spf13/jwalterweatherman github.com/spf13/pflag # github.com/spf13/viper v1.3.1 github.com/spf13/viper +# go.uber.org/atomic v1.4.0 +go.uber.org/atomic +# go.uber.org/multierr v1.2.0 +go.uber.org/multierr +# go.uber.org/zap v1.10.0 +go.uber.org/zap +go.uber.org/zap/internal/bufferpool +go.uber.org/zap/zapcore +go.uber.org/zap/buffer +go.uber.org/zap/internal/color +go.uber.org/zap/internal/exit # golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 golang.org/x/crypto/ssh/terminal # golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 @@ -101,9 +112,9 @@ golang.org/x/net/http2 golang.org/x/net/http/httpguts golang.org/x/net/http2/hpack golang.org/x/net/idna +golang.org/x/net/http2/h2c golang.org/x/net/context/ctxhttp golang.org/x/net/context -golang.org/x/net/http2/h2c # golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 golang.org/x/oauth2 golang.org/x/oauth2/google @@ -150,9 +161,9 @@ gotest.tools/internal/difflib # k8s.io/api v0.0.0-20190226173710-145d52631d00 k8s.io/api/core/v1 k8s.io/api/authentication/v1 +k8s.io/api/apps/v1 k8s.io/api/admissionregistration/v1alpha1 k8s.io/api/admissionregistration/v1beta1 -k8s.io/api/apps/v1 k8s.io/api/apps/v1beta1 k8s.io/api/apps/v1beta2 k8s.io/api/authentication/v1beta1 @@ -370,17 +381,19 @@ k8s.io/client-go/listers/storage/v1alpha1 k8s.io/client-go/listers/storage/v1beta1 # k8s.io/kube-openapi v0.0.0-20190722073852-5e22f3d471e6 k8s.io/kube-openapi/pkg/util/proto -# knative.dev/pkg v0.0.0-20190815170108-426561fd098d +# knative.dev/pkg v0.0.0-20191022181926-0b19b4ad9139 knative.dev/pkg/apis knative.dev/pkg/apis/duck/v1beta1 knative.dev/pkg/ptr knative.dev/pkg/kmp knative.dev/pkg/apis/duck +knative.dev/pkg/apis/duck/v1 knative.dev/pkg/apis/v1alpha1 knative.dev/pkg/apis/duck/v1alpha1 knative.dev/pkg/kmeta knative.dev/pkg/configmap -# knative.dev/serving v0.8.0 +knative.dev/pkg/network +# knative.dev/serving v0.9.0 knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1alpha1 knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1alpha1/fake knative.dev/serving/pkg/apis/serving @@ -390,9 +403,10 @@ knative.dev/serving/pkg/apis/serving/v1beta1 knative.dev/serving/pkg/client/clientset/versioned/scheme knative.dev/serving/pkg/apis/config knative.dev/serving/pkg/apis/networking -knative.dev/serving/pkg/apis/networking/v1alpha1 knative.dev/serving/pkg/reconciler/route/config knative.dev/serving/pkg/apis/autoscaling/v1alpha1 +knative.dev/serving/pkg/apis/networking/v1alpha1 +knative.dev/serving/pkg/apis/serving/v1 knative.dev/serving/pkg/gc knative.dev/serving/pkg/network # knative.dev/test-infra v0.0.0-20190730202142-17f2331e80ad From 54b070e75fea5aeba5ab11720a92ac22312534a9 Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Thu, 24 Oct 2019 22:03:00 +0530 Subject: [PATCH 2/5] Updates references per serving v0.9.0 vendoring - Updates code and tests to refer the required data structure and method/function calls - duckv1beta1 -> duckv1 conditions - traffic percent value is now *int64 - containerConcurrency validation method relocation --- pkg/kn/commands/human_readable_flags.go | 8 ++--- pkg/kn/commands/route/list_test.go | 7 ++-- .../service/configuration_edit_flags.go | 2 +- pkg/kn/commands/service/create_test.go | 2 +- pkg/kn/commands/service/describe.go | 15 ++++---- pkg/kn/commands/service/describe_test.go | 32 ++++++++--------- pkg/kn/commands/service/update_test.go | 2 +- pkg/kn/traffic/compute.go | 24 ++++++------- pkg/kn/traffic/compute_test.go | 36 +++++++++---------- pkg/serving/config_changes.go | 17 ++++----- pkg/serving/config_changes_test.go | 23 ++++++------ pkg/wait/test_wait_helper.go | 2 +- vendor/modules.txt | 6 ++-- 13 files changed, 89 insertions(+), 87 deletions(-) diff --git a/pkg/kn/commands/human_readable_flags.go b/pkg/kn/commands/human_readable_flags.go index 6d64f868bc..198ed32dbd 100644 --- a/pkg/kn/commands/human_readable_flags.go +++ b/pkg/kn/commands/human_readable_flags.go @@ -23,7 +23,7 @@ import ( "k8s.io/apimachinery/pkg/util/duration" hprinters "knative.dev/client/pkg/printers" "knative.dev/pkg/apis" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" ) // HumanPrintFlags provides default flags necessary for printing. @@ -70,7 +70,7 @@ func (f *HumanPrintFlags) EnsureWithNamespace() { // Private functions // conditionsValue returns the True conditions count among total conditions -func ConditionsValue(conditions duckv1beta1.Conditions) string { +func ConditionsValue(conditions duckv1.Conditions) string { var ok int for _, condition := range conditions { if condition.Status == "True" { @@ -81,7 +81,7 @@ func ConditionsValue(conditions duckv1beta1.Conditions) string { } // readyCondition returns status of resource's Ready type condition -func ReadyCondition(conditions duckv1beta1.Conditions) string { +func ReadyCondition(conditions duckv1.Conditions) string { for _, condition := range conditions { if condition.Type == apis.ConditionReady { return string(condition.Status) @@ -90,7 +90,7 @@ func ReadyCondition(conditions duckv1beta1.Conditions) string { return "" } -func NonReadyConditionReason(conditions duckv1beta1.Conditions) string { +func NonReadyConditionReason(conditions duckv1.Conditions) string { for _, condition := range conditions { if condition.Type == apis.ConditionReady { if string(condition.Status) == "True" { diff --git a/pkg/kn/commands/route/list_test.go b/pkg/kn/commands/route/list_test.go index 42adf0de13..a89de163f6 100644 --- a/pkg/kn/commands/route/list_test.go +++ b/pkg/kn/commands/route/list_test.go @@ -23,8 +23,9 @@ import ( client_testing "k8s.io/client-go/testing" "knative.dev/client/pkg/kn/commands" "knative.dev/client/pkg/util" + "knative.dev/pkg/ptr" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" "knative.dev/serving/pkg/apis/serving/v1alpha1" - "knative.dev/serving/pkg/apis/serving/v1beta1" ) func fakeRouteList(args []string, response *v1alpha1.RouteList) (action client_testing.Action, output []string, err error) { @@ -115,9 +116,9 @@ func createMockRouteMeta(name string) *v1alpha1.Route { func createMockTrafficTarget(revision string, percent int) *v1alpha1.TrafficTarget { return &v1alpha1.TrafficTarget{ - TrafficTarget: v1beta1.TrafficTarget{ + TrafficTarget: servingv1.TrafficTarget{ RevisionName: revision, - Percent: percent, + Percent: ptr.Int64(int64(percent)), }, } } diff --git a/pkg/kn/commands/service/configuration_edit_flags.go b/pkg/kn/commands/service/configuration_edit_flags.go index 70cdf2ca8e..587a0b345c 100644 --- a/pkg/kn/commands/service/configuration_edit_flags.go +++ b/pkg/kn/commands/service/configuration_edit_flags.go @@ -238,7 +238,7 @@ func (p *ConfigurationEditFlags) Apply( } if cmd.Flags().Changed("concurrency-limit") { - err = servinglib.UpdateConcurrencyLimit(template, p.ConcurrencyLimit) + err = servinglib.UpdateConcurrencyLimit(template, int64(p.ConcurrencyLimit)) if err != nil { return err } diff --git a/pkg/kn/commands/service/create_test.go b/pkg/kn/commands/service/create_test.go index 3fa241638d..e9ad155716 100644 --- a/pkg/kn/commands/service/create_test.go +++ b/pkg/kn/commands/service/create_test.go @@ -349,7 +349,7 @@ func TestServiceCreateMaxMinScale(t *testing.T) { } } - if template.Spec.ContainerConcurrency != 100 { + if *template.Spec.ContainerConcurrency != int64(100) { t.Fatalf("container concurrency not set to given value 1000") } } diff --git a/pkg/kn/commands/service/describe.go b/pkg/kn/commands/service/describe.go index 813b1fc38a..2e21e718fe 100644 --- a/pkg/kn/commands/service/describe.go +++ b/pkg/kn/commands/service/describe.go @@ -34,7 +34,7 @@ import ( serving_kn_v1alpha1 "knative.dev/client/pkg/serving/v1alpha1" "knative.dev/pkg/apis" - "knative.dev/pkg/apis/duck/v1beta1" + duckv1 "knative.dev/pkg/apis/duck/v1" "knative.dev/serving/pkg/apis/serving/v1alpha1" "github.com/spf13/cobra" @@ -68,7 +68,7 @@ type revisionDesc struct { creationTimestamp time.Time // traffic stuff - percent int + percent int64 tag string latestTraffic *bool @@ -319,7 +319,7 @@ func revisionHeader(desc *revisionDesc) string { // Used for conditions table to do own formatting for the table, // as the tabbed writer doesn't work nicely with colors -func getMaxTypeLen(conditions v1beta1.Conditions) int { +func getMaxTypeLen(conditions duckv1.Conditions) int { max := 0 for _, condition := range conditions { if len(condition.Type) > max { @@ -474,7 +474,7 @@ func joinAndTruncate(sortedKeys []string, m map[string]string) string { } // Format target percentage that it fits in the revision table -func formatBullet(percentage int, status corev1.ConditionStatus) string { +func formatBullet(percentage int64, status corev1.ConditionStatus) string { symbol := "+" switch status { case v1.ConditionTrue: @@ -620,7 +620,7 @@ func addStatusInfo(desc *revisionDesc, revision *v1alpha1.Revision) { func addTargetInfo(desc *revisionDesc, target *v1alpha1.TrafficTarget) { if target != nil { - desc.percent = target.Percent + desc.percent = *target.Percent desc.latestTraffic = target.LatestRevision desc.tag = target.Tag } @@ -669,9 +669,8 @@ func addConcurrencyAndScaleInfo(desc *revisionDesc, revision *v1alpha1.Revision) } desc.concurrencyTarget = target - if revision.Spec.ContainerConcurrency != 0 { - limit := int64(revision.Spec.ContainerConcurrency) - desc.concurrencyLimit = &limit + if revision.Spec.ContainerConcurrency != nil { + desc.concurrencyLimit = revision.Spec.ContainerConcurrency } return nil diff --git a/pkg/kn/commands/service/describe_test.go b/pkg/kn/commands/service/describe_test.go index d8dffc889d..c6aebfa684 100644 --- a/pkg/kn/commands/service/describe_test.go +++ b/pkg/kn/commands/service/describe_test.go @@ -27,12 +27,12 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" duckv1alpha1 "knative.dev/pkg/apis/duck/v1alpha1" - duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" "knative.dev/serving/pkg/apis/autoscaling" api_serving "knative.dev/serving/pkg/apis/serving" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" "knative.dev/serving/pkg/apis/serving/v1alpha1" - "knative.dev/serving/pkg/apis/serving/v1beta1" client_serving "knative.dev/client/pkg/serving" knclient "knative.dev/client/pkg/serving/v1alpha1" @@ -128,7 +128,7 @@ func TestServiceDescribeLatestNotInTraffic(t *testing.T) { expectedService := createTestService("foo", []string{"rev1", "rev2"}, goodConditions()) expectedService.Status.Traffic = expectedService.Status.Traffic[:1] expectedService.Status.Traffic[0].LatestRevision = ptr.Bool(false) - expectedService.Status.Traffic[0].Percent = 100 + expectedService.Status.Traffic[0].Percent = ptr.Int64(int64(100)) // Get service & revision r.GetService("foo", &expectedService, nil) @@ -159,7 +159,7 @@ func TestServiceDescribeEachNamedOnce(t *testing.T) { expectedService := createTestService("foo", []string{"rev1", "rev2"}, goodConditions()) expectedService.Status.Traffic = expectedService.Status.Traffic[:1] expectedService.Status.Traffic[0].LatestRevision = ptr.Bool(false) - expectedService.Status.Traffic[0].Percent = 100 + expectedService.Status.Traffic[0].Percent = ptr.Int64(int64(100)) // Get service & revision r.GetService("foo", &expectedService, nil) @@ -495,7 +495,7 @@ func validateServiceOutput(t *testing.T, service string, output string) { assert.Assert(t, util.ContainsAll(output, "Ready", "RoutesReady", "OK", "TYPE", "AGE", "REASON")) } -func createTestService(name string, revisionNames []string, conditions duckv1beta1.Conditions) v1alpha1.Service { +func createTestService(name string, revisionNames []string, conditions duckv1.Conditions) v1alpha1.Service { labelMap := make(map[string]string) labelMap["label1"] = "lval1" @@ -522,7 +522,7 @@ func createTestService(name string, revisionNames []string, conditions duckv1bet DeprecatedDomain: name + ".default.example.com", Address: &duckv1alpha1.Addressable{Hostname: name + ".default.svc.cluster.local"}, }, - Status: duckv1beta1.Status{ + Status: duckv1.Status{ Conditions: conditions, }, }, @@ -535,10 +535,10 @@ func createTestService(name string, revisionNames []string, conditions duckv1bet for _, rname := range revisionNames { url, _ := apis.ParseURL(fmt.Sprintf("https://%s", rname)) target := v1alpha1.TrafficTarget{ - TrafficTarget: v1beta1.TrafficTarget{ + TrafficTarget: servingv1.TrafficTarget{ RevisionName: rname, ConfigurationName: name, - Percent: 100 / len(revisionNames), + Percent: ptr.Int64(int64(100 / len(revisionNames))), URL: url, }, } @@ -549,7 +549,7 @@ func createTestService(name string, revisionNames []string, conditions duckv1bet return service } -func addScaling(revision *v1alpha1.Revision, minScale, maxScale, concurrencyTarget, concurrenyLimit string) { +func addScaling(revision *v1alpha1.Revision, minScale, maxScale, concurrencyTarget, concurrencyLimit string) { annos := make(map[string]string) if minScale != "" { annos[autoscaling.MinScaleAnnotationKey] = minScale @@ -561,9 +561,9 @@ func addScaling(revision *v1alpha1.Revision, minScale, maxScale, concurrencyTarg annos[autoscaling.TargetAnnotationKey] = concurrencyTarget } revision.Annotations = annos - if concurrenyLimit != "" { - l, _ := strconv.Atoi(concurrenyLimit) - revision.Spec.ContainerConcurrency = v1beta1.RevisionContainerConcurrencyType(l) + if concurrencyLimit != "" { + l, _ := strconv.ParseInt(concurrencyLimit, 10, 64) + revision.Spec.ContainerConcurrency = ptr.Int64(l) } } @@ -603,7 +603,7 @@ func createTestRevision(revision string, gen int64) v1alpha1.Revision { CreationTimestamp: metav1.Time{Time: time.Now()}, }, Spec: v1alpha1.RevisionSpec{ - RevisionSpec: v1beta1.RevisionSpec{ + RevisionSpec: servingv1.RevisionSpec{ PodSpec: v1.PodSpec{ Containers: []v1.Container{ { @@ -622,15 +622,15 @@ func createTestRevision(revision string, gen int64) v1alpha1.Revision { }, Status: v1alpha1.RevisionStatus{ ImageDigest: "gcr.io/test/image@" + imageDigest, - Status: duckv1beta1.Status{ + Status: duckv1.Status{ Conditions: goodConditions(), }, }, } } -func goodConditions() duckv1beta1.Conditions { - ret := make(duckv1beta1.Conditions, 0) +func goodConditions() duckv1.Conditions { + ret := make(duckv1.Conditions, 0) ret = append(ret, apis.Condition{ Type: apis.ConditionReady, Status: v1.ConditionTrue, diff --git a/pkg/kn/commands/service/update_test.go b/pkg/kn/commands/service/update_test.go index 8f89c506a8..12afac6337 100644 --- a/pkg/kn/commands/service/update_test.go +++ b/pkg/kn/commands/service/update_test.go @@ -328,7 +328,7 @@ func TestServiceUpdateMaxMinScale(t *testing.T) { } } - if template.Spec.ContainerConcurrency != 100 { + if *template.Spec.ContainerConcurrency != int64(100) { t.Fatalf("container concurrency not set to given value 1000") } diff --git a/pkg/kn/traffic/compute.go b/pkg/kn/traffic/compute.go index 41060a39ef..dd066f1eaf 100644 --- a/pkg/kn/traffic/compute.go +++ b/pkg/kn/traffic/compute.go @@ -42,8 +42,8 @@ func splitByEqualSign(pair string) (string, string, error) { return parts[0], strings.TrimSuffix(parts[1], "%"), nil } -func newTarget(tag, revision string, percent int, latestRevision bool) (target v1alpha1.TrafficTarget) { - target.Percent = percent +func newTarget(tag, revision string, percent int64, latestRevision bool) (target v1alpha1.TrafficTarget) { + target.Percent = ptr.Int64(percent) target.Tag = tag if latestRevision { target.LatestRevision = ptr.Bool(true) @@ -140,30 +140,30 @@ func (e ServiceTraffic) TagLatestRevision(tag string) ServiceTraffic { } // SetTrafficByRevision checks given revision in existing traffic block and sets given percent if found -func (e ServiceTraffic) SetTrafficByRevision(revision string, percent int) { +func (e ServiceTraffic) SetTrafficByRevision(revision string, percent int64) { for i, target := range e { if target.RevisionName == revision { - e[i].Percent = percent + e[i].Percent = ptr.Int64(percent) break } } } // SetTrafficByTag checks given tag in existing traffic block and sets given percent if found -func (e ServiceTraffic) SetTrafficByTag(tag string, percent int) { +func (e ServiceTraffic) SetTrafficByTag(tag string, percent int64) { for i, target := range e { if target.Tag == tag { - e[i].Percent = percent + e[i].Percent = ptr.Int64(percent) break } } } // SetTrafficByLatestRevision sets given percent to latest ready revision of service -func (e ServiceTraffic) SetTrafficByLatestRevision(percent int) { +func (e ServiceTraffic) SetTrafficByLatestRevision(percent int64) { for i, target := range e { if *target.LatestRevision { - e[i].Percent = percent + e[i].Percent = ptr.Int64(percent) break } } @@ -172,14 +172,14 @@ func (e ServiceTraffic) SetTrafficByLatestRevision(percent int) { // ResetAllTargetPercent resets (0) 'Percent' field for all the traffic targets func (e ServiceTraffic) ResetAllTargetPercent() { for i := range e { - e[i].Percent = 0 + e[i].Percent = ptr.Int64(0) } } // RemoveNullTargets removes targets from traffic block if they don't have and 0 percent traffic func (e ServiceTraffic) RemoveNullTargets() (newTraffic ServiceTraffic) { for _, target := range e { - if target.Tag == "" && target.Percent == 0 { + if target.Tag == "" && target.Percent == ptr.Int64(0) { } else { newTraffic = append(newTraffic, target) } @@ -323,8 +323,8 @@ func Compute(cmd *cobra.Command, targets []v1alpha1.TrafficTarget, trafficFlags for _, each := range trafficFlags.RevisionsPercentages { // revisionRef works here as either revision or tag as either can be specified on CLI - revisionRef, percent, _ := splitByEqualSign(each) // err is verified in verifyInputSanity - percentInt, _ := strconv.Atoi(percent) // percentInt (for int) is verified in verifyInputSanity + revisionRef, percent, _ := splitByEqualSign(each) // err is verified in verifyInputSanity + percentInt, _ := strconv.ParseInt(percent, 10, 64) // percentInt (for int) is verified in verifyInputSanity // fourth precedence: set traffic for latest revision if revisionRef == latestRevisionRef { diff --git a/pkg/kn/traffic/compute_test.go b/pkg/kn/traffic/compute_test.go index c37a403cab..f1dccb58f2 100644 --- a/pkg/kn/traffic/compute_test.go +++ b/pkg/kn/traffic/compute_test.go @@ -30,7 +30,7 @@ type trafficTestCase struct { inputFlags []string desiredRevisions []string desiredTags []string - desiredPercents []int + desiredPercents []int64 } type trafficErrorTestCase struct { @@ -59,7 +59,7 @@ func TestCompute(t *testing.T) { []string{"--tag", "@latest=latest"}, []string{"@latest"}, []string{"latest"}, - []int{100}, + []int64{100}, }, { "assign tag to revision", @@ -67,7 +67,7 @@ func TestCompute(t *testing.T) { []string{"--tag", "echo-v1=stable"}, []string{"echo-v1"}, []string{"stable"}, - []int{100}, + []int64{100}, }, { "re-assign same tag to same revision (unchanged)", @@ -75,7 +75,7 @@ func TestCompute(t *testing.T) { []string{"--tag", "@latest=current"}, []string{""}, []string{"current"}, - []int{100}, + []int64{100}, }, { "split traffic to tags", @@ -83,7 +83,7 @@ func TestCompute(t *testing.T) { []string{"--traffic", "@latest=10,rev-v1=90"}, []string{"@latest", "rev-v1"}, []string{"", ""}, - []int{10, 90}, + []int64{10, 90}, }, { "split traffic to tags with '%' suffix", @@ -91,7 +91,7 @@ func TestCompute(t *testing.T) { []string{"--traffic", "@latest=10%,rev-v1=90%"}, []string{"@latest", "rev-v1"}, []string{"", ""}, - []int{10, 90}, + []int64{10, 90}, }, { "add 2 more tagged revisions without giving them traffic portions", @@ -99,7 +99,7 @@ func TestCompute(t *testing.T) { []string{"--tag", "echo-v0=stale,echo-v1=old"}, []string{"@latest", "echo-v0", "echo-v1"}, []string{"latest", "stale", "old"}, - []int{100, 0, 0}, + []int64{100, 0, 0}, }, { "re-assign same tag to 'echo-v1' revision", @@ -107,7 +107,7 @@ func TestCompute(t *testing.T) { []string{"--tag", "echo-v1=latest"}, []string{"echo-v1"}, []string{"latest"}, - []int{100}, + []int64{100}, }, { "set 2% traffic to latest revision by appending it in traffic block", @@ -115,7 +115,7 @@ func TestCompute(t *testing.T) { []string{"--traffic", "@latest=2,echo-v1=98"}, []string{"echo-v1", "@latest"}, []string{"latest", ""}, - []int{98, 2}, + []int64{98, 2}, }, { "set 2% to @latest with tag (append it in traffic block)", @@ -123,7 +123,7 @@ func TestCompute(t *testing.T) { []string{"--traffic", "@latest=2,echo-v1=98", "--tag", "@latest=testing"}, []string{"echo-v1", "@latest"}, []string{"latest", "testing"}, - []int{98, 2}, + []int64{98, 2}, }, { "change traffic percent of an existing revision in traffic block, add new revision with traffic share", @@ -131,7 +131,7 @@ func TestCompute(t *testing.T) { []string{"--tag", "echo-v2=v2", "--traffic", "v1=10,v2=90"}, []string{"echo-v1", "echo-v2"}, []string{"v1", "v2"}, - []int{10, 90}, //default value, + []int64{10, 90}, //default value, }, { "untag 'latest' tag from 'echo-v1' revision", @@ -139,7 +139,7 @@ func TestCompute(t *testing.T) { []string{"--untag", "latest"}, []string{"echo-v1"}, []string{""}, - []int{100}, + []int64{100}, }, { "replace revision pointing to 'latest' tag from 'echo-v1' to 'echo-v2' revision", @@ -147,7 +147,7 @@ func TestCompute(t *testing.T) { []string{"--untag", "latest", "--tag", "echo-v1=old,echo-v2=latest"}, []string{"echo-v1", "echo-v2"}, []string{"old", "latest"}, - []int{50, 50}, + []int64{50, 50}, }, { "have multiple tags for a revision, revision present in traffic block", @@ -155,7 +155,7 @@ func TestCompute(t *testing.T) { []string{"--tag", "echo-v1=latest,echo-v1=current"}, []string{"echo-v1", "echo-v2", "echo-v1"}, // appends a new target []string{"latest", "", "current"}, // with new tag requested - []int{50, 50, 0}, // and assign 0% to it + []int64{50, 50, 0}, // and assign 0% to it }, { @@ -164,7 +164,7 @@ func TestCompute(t *testing.T) { []string{"--tag", "echo-v1=latest,echo-v1=current"}, []string{"echo-v2", "echo-v1", "echo-v1"}, // appends two new targets []string{"", "latest", "current"}, // with new tags requested - []int{100, 0, 0}, // and assign 0% to each + []int64{100, 0, 0}, // and assign 0% to each }, { "re-assign same tag 'current' to @latest", @@ -172,7 +172,7 @@ func TestCompute(t *testing.T) { []string{"--tag", "@latest=current"}, []string{""}, []string{"current"}, // since no change, no error - []int{100}, + []int64{100}, }, { "assign echo-v1 10% traffic adjusting rest to @latest, echo-v1 isn't present in existing traffic block", @@ -180,7 +180,7 @@ func TestCompute(t *testing.T) { []string{"--traffic", "echo-v1=10,@latest=90"}, []string{"", "echo-v1"}, []string{"", ""}, // since no change, no error - []int{90, 10}, + []int64{90, 10}, }, } { t.Run(testCase.name, func(t *testing.T) { @@ -203,7 +203,7 @@ func TestCompute(t *testing.T) { assert.Equal(t, target.RevisionName, testCase.desiredRevisions[i]) } assert.Equal(t, target.Tag, testCase.desiredTags[i]) - assert.Equal(t, target.Percent, testCase.desiredPercents[i]) + assert.Equal(t, *target.Percent, testCase.desiredPercents[i]) } }) } diff --git a/pkg/serving/config_changes.go b/pkg/serving/config_changes.go index cb73ed9149..37224fdbab 100644 --- a/pkg/serving/config_changes.go +++ b/pkg/serving/config_changes.go @@ -15,7 +15,6 @@ package serving import ( - "context" "errors" "fmt" "sort" @@ -24,9 +23,12 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/sets" + "knative.dev/pkg/ptr" "knative.dev/serving/pkg/apis/autoscaling" servingv1alpha1 "knative.dev/serving/pkg/apis/serving/v1alpha1" - servingv1beta1 "knative.dev/serving/pkg/apis/serving/v1beta1" + + //servingv1beta1 "knative.dev/serving/pkg/apis/serving/v1beta1" + "knative.dev/serving/pkg/apis/serving" ) var UserImageAnnotationKey = "client.knative.dev/user-image" @@ -66,14 +68,13 @@ func UpdateConcurrencyTarget(template *servingv1alpha1.RevisionTemplateSpec, tar } // UpdateConcurrencyLimit updates container concurrency limit -func UpdateConcurrencyLimit(template *servingv1alpha1.RevisionTemplateSpec, limit int) error { - cc := servingv1beta1.RevisionContainerConcurrencyType(limit) - // Validate input limit - ctx := context.Background() - if err := cc.Validate(ctx).ViaField("spec.containerConcurrency"); err != nil { +func UpdateConcurrencyLimit(template *servingv1alpha1.RevisionTemplateSpec, limit int64) error { + err := serving.ValidateContainerConcurrency(ptr.Int64(limit)).ViaField("spec.containerConcurrency") + if err != nil { return fmt.Errorf("invalid 'concurrency-limit' value: %s", err) } - template.Spec.ContainerConcurrency = cc + + template.Spec.ContainerConcurrency = ptr.Int64(limit) return nil } diff --git a/pkg/serving/config_changes_test.go b/pkg/serving/config_changes_test.go index e1c0c70389..5bc6e8d23f 100644 --- a/pkg/serving/config_changes_test.go +++ b/pkg/serving/config_changes_test.go @@ -21,11 +21,12 @@ import ( "gotest.tools/assert" + "knative.dev/pkg/ptr" "knative.dev/serving/pkg/apis/autoscaling" - "knative.dev/serving/pkg/apis/serving/v1beta1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + servingv1 "knative.dev/serving/pkg/apis/serving/v1" servingv1alpha1 "knative.dev/serving/pkg/apis/serving/v1alpha1" ) @@ -42,7 +43,7 @@ func TestUpdateAutoscalingAnnotations(t *testing.T) { if annos[autoscaling.TargetAnnotationKey] != "1000" { t.Error("target failed") } - if template.Spec.ContainerConcurrency != 1000 { + if *template.Spec.ContainerConcurrency != int64(1000) { t.Error("limit failed") } } @@ -62,8 +63,8 @@ func TestUpdateInvalidAutoscalingAnnotations(t *testing.T) { if annos[autoscaling.TargetAnnotationKey] != "1000" { t.Error("target failed") } - if template.Spec.ContainerConcurrency != 1000 { - t.Error("limit failed") + if *template.Spec.ContainerConcurrency != 1000 { + t.Errorf("limit failed") } } @@ -256,7 +257,7 @@ func TestUpdateConcurrencyLimit(t *testing.T) { err := UpdateConcurrencyLimit(template, 10) assert.NilError(t, err) // Verify update is successful or not - checkContainerConcurrency(t, template, 10) + checkContainerConcurrency(t, template, ptr.Int64(int64(10))) // Update with invalid value err = UpdateConcurrencyLimit(template, -1) assert.ErrorContains(t, err, "invalid") @@ -492,7 +493,7 @@ func getV1alpha1RevisionTemplateWithOldFields() (*servingv1alpha1.RevisionTempla container := &corev1.Container{} template := &servingv1alpha1.RevisionTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Name: "template-foo", + Name: "-template-foo", Namespace: "default", }, Spec: servingv1alpha1.RevisionSpec{ @@ -506,11 +507,11 @@ func getV1alpha1Config() (*servingv1alpha1.RevisionTemplateSpec, *corev1.Contain containers := []corev1.Container{{}} template := &servingv1alpha1.RevisionTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Name: "template-foo", + Name: "-template-foo", Namespace: "default", }, Spec: servingv1alpha1.RevisionSpec{ - RevisionSpec: v1beta1.RevisionSpec{ + RevisionSpec: servingv1.RevisionSpec{ PodSpec: corev1.PodSpec{ Containers: containers, }, @@ -561,8 +562,8 @@ func checkAnnotationValue(t *testing.T, template *servingv1alpha1.RevisionTempla } } -func checkContainerConcurrency(t *testing.T, template *servingv1alpha1.RevisionTemplateSpec, value int) { - if got, want := template.Spec.ContainerConcurrency, value; got != v1beta1.RevisionContainerConcurrencyType(want) { +func checkContainerConcurrency(t *testing.T, template *servingv1alpha1.RevisionTemplateSpec, value *int64) { + if got, want := *template.Spec.ContainerConcurrency, *value; got != want { t.Errorf("Failed to update containerConcurrency value: got=%d, want=%d", got, want) } } @@ -571,5 +572,5 @@ func updateConcurrencyConfiguration(template *servingv1alpha1.RevisionTemplateSp UpdateMinScale(template, minScale) UpdateMaxScale(template, maxScale) UpdateConcurrencyTarget(template, target) - UpdateConcurrencyLimit(template, limit) + UpdateConcurrencyLimit(template, int64(limit)) } diff --git a/pkg/wait/test_wait_helper.go b/pkg/wait/test_wait_helper.go index 050cc260ad..65ce727522 100644 --- a/pkg/wait/test_wait_helper.go +++ b/pkg/wait/test_wait_helper.go @@ -20,7 +20,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" "knative.dev/pkg/apis" - duck "knative.dev/pkg/apis/duck/v1beta1" + duck "knative.dev/pkg/apis/duck/v1" "knative.dev/serving/pkg/apis/serving/v1alpha1" ) diff --git a/vendor/modules.txt b/vendor/modules.txt index ff05eea495..0c4fdb7668 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -383,23 +383,22 @@ k8s.io/client-go/listers/storage/v1beta1 k8s.io/kube-openapi/pkg/util/proto # knative.dev/pkg v0.0.0-20191022181926-0b19b4ad9139 knative.dev/pkg/apis -knative.dev/pkg/apis/duck/v1beta1 +knative.dev/pkg/apis/duck/v1 knative.dev/pkg/ptr knative.dev/pkg/kmp knative.dev/pkg/apis/duck -knative.dev/pkg/apis/duck/v1 knative.dev/pkg/apis/v1alpha1 knative.dev/pkg/apis/duck/v1alpha1 knative.dev/pkg/kmeta knative.dev/pkg/configmap knative.dev/pkg/network +knative.dev/pkg/apis/duck/v1beta1 # knative.dev/serving v0.9.0 knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1alpha1 knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1alpha1/fake knative.dev/serving/pkg/apis/serving knative.dev/serving/pkg/apis/serving/v1alpha1 knative.dev/serving/pkg/apis/autoscaling -knative.dev/serving/pkg/apis/serving/v1beta1 knative.dev/serving/pkg/client/clientset/versioned/scheme knative.dev/serving/pkg/apis/config knative.dev/serving/pkg/apis/networking @@ -407,6 +406,7 @@ knative.dev/serving/pkg/reconciler/route/config knative.dev/serving/pkg/apis/autoscaling/v1alpha1 knative.dev/serving/pkg/apis/networking/v1alpha1 knative.dev/serving/pkg/apis/serving/v1 +knative.dev/serving/pkg/apis/serving/v1beta1 knative.dev/serving/pkg/gc knative.dev/serving/pkg/network # knative.dev/test-infra v0.0.0-20190730202142-17f2331e80ad From 1a2f0f9b524c1da3e3e9e6a67135c1a6e6dc3867 Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Thu, 24 Oct 2019 22:16:26 +0530 Subject: [PATCH 3/5] fix(golint): exported function should have comment for NonReadyConditionReason function --- pkg/kn/commands/human_readable_flags.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/kn/commands/human_readable_flags.go b/pkg/kn/commands/human_readable_flags.go index 198ed32dbd..811d50ad19 100644 --- a/pkg/kn/commands/human_readable_flags.go +++ b/pkg/kn/commands/human_readable_flags.go @@ -90,6 +90,8 @@ func ReadyCondition(conditions duckv1.Conditions) string { return "" } +// NonReadyConditionReason returns formatted string of +// reason and message for non ready conditions func NonReadyConditionReason(conditions duckv1.Conditions) string { for _, condition := range conditions { if condition.Type == apis.ConditionReady { From bc08d1b384a576c6ecdf49da465ae4ddaf5f4653 Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Fri, 25 Oct 2019 15:02:12 +0530 Subject: [PATCH 4/5] Updates check for removing null targets fixes the pointer value check --- pkg/kn/traffic/compute.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/kn/traffic/compute.go b/pkg/kn/traffic/compute.go index dd066f1eaf..97a706d832 100644 --- a/pkg/kn/traffic/compute.go +++ b/pkg/kn/traffic/compute.go @@ -176,14 +176,15 @@ func (e ServiceTraffic) ResetAllTargetPercent() { } } -// RemoveNullTargets removes targets from traffic block if they don't have and 0 percent traffic +// RemoveNullTargets removes targets from traffic block +// if they don't have a tag and 0 percent traffic func (e ServiceTraffic) RemoveNullTargets() (newTraffic ServiceTraffic) { for _, target := range e { - if target.Tag == "" && target.Percent == ptr.Int64(0) { - } else { + if target.Tag != "" || *target.Percent != int64(0) { newTraffic = append(newTraffic, target) } } + return newTraffic } @@ -192,6 +193,7 @@ func errorOverWritingtagOfLatestReadyRevision(existingTag, requestedTag string) "refusing to overwrite existing tag with '%s', "+ "add flag '--untag %s' in command to untag it", existingTag, requestedTag, existingTag) } + func errorOverWritingTag(tag string) error { return fmt.Errorf("refusing to overwrite existing tag in service, "+ "add flag '--untag %s' in command to untag it", tag) From 9051ee362d7324b67aca0b9767e4bb4821ecf70c Mon Sep 17 00:00:00 2001 From: Navid Shaikh Date: Sat, 26 Oct 2019 12:04:40 +0530 Subject: [PATCH 5/5] Updates per review comments --- pkg/serving/config_changes.go | 4 +--- pkg/serving/config_changes_test.go | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/pkg/serving/config_changes.go b/pkg/serving/config_changes.go index 37224fdbab..52a1ceebb5 100644 --- a/pkg/serving/config_changes.go +++ b/pkg/serving/config_changes.go @@ -25,10 +25,8 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "knative.dev/pkg/ptr" "knative.dev/serving/pkg/apis/autoscaling" - servingv1alpha1 "knative.dev/serving/pkg/apis/serving/v1alpha1" - - //servingv1beta1 "knative.dev/serving/pkg/apis/serving/v1beta1" "knative.dev/serving/pkg/apis/serving" + servingv1alpha1 "knative.dev/serving/pkg/apis/serving/v1alpha1" ) var UserImageAnnotationKey = "client.knative.dev/user-image" diff --git a/pkg/serving/config_changes_test.go b/pkg/serving/config_changes_test.go index 5bc6e8d23f..e81594c8ca 100644 --- a/pkg/serving/config_changes_test.go +++ b/pkg/serving/config_changes_test.go @@ -64,7 +64,7 @@ func TestUpdateInvalidAutoscalingAnnotations(t *testing.T) { t.Error("target failed") } if *template.Spec.ContainerConcurrency != 1000 { - t.Errorf("limit failed") + t.Error("limit failed") } } @@ -493,7 +493,7 @@ func getV1alpha1RevisionTemplateWithOldFields() (*servingv1alpha1.RevisionTempla container := &corev1.Container{} template := &servingv1alpha1.RevisionTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Name: "-template-foo", + Name: "template-foo", Namespace: "default", }, Spec: servingv1alpha1.RevisionSpec{ @@ -507,7 +507,7 @@ func getV1alpha1Config() (*servingv1alpha1.RevisionTemplateSpec, *corev1.Contain containers := []corev1.Container{{}} template := &servingv1alpha1.RevisionTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Name: "-template-foo", + Name: "template-foo", Namespace: "default", }, Spec: servingv1alpha1.RevisionSpec{