From e78109d79eb159f96cf05e46b136a9c60989fbcd Mon Sep 17 00:00:00 2001 From: Vaibhav Kumbhar Date: Mon, 1 Nov 2021 01:03:05 -0700 Subject: [PATCH 1/3] feat(sync-delete): disable alerts on individual resource Squashed commit of the following: commit 48b594b3ff7bb38c897f7b9f39781f5c76f28150 Author: Vaibhav Kumbhar Date: Mon Nov 1 12:43:27 2021 +0530 dev-vk: comment commit 7dc7c89ffdb467ee96ddd2a8c86bcc4183840e63 Author: Vaibhav Kumbhar Date: Fri Oct 29 18:32:10 2021 +0530 dev-vk: iDEV-86929 commit ef00f8f44e3fdacc9fe23b3b18af7d3627216eb3 Merge: 7e04fea55 ce95817f9 Author: Vaibhav Kumbhar Date: Fri Oct 29 18:30:59 2021 +0530 Merge branch 'develop' into dev-vk-disable commit 7e04fea55f8c7cd063255e035aa2563c0ecfd897 Author: Vaibhav Kumbhar Date: Fri Oct 29 18:29:56 2021 +0530 dev-vk: as commit 7f2b4378d72498873b00c01097cbcb343e4f2a00 Author: Vaibhav Kumbhar Date: Thu Oct 28 19:01:04 2021 +0530 dev-vk: asdf commit 54bf4b9c8b474d4b491b81334590012b4b8d40c1 Author: Vaibhav Kumbhar Date: Thu Oct 28 14:32:00 2021 +0530 dev-vk: sd commit 9953e42d290db13c27eced0ccc95ed225d81df6c Author: Vaibhav Kumbhar Date: Thu Oct 28 14:23:46 2021 +0530 dev-vk: delete commit b4ff104d73dbac23a787edd66d7c2f959f70da5b Author: Vaibhav Kumbhar Date: Wed Oct 27 01:29:09 2021 +0530 dev-vk: disable alert --- .golangci.yml | 1 + go.mod | 1 + go.sum | 2 + main.go | 4 +- pkg/config/config.go | 6 +- pkg/resource/builder/builder.go | 13 +- pkg/resource/watcher.go | 21 ++- pkg/sync/initsyncer.go | 28 ++-- pkg/tree/tree.go | 32 ++-- pkg/types/types.go | 4 + .../github.com/senseyeio/duration/.travis.yml | 14 ++ vendor/github.com/senseyeio/duration/LICENSE | 22 +++ .../github.com/senseyeio/duration/README.md | 84 ++++++++++ .../senseyeio/duration/coveralls.bash | 25 +++ .../github.com/senseyeio/duration/duration.go | 146 ++++++++++++++++++ vendor/modules.txt | 3 + 16 files changed, 373 insertions(+), 33 deletions(-) create mode 100644 vendor/github.com/senseyeio/duration/.travis.yml create mode 100644 vendor/github.com/senseyeio/duration/LICENSE create mode 100644 vendor/github.com/senseyeio/duration/README.md create mode 100644 vendor/github.com/senseyeio/duration/coveralls.bash create mode 100644 vendor/github.com/senseyeio/duration/duration.go diff --git a/.golangci.yml b/.golangci.yml index 56f13cbea..602bb2c42 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -129,6 +129,7 @@ linters-settings: - github.com/logicmonitor/lm-sdk-go - github.com/logicmonitor/k8s-collectorset-controller - github.com/pkg/profile + - github.com/senseyeio/duration blocked: modules: diff --git a/go.mod b/go.mod index 31988a3ba..f0d614bdb 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,7 @@ require ( github.com/pkg/profile v1.6.0 github.com/prometheus/client_golang v0.9.3 github.com/robfig/cron/v3 v3.0.1 + github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 github.com/sirupsen/logrus v1.4.2 github.com/soheilhy/cmux v0.1.5 // indirect github.com/spf13/cobra v0.0.3 diff --git a/go.sum b/go.sum index deb2a1014..c8de29a6f 100644 --- a/go.sum +++ b/go.sum @@ -384,6 +384,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 h1:Dz0HrI1AtNSGCE8LXLLqoZU4iuOJXPWndenCsZfstA8= +github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46/go.mod h1:is8FVkzSi7PYLWEXT5MgWhglFsyyiW8ffxAoJqfuFZo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= diff --git a/main.go b/main.go index c936fdb79..18ebecde1 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,8 @@ package main -import "github.com/logicmonitor/k8s-argus/cmd" +import ( + "github.com/logicmonitor/k8s-argus/cmd" +) func main() { cmd.Execute() diff --git a/pkg/config/config.go b/pkg/config/config.go index 35e77cabc..7eb6a48e5 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -37,7 +37,7 @@ type Config struct { EnableNewResourceTree bool `yaml:"enable_new_resource_tree"` EnableNamespacesDeletedGroups bool `yaml:"enable_namespaces_deleted_groups"` RegisterGenericFilter bool `yaml:"register_generic_filter"` - DeleteArgusPodAfter *string `yaml:"delete_argus_pod_after"` + DeleteInfraPodsAfter *string `yaml:"delete_infra_pods_after"` DisableResourceMonitoring []enums.ResourceType `yaml:"disable_resource_monitoring"` DisableResourceAlerting []enums.ResourceType `yaml:"disable_resource_alerting"` TelemetryCronString *string `yaml:"telemetry_cron_string"` @@ -281,9 +281,9 @@ func validateConfig(conf *Config) { defaultQueueSize := 100 conf.ParallelRunnerQueueSize = &defaultQueueSize } - if conf.DeleteArgusPodAfter == nil { + if conf.DeleteInfraPodsAfter == nil { scheduledDeleteTime := "P10DT0H0M0S" - conf.DeleteArgusPodAfter = &scheduledDeleteTime + conf.DeleteInfraPodsAfter = &scheduledDeleteTime } if conf.TelemetryCronString == nil { // Defaults to 10 minute if not specified diff --git a/pkg/resource/builder/builder.go b/pkg/resource/builder/builder.go index 24a8e2445..9180e4182 100644 --- a/pkg/resource/builder/builder.go +++ b/pkg/resource/builder/builder.go @@ -48,6 +48,13 @@ func (b *Builder) SystemCategory(category string, action enums.BuilderAction) ty return setProperty(constants.K8sSystemCategoriesPropertyKey, category, action) } +// DisableResourceAlerting implements types.ResourceBuilder +func (b *Builder) DisableResourceAlerting(disable bool) types.ResourceOption { + return func(device *models.Device) { + device.DisableAlerting = disable + } +} + // ResourceAnnotations implements types.ResourceBuilder func (b *Builder) ResourceAnnotations(properties map[string]string) types.ResourceOption { return func(resource *models.Device) { @@ -369,16 +376,20 @@ func (b *Builder) GetMarkDeleteOptions(lctx *lmctx.LMContext, rt enums.ResourceT options := []types.ResourceOption{ b.SystemCategory(rt.GetDeletedCategory(), enums.Add), + b.DisableResourceAlerting(true), b.DeletedOn(meta.DeletionTimestamp.Time), b.ChangePrimaryKeysToMarkDelete(), } + if val, ok := meta.Labels["logicmonitor/deleteafterduration"]; ok { + options = append(options, b.Custom("kubernetes.resourcedeleteafterduration", val)) + } // We are not deleting argus pod, as we need argus pod logs for troubleshooting if util.IsArgusPodObject(lctx, rt, meta) { // defaults to 10 days scheduledDeleteTime := "P10DT0H0M0S" conf, err := config.GetConfig(lctx) if err == nil { - scheduledDeleteTime = *conf.DeleteArgusPodAfter + scheduledDeleteTime = *conf.DeleteInfraPodsAfter } options = append(options, b.Custom("kubernetes.resourcedeleteafterduration", scheduledDeleteTime)) } diff --git a/pkg/resource/watcher.go b/pkg/resource/watcher.go index 45d30dcd4..99d1d2b4e 100644 --- a/pkg/resource/watcher.go +++ b/pkg/resource/watcher.go @@ -16,6 +16,7 @@ import ( "github.com/logicmonitor/k8s-argus/pkg/types" util "github.com/logicmonitor/k8s-argus/pkg/utilities" "github.com/logicmonitor/lm-sdk-go/models" + "github.com/senseyeio/duration" ) // AddFunc returns func @@ -59,7 +60,7 @@ func (m *Manager) UpdateFunc() func(*lmctx.LMContext, enums.ResourceType, interf } // DeleteFunc returns function -func (m *Manager) DeleteFunc() func(*lmctx.LMContext, enums.ResourceType, interface{}, ...types.ResourceOption) error { +func (m *Manager) DeleteFunc() func(*lmctx.LMContext, enums.ResourceType, interface{}, ...types.ResourceOption) error { //nolint:cyclop return func(lctx *lmctx.LMContext, rt enums.ResourceType, obj interface{}, options ...types.ResourceOption) error { log := lmlog.Logger(lctx) conf, err := config.GetConfig(lctx) @@ -71,8 +72,22 @@ func (m *Manager) DeleteFunc() func(*lmctx.LMContext, enums.ResourceType, interf if err != nil { return err } - if conf.DeleteResources && - !util.IsArgusPod(lctx, rt, resource) { + objMeta, err := rt.ObjectMeta(obj) + if err != nil { + return err + } + val, deleteAfterLabelExists := objMeta.Labels["logicmonitor/deleteafterduration"] + d := duration.Duration{} + if deleteAfterLabelExists { + du, err := duration.ParseISO8601(val) + if err != nil { + deleteAfterLabelExists = false + } else { + d = du + } + } + if (conf.DeleteResources && !util.IsArgusPod(lctx, rt, resource)) || + (!conf.DeleteResources && deleteAfterLabelExists && d.IsZero()) { err := m.Delete(lctx, rt, obj, options...) if err != nil { if util.GetHTTPStatusCodeFromLMSDKError(err) == http.StatusNotFound { diff --git a/pkg/sync/initsyncer.go b/pkg/sync/initsyncer.go index 120207dae..8d166045b 100644 --- a/pkg/sync/initsyncer.go +++ b/pkg/sync/initsyncer.go @@ -20,6 +20,7 @@ import ( "github.com/logicmonitor/k8s-argus/pkg/types" util "github.com/logicmonitor/k8s-argus/pkg/utilities" "github.com/logicmonitor/lm-sdk-go/models" + "github.com/senseyeio/duration" "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,11 +93,13 @@ func (i *InitSyncer) Sync(lctx *lmctx.LMContext) { }) childLctx = childLctx.LMContextWith(map[string]interface{}{constants.PartitionKey: fmt.Sprintf("%s-%s", cacheResourceName.Resource.String(), cacheResourceName.Name)}) - if cacheResourceName.Resource == enums.Namespaces && cacheResourceName.Name != constants.DeletedResourceGroup { - if err := i.deleteNamespace(allK8SResourcesStore, childLctx, cacheResourceName, cacheResourceMeta, log, conf); err != nil && !errors.Is(err, aerrors.ErrResourceGroupIsNotEmpty) && - !errors.Is(err, aerrors.ErrResourceGroupParentIsNotValid) && - !strings.Contains(err.Error(), util.ClusterGroupName(conf.ClusterName)) { - log.Errorf("failed to delete resource group: %s", err) + if cacheResourceName.Resource == enums.Namespaces { + if cacheResourceName.Name != constants.DeletedResourceGroup { + if err := i.deleteNamespace(allK8SResourcesStore, childLctx, cacheResourceName, cacheResourceMeta, log, conf); err != nil && !errors.Is(err, aerrors.ErrResourceGroupIsNotEmpty) && + !errors.Is(err, aerrors.ErrResourceGroupParentIsNotValid) && + !strings.Contains(err.Error(), util.ClusterGroupName(conf.ClusterName)) { + log.Errorf("failed to delete resource group: %s", err) + } } continue } @@ -198,15 +201,20 @@ func (i *InitSyncer) resolveConflicts(lctx *lmctx.LMContext, cacheMeta types.Res } } -func (i *InitSyncer) deleteResource(lctx *lmctx.LMContext, resourceName types.ResourceName, resourceMeta types.ResourceMeta) { +func (i *InitSyncer) deleteResource(lctx *lmctx.LMContext, resourceName types.ResourceName, resourceMeta types.ResourceMeta) { //nolint:cyclop log := lmlog.Logger(lctx) conf, err := config.GetConfig(lctx) if err != nil { log.Errorf("Failed to get config") return } - if conf.DeleteResources && - !util.IsArgusPodCacheMeta(lctx, resourceName.Resource, resourceMeta) { + argusDeleteAfter, err := duration.ParseISO8601(*conf.DeleteInfraPodsAfter) + if err != nil { + log.Errorf("Failed to parse delete argus after parameter to duration as per ISO 8601 format: %s", err) + return + } + if (conf.DeleteResources && !util.IsArgusPodCacheMeta(lctx, resourceName.Resource, resourceMeta)) || + (util.IsArgusPodCacheMeta(lctx, resourceName.Resource, resourceMeta) && argusDeleteAfter.IsZero() && conf.DeleteResources) { log.Info("Deleting resource") err := i.ResourceManager.DeleteResourceByID(lctx, resourceName.Resource, resourceMeta.LMID) if err != nil { @@ -223,7 +231,9 @@ func (i *InitSyncer) deleteResource(lctx *lmctx.LMContext, resourceName types.Re } } else if !resourceMeta.HasSysCategory(resourceName.Resource.GetDeletedCategory()) { log.Info("Soft delete") - deleteOptions := i.ResourceManager.GetMarkDeleteOptions(lctx, resourceName.Resource, meta.AsPartialObjectMetadata(&metav1.ObjectMeta{})) + deleteOptions := i.ResourceManager.GetMarkDeleteOptions(lctx, resourceName.Resource, meta.AsPartialObjectMetadata(&metav1.ObjectMeta{ + Labels: resourceMeta.Labels, + })) _, err = i.ResourceManager.UpdateResourceByID(lctx, resourceName.Resource, resourceMeta.LMID, deleteOptions...) if err != nil { diff --git a/pkg/tree/tree.go b/pkg/tree/tree.go index 75c6604c3..2a2a5d56b 100644 --- a/pkg/tree/tree.go +++ b/pkg/tree/tree.go @@ -89,24 +89,24 @@ func GetResourceGroupTree(lctx *lmctx.LMContext, dgBuilder types.ResourceManager for _, resource := range enums.ALLResourceTypes { if resource != enums.Namespaces && resource.IsNamespaceScopedResource() && !conf.IsMonitoringDisabled(resource) { - treeObj.ChildGroups = append(treeObj.ChildGroups, - &types.ResourceGroupTree{ - Options: []types.ResourceGroupOption{ - dgBuilder.GroupName(resource.TitlePlural()), - dgBuilder.DisableAlerting(conf.ShouldDisableAlerting(resource)), - dgBuilder.CustomProperties(dgbuilder.NewPropertyBuilder().AddProperties(conf.ResourceGroupProperties.Get(resource))), - }, - ChildGroups: []*types.ResourceGroupTree{ - { - DontCreate: doNotCreateDeletedGroup, - Options: []types.ResourceGroupOption{ - dgBuilder.GroupName(constants.DeletedResourceGroup), - dgBuilder.DisableAlerting(true), - dgBuilder.AppliesTo(dgbuilder.NewAppliesToBuilder().HasCategory(resource.GetDeletedCategory()).And().Auto("clustername").Equals(conf.ClusterName)), - }, + resourceTree := &types.ResourceGroupTree{ + Options: []types.ResourceGroupOption{ + dgBuilder.GroupName(resource.TitlePlural()), + dgBuilder.DisableAlerting(conf.ShouldDisableAlerting(resource)), + dgBuilder.CustomProperties(dgbuilder.NewPropertyBuilder().AddProperties(conf.ResourceGroupProperties.Get(resource))), + }, + ChildGroups: []*types.ResourceGroupTree{ + { + DontCreate: doNotCreateDeletedGroup && !(resource == enums.Pods), + Options: []types.ResourceGroupOption{ + dgBuilder.GroupName(constants.DeletedResourceGroup), + dgBuilder.DisableAlerting(true), + dgBuilder.AppliesTo(dgbuilder.NewAppliesToBuilder().HasCategory(resource.GetDeletedCategory()).And().Auto("clustername").Equals(conf.ClusterName)), }, }, - }) + }, + } + treeObj.ChildGroups = append(treeObj.ChildGroups, resourceTree) } } return treeObj, nil diff --git a/pkg/types/types.go b/pkg/types/types.go index b97996a1d..3608391d0 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -163,6 +163,10 @@ type ResourceBuilder interface { // DeletedOn adds kubernetes.resourceDeletedOn property to the resource. DeletedOn(time.Time) ResourceOption + // DisableResourceAlerting disable alerting + DisableResourceAlerting(bool) ResourceOption + + // GetMarkDeleteOptions get deleted options GetMarkDeleteOptions(*lmctx.LMContext, enums.ResourceType, *metav1.PartialObjectMetadata) []ResourceOption } diff --git a/vendor/github.com/senseyeio/duration/.travis.yml b/vendor/github.com/senseyeio/duration/.travis.yml new file mode 100644 index 000000000..be839df16 --- /dev/null +++ b/vendor/github.com/senseyeio/duration/.travis.yml @@ -0,0 +1,14 @@ +language: go + +before_install: + - go get github.com/mattn/goveralls + - go get github.com/modocache/gover + +script: + - go test -race -v ./... + - ./coveralls.bash + +go: + - 1.9.x + - 1.10.x + - tip diff --git a/vendor/github.com/senseyeio/duration/LICENSE b/vendor/github.com/senseyeio/duration/LICENSE new file mode 100644 index 000000000..8d0173876 --- /dev/null +++ b/vendor/github.com/senseyeio/duration/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2018 Senseye +Adapted from https://github.com/ChannelMeter/iso8601duration, Copyright (c) 2014 ChannelMeter + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/senseyeio/duration/README.md b/vendor/github.com/senseyeio/duration/README.md new file mode 100644 index 000000000..b802bbb2a --- /dev/null +++ b/vendor/github.com/senseyeio/duration/README.md @@ -0,0 +1,84 @@ +Duration [![Build](https://travis-ci.org/senseyeio/duration.svg?branch=master)](https://travis-ci.org/senseyeio/duration) [![Coverage](https://coveralls.io/repos/github/senseyeio/duration/badge.svg?branch=master)](https://coveralls.io/github/senseyeio/duration?branch=master) [![Go Report Card](https://goreportcard.com/badge/senseyeio/duration)](https://goreportcard.com/report/senseyeio/duration) [![GoDoc](https://godoc.org/github.com/senseyeio/duration?status.svg)](https://godoc.org/github.com/senseyeio/duration) +======= +Parse ISO8601 duration strings, and use to shift dates/times. + +Basic Example +------------- + +```go +package main + +import ( + "fmt" + "time" + + "github.com/senseyeio/duration" +) + +func main() { + d, _ := iso8601.ParseISO8601("P1D") + today := time.Now() + tomorrow := d.Shift(today) + fmt.Println(today.Format("Jan _2")) + fmt.Println(tomorrow.Format("Jan _2")) +} +``` + +Why Does This Package Exist +--------------------------- +> Why can't we just use a `time.Duration` and `time.Add`? + +A very reasonable question. + +The code below repeatedly adds 24 hours to a `time.Time`. You might expect the time on that date to stay the same, but [_there are not always 24 hours in a day_](http://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time). When the clocks change in New York, the time will skew by an hour. As you can see from the output, duration.Duration.Shift() can increment the date without shifting the time. + +```go +package main + +import ( + "fmt" + "time" + + "github.com/senseyeio/duration" +) + +func main() { + loc, _ := time.LoadLocation("America/New_York") + d, _ := iso8601.ParseISO8601("P1D") + t1, _ := time.ParseInLocation("Jan 2, 2006 at 3:04pm", "Jan 1, 2006 at 3:04pm", loc) + t2 := t1 + for i := 0; i < 365; i++ { + t1 = t1.Add(24 * time.Hour) + t2 = d.Shift(t2) + fmt.Printf("time.Add:%d Duration.Shift:%d\n", t1.Hour(), t2.Hour()) + } +} + +// Outputs +// time.Add:15 Duration.Shift:15 +// time.Add:15 Duration.Shift:15 +// time.Add:15 Duration.Shift:15 +// ... +// time.Add:16 Duration.Shift:15 +// time.Add:16 Duration.Shift:15 +// time.Add:16 Duration.Shift:15 +// ... +``` + +------- +Months are tricky. Shifting by months uses `time.AddDate()`, which is great. However, be aware of how differing days in the month are accommodated. Dates will 'roll over' if the month you're shifting to has fewer days. e.g. if you start on Jan 30th and repeat every "P1M", you'll get this: + +``` +Jan 30, 2006 +Mar 2, 2006 +Apr 2, 2006 +May 2, 2006 +Jun 2, 2006 +Jul 2, 2006 +Aug 2, 2006 +Sep 2, 2006 +Oct 2, 2006 +Nov 2, 2006 +Dec 2, 2006 +Jan 2, 2007 +``` diff --git a/vendor/github.com/senseyeio/duration/coveralls.bash b/vendor/github.com/senseyeio/duration/coveralls.bash new file mode 100644 index 000000000..ac5b5716a --- /dev/null +++ b/vendor/github.com/senseyeio/duration/coveralls.bash @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +if ! type -P gover +then + echo gover missing: go get github.com/modocache/gover + exit 1 +fi + +if ! type -P goveralls +then + echo goveralls missing: go get github.com/mattn/goveralls + exit 1 +fi + +if [[ "$COVERALLS_TOKEN" == "" ]] +then + echo COVERALLS_TOKEN not set + exit 1 +fi + +go test -covermode count -coverprofile coverage.coverprofile + +gover +goveralls -coverprofile gover.coverprofile -service travis-ci -repotoken $COVERALLS_TOKEN +find . -name '*.coverprofile' -delete diff --git a/vendor/github.com/senseyeio/duration/duration.go b/vendor/github.com/senseyeio/duration/duration.go new file mode 100644 index 000000000..7163e3df9 --- /dev/null +++ b/vendor/github.com/senseyeio/duration/duration.go @@ -0,0 +1,146 @@ +// Package duration handles ISO8601-formatted durations. +package duration + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "html/template" + "regexp" + "strconv" + "time" +) + +// Duration represents an ISO8601 Duration +// https://en.wikipedia.org/wiki/ISO_8601#Durations +type Duration struct { + Y int + M int + W int + D int + // Time Component + TH int + TM int + TS int +} + +var pattern = regexp.MustCompile(`^P((?P\d+)Y)?((?P\d+)M)?((?P\d+)W)?((?P\d+)D)?(T((?P\d+)H)?((?P\d+)M)?((?P\d+)S)?)?$`) + +// ParseISO8601 parses an ISO8601 duration string. +func ParseISO8601(from string) (Duration, error) { + var match []string + var d Duration + + if pattern.MatchString(from) { + match = pattern.FindStringSubmatch(from) + } else { + return d, errors.New("could not parse duration string") + } + + for i, name := range pattern.SubexpNames() { + part := match[i] + if i == 0 || name == "" || part == "" { + continue + } + + val, err := strconv.Atoi(part) + if err != nil { + return d, err + } + switch name { + case "year": + d.Y = val + case "month": + d.M = val + case "week": + d.W = val + case "day": + d.D = val + case "hour": + d.TH = val + case "minute": + d.TM = val + case "second": + d.TS = val + default: + return d, fmt.Errorf("unknown field %s", name) + } + } + + return d, nil +} + +// IsZero reports whether d represents the zero duration, P0D. +func (d Duration) IsZero() bool { + return d.Y == 0 && d.M == 0 && d.W == 0 && d.D == 0 && d.TH == 0 && d.TM == 0 && d.TS == 0 +} + +// HasTimePart returns true if the time part of the duration is non-zero. +func (d Duration) HasTimePart() bool { + return d.TH > 0 || d.TM > 0 || d.TS > 0 +} + +// Shift returns a time.Time, shifted by the duration from the given start. +// +// NB: Shift uses time.AddDate for years, months, weeks, and days, and so +// shares its limitations. In particular, shifting by months is not recommended +// unless the start date is before the 28th of the month. Otherwise, dates will +// roll over, e.g. Aug 31 + P1M = Oct 1. +// +// Week and Day values will be combined as W*7 + D. +func (d Duration) Shift(t time.Time) time.Time { + if d.Y != 0 || d.M != 0 || d.W != 0 || d.D != 0 { + days := d.W*7 + d.D + t = t.AddDate(d.Y, d.M, days) + } + t = t.Add(d.timeDuration()) + return t +} + +func (d Duration) timeDuration() time.Duration { + var dur time.Duration + dur = dur + (time.Duration(d.TH) * time.Hour) + dur = dur + (time.Duration(d.TM) * time.Minute) + dur = dur + (time.Duration(d.TS) * time.Second) + return dur +} + +var tmpl = template.Must(template.New("duration").Parse(`P{{if .Y}}{{.Y}}Y{{end}}{{if .M}}{{.M}}M{{end}}{{if .W}}{{.W}}W{{end}}{{if .D}}{{.D}}D{{end}}{{if .HasTimePart}}T{{end }}{{if .TH}}{{.TH}}H{{end}}{{if .TM}}{{.TM}}M{{end}}{{if .TS}}{{.TS}}S{{end}}`)) + +// String returns an ISO8601-ish representation of the duration. +func (d Duration) String() string { + var s bytes.Buffer + + if d.IsZero() { + return "P0D" + } + + err := tmpl.Execute(&s, d) + if err != nil { + panic(err) + } + + return s.String() +} + +// MarshalJSON satisfies json.Marshaler. +func (d Duration) MarshalJSON() ([]byte, error) { + return json.Marshal(d.String()) +} + +// UnmarshalJSON satisfies json.Unmarshaler. +func (d *Duration) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + tmp, err := ParseISO8601(s) + if err != nil { + return err + } + *d = tmp + + return nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 33a697e0f..ea77fb982 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -167,6 +167,9 @@ github.com/prometheus/procfs/internal/fs # github.com/robfig/cron/v3 v3.0.1 ## explicit github.com/robfig/cron/v3 +# github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 +## explicit +github.com/senseyeio/duration # github.com/sirupsen/logrus v1.4.2 ## explicit github.com/sirupsen/logrus From c003498d8d2c4e15cf7a5e2e1f94354349b01a4e Mon Sep 17 00:00:00 2001 From: Rohit Phatak Date: Tue, 9 Nov 2021 01:36:51 -0800 Subject: [PATCH 2/3] fix(tree): dynamic folders renamed renamed hpas and etcs dynamic folders in resource tree Squashed commit of the following: commit ea51123b11ad0e8b4e1864e5dd885100d52488c5 Author: Rohit Phatak Date: Mon Nov 8 14:26:53 2021 +0530 dev-rp: dynamic folders renamed --- pkg/enums/enums.go | 4 ++-- pkg/enums/enums.yaml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/enums/enums.go b/pkg/enums/enums.go index d1f851d7d..73a0c09dc 100644 --- a/pkg/enums/enums.go +++ b/pkg/enums/enums.go @@ -320,11 +320,11 @@ func (resourceType *ResourceType) TitlePlural() string { case Services: return "Services" case Hpas: - return "Hpas" + return "HorizontalPodAutoscalers" case Nodes: return "Nodes" case ETCD: - return "Etcds" + return "Etcd" case Namespaces: return "Namespaces" case DaemonSets: diff --git a/pkg/enums/enums.yaml b/pkg/enums/enums.yaml index 40029bb88..7fc75112c 100644 --- a/pkg/enums/enums.yaml +++ b/pkg/enums/enums.yaml @@ -60,6 +60,7 @@ resources: - hpa longName: Hpas lowerCase: horizontalpodautoscalers + titlePlural: HorizontalPodAutoscalers parsedResourceType: - horizontalpodautoscalers - horizontalpodautoscaler @@ -83,7 +84,7 @@ resources: shortName: - etcd longName: ETCD - titlePlural: Etcds + titlePlural: Etcd lowerCase: etcd parsedResourceType: - etcd From 841f192943190c756d9278fbaee7f3f17cf8bd03 Mon Sep 17 00:00:00 2001 From: Rohit Phatak Date: Fri, 12 Nov 2021 02:02:57 -0800 Subject: [PATCH 3/3] feat(permission): permission check added for resources permission check added before creating dynamic folders Squashed commit of the following: commit 56f4014f7572de19a5e6a4ad2333d5fc18092521 Author: Rohit Phatak Date: Thu Nov 11 17:38:41 2021 +0530 dev-rp: permission check for new tree commit 074074b1025537c89a172080e7046a01d5f753e8 Author: Rohit Phatak Date: Thu Nov 11 17:20:47 2021 +0530 dev-rp: permission check added for resources --- pkg/tree/tree.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/tree/tree.go b/pkg/tree/tree.go index 2a2a5d56b..3ebf6bcad 100644 --- a/pkg/tree/tree.go +++ b/pkg/tree/tree.go @@ -8,6 +8,7 @@ import ( "github.com/logicmonitor/k8s-argus/pkg/enums" "github.com/logicmonitor/k8s-argus/pkg/lmctx" lmlog "github.com/logicmonitor/k8s-argus/pkg/log" + "github.com/logicmonitor/k8s-argus/pkg/permission" "github.com/logicmonitor/k8s-argus/pkg/resourcegroup" "github.com/logicmonitor/k8s-argus/pkg/resourcegroup/dgbuilder" "github.com/logicmonitor/k8s-argus/pkg/types" @@ -67,6 +68,7 @@ func GetResourceGroupTree(lctx *lmctx.LMContext, dgBuilder types.ResourceManager if !resource.IsNamespaceScopedResource() && resource != nodes && !conf.IsMonitoringDisabled(resource) { treeObj.ChildGroups = append(treeObj.ChildGroups, &types.ResourceGroupTree{ + DontCreate: !permission.HasPermissions(resource), Options: []types.ResourceGroupOption{ dgBuilder.GroupName(resource.TitlePlural()), dgBuilder.DisableAlerting(conf.ShouldDisableAlerting(resource)), @@ -90,6 +92,7 @@ func GetResourceGroupTree(lctx *lmctx.LMContext, dgBuilder types.ResourceManager for _, resource := range enums.ALLResourceTypes { if resource != enums.Namespaces && resource.IsNamespaceScopedResource() && !conf.IsMonitoringDisabled(resource) { resourceTree := &types.ResourceGroupTree{ + DontCreate: !permission.HasPermissions(resource), Options: []types.ResourceGroupOption{ dgBuilder.GroupName(resource.TitlePlural()), dgBuilder.DisableAlerting(conf.ShouldDisableAlerting(resource)), @@ -131,6 +134,7 @@ func GetResourceGroupTree2(lctx *lmctx.LMContext, dgBuilder types.ResourceManage if !resource.IsNamespaceScopedResource() && resource != enums.Nodes { clusterscoped = append(clusterscoped, &types.ResourceGroupTree{ + DontCreate: !permission.HasPermissions(resource), Options: []types.ResourceGroupOption{ dgBuilder.GroupName(resource.TitlePlural()), dgBuilder.DisableAlerting(conf.ShouldDisableAlerting(resource)),