Hello community,

here is the log from the commit of package kured for openSUSE:Leap:15.2 checked 
in at 2020-03-09 18:12:47
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Leap:15.2/kured (Old)
 and      /work/SRC/openSUSE:Leap:15.2/.kured.new.26092 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kured"

Mon Mar  9 18:12:47 2020 rev:2 rq:781956 version:1.3.0

Changes:
--------
--- /work/SRC/openSUSE:Leap:15.2/kured/kured.changes    2020-02-19 
18:36:22.181686758 +0100
+++ /work/SRC/openSUSE:Leap:15.2/.kured.new.26092/kured.changes 2020-03-09 
18:13:37.957389990 +0100
@@ -1,0 +2,12 @@
+Mon Mar  2 14:26:38 UTC 2020 - Thorsten Kukuk <[email protected]>
+
+- Update to version 1.3.0
+  - Update k8s client tools to 1.15.x
+  - Ad Slack channel name configuration
+  - Add reboot window
+- Obsoletes k8s-1.14.diff 
+- Remove kured-telemetrics.patch, chances that upstream accepts
+  any third party code are nearly zero.
+- Update vendor.tar.xz
+
+-------------------------------------------------------------------

Old:
----
  k8s-1.14.diff
  kured-1.2.0.tar.gz
  kured-telemetrics.patch
  vendor.tar.gz

New:
----
  kured-1.3.0.tar.gz
  vendor.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kured.spec ++++++
--- /var/tmp/diff_new_pack.BL7ANT/_old  2020-03-09 18:13:39.553390764 +0100
+++ /var/tmp/diff_new_pack.BL7ANT/_new  2020-03-09 18:13:39.593390784 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package kured
 #
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -22,20 +22,18 @@
 # Project name when using go tooling.
 %define project github.com/weaveworks/kured
 # Project upstream commit.
-%define commit dcddbff
+%define commit 2a0ad53
 Name:           kured
-Version:        1.2.0
+Version:        1.3.0
 Release:        0
 Summary:        Kubernetes daemonset to perform safe automatic node reboots
 License:        Apache-2.0
 Group:          System/Management
 URL:            https://github.com/weaveworks/kured
 Source:         %{name}-%{version}.tar.gz
-Source1:        vendor.tar.gz
-Patch:          kured-telemetrics.patch
-Patch1:         k8s-1.14.diff
+Source1:        vendor.tar.xz
 BuildRequires:  fdupes
-BuildRequires:  go >= 1.10
+BuildRequires:  go = 1.12
 BuildRequires:  go-go-md2man
 ExcludeArch:    s390
 
@@ -63,27 +61,15 @@
 
 %prep
 %setup -qa1
-%patch -p1
-%patch1 -p1
 
 %build
-
-# We can't use symlinks here because go-list gets confused by symlinks, so we
-# have to copy the source to $HOME/go and then use that as the GOPATH.
-export GOPATH=$HOME/go
-mkdir -pv $HOME/go/src/%{project}
-rm -rf $HOME/go/src/%{project}/*
-cp -avr * $HOME/go/src/%{project}
-
 # Build the binary.
 export VERSION=%{version}
 export COMMIT=%{commit}
-export CGO_ENABLED=0
 go build \
-   -buildmode=pie \
+   -mod vendor -buildmode=pie \
    -ldflags "-s -w -X main.gitCommit=$COMMIT -X main.version=$VERSION" \
-   -o %{name} \
-   $HOME/go/src/%{project}/cmd/kured/*go
+   -o %{name} cmd/kured/*go
 
 %install
 # Install the binary.

++++++ kured-1.2.0.tar.gz -> kured-1.3.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/.circleci/config.yml 
new/kured-1.3.0/.circleci/config.yml
--- old/kured-1.2.0/.circleci/config.yml        2019-05-16 12:29:26.000000000 
+0200
+++ new/kured-1.3.0/.circleci/config.yml        2020-02-25 11:22:03.000000000 
+0100
@@ -1,14 +1,11 @@
 version: 2
 jobs:
   build:
-    working_directory: /go/src/github.com/weaveworks/kured
     docker:
-      - image: circleci/golang:1.11
+      - image: circleci/golang:1.12.5
     steps:
       - checkout
       - setup_remote_docker
-      - run: go get github.com/golang/dep/cmd/dep
-      - run: dep ensure
       - deploy:
           name: Build and push image
           command: |
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/DEVELOPMENT.md 
new/kured-1.3.0/DEVELOPMENT.md
--- old/kured-1.2.0/DEVELOPMENT.md      1970-01-01 01:00:00.000000000 +0100
+++ new/kured-1.3.0/DEVELOPMENT.md      2020-02-25 11:22:03.000000000 +0100
@@ -0,0 +1,106 @@
+# Developing `kured`
+
+We love contributions to `kured`, no matter if you are [helping out on
+Slack][slack], reporting or triaging [issues][issues] or contributing code
+to `kured`.
+
+In any case, it will make sense to familiarise yourself with the main
+[README][readme] to understand the different features and options, which is
+helpful for testing. The "building" section in particular makes sense if
+you are planning to contribute code.
+
+[slack]: README.md#getting-help
+[issues]: https://github.com/weaveworks/kured/issues
+[readme]: README.md
+
+## Updating k8s support
+
+Whenever we want to update e.g. [`kubectl` in the
+image](cmd/kured/Dockerfile), we need to consider if we update `client-go`
+as well, some RBAC changes might be necessary too.
+
+This is what it took to support Kubernetes 1.14:
+<https://github.com/weaveworks/kured/pull/75>
+
+That the process can be more involved that that can be seen in
+<https://github.com/weaveworks/kured/commits/support-k8s-1.10>
+
+Once you updated everything, make sure you update the support matrix on
+the main [README][readme] as well.
+
+## Release testing
+
+Before `kured` is released, we want to make sure it still works fine on the
+previous, current and next minor version of Kubernetes (with respect to the
+embedded `client-go` & `kubectl`). For local testing e.g. `minikube` can be
+sufficient.
+
+Deploy kured in your test scenario, make sure you pass the right `image`,
+update the e.g. `period` and `reboot-days` options, so you get immediate
+results, if you login to a node and run:
+
+```console
+sudo touch /var/run/reboot-required
+```
+
+### Testing with `minikube`
+
+A test-run with `minikube` could look like this:
+
+```console
+minikube start --vm-driver kvm2 --kubernetes-version <k8s-release>
+
+# edit kured-ds.yaml to
+#   - point to new image
+#   - change e.g. period and reboot-days option for immediate results
+
+minikube kubectl -- apply -f kured-rbac.yaml
+minikube kubectl -- apply -f kured-ds.yaml
+minikube kubectl -- logs daemonset.apps/kured -n kube-system -f
+
+# In separate terminal
+minikube ssh
+ sudo touch /var/run/reboot-required
+minikube logs -f
+```
+
+Now check for the 'Commanding reboot' message and minikube going down.
+
+Unfortunately as of today, you are going to run into
+<https://github.com/kubernetes/minikube/issues/2874>. This means that
+minikube won't come back easily. You will need to start minikube again.
+Then you can check for the lock release.
+
+If all the tests ran well, kured maintainers can reach out to the Weaveworks
+team to get an upcoming `kured` release tested in the Dev environment for
+real life testing.
+
+## Publishing a new kured release
+
+Check that `README.md` has an updated compatibility matrix and that the
+url in the `kubectl` incantation (under "Installation") is updated to the
+new version you want to release.
+
+Now create the `kured-<release>-dockerhub.yaml` for e.g. `1.3.0`:
+
+```sh
+VERSION=1.3.0
+MANIFEST="kured-$VERSION-dockerhub.yaml"
+cat kured-rbac.yaml > "$MANIFEST"
+cat kured-ds.yaml >> "$MANIFEST"
+sed -i "s#docker.io/weaveworks/kured#docker.io/weaveworks/kured:$VERSION#g" 
"$MANIFEST"
+```
+
+The last thing you need to do is update the `image:` to point to the release
+tag, e.g. `docker.io/weaveworks/kured:1.3.0`.
+
+Now you can head to the Github UI, use the version number as tag and upload the
+`kured-<release>-dockerhub.yaml` file.
+
+### Release notes
+
+Please describe what's new and noteworthy in the release notes, list the PRs
+that landed and give a shout-out to everyone who contributed.
+
+Please also note down on which releases the upcoming `kured` release was
+tested on. (Check old release notes if you're unsure.)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/Gopkg.lock new/kured-1.3.0/Gopkg.lock
--- old/kured-1.2.0/Gopkg.lock  2019-05-16 12:29:26.000000000 +0200
+++ new/kured-1.3.0/Gopkg.lock  1970-01-01 01:00:00.000000000 +0100
@@ -1,412 +0,0 @@
-# This file is autogenerated, do not edit; changes may be undone by the next 
'dep ensure'.
-
-
-[[projects]]
-  branch = "master"
-  name = "github.com/beorn7/perks"
-  packages = ["quantile"]
-  revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
-
-[[projects]]
-  name = "github.com/gogo/protobuf"
-  packages = [
-    "proto",
-    "sortkeys"
-  ]
-  revision = "4cbf7e384e768b4e01799441fdf2a706a5635ae7"
-  version = "v1.2.0"
-
-[[projects]]
-  name = "github.com/golang/protobuf"
-  packages = [
-    "proto",
-    "ptypes",
-    "ptypes/any",
-    "ptypes/duration",
-    "ptypes/timestamp"
-  ]
-  revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
-  version = "v1.2.0"
-
-[[projects]]
-  branch = "master"
-  name = "github.com/google/btree"
-  packages = ["."]
-  revision = "4030bb1f1f0c35b30ca7009e9ebd06849dd45306"
-
-[[projects]]
-  branch = "master"
-  name = "github.com/google/gofuzz"
-  packages = ["."]
-  revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1"
-
-[[projects]]
-  name = "github.com/googleapis/gnostic"
-  packages = [
-    "OpenAPIv2",
-    "compiler",
-    "extensions"
-  ]
-  revision = "7c663266750e7d82587642f65e60bc4083f1f84e"
-  version = "v0.2.0"
-
-[[projects]]
-  branch = "master"
-  name = "github.com/gregjones/httpcache"
-  packages = [
-    ".",
-    "diskcache"
-  ]
-  revision = "c63ab54fda8f77302f8d414e19933f2b6026a089"
-
-[[projects]]
-  name = "github.com/inconshreveable/mousetrap"
-  packages = ["."]
-  revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
-  version = "v1.0"
-
-[[projects]]
-  name = "github.com/json-iterator/go"
-  packages = ["."]
-  revision = "1624edc4454b8682399def8740d46db5e4362ba4"
-  version = "v1.1.5"
-
-[[projects]]
-  name = "github.com/konsorten/go-windows-terminal-sequences"
-  packages = ["."]
-  revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242"
-  version = "v1.0.1"
-
-[[projects]]
-  name = "github.com/matttproud/golang_protobuf_extensions"
-  packages = ["pbutil"]
-  revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c"
-  version = "v1.0.1"
-
-[[projects]]
-  name = "github.com/modern-go/concurrent"
-  packages = ["."]
-  revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94"
-  version = "1.0.3"
-
-[[projects]]
-  name = "github.com/modern-go/reflect2"
-  packages = ["."]
-  revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd"
-  version = "1.0.1"
-
-[[projects]]
-  branch = "master"
-  name = "github.com/petar/GoLLRB"
-  packages = ["llrb"]
-  revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4"
-
-[[projects]]
-  name = "github.com/peterbourgon/diskv"
-  packages = ["."]
-  revision = "5f041e8faa004a95c88a202771f4cc3e991971e6"
-  version = "v2.0.1"
-
-[[projects]]
-  branch = "master"
-  name = "github.com/prometheus/client_golang"
-  packages = [
-    "api",
-    "api/prometheus/v1",
-    "prometheus",
-    "prometheus/internal",
-    "prometheus/promhttp"
-  ]
-  revision = "fb3d5cb2ad5789367093b409855a3937d651b572"
-
-[[projects]]
-  branch = "master"
-  name = "github.com/prometheus/client_model"
-  packages = ["go"]
-  revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f"
-
-[[projects]]
-  branch = "master"
-  name = "github.com/prometheus/common"
-  packages = [
-    "expfmt",
-    "internal/bitbucket.org/ww/goautoneg",
-    "model"
-  ]
-  revision = "67670fe90761d7ff18ec1d640135e53b9198328f"
-
-[[projects]]
-  branch = "master"
-  name = "github.com/prometheus/procfs"
-  packages = [
-    ".",
-    "internal/util",
-    "nfs",
-    "xfs"
-  ]
-  revision = "14fa7590c24d4615893b68e22fce3b3489689f65"
-
-[[projects]]
-  name = "github.com/sirupsen/logrus"
-  packages = ["."]
-  revision = "bcd833dfe83d3cebad139e4a29ed79cb2318bf95"
-  version = "v1.2.0"
-
-[[projects]]
-  branch = "master"
-  name = "github.com/spf13/cobra"
-  packages = ["."]
-  revision = "d2d81d9a96e23f0255397222bb0b4e3165e492dc"
-
-[[projects]]
-  name = "github.com/spf13/pflag"
-  packages = ["."]
-  revision = "298182f68c66c05229eb03ac171abe6e309ee79a"
-  version = "v1.0.3"
-
-[[projects]]
-  branch = "master"
-  name = "golang.org/x/crypto"
-  packages = ["ssh/terminal"]
-  revision = "8d7daa0c54b357f3071e11eaef7efc4e19a417e2"
-
-[[projects]]
-  branch = "master"
-  name = "golang.org/x/net"
-  packages = [
-    "context",
-    "context/ctxhttp",
-    "http/httpguts",
-    "http2",
-    "http2/hpack",
-    "idna"
-  ]
-  revision = "927f97764cc334a6575f4b7a1584a147864d5723"
-
-[[projects]]
-  branch = "master"
-  name = "golang.org/x/oauth2"
-  packages = [
-    ".",
-    "internal"
-  ]
-  revision = "d668ce993890a79bda886613ee587a69dd5da7a6"
-
-[[projects]]
-  branch = "master"
-  name = "golang.org/x/sys"
-  packages = [
-    "unix",
-    "windows"
-  ]
-  revision = "82a175fd1598e8a172e58ebdf5ed262bb29129e5"
-
-[[projects]]
-  name = "golang.org/x/text"
-  packages = [
-    "collate",
-    "collate/build",
-    "internal/colltab",
-    "internal/gen",
-    "internal/tag",
-    "internal/triegen",
-    "internal/ucd",
-    "language",
-    "secure/bidirule",
-    "transform",
-    "unicode/bidi",
-    "unicode/cldr",
-    "unicode/norm",
-    "unicode/rangetable"
-  ]
-  revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
-  version = "v0.3.0"
-
-[[projects]]
-  branch = "master"
-  name = "golang.org/x/time"
-  packages = ["rate"]
-  revision = "85acf8d2951cb2a3bde7632f9ff273ef0379bcbd"
-
-[[projects]]
-  name = "google.golang.org/appengine"
-  packages = [
-    "internal",
-    "internal/base",
-    "internal/datastore",
-    "internal/log",
-    "internal/remote_api",
-    "internal/urlfetch",
-    "urlfetch"
-  ]
-  revision = "e9657d882bb81064595ca3b56cbe2546bbabf7b1"
-  version = "v1.4.0"
-
-[[projects]]
-  name = "gopkg.in/inf.v0"
-  packages = ["."]
-  revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf"
-  version = "v0.9.1"
-
-[[projects]]
-  name = "gopkg.in/yaml.v2"
-  packages = ["."]
-  revision = "51d6538a90f86fe93ac480b35f37b2be17fef232"
-  version = "v2.2.2"
-
-[[projects]]
-  branch = "master"
-  name = "k8s.io/api"
-  packages = [
-    "admissionregistration/v1alpha1",
-    "admissionregistration/v1beta1",
-    "apps/v1",
-    "apps/v1beta1",
-    "apps/v1beta2",
-    "auditregistration/v1alpha1",
-    "authentication/v1",
-    "authentication/v1beta1",
-    "authorization/v1",
-    "authorization/v1beta1",
-    "autoscaling/v1",
-    "autoscaling/v2beta1",
-    "autoscaling/v2beta2",
-    "batch/v1",
-    "batch/v1beta1",
-    "batch/v2alpha1",
-    "certificates/v1beta1",
-    "coordination/v1beta1",
-    "core/v1",
-    "events/v1beta1",
-    "extensions/v1beta1",
-    "networking/v1",
-    "policy/v1beta1",
-    "rbac/v1",
-    "rbac/v1alpha1",
-    "rbac/v1beta1",
-    "scheduling/v1alpha1",
-    "scheduling/v1beta1",
-    "settings/v1alpha1",
-    "storage/v1",
-    "storage/v1alpha1",
-    "storage/v1beta1"
-  ]
-  revision = "173ce66c1e39d1d0f56e0b3347ff2988068aecd0"
-
-[[projects]]
-  branch = "release-1.13"
-  name = "k8s.io/apimachinery"
-  packages = [
-    "pkg/api/errors",
-    "pkg/api/meta",
-    "pkg/api/resource",
-    "pkg/apis/meta/v1",
-    "pkg/apis/meta/v1/unstructured",
-    "pkg/apis/meta/v1beta1",
-    "pkg/conversion",
-    "pkg/conversion/queryparams",
-    "pkg/fields",
-    "pkg/labels",
-    "pkg/runtime",
-    "pkg/runtime/schema",
-    "pkg/runtime/serializer",
-    "pkg/runtime/serializer/json",
-    "pkg/runtime/serializer/protobuf",
-    "pkg/runtime/serializer/recognizer",
-    "pkg/runtime/serializer/streaming",
-    "pkg/runtime/serializer/versioning",
-    "pkg/selection",
-    "pkg/types",
-    "pkg/util/clock",
-    "pkg/util/errors",
-    "pkg/util/framer",
-    "pkg/util/intstr",
-    "pkg/util/json",
-    "pkg/util/naming",
-    "pkg/util/net",
-    "pkg/util/runtime",
-    "pkg/util/sets",
-    "pkg/util/validation",
-    "pkg/util/validation/field",
-    "pkg/util/yaml",
-    "pkg/version",
-    "pkg/watch",
-    "third_party/forked/golang/reflect"
-  ]
-  revision = "2b1284ed4c93a43499e781493253e2ac5959c4fd"
-
-[[projects]]
-  name = "k8s.io/client-go"
-  packages = [
-    "discovery",
-    "kubernetes",
-    "kubernetes/scheme",
-    "kubernetes/typed/admissionregistration/v1alpha1",
-    "kubernetes/typed/admissionregistration/v1beta1",
-    "kubernetes/typed/apps/v1",
-    "kubernetes/typed/apps/v1beta1",
-    "kubernetes/typed/apps/v1beta2",
-    "kubernetes/typed/auditregistration/v1alpha1",
-    "kubernetes/typed/authentication/v1",
-    "kubernetes/typed/authentication/v1beta1",
-    "kubernetes/typed/authorization/v1",
-    "kubernetes/typed/authorization/v1beta1",
-    "kubernetes/typed/autoscaling/v1",
-    "kubernetes/typed/autoscaling/v2beta1",
-    "kubernetes/typed/autoscaling/v2beta2",
-    "kubernetes/typed/batch/v1",
-    "kubernetes/typed/batch/v1beta1",
-    "kubernetes/typed/batch/v2alpha1",
-    "kubernetes/typed/certificates/v1beta1",
-    "kubernetes/typed/coordination/v1beta1",
-    "kubernetes/typed/core/v1",
-    "kubernetes/typed/events/v1beta1",
-    "kubernetes/typed/extensions/v1beta1",
-    "kubernetes/typed/networking/v1",
-    "kubernetes/typed/policy/v1beta1",
-    "kubernetes/typed/rbac/v1",
-    "kubernetes/typed/rbac/v1alpha1",
-    "kubernetes/typed/rbac/v1beta1",
-    "kubernetes/typed/scheduling/v1alpha1",
-    "kubernetes/typed/scheduling/v1beta1",
-    "kubernetes/typed/settings/v1alpha1",
-    "kubernetes/typed/storage/v1",
-    "kubernetes/typed/storage/v1alpha1",
-    "kubernetes/typed/storage/v1beta1",
-    "pkg/apis/clientauthentication",
-    "pkg/apis/clientauthentication/v1alpha1",
-    "pkg/apis/clientauthentication/v1beta1",
-    "pkg/version",
-    "plugin/pkg/client/auth/exec",
-    "rest",
-    "rest/watch",
-    "tools/clientcmd/api",
-    "tools/metrics",
-    "tools/reference",
-    "transport",
-    "util/cert",
-    "util/connrotation",
-    "util/flowcontrol",
-    "util/integer"
-  ]
-  revision = "e64494209f554a6723674bd494d69445fb76a1d4"
-  version = "v10.0.0"
-
-[[projects]]
-  name = "k8s.io/klog"
-  packages = ["."]
-  revision = "a5bc97fbc634d635061f3146511332c7e313a55a"
-  version = "v0.1.0"
-
-[[projects]]
-  name = "sigs.k8s.io/yaml"
-  packages = ["."]
-  revision = "fd68e9863619f6ec2fdd8625fe1f02e7c877e480"
-  version = "v1.1.0"
-
-[solve-meta]
-  analyzer-name = "dep"
-  analyzer-version = 1
-  inputs-digest = 
"96704623ac96e94ce47b0820b4ff9e359b76c68a72eb83621a3de9d99d3d9d4f"
-  solver-name = "gps-cdcl"
-  solver-version = 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/Gopkg.toml new/kured-1.3.0/Gopkg.toml
--- old/kured-1.2.0/Gopkg.toml  2019-05-16 12:29:26.000000000 +0200
+++ new/kured-1.3.0/Gopkg.toml  1970-01-01 01:00:00.000000000 +0100
@@ -1,27 +0,0 @@
-[[constraint]]
-  name = "github.com/sirupsen/logrus"
-  version = "v1.0.5"
-
-[[constraint]]
-  branch = "master"
-  name = "github.com/prometheus/client_golang"
-
-[[constraint]]
-  branch = "master"
-  name = "github.com/prometheus/common"
-
-[[constraint]]
-  branch = "master"
-  name = "github.com/spf13/cobra"
-
-[[constraint]]
-  name = "k8s.io/client-go"
-  version = "v10.0.0"
-
-[[constraint]]
-  name = "k8s.io/apimachinery"
-  branch = "release-1.13"
-
-[prune]
-  go-tests = true
-  unused-packages = true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/Makefile new/kured-1.3.0/Makefile
--- old/kured-1.2.0/Makefile    2019-05-16 12:29:26.000000000 +0200
+++ new/kured-1.3.0/Makefile    2020-02-25 11:22:03.000000000 +0100
@@ -8,7 +8,6 @@
 all: image
 
 clean:
-       go clean
        rm -f cmd/kured/kured
        rm -rf ./build
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/README.md new/kured-1.3.0/README.md
--- old/kured-1.2.0/README.md   2019-05-16 12:29:26.000000000 +0200
+++ new/kured-1.3.0/README.md   2020-02-25 11:22:03.000000000 +0100
@@ -6,6 +6,7 @@
 * [Installation](#installation)
 * [Configuration](#configuration)
        * [Reboot Sentinel File & Period](#reboot-sentinel-file-&-period)
+       * [Setting a schedule](#setting-a-schedule)
        * [Blocking Reboots via Alerts](#blocking-reboots-via-alerts)
        * [Blocking Reboots via Pods](#blocking-reboots-via-pods)
        * [Prometheus Metrics](#prometheus-metrics)
@@ -40,7 +41,9 @@
 
 | kured  | kubectl | k8s.io/client-go | k8s.io/apimachinery | expected 
kubernetes compatibility |
 
|--------|---------|------------------|---------------------|-----------------------------------|
-| master | 1.13.6  | v10.0.0          | release-1.13        | 1.12.x, 1.13.x, 
1.14.x            |
+| master | 1.15.10 | v12.0.0          | release-1.15        | 1.15.x, 1.16.x, 
1.17.x            |
+| 1.3.0  | 1.15.10 | v12.0.0          | release-1.15        | 1.15.x, 1.16.x, 
1.17.x            |
+| 1.2.0  | 1.13.6  | v10.0.0          | release-1.13        | 1.12.x, 1.13.x, 
1.14.x            |
 | 1.1.0  | 1.12.1  | v9.0.0           | release-1.12        | 1.11.x, 1.12.x, 
1.13.x            |
 | 1.0.0  | 1.7.6   | v4.0.0           | release-1.7         | 1.6.x, 1.7.x, 
1.8.x               | 
 
@@ -57,7 +60,7 @@
 or Slack notifications:
 
 ```
-kubectl apply -f 
https://github.com/weaveworks/kured/releases/download/1.1.0/kured-1.1.0-dockerhub.yaml
+kubectl apply -f 
https://github.com/weaveworks/kured/releases/download/1.3.0/kured-1.3.0-dockerhub.yaml
 ```
 
 If you want to customise the installation, download the manifest and
@@ -73,13 +76,18 @@
       --blocking-pod-selector stringArray   label selector identifying pods 
whose presence should prevent reboots
       --ds-name string                      name of daemonset on which to 
place lock (default "kured")
       --ds-namespace string                 namespace containing daemonset on 
which to place lock (default "kube-system")
+      --end-time string                     only reboot before this time of 
day (default "23:59")
   -h, --help                                help for kured
       --lock-annotation string              annotation in which to record 
locking node (default "weave.works/kured-node-lock")
       --period duration                     reboot check period (default 
1h0m0s)
       --prometheus-url string               Prometheus instance to probe for 
active alerts
+      --reboot-days strings                 only reboot on these days (default 
[su,mo,tu,we,th,fr,sa])
       --reboot-sentinel string              path to file whose existence 
signals need to reboot (default "/var/run/reboot-required")
+      --slack-channel string                slack channel for reboot 
notfications
       --slack-hook-url string               slack hook URL for reboot 
notfications
       --slack-username string               slack username for reboot 
notfications (default "kured")
+      --start-time string                   only reboot after this time of day 
(default "0:00")
+      --time-zone string                    use this timezone to calculate 
allowed reboot time (default "UTC")
 ```
 
 ### Reboot Sentinel File & Period
@@ -90,6 +98,29 @@
 daemon uses a random offset derived from the period on startup so that
 nodes don't all contend for the lock simultaneously.
 
+### Setting a schedule
+
+By default, kured will reboot any time it detects the sentinel, but this
+may cause reboots during odd hours.  While service disruption does not
+normally occur, anything is possible and operators may want to restrict
+reboots to predictable schedules.  Use `--reboot-days`, `--start-time`,
+`--end-time`, and `--time-zone` to set a schedule.  For example, business
+hours on the west coast USA can be specified with:
+
+```
+       --reboot-days mon,tue,wed,thu,fri
+       --start-time 9am
+       --end-time 5pm
+       --time-zone America/Los_Angeles
+```
+
+Times can be formatted in numerous ways, including `5pm`, `5:00pm` `17:00`,
+and `17`.  `--time-zone` represents a Go `time.Location`, and can be `UTC`,
+`Local`, or any entry in the standard Linux tz database.
+
+Note that when using smaller time windows, you should consider shortening
+the sentinel check period (`--period`).
+
 ### Blocking Reboots via Alerts
 
 You may find it desirable to block automatic node reboots when there
@@ -229,9 +260,28 @@
 
 ## Building
 
+See the [CircleCI config](.circleci/config.yml) for the preferred
+version of Golang. Kured now uses [Go
+Modules](https://github.com/golang/go/wiki/Modules), so build
+instructions vary depending on where you have checked out the
+repository:
+
+**Building outside $GOPATH:**
+
+```
+make
 ```
-dep ensure && make
+
+**Building inside $GOPATH:**
+
 ```
+GO111MODULE=on make
+```
+
+If you are interested in contributing code to kured, please take a look at
+our [development][development] docs.
+
+[development]: DEVELOPMENT.md
 
 ## Frequently Asked/Anticipated Questions
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/cmd/kured/Dockerfile 
new/kured-1.3.0/cmd/kured/Dockerfile
--- old/kured-1.2.0/cmd/kured/Dockerfile        2019-05-16 12:29:26.000000000 
+0200
+++ new/kured-1.3.0/cmd/kured/Dockerfile        2020-02-25 11:22:03.000000000 
+0100
@@ -1,7 +1,7 @@
-FROM alpine:3.8
-RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/*
+FROM alpine:3.10.3
+RUN apk update && apk add ca-certificates tzdata && rm -rf /var/cache/apk/*
 # NB: you may need to update RBAC permissions when upgrading kubectl - see 
kured-rbac.yaml for details
-ADD 
https://storage.googleapis.com/kubernetes-release/release/v1.13.6/bin/linux/amd64/kubectl
 /usr/bin/kubectl
+ADD 
https://storage.googleapis.com/kubernetes-release/release/v1.15.10/bin/linux/amd64/kubectl
 /usr/bin/kubectl
 RUN chmod 0755 /usr/bin/kubectl
 COPY ./kured /usr/bin/kured
 ENTRYPOINT ["/usr/bin/kured"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/cmd/kured/main.go 
new/kured-1.3.0/cmd/kured/main.go
--- old/kured-1.2.0/cmd/kured/main.go   2019-05-16 12:29:26.000000000 +0200
+++ new/kured-1.3.0/cmd/kured/main.go   2020-02-25 11:22:03.000000000 +0100
@@ -21,6 +21,7 @@
        "github.com/weaveworks/kured/pkg/daemonsetlock"
        "github.com/weaveworks/kured/pkg/delaytick"
        "github.com/weaveworks/kured/pkg/notifications/slack"
+       "github.com/weaveworks/kured/pkg/timewindow"
 )
 
 var (
@@ -36,8 +37,14 @@
        rebootSentinel string
        slackHookURL   string
        slackUsername  string
+       slackChannel   string
        podSelectors   []string
 
+       rebootDays  []string
+       rebootStart string
+       rebootEnd   string
+       timezone    string
+
        // Metrics
        rebootRequiredGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
                Subsystem: "kured",
@@ -75,10 +82,21 @@
                "slack hook URL for reboot notfications")
        rootCmd.PersistentFlags().StringVar(&slackUsername, "slack-username", 
"kured",
                "slack username for reboot notfications")
+       rootCmd.PersistentFlags().StringVar(&slackChannel, "slack-channel", "",
+               "slack channel for reboot notfications")
 
        rootCmd.PersistentFlags().StringArrayVar(&podSelectors, 
"blocking-pod-selector", nil,
                "label selector identifying pods whose presence should prevent 
reboots")
 
+       rootCmd.PersistentFlags().StringSliceVar(&rebootDays, "reboot-days", 
timewindow.EveryDay,
+               "schedule reboot on these days")
+       rootCmd.PersistentFlags().StringVar(&rebootStart, "start-time", "0:00",
+               "schedule reboot only after this time of day")
+       rootCmd.PersistentFlags().StringVar(&rebootEnd, "end-time", "23:59:59",
+               "schedule reboot only before this time of day")
+       rootCmd.PersistentFlags().StringVar(&timezone, "time-zone", "UTC",
+               "use this timezone for schedule inputs")
+
        if err := rootCmd.Execute(); err != nil {
                log.Fatal(err)
        }
@@ -212,7 +230,7 @@
        log.Infof("Draining node %s", nodeID)
 
        if slackHookURL != "" {
-               if err := slack.NotifyDrain(slackHookURL, slackUsername, 
nodeID); err != nil {
+               if err := slack.NotifyDrain(slackHookURL, slackUsername, 
slackChannel, nodeID); err != nil {
                        log.Warnf("Error notifying slack: %v", err)
                }
        }
@@ -237,7 +255,7 @@
        log.Infof("Commanding reboot")
 
        if slackHookURL != "" {
-               if err := slack.NotifyReboot(slackHookURL, slackUsername, 
nodeID); err != nil {
+               if err := slack.NotifyReboot(slackHookURL, slackUsername, 
slackChannel, nodeID); err != nil {
                        log.Warnf("Error notifying slack: %v", err)
                }
        }
@@ -265,7 +283,7 @@
        Unschedulable bool `json:"unschedulable"`
 }
 
-func rebootAsRequired(nodeID string) {
+func rebootAsRequired(nodeID string, window *timewindow.TimeWindow) {
        config, err := rest.InClusterConfig()
        if err != nil {
                log.Fatal(err)
@@ -289,7 +307,7 @@
        source := rand.NewSource(time.Now().UnixNano())
        tick := delaytick.New(source, period)
        for _ = range tick {
-               if rebootRequired() && !rebootBlocked(client, nodeID) {
+               if window.Contains(time.Now()) && rebootRequired() && 
!rebootBlocked(client, nodeID) {
                        node, err := client.CoreV1().Nodes().Get(nodeID, 
metav1.GetOptions{})
                        if err != nil {
                                log.Fatal(err)
@@ -318,12 +336,18 @@
                log.Fatal("KURED_NODE_ID environment variable required")
        }
 
+       window, err := timewindow.New(rebootDays, rebootStart, rebootEnd, 
timezone)
+       if err != nil {
+               log.Fatalf("Failed to build time window: %v", err)
+       }
+
        log.Infof("Node ID: %s", nodeID)
        log.Infof("Lock Annotation: %s/%s:%s", dsNamespace, dsName, 
lockAnnotation)
        log.Infof("Reboot Sentinel: %s every %v", rebootSentinel, period)
        log.Infof("Blocking Pod Selectors: %v", podSelectors)
+       log.Infof("Reboot on: %v", window)
 
-       go rebootAsRequired(nodeID)
+       go rebootAsRequired(nodeID, window)
        go maintainRebootRequiredMetric(nodeID)
 
        http.Handle("/metrics", promhttp.Handler())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/go.mod new/kured-1.3.0/go.mod
--- old/kured-1.2.0/go.mod      1970-01-01 01:00:00.000000000 +0100
+++ new/kured-1.3.0/go.mod      2020-02-25 11:22:03.000000000 +0100
@@ -0,0 +1,23 @@
+module github.com/weaveworks/kured
+
+go 1.12
+
+require (
+       github.com/gogo/protobuf v1.2.0 // indirect
+       github.com/googleapis/gnostic v0.2.0 // indirect
+       github.com/inconshreveable/mousetrap v1.0.0 // indirect
+       github.com/json-iterator/go v1.1.5 // indirect
+       github.com/prometheus/client_golang v0.0.0-20181230203121-fb3d5cb2ad57
+       github.com/prometheus/common v0.0.0-20181218105931-67670fe90761
+       github.com/prometheus/procfs v0.0.0-20190102135031-14fa7590c24d // 
indirect
+       github.com/sirupsen/logrus v1.2.0
+       github.com/spf13/cobra v0.0.0-20181127133106-d2d81d9a96e2
+       github.com/spf13/pflag v1.0.3 // indirect
+       golang.org/x/crypto v0.0.0-20190102171810-8d7daa0c54b3 // indirect
+       golang.org/x/time v0.0.0-20181108054448-85acf8d2951c // indirect
+       gopkg.in/inf.v0 v0.9.1 // indirect
+       gopkg.in/yaml.v2 v2.2.2 // indirect
+       k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719
+       k8s.io/client-go v12.0.0+incompatible
+       k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 // indirect
+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/go.sum new/kured-1.3.0/go.sum
--- old/kured-1.2.0/go.sum      1970-01-01 01:00:00.000000000 +0100
+++ new/kured-1.3.0/go.sum      2020-02-25 11:22:03.000000000 +0100
@@ -0,0 +1,132 @@
+cloud.google.com/go v0.34.0/go.mod 
h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/Azure/go-autorest v11.1.2+incompatible/go.mod 
h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 
h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod 
h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/davecgh/go-spew v1.1.0/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 
h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod 
h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod 
h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
+github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod 
h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
+github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod 
h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
+github.com/fsnotify/fsnotify v1.4.7/go.mod 
h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod 
h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI=
+github.com/gogo/protobuf v1.2.0/go.mod 
h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod 
h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/protobuf v1.2.0 
h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
+github.com/golang/protobuf v1.2.0/go.mod 
h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod 
h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
+github.com/google/go-cmp v0.3.0/go.mod 
h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf 
h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
+github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod 
h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
+github.com/google/uuid v1.0.0/go.mod 
h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod 
h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
+github.com/googleapis/gnostic v0.2.0 
h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g=
+github.com/googleapis/gnostic v0.2.0/go.mod 
h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
+github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod 
h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
+github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod 
h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/hashicorp/golang-lru v0.5.0/go.mod 
h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hpcloud/tail v1.0.0/go.mod 
h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/imdario/mergo v0.3.5/go.mod 
h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/inconshreveable/mousetrap v1.0.0 
h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod 
h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod 
h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.5 
h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE=
+github.com/json-iterator/go v1.1.5/go.mod 
h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1 
h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod 
h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/matttproud/golang_protobuf_extensions v1.0.1 
h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod 
h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd 
h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod 
h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.1 
h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
+github.com/modern-go/reflect2 v1.0.1/go.mod 
h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod 
h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
+github.com/onsi/ginkgo v1.6.0/go.mod 
h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod 
h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod 
h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
+github.com/pmezard/go-difflib v1.0.0 
h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod 
h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v0.0.0-20181230203121-fb3d5cb2ad57 
h1:+cstagqzfjiYrs1QrmypZRndHJafhB9W3ab/zPiwl1Q=
+github.com/prometheus/client_golang v0.0.0-20181230203121-fb3d5cb2ad57/go.mod 
h1:PS8H/EtMiYNSR3o4jWYMuyp9FkDf2ptwxn1kTerl5EM=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 
h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod 
h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/common v0.0.0-20181218105931-67670fe90761 
h1:z6tvbDJ5OLJ48FFmnksv04a78maSTRBUIhkdHYV5Y98=
+github.com/prometheus/common v0.0.0-20181218105931-67670fe90761/go.mod 
h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod 
h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20190102135031-14fa7590c24d 
h1:iSxvUGRUGQTUgEo5+8TqMVQoH5AdaphEIjh8AnM7TPo=
+github.com/prometheus/procfs v0.0.0-20190102135031-14fa7590c24d/go.mod 
h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/sirupsen/logrus v1.2.0 
h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
+github.com/sirupsen/logrus v1.2.0/go.mod 
h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/spf13/afero v1.2.2/go.mod 
h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
+github.com/spf13/cobra v0.0.0-20181127133106-d2d81d9a96e2 
h1:gPjqutnNhLnq5t4hT2UfL06h/mvp4je4OY7Dk71vhuk=
+github.com/spf13/cobra v0.0.0-20181127133106-d2d81d9a96e2/go.mod 
h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/pflag v1.0.1/go.mod 
h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
+github.com/spf13/pflag v1.0.3/go.mod 
h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/stretchr/objx v0.1.0/go.mod 
h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod 
h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod 
h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0 
h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
+github.com/stretchr/testify v1.3.0/go.mod 
h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod 
h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod 
h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190102171810-8d7daa0c54b3 
h1:35ZwriXqdZtBGoFgUpW71Z7xz5o23fRpWHFAO2PlnIA=
+golang.org/x/crypto v0.0.0-20190102171810-8d7daa0c54b3/go.mod 
h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181217023233-e147a9138326/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 
h1:bfLnR+k0tq5Lqt6dflRLcZiz6UaXCMt3vhYJ1l4FQ80=
+golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a 
h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA=
+golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod 
h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f 
h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 
h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod 
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod 
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313 
h1:pczuHS43Cp2ktBEEmLwScxgjWsBSzdaQiKzUyf3DTTc=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db 
h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU=
+golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod 
h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod 
h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c 
h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod 
h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod 
h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+google.golang.org/appengine v1.4.0 
h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
+google.golang.org/appengine v1.4.0/go.mod 
h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0 
h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
+google.golang.org/appengine v1.5.0/go.mod 
h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 
h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod 
h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
+gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod 
h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+k8s.io/api v0.0.0-20190620084959-7cf5895f2711 
h1:BblVYz/wE5WtBsD/Gvu54KyBUTJMflolzc5I2DTvh50=
+k8s.io/api v0.0.0-20190620084959-7cf5895f2711/go.mod 
h1:TBhBqb1AWbBQbW3XRusr7n7E4v2+5ZY8r8sAMnyFC5A=
+k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719 
h1:uV4S5IB5g4Nvi+TBVNf3e9L4wrirlwYJ6w88jUQxTUw=
+k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719/go.mod 
h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA=
+k8s.io/client-go v12.0.0+incompatible 
h1:YlJxncpeVUC98/WMZKC3JZGk/OXQWCZjAB4Xr3B17RY=
+k8s.io/client-go v12.0.0+incompatible/go.mod 
h1:E95RaSlHr79aHaX0aGSwcPNfygDiPKOVXdmivCIZT0k=
+k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE=
+k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
+k8s.io/klog v0.3.1 h1:RVgyDHY/kFKtLqh67NvEWIgkMneNoIrdkN0CxDSQc68=
+k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
+k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod 
h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
+k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod 
h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
+k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 
h1:VBM/0P5TWxwk+Nw6Z+lAw3DKgO76g90ETOiA6rfLV1Y=
+k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod 
h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
+sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
+sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/kured-ds.yaml 
new/kured-1.3.0/kured-ds.yaml
--- old/kured-1.2.0/kured-ds.yaml       2019-05-16 12:29:26.000000000 +0200
+++ new/kured-1.3.0/kured-ds.yaml       2020-02-25 11:22:03.000000000 +0100
@@ -29,10 +29,9 @@
       restartPolicy: Always
       containers:
         - name: kured
-          image: docker.io/weaveworks/kured # If you find yourself here
-                                            # wondering why there is no
-                                            # :latest tag on Docker Hub,
-                                            # see the FAQ in the README
+          image: docker.io/weaveworks/kured
+                 # If you find yourself here wondering why there is no
+                 # :latest tag on Docker Hub,see the FAQ in the README
           imagePullPolicy: IfNotPresent
           securityContext:
             privileged: true # Give permission to nsenter /proc/1/ns/mnt
@@ -51,9 +50,14 @@
 #            - --blocking-pod-selector=...
 #            - --ds-name=kured
 #            - --ds-namespace=kube-system
+#            - --end-time=23:59:59
 #            - --lock-annotation=weave.works/kured-node-lock
 #            - --period=1h
 #            - --prometheus-url=http://prometheus.monitoring.svc.cluster.local
+#            - --reboot-days=sun,mon,tue,wed,thu,fri,sat
 #            - --reboot-sentinel=/var/run/reboot-required
 #            - --slack-hook-url=https://hooks.slack.com/...
 #            - --slack-username=prod
+#            - --slack-channel=alerting
+#            - --start-time=0:00
+#            - --time-zone=UTC
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/kured-rbac.yaml 
new/kured-1.3.0/kured-rbac.yaml
--- old/kured-1.2.0/kured-rbac.yaml     2019-05-16 12:29:26.000000000 +0200
+++ new/kured-1.3.0/kured-rbac.yaml     2020-02-25 11:22:03.000000000 +0100
@@ -8,7 +8,7 @@
 # Allow kubectl to drain/uncordon
 #
 # NB: These permissions are tightly coupled to the bundled version of kubectl; 
the ones below
-# match 
https://github.com/kubernetes/kubernetes/blob/v1.12.1/pkg/kubectl/cmd/drain.go
+# match 
https://github.com/kubernetes/kubernetes/blob/v1.14.1/pkg/kubectl/cmd/drain/drain.go
 #
 - apiGroups: [""]
   resources: ["nodes"]
@@ -16,7 +16,7 @@
 - apiGroups: [""]
   resources: ["pods"]
   verbs:     ["list","delete","get"]
-- apiGroups: ["extensions"]
+- apiGroups: ["apps"]
   resources: ["daemonsets"]
   verbs:     ["get"]
 - apiGroups: [""]
@@ -43,7 +43,7 @@
   name: kured
 rules:
 # Allow kured to lock/unlock itself
-- apiGroups:     ["extensions"]
+- apiGroups:     ["apps"]
   resources:     ["daemonsets"]
   resourceNames: ["kured"]
   verbs:         ["update"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/pkg/daemonsetlock/daemonsetlock.go 
new/kured-1.3.0/pkg/daemonsetlock/daemonsetlock.go
--- old/kured-1.2.0/pkg/daemonsetlock/daemonsetlock.go  2019-05-16 
12:29:26.000000000 +0200
+++ new/kured-1.3.0/pkg/daemonsetlock/daemonsetlock.go  2020-02-25 
11:22:03.000000000 +0100
@@ -29,7 +29,7 @@
 
 func (dsl *DaemonSetLock) Acquire(metadata interface{}) (acquired bool, owner 
string, err error) {
        for {
-               ds, err := 
dsl.client.ExtensionsV1beta1().DaemonSets(dsl.namespace).Get(dsl.name, 
metav1.GetOptions{})
+               ds, err := 
dsl.client.AppsV1().DaemonSets(dsl.namespace).Get(dsl.name, metav1.GetOptions{})
                if err != nil {
                        return false, "", err
                }
@@ -53,7 +53,7 @@
                }
                ds.ObjectMeta.Annotations[dsl.annotation] = string(valueBytes)
 
-               _, err = 
dsl.client.ExtensionsV1beta1().DaemonSets(dsl.namespace).Update(ds)
+               _, err = 
dsl.client.AppsV1().DaemonSets(dsl.namespace).Update(ds)
                if err != nil {
                        if se, ok := err.(*errors.StatusError); ok && 
se.ErrStatus.Reason == metav1.StatusReasonConflict {
                                // Something else updated the resource between 
us reading and writing - try again soon
@@ -68,7 +68,7 @@
 }
 
 func (dsl *DaemonSetLock) Test(metadata interface{}) (holding bool, err error) 
{
-       ds, err := 
dsl.client.ExtensionsV1beta1().DaemonSets(dsl.namespace).Get(dsl.name, 
metav1.GetOptions{})
+       ds, err := dsl.client.AppsV1().DaemonSets(dsl.namespace).Get(dsl.name, 
metav1.GetOptions{})
        if err != nil {
                return false, err
        }
@@ -87,7 +87,7 @@
 
 func (dsl *DaemonSetLock) Release() error {
        for {
-               ds, err := 
dsl.client.ExtensionsV1beta1().DaemonSets(dsl.namespace).Get(dsl.name, 
metav1.GetOptions{})
+               ds, err := 
dsl.client.AppsV1().DaemonSets(dsl.namespace).Get(dsl.name, metav1.GetOptions{})
                if err != nil {
                        return err
                }
@@ -107,7 +107,7 @@
 
                delete(ds.ObjectMeta.Annotations, dsl.annotation)
 
-               _, err = 
dsl.client.ExtensionsV1beta1().DaemonSets(dsl.namespace).Update(ds)
+               _, err = 
dsl.client.AppsV1().DaemonSets(dsl.namespace).Update(ds)
                if err != nil {
                        if se, ok := err.(*errors.StatusError); ok && 
se.ErrStatus.Reason == metav1.StatusReasonConflict {
                                // Something else updated the resource between 
us reading and writing - try again soon
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/pkg/notifications/slack/slack.go 
new/kured-1.3.0/pkg/notifications/slack/slack.go
--- old/kured-1.2.0/pkg/notifications/slack/slack.go    2019-05-16 
12:29:26.000000000 +0200
+++ new/kured-1.3.0/pkg/notifications/slack/slack.go    2020-02-25 
11:22:03.000000000 +0100
@@ -15,12 +15,14 @@
 type body struct {
        Text     string `json:"text,omitempty"`
        Username string `json:"username,omitempty"`
+       Channel  string `json:"channel,omitempty"`
 }
 
-func notify(hookURL, username, message string) error {
+func notify(hookURL, username, channel, message string) error {
        msg := body{
                Text:     message,
                Username: username,
+               Channel:  channel,
        }
 
        var buf bytes.Buffer
@@ -41,10 +43,10 @@
        return nil
 }
 
-func NotifyDrain(hookURL, username, nodeID string) error {
-       return notify(hookURL, username, fmt.Sprintf("Draining node %s", 
nodeID))
+func NotifyDrain(hookURL, username, channel, nodeID string) error {
+       return notify(hookURL, username, channel, fmt.Sprintf("Draining node 
%s", nodeID))
 }
 
-func NotifyReboot(hookURL, username, nodeID string) error {
-       return notify(hookURL, username, fmt.Sprintf("Rebooting node %s", 
nodeID))
+func NotifyReboot(hookURL, username, channel, nodeID string) error {
+       return notify(hookURL, username, channel, fmt.Sprintf("Rebooting node 
%s", nodeID))
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/pkg/timewindow/days.go 
new/kured-1.3.0/pkg/timewindow/days.go
--- old/kured-1.2.0/pkg/timewindow/days.go      1970-01-01 01:00:00.000000000 
+0100
+++ new/kured-1.3.0/pkg/timewindow/days.go      2020-02-25 11:22:03.000000000 
+0100
@@ -0,0 +1,91 @@
+package timewindow
+
+import (
+       "fmt"
+       "strconv"
+       "strings"
+       "time"
+)
+
+var EveryDay = []string{"su", "mo", "tu", "we", "th", "fr", "sa"}
+
+// dayStrings maps day strings to time.Weekdays
+var dayStrings = map[string]time.Weekday{
+       "su":        time.Sunday,
+       "sun":       time.Sunday,
+       "sunday":    time.Sunday,
+       "mo":        time.Monday,
+       "mon":       time.Monday,
+       "monday":    time.Monday,
+       "tu":        time.Tuesday,
+       "tue":       time.Tuesday,
+       "tuesday":   time.Tuesday,
+       "we":        time.Wednesday,
+       "wed":       time.Wednesday,
+       "wednesday": time.Wednesday,
+       "th":        time.Thursday,
+       "thu":       time.Thursday,
+       "thursday":  time.Thursday,
+       "fr":        time.Friday,
+       "fri":       time.Friday,
+       "friday":    time.Friday,
+       "sa":        time.Saturday,
+       "sat":       time.Saturday,
+       "saturday":  time.Saturday,
+}
+
+type weekdays uint32
+
+// parseWeekdays creates a set of weekdays from a string slice
+func parseWeekdays(days []string) (weekdays, error) {
+       var result uint32
+       for _, day := range days {
+               if len(day) == 0 {
+                       continue
+               }
+
+               weekday, err := parseWeekday(day)
+               if err != nil {
+                       return weekdays(0), err
+               }
+
+               result |= 1 << uint32(weekday)
+       }
+
+       return weekdays(result), nil
+}
+
+// Contains returns true if the specified weekday is a member of this set.
+func (w weekdays) Contains(day time.Weekday) bool {
+       return uint32(w)&(1<<uint32(day)) != 0
+}
+
+// String returns a string representation of the set of weekdays.
+func (w weekdays) String() string {
+       var b strings.Builder
+       for i := uint32(0); i < 7; i++ {
+               if uint32(w)&(1<<i) != 0 {
+                       b.WriteString(time.Weekday(i).String()[0:3])
+               } else {
+                       b.WriteString("---")
+               }
+       }
+
+       return b.String()
+}
+
+func parseWeekday(day string) (time.Weekday, error) {
+       if n, err := strconv.Atoi(day); err == nil {
+               if n >= 0 && n < 7 {
+                       return time.Weekday(n), nil
+               } else {
+                       return time.Sunday, fmt.Errorf("Invalid weekday, number 
out of range: %s", day)
+               }
+       }
+
+       if weekday, ok := dayStrings[strings.ToLower(day)]; ok {
+               return weekday, nil
+       } else {
+               return time.Sunday, fmt.Errorf("Invalid weekday: %s", day)
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/pkg/timewindow/days_test.go 
new/kured-1.3.0/pkg/timewindow/days_test.go
--- old/kured-1.2.0/pkg/timewindow/days_test.go 1970-01-01 01:00:00.000000000 
+0100
+++ new/kured-1.3.0/pkg/timewindow/days_test.go 2020-02-25 11:22:03.000000000 
+0100
@@ -0,0 +1,46 @@
+package timewindow
+
+import (
+       "strings"
+       "testing"
+)
+
+func TestParseWeekdays(t *testing.T) {
+       tests := []struct {
+               input  string
+               result string
+       }{
+               {"0,4", "Sun---------Thu------"},
+               {"su,mo,tu", "SunMonTue------------"},
+               {"sunday,tu,thu", "Sun---Tue---Thu------"},
+               {"THURSDAY", "------------Thu------"},
+               {"we,WED,WeDnEsDaY", "---------Wed---------"},
+               {"", "---------------------"},
+               {",,,", "---------------------"},
+       }
+
+       for _, tst := range tests {
+               res, err := parseWeekdays(strings.Split(tst.input, ","))
+               if err != nil {
+                       t.Errorf("Received error for input %s: %v", tst.input, 
err)
+               } else if res.String() != tst.result {
+                       t.Errorf("Test %s: Expected %s got %s", tst.input, 
tst.result, res.String())
+               }
+       }
+}
+
+func TestParseWeekdaysErrors(t *testing.T) {
+       tests := []string{
+               "15",
+               "-8",
+               "8",
+               "mon,tue,wed,fridayyyy",
+       }
+
+       for _, tst := range tests {
+               _, err := parseWeekdays(strings.Split(tst, ","))
+               if err == nil {
+                       t.Errorf("Expected to receive error for input %s", tst)
+               }
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/pkg/timewindow/timewindow.go 
new/kured-1.3.0/pkg/timewindow/timewindow.go
--- old/kured-1.2.0/pkg/timewindow/timewindow.go        1970-01-01 
01:00:00.000000000 +0100
+++ new/kured-1.3.0/pkg/timewindow/timewindow.go        2020-02-25 
11:22:03.000000000 +0100
@@ -0,0 +1,68 @@
+package timewindow
+
+import (
+       "fmt"
+       "time"
+)
+
+// TimeWindow specifies a schedule of days and times.
+type TimeWindow struct {
+       days      weekdays
+       location  *time.Location
+       startTime time.Time
+       endTime   time.Time
+}
+
+// New creates a TimeWindow instance based on string inputs specifying a 
schedule.
+func New(days []string, startTime, endTime, location string) (*TimeWindow, 
error) {
+       tw := &TimeWindow{}
+
+       var err error
+       if tw.days, err = parseWeekdays(days); err != nil {
+               return nil, err
+       }
+
+       if tw.location, err = time.LoadLocation(location); err != nil {
+               return nil, err
+       }
+
+       if tw.startTime, err = parseTime(startTime, tw.location); err != nil {
+               return nil, err
+       }
+
+       if tw.endTime, err = parseTime(endTime, tw.location); err != nil {
+               return nil, err
+       }
+
+       return tw, nil
+}
+
+// Contains determines whether the specified time is within this time window.
+func (tw *TimeWindow) Contains(t time.Time) bool {
+       loctime := t.In(tw.location)
+       if !tw.days.Contains(loctime.Weekday()) {
+               return false
+       }
+
+       start := time.Date(loctime.Year(), loctime.Month(), loctime.Day(), 
tw.startTime.Hour(), tw.startTime.Minute(), tw.startTime.Second(), 0, 
tw.location)
+       end := time.Date(loctime.Year(), loctime.Month(), loctime.Day(), 
tw.endTime.Hour(), tw.endTime.Minute(), tw.endTime.Second(), 1e9-1, tw.location)
+
+       return (loctime.After(start) || loctime.Equal(start)) && 
(loctime.Before(end) || loctime.Equal(end))
+}
+
+// String returns a string representation of this time window.
+func (tw *TimeWindow) String() string {
+       return fmt.Sprintf("%s between %02d:%02d and %02d:%02d %s", 
tw.days.String(), tw.startTime.Hour(), tw.startTime.Minute(), 
tw.endTime.Hour(), tw.endTime.Minute(), tw.location.String())
+}
+
+// parseTime tries to parse a time with several formats.
+func parseTime(s string, loc *time.Location) (time.Time, error) {
+       fmts := []string{"15:04", "15:04:05", "03:04pm", "15", "03pm", "3pm"}
+       for _, f := range fmts {
+               if t, err := time.ParseInLocation(f, s, loc); err == nil {
+                       return t, nil
+               }
+       }
+
+       return time.Now(), fmt.Errorf("Invalid time format: %s", s)
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kured-1.2.0/pkg/timewindow/timewindow_test.go 
new/kured-1.3.0/pkg/timewindow/timewindow_test.go
--- old/kured-1.2.0/pkg/timewindow/timewindow_test.go   1970-01-01 
01:00:00.000000000 +0100
+++ new/kured-1.3.0/pkg/timewindow/timewindow_test.go   2020-02-25 
11:22:03.000000000 +0100
@@ -0,0 +1,60 @@
+package timewindow
+
+import (
+       "strings"
+       "testing"
+       "time"
+)
+
+func TestTimeWindows(t *testing.T) {
+       type testcase struct {
+               time   string
+               result bool
+       }
+
+       tests := []struct {
+               days  string
+               start string
+               end   string
+               loc   string
+               cases []testcase
+       }{
+               {"mon,tue,wed,thu,fri", "9am", "5pm", "America/Los_Angeles", 
[]testcase{
+                       {"2019/04/04 00:49 PDT", false},
+                       {"2019/04/05 08:59 PDT", false},
+                       {"2019/04/05 9:01 PDT", true},
+                       {"2019/03/31 10:00 PDT", false},
+                       {"2019/04/04 12:00 PDT", true},
+                       {"2019/04/04 11:59 UTC", false},
+               }},
+               {"mon,we,fri", "10:01", "11:30am", "America/Los_Angeles", 
[]testcase{
+                       {"2019/04/05 10:30 PDT", true},
+                       {"2019/04/06 10:30 PDT", false},
+                       {"2019/04/07 10:30 PDT", false},
+                       {"2019/04/08 10:30 PDT", true},
+                       {"2019/04/09 10:30 PDT", false},
+                       {"2019/04/10 10:30 PDT", true},
+                       {"2019/04/11 10:30 PDT", false},
+               }},
+               {"mo,tu,we,th,fr", "00:00", "23:59:59", "UTC", []testcase{
+                       {"2019/04/18 00:00 UTC", true},
+                       {"2019/04/18 23:59 UTC", true},
+               }},
+       }
+
+       for i, tst := range tests {
+               tw, err := New(strings.Split(tst.days, ","), tst.start, 
tst.end, tst.loc)
+               if err != nil {
+                       t.Errorf("Test [%d] failed to create TimeWindow: %v", 
i, err)
+               }
+
+               for _, cas := range tst.cases {
+                       tm, err := time.ParseInLocation("2006/01/02 15:04 MST", 
cas.time, tw.location)
+                       if err != nil {
+                               t.Errorf("Failed to parse time \"%s\": %v", 
cas.time, err)
+                       } else if cas.result != tw.Contains(tm) {
+                               t.Errorf("(%s) contains (%s) didn't match 
expected result of %v", tw.String(), cas.time, cas.result)
+                       }
+               }
+       }
+}


Reply via email to