Merge pull request #53695 from hzxuzhonghu/audit-graceful-shutdown
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Shutdown http handlers before shutting down audit backend **What this PR does / why we need it**: Currently, audit backend is shut down before http handlers stop processing requests, so some audit events can be dropped in case of batching webhook. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #50781 **Special notes for your reviewer**: **Release note**: ```release-note Shutdown http handlers in kube-apiserver before shutting down audit backend. ``` Kubernetes-commit: 7a6a58f4444c60a9b3fefe335a303f0c230d8f10
This commit is contained in:
commit
199394ed2d
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"ImportPath": "k8s.io/apiserver",
|
||||
"GoVersion": "go1.8",
|
||||
"GoVersion": "go1.9",
|
||||
"GodepVersion": "v79",
|
||||
"Packages": [
|
||||
"./..."
|
||||
|
|
@ -764,339 +764,339 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/admission/v1alpha1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/admissionregistration/v1alpha1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/apps/v1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/apps/v1beta1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/apps/v1beta2",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/authentication/v1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/authentication/v1beta1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/authorization/v1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/authorization/v1beta1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/autoscaling/v1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/autoscaling/v2beta1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/batch/v1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/batch/v1beta1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/batch/v2alpha1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/certificates/v1beta1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/core/v1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/extensions/v1beta1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/networking/v1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/policy/v1beta1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/rbac/v1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/rbac/v1alpha1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/rbac/v1beta1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/scheduling/v1alpha1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/settings/v1alpha1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/storage/v1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/storage/v1beta1",
|
||||
"Rev": "218912509d74a117d05a718bb926d0948e531c20"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/equality",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/errors",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/meta",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/testing",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/validation",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/validation/path",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apimachinery",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apimachinery/announced",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apimachinery/registered",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/validation",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1alpha1",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/conversion",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/conversion/unstructured",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/fields",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/labels",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/selection",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/types",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/cache",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/clock",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/diff",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/errors",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/framer",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/intstr",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/json",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/net",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/proxy",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/rand",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/runtime",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/sets",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/uuid",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/validation",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/validation/field",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/wait",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/yaml",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/version",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/watch",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
|
||||
"Rev": "18a564baac720819100827c16fdebcadb05b2d0d"
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/discovery",
|
||||
|
|
@ -1106,10 +1106,6 @@
|
|||
"ImportPath": "k8s.io/client-go/discovery/fake",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/informers",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/informers/admissionregistration",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
|
|
@ -1254,10 +1250,6 @@
|
|||
"ImportPath": "k8s.io/client-go/kubernetes",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/kubernetes/fake",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/kubernetes/scheme",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
|
|
@ -1570,10 +1562,6 @@
|
|||
"ImportPath": "k8s.io/client-go/tools/cache",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/tools/clientcmd",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/tools/clientcmd/api",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
|
|
@ -1637,6 +1625,74 @@
|
|||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util",
|
||||
"Rev": "61b46af70dfed79c6d24530cd23b41440a7f22a5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/discovery",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/informers",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/kubernetes",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/kubernetes/fake",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/kubernetes/scheme",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/kubernetes/typed/authentication/v1beta1",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/kubernetes/typed/authorization/v1beta1",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/kubernetes/typed/core/v1",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/listers/core/v1",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/rest",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/testing",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/tools/cache",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/tools/clientcmd",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/tools/clientcmd/api",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/tools/clientcmd/api/v1",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/util/cert",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go/util/flowcontrol",
|
||||
"Rev": "dbe8fe09ed1682bc26b4e55cac5ef65dcd7664e9"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,10 @@ go_test(
|
|||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/endpoints/discovery:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/endpoints/filters:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server/filters:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server/healthz:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/etcd/testing:go_default_library",
|
||||
"//vendor/k8s.io/client-go/informers:go_default_library",
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/emicklei/go-restful-swagger12"
|
||||
|
|
@ -128,6 +129,8 @@ type Config struct {
|
|||
|
||||
// BuildHandlerChainFunc allows you to build custom handler chains by decorating the apiHandler.
|
||||
BuildHandlerChainFunc func(apiHandler http.Handler, c *Config) (secure http.Handler)
|
||||
// HandlerChainWaitGroup allows you to wait for all chain handlers exit after the server shutdown.
|
||||
HandlerChainWaitGroup *sync.WaitGroup
|
||||
// DiscoveryAddresses is used to build the IPs pass to discovery. If nil, the ExternalAddress is
|
||||
// always reported
|
||||
DiscoveryAddresses discovery.Addresses
|
||||
|
|
@ -236,6 +239,7 @@ func NewConfig(codecs serializer.CodecFactory) *Config {
|
|||
ReadWritePort: 443,
|
||||
RequestContextMapper: apirequest.NewRequestContextMapper(),
|
||||
BuildHandlerChainFunc: DefaultBuildHandlerChain,
|
||||
HandlerChainWaitGroup: new(sync.WaitGroup),
|
||||
LegacyAPIGroupPrefixes: sets.NewString(DefaultLegacyAPIPrefix),
|
||||
DisabledPostStartHooks: sets.NewString(),
|
||||
HealthzChecks: []healthz.HealthzChecker{healthz.PingHealthz},
|
||||
|
|
@ -446,8 +450,10 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G
|
|||
Serializer: c.Serializer,
|
||||
AuditBackend: c.AuditBackend,
|
||||
delegationTarget: delegationTarget,
|
||||
HandlerChainWaitGroup: c.HandlerChainWaitGroup,
|
||||
|
||||
minRequestTimeout: time.Duration(c.MinRequestTimeout) * time.Second,
|
||||
shutdownTimeout: c.RequestTimeout,
|
||||
|
||||
SecureServingInfo: c.SecureServingInfo,
|
||||
ExternalAddress: c.ExternalAddress,
|
||||
|
|
@ -488,6 +494,7 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for _, delegateCheck := range delegationTarget.HealthzChecks() {
|
||||
skip := false
|
||||
for _, existingCheck := range c.HealthzChecks {
|
||||
|
|
@ -535,6 +542,7 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
|
|||
handler = genericapifilters.WithAuthentication(handler, c.RequestContextMapper, c.Authenticator, failedHandler)
|
||||
handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true")
|
||||
handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.RequestContextMapper, c.LongRunningFunc, c.RequestTimeout)
|
||||
handler = genericfilters.WithWaitGroup(handler, c.RequestContextMapper, c.LongRunningFunc, c.HandlerChainWaitGroup)
|
||||
handler = genericapifilters.WithRequestInfo(handler, c.RequestInfoResolver, c.RequestContextMapper)
|
||||
handler = apirequest.WithRequestContext(handler, c.RequestContextMapper)
|
||||
handler = genericfilters.WithPanicRecovery(handler)
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ go_library(
|
|||
"longrunning.go",
|
||||
"maxinflight.go",
|
||||
"timeout.go",
|
||||
"waitgroup.go",
|
||||
"wrap.go",
|
||||
],
|
||||
importpath = "k8s.io/apiserver/pkg/server/filters",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package filters
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
apirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
)
|
||||
|
||||
// WithWaitGroup adds all non long-running requests to wait group, which is used for graceful shutdown.
|
||||
func WithWaitGroup(handler http.Handler, requestContextMapper apirequest.RequestContextMapper, longRunning apirequest.LongRunningRequestCheck, wg *sync.WaitGroup) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
ctx, ok := requestContextMapper.Get(req)
|
||||
if !ok {
|
||||
// if this happens, the handler chain isn't setup correctly because there is no context mapper
|
||||
handler.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
requestInfo, ok := apirequest.RequestInfoFrom(ctx)
|
||||
if !ok {
|
||||
// if this happens, the handler chain isn't setup correctly because there is no request info
|
||||
handler.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
if !longRunning(req, requestInfo) {
|
||||
wg.Add(1)
|
||||
defer wg.Done()
|
||||
}
|
||||
|
||||
handler.ServeHTTP(w, req)
|
||||
})
|
||||
}
|
||||
|
|
@ -89,6 +89,9 @@ type GenericAPIServer struct {
|
|||
// minRequestTimeout is how short the request timeout can be. This is used to build the RESTHandler
|
||||
minRequestTimeout time.Duration
|
||||
|
||||
// shutdownTimeout is the timeout used for server shutdown.
|
||||
shutdownTimeout time.Duration
|
||||
|
||||
// legacyAPIGroupPrefixes is used to set up URL parsing for authorization and for validating requests
|
||||
// to InstallLegacyAPIGroup
|
||||
legacyAPIGroupPrefixes sets.String
|
||||
|
|
@ -152,6 +155,9 @@ type GenericAPIServer struct {
|
|||
|
||||
// delegationTarget is the next delegate in the chain or nil
|
||||
delegationTarget DelegationTarget
|
||||
|
||||
// HandlerChainWaitGroup allows you to wait for all chain handlers finish after the server shutdown.
|
||||
HandlerChainWaitGroup *sync.WaitGroup
|
||||
}
|
||||
|
||||
// DelegationTarget is an interface which allows for composition of API servers with top level handling that works
|
||||
|
|
@ -281,16 +287,28 @@ func (s preparedGenericAPIServer) Run(stopCh <-chan struct{}) error {
|
|||
|
||||
<-stopCh
|
||||
|
||||
return s.RunPreShutdownHooks()
|
||||
err = s.RunPreShutdownHooks()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Wait for all requests to finish, which is bounded by the RequestTimeout variable.
|
||||
s.HandlerChainWaitGroup.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NonBlockingRun spawns the secure http server. An error is
|
||||
// returned if the secure port cannot be listened on.
|
||||
func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) error {
|
||||
// Use an stop channel to allow graceful shutdown without dropping audit events
|
||||
// after http server shutdown.
|
||||
auditStopCh := make(chan struct{})
|
||||
|
||||
// Start the audit backend before any request comes in. This means we must call Backend.Run
|
||||
// before http server start serving. Otherwise the Backend.ProcessEvents call might block.
|
||||
if s.AuditBackend != nil {
|
||||
if err := s.AuditBackend.Run(stopCh); err != nil {
|
||||
if err := s.AuditBackend.Run(auditStopCh); err != nil {
|
||||
return fmt.Errorf("failed to run the audit backend: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
@ -311,6 +329,8 @@ func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) error {
|
|||
go func() {
|
||||
<-stopCh
|
||||
close(internalStopCh)
|
||||
s.HandlerChainWaitGroup.Wait()
|
||||
close(auditStopCh)
|
||||
}()
|
||||
|
||||
s.RunPostStartHooks(stopCh)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
goruntime "runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -44,8 +46,11 @@ import (
|
|||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/endpoints/discovery"
|
||||
genericapifilters "k8s.io/apiserver/pkg/endpoints/filters"
|
||||
apirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
genericfilters "k8s.io/apiserver/pkg/server/filters"
|
||||
etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
|
|
@ -509,3 +514,75 @@ func fakeVersion() version.Info {
|
|||
Platform: fmt.Sprintf("%s/%s", goruntime.GOOS, goruntime.GOARCH),
|
||||
}
|
||||
}
|
||||
|
||||
// TestGracefulShutdown verifies server shutdown after request handler finish.
|
||||
func TestGracefulShutdown(t *testing.T) {
|
||||
etcdserver, config, _ := setUp(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
var graceShutdown bool
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
|
||||
config.BuildHandlerChainFunc = func(apiHandler http.Handler, c *Config) http.Handler {
|
||||
handler := genericfilters.WithWaitGroup(apiHandler, c.RequestContextMapper, c.LongRunningFunc, c.HandlerChainWaitGroup)
|
||||
handler = genericapifilters.WithRequestInfo(handler, c.RequestInfoResolver, c.RequestContextMapper)
|
||||
handler = apirequest.WithRequestContext(handler, c.RequestContextMapper)
|
||||
return handler
|
||||
}
|
||||
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
wg.Done()
|
||||
time.Sleep(2 * time.Second)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
graceShutdown = true
|
||||
})
|
||||
|
||||
s, err := config.Complete(nil).New("test", EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in bringing up the server: %v", err)
|
||||
}
|
||||
|
||||
s.Handler.NonGoRestfulMux.Handle("/test", handler)
|
||||
|
||||
insecureServer := &http.Server{
|
||||
Addr: "0.0.0.0:0",
|
||||
Handler: s.Handler,
|
||||
}
|
||||
stopCh := make(chan struct{})
|
||||
serverPort, err := RunServer(insecureServer, "tcp", 10*time.Second, stopCh)
|
||||
if err != nil {
|
||||
t.Errorf("RunServer err: %v", err)
|
||||
}
|
||||
|
||||
graceCh := make(chan struct{})
|
||||
// mock a client request
|
||||
go func() {
|
||||
resp, err := http.Get("http://127.0.0.1:" + strconv.Itoa(serverPort) + "/test")
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected http error: %v", err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("Unexpected http status code: %v", resp.StatusCode)
|
||||
}
|
||||
close(graceCh)
|
||||
}()
|
||||
|
||||
// close stopCh after request sent to server to guarantee request handler is running.
|
||||
wg.Wait()
|
||||
close(stopCh)
|
||||
// wait for wait group handler finish
|
||||
s.HandlerChainWaitGroup.Wait()
|
||||
|
||||
// check server all handlers finished.
|
||||
if !graceShutdown {
|
||||
t.Errorf("server shutdown not gracefully.")
|
||||
}
|
||||
// check client to make sure receive response.
|
||||
select {
|
||||
case <-graceCh:
|
||||
t.Logf("server shutdown gracefully.")
|
||||
case <-time.After(30 * time.Second):
|
||||
t.Errorf("Timed out waiting for response.")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
|
|
@ -84,13 +85,13 @@ func (s *GenericAPIServer) serveSecurely(stopCh <-chan struct{}) error {
|
|||
|
||||
glog.Infof("Serving securely on %s", s.SecureServingInfo.BindAddress)
|
||||
var err error
|
||||
s.effectiveSecurePort, err = RunServer(secureServer, s.SecureServingInfo.BindNetwork, stopCh)
|
||||
s.effectiveSecurePort, err = RunServer(secureServer, s.SecureServingInfo.BindNetwork, s.shutdownTimeout, stopCh)
|
||||
return err
|
||||
}
|
||||
|
||||
// RunServer listens on the given port, then spawns a go-routine continuously serving
|
||||
// until the stopCh is closed. The port is returned. This function does not block.
|
||||
func RunServer(server *http.Server, network string, stopCh <-chan struct{}) (int, error) {
|
||||
func RunServer(server *http.Server, network string, shutDownTimeout time.Duration, stopCh <-chan struct{}) (int, error) {
|
||||
if len(server.Addr) == 0 {
|
||||
return 0, errors.New("address cannot be empty")
|
||||
}
|
||||
|
|
@ -111,10 +112,12 @@ func RunServer(server *http.Server, network string, stopCh <-chan struct{}) (int
|
|||
return 0, fmt.Errorf("invalid listen address: %q", ln.Addr().String())
|
||||
}
|
||||
|
||||
// Stop the server by closing the listener
|
||||
// Shutdown server gracefully.
|
||||
go func() {
|
||||
<-stopCh
|
||||
ln.Close()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), shutDownTimeout)
|
||||
server.Shutdown(ctx)
|
||||
cancel()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue