diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index d0febdc0f..f515ebb1d 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -34,7 +34,7 @@ const ( // EtcdCategory is the system.category used to identity the Kubernetes Pod resource type in LogicMonitor. EtcdCategory = "KubernetesEtcd" // EtcdDeletedCategory is the system.category used to identity a deleted Kubernetes Etcd node in LogicMonitor. - EtcdDeletedCategory = "KubernetesNodeDeleted" + EtcdDeletedCategory = "KubernetesEtcdDeleted" // NodeCategory is the system.category used to identity the Kubernetes Node resource type in LogicMonitor. NodeCategory = "KubernetesNode" // NodeDeletedCategory is the system.category used to identity a deleted Kubernetes Node resource type in LogicMonitor. diff --git a/pkg/etcd/etcd.go b/pkg/etcd/etcd.go index ceebec65a..64164acda 100644 --- a/pkg/etcd/etcd.go +++ b/pkg/etcd/etcd.go @@ -65,7 +65,7 @@ func (c *Controller) DiscoverByToken() ([]*Member, error) { func (c *Controller) addDevice(member *Member) { // Check if the etcd member has already been added. - d, err := device.FindByDisplayName(member.Name, c.LMClient) + d, err := device.FindByName(member.URL.Hostname(), c.LMClient) if err != nil { log.Errorf("Failed to find etcd member %q: %v", member.Name, err) return diff --git a/pkg/tree/device/device.go b/pkg/tree/device/device.go index 3d6005254..fd2e94b00 100644 --- a/pkg/tree/device/device.go +++ b/pkg/tree/device/device.go @@ -7,11 +7,20 @@ import ( lm "github.com/logicmonitor/lm-sdk-go" ) -// FindByDisplayName searches for a device by it's display name. It will only -// return a device if and only if one device was found, and return nil -// otherwise. +// FindByName searches for a device by it's name. It will return a device if and only +// if one device was found, and return nil otherwise. +func FindByName(name string, client *lm.DefaultApi) (*lm.RestDevice, error) { + return find("name", name, client) +} + +// FindByDisplayName searches for a device by it's display name. It will return a device if and only if +// one device was found, and return nil otherwise. func FindByDisplayName(name string, client *lm.DefaultApi) (*lm.RestDevice, error) { - filter := fmt.Sprintf("displayName:%s", name) + return find("displayName", name, client) +} + +func find(field, name string, client *lm.DefaultApi) (*lm.RestDevice, error) { + filter := fmt.Sprintf("%s:%s", field, name) restResponse, apiResponse, err := client.GetDeviceList("", -1, 0, filter) if _err := utilities.CheckAllErrors(restResponse, apiResponse, err); _err != nil { return nil, _err diff --git a/pkg/tree/devicegroup/devicegroup.go b/pkg/tree/devicegroup/devicegroup.go index 080208bc9..3fcb77fc4 100644 --- a/pkg/tree/devicegroup/devicegroup.go +++ b/pkg/tree/devicegroup/devicegroup.go @@ -17,12 +17,12 @@ const hasCategoryClose = ")" // Options are the options for creating a device group. type Options struct { AppliesTo AppliesToBuilder - DeletedGroupAppliesTo AppliesToBuilder + AppliesToDeletedGroup AppliesToBuilder Client *lm.DefaultApi Name string ParentID int32 DisableAlerting bool - CreateDeletedGroup bool + DeleteDevices bool } // AppliesToBuilder is an interface for building an appliesTo string. @@ -80,7 +80,7 @@ func Create(opts *Options) (int32, error) { } if clusterDeviceGroup == nil { - log.Infof("Could not find cluster device group %q", opts.Name) + log.Infof("Could not find device group %q", opts.Name) cdg, err := create(opts.Name, opts.AppliesTo.String(), opts.DisableAlerting, opts.ParentID, opts.Client) if err != nil { return 0, err @@ -89,11 +89,17 @@ func Create(opts *Options) (int32, error) { clusterDeviceGroup = cdg } - if opts.CreateDeletedGroup { - _, err := create(constants.DeletedDeviceGroup, opts.AppliesTo.String(), true, clusterDeviceGroup.Id, opts.Client) + if !opts.DeleteDevices && opts.AppliesToDeletedGroup != nil { + deletedDeviceGroup, err := Find(clusterDeviceGroup.Id, constants.DeletedDeviceGroup, opts.Client) if err != nil { return 0, err } + if deletedDeviceGroup == nil { + _, err := create(constants.DeletedDeviceGroup, opts.AppliesToDeletedGroup.String(), true, clusterDeviceGroup.Id, opts.Client) + if err != nil { + return 0, err + } + } } @@ -113,7 +119,7 @@ func Find(parentID int32, name string, client *lm.DefaultApi) (*lm.RestDeviceGro var deviceGroup *lm.RestDeviceGroup for _, d := range restResponse.Data.Items { if d.ParentId == parentID { - log.Infof("Found device group %q with id %d", name, parentID) + log.Infof("Found device group %q with id %d", name, d.Id) deviceGroup = &d break } @@ -131,11 +137,11 @@ func create(name, appliesTo string, disableAlerting bool, parentID int32, client DisableAlerting: disableAlerting, }) if e := utilities.CheckAllErrors(restResponse, apiResponse, err); e != nil { - return nil, fmt.Errorf("Failed to add device group: %v", e) + return nil, fmt.Errorf("Failed to add device group %q: %v", name, e) } deviceGroup := &restResponse.Data - log.Infof("Created device group with id %d", deviceGroup.Id) + log.Infof("Created device group %q with id %d", name, deviceGroup.Id) return deviceGroup, nil } diff --git a/pkg/tree/tree.go b/pkg/tree/tree.go index 16de9ad1f..61a618b71 100644 --- a/pkg/tree/tree.go +++ b/pkg/tree/tree.go @@ -4,7 +4,6 @@ import ( "github.com/logicmonitor/k8s-argus/pkg/constants" "github.com/logicmonitor/k8s-argus/pkg/tree/devicegroup" "github.com/logicmonitor/k8s-argus/pkg/types" - log "github.com/sirupsen/logrus" ) // DeviceTree manages the device tree representation of a Kubernetes cluster in LogicMonitor. @@ -17,44 +16,44 @@ func (d *DeviceTree) buildOptsSlice() []*devicegroup.Options { // The device group at index 0 will be the root device group for all subsequent device groups. return []*devicegroup.Options{ { - Name: "Kubernetes Cluster: " + d.Config.ClusterName, - ParentID: constants.RootDeviceGroupID, - DisableAlerting: d.Config.DisableAlerting, - AppliesTo: devicegroup.NewAppliesToBuilder().HasCategory(constants.ClusterCategory).And().Auto("clustername").Equals(d.Config.ClusterName), - Client: d.LMClient, - CreateDeletedGroup: d.Config.DeleteDevices, + Name: "Kubernetes Cluster: " + d.Config.ClusterName, + ParentID: constants.RootDeviceGroupID, + DisableAlerting: d.Config.DisableAlerting, + AppliesTo: devicegroup.NewAppliesToBuilder().HasCategory(constants.ClusterCategory).And().Auto("clustername").Equals(d.Config.ClusterName), + Client: d.LMClient, + DeleteDevices: d.Config.DeleteDevices, }, { Name: constants.EtcdDeviceGroupName, DisableAlerting: d.Config.DisableAlerting, AppliesTo: devicegroup.NewAppliesToBuilder().HasCategory(constants.EtcdCategory).And().Auto("clustername").Equals(d.Config.ClusterName), Client: d.LMClient, - CreateDeletedGroup: d.Config.DeleteDevices, - DeletedGroupAppliesTo: devicegroup.NewAppliesToBuilder().HasCategory(constants.EtcdDeletedCategory).And().Auto("clustername").Equals(d.Config.ClusterName), + DeleteDevices: d.Config.DeleteDevices, + AppliesToDeletedGroup: devicegroup.NewAppliesToBuilder().HasCategory(constants.EtcdDeletedCategory).And().Auto("clustername").Equals(d.Config.ClusterName), }, { Name: constants.NodeDeviceGroupName, DisableAlerting: d.Config.DisableAlerting, AppliesTo: devicegroup.NewAppliesToBuilder().HasCategory(constants.NodeCategory).And().Auto("clustername").Equals(d.Config.ClusterName), Client: d.LMClient, - CreateDeletedGroup: d.Config.DeleteDevices, - DeletedGroupAppliesTo: devicegroup.NewAppliesToBuilder().HasCategory(constants.NodeDeletedCategory).And().Auto("clustername").Equals(d.Config.ClusterName), + DeleteDevices: d.Config.DeleteDevices, + AppliesToDeletedGroup: devicegroup.NewAppliesToBuilder().HasCategory(constants.NodeDeletedCategory).And().Auto("clustername").Equals(d.Config.ClusterName), }, { Name: constants.ServiceDeviceGroupName, DisableAlerting: d.Config.DisableAlerting, AppliesTo: devicegroup.NewAppliesToBuilder(), Client: d.LMClient, - CreateDeletedGroup: d.Config.DeleteDevices, - DeletedGroupAppliesTo: devicegroup.NewAppliesToBuilder().HasCategory(constants.ServiceDeletedCategory).And().Auto("clustername").Equals(d.Config.ClusterName), + DeleteDevices: d.Config.DeleteDevices, + AppliesToDeletedGroup: devicegroup.NewAppliesToBuilder().HasCategory(constants.ServiceDeletedCategory).And().Auto("clustername").Equals(d.Config.ClusterName), }, { Name: constants.PodDeviceGroupName, DisableAlerting: d.Config.DisableAlerting, AppliesTo: devicegroup.NewAppliesToBuilder(), Client: d.LMClient, - CreateDeletedGroup: d.Config.DeleteDevices, - DeletedGroupAppliesTo: devicegroup.NewAppliesToBuilder().HasCategory(constants.PodDeletedCategory).And().Auto("clustername").Equals(d.Config.ClusterName), + DeleteDevices: d.Config.DeleteDevices, + AppliesToDeletedGroup: devicegroup.NewAppliesToBuilder().HasCategory(constants.PodDeletedCategory).And().Auto("clustername").Equals(d.Config.ClusterName), }, } } @@ -71,7 +70,6 @@ func (d *DeviceTree) CreateDeviceTree() (map[string]int32, error) { return nil, err } deviceGroups[opts.Name] = id - log.Infof("%s has device group id %d", opts.Name, id) } return deviceGroups, nil diff --git a/pkg/watch/namespace/namespace.go b/pkg/watch/namespace/namespace.go index a7473a4c4..df69c6c86 100644 --- a/pkg/watch/namespace/namespace.go +++ b/pkg/watch/namespace/namespace.go @@ -35,32 +35,35 @@ func (w Watcher) ObjType() runtime.Object { func (w Watcher) AddFunc() func(obj interface{}) { return func(obj interface{}) { namespace := obj.(*v1.Namespace) - for k, parentID := range w.DeviceGroups { + for name, parentID := range w.DeviceGroups { var appliesTo devicegroup.AppliesToBuilder // Ensure that we are creating namespaces for namespaced resources. - switch k { - case constants.ServiceCategory: + switch name { + case constants.ServiceDeviceGroupName: appliesTo = devicegroup.NewAppliesToBuilder().HasCategory(constants.ServiceCategory).And().Auto("namespace").Equals(namespace.Name).And().Auto("clustername").Equals(w.Config.ClusterName) - case constants.PodCategory: + case constants.PodDeviceGroupName: appliesTo = devicegroup.NewAppliesToBuilder().HasCategory(constants.PodCategory).And().Auto("namespace").Equals(namespace.Name).And().Auto("clustername").Equals(w.Config.ClusterName) default: - return + continue } opts := &devicegroup.Options{ - Name: namespace.Name, AppliesTo: appliesTo, - ParentID: parentID, + Client: w.LMClient, DisableAlerting: w.Config.DisableAlerting, + Name: namespace.Name, + ParentID: parentID, } + + log.Debugf("%v", opts) + _, err := devicegroup.Create(opts) if err != nil { - log.Errorf("Failed to add namespace: %v", err) - + log.Errorf("Failed to add namespace to %q: %v", name, err) return } - log.Printf("Added namespace %s", namespace.Name) + log.Printf("Added namespace %q to %q", namespace.Name, name) } } } diff --git a/pkg/watch/node/node.go b/pkg/watch/node/node.go index 3f0db8a7c..c7c72e388 100644 --- a/pkg/watch/node/node.go +++ b/pkg/watch/node/node.go @@ -74,6 +74,7 @@ func (w Watcher) UpdateFunc() func(oldObj, newObj interface{}) { err := device.Add(d, w.LMClient) if err != nil { log.Errorf("Failed to add node %s: %s", d.DisplayName, err) + return } log.Infof("Added node %s", d.DisplayName) return @@ -123,6 +124,7 @@ func (w Watcher) DeleteFunc() func(obj interface{}) { err = device.Delete(d, w.LMClient) if err != nil { log.Errorf("Failed to delete node: %v", err) + return } log.Infof("Deleted node %s with id %d", d.DisplayName, d.Id) return diff --git a/pkg/watch/pod/pod.go b/pkg/watch/pod/pod.go index fbb874332..0f2f7ebff 100644 --- a/pkg/watch/pod/pod.go +++ b/pkg/watch/pod/pod.go @@ -52,8 +52,9 @@ func (w Watcher) AddFunc() func(obj interface{}) { newDevice := w.makeDeviceObject(pod) err = device.Add(newDevice, w.LMClient) if err != nil { - log.Errorf("Failed to add node %q: %v", newDevice.DisplayName, err) + log.Errorf("Failed to add pod %q: %v", newDevice.DisplayName, err) } + log.Infof("Added pod %s", newDevice.DisplayName) } } } @@ -72,6 +73,7 @@ func (w Watcher) UpdateFunc() func(oldObj, newObj interface{}) { err := device.Add(d, w.LMClient) if err != nil { log.Errorf("Failed to add pod %s: %s", d.DisplayName, err) + return } log.Infof("Added pod %s", d.DisplayName) return @@ -121,6 +123,7 @@ func (w Watcher) DeleteFunc() func(obj interface{}) { err = device.Delete(d, w.LMClient) if err != nil { log.Errorf("Failed to delete pod: %v", err) + return } log.Infof("Deleted pod %s with id %d", d.DisplayName, d.Id) return diff --git a/pkg/watch/service/service.go b/pkg/watch/service/service.go index da07fb9b2..428d08dec 100644 --- a/pkg/watch/service/service.go +++ b/pkg/watch/service/service.go @@ -46,7 +46,7 @@ func (w Watcher) AddFunc() func(obj interface{}) { } // Check if the service has already been added. - d, err := device.FindByDisplayName(service.Name, w.LMClient) + d, err := device.FindByDisplayName(fmtServiceDisplayName(service), w.LMClient) if err != nil { log.Errorf("Failed to find service %q: %v", service.Name, err) return @@ -59,6 +59,7 @@ func (w Watcher) AddFunc() func(obj interface{}) { if err != nil { log.Errorf("Failed to add service %q: %v", newDevice.DisplayName, err) } + log.Infof("Added service %s", newDevice.DisplayName) } } } @@ -82,6 +83,7 @@ func (w Watcher) UpdateFunc() func(oldObj, newObj interface{}) { err := device.Add(d, w.LMClient) if err != nil { log.Errorf("Failed to add service %s: %s", d.DisplayName, err) + return } log.Infof("Added service %s", d.DisplayName) return @@ -90,7 +92,7 @@ func (w Watcher) UpdateFunc() func(oldObj, newObj interface{}) { // Covers the case when a service has been terminated (new ip doesn't exist) // and if a service needs to be added. if oldService.Spec.ClusterIP != "" && newService.Spec.ClusterIP != "" { - oldDevice, err := device.FindByDisplayName(oldService.Name, w.LMClient) + oldDevice, err := device.FindByDisplayName(fmtServiceDisplayName(oldService), w.LMClient) if err != nil { log.Errorf("Failed to find service %q: %v", oldService.Name, err) return @@ -116,7 +118,7 @@ func (w Watcher) UpdateFunc() func(oldObj, newObj interface{}) { func (w Watcher) DeleteFunc() func(obj interface{}) { return func(obj interface{}) { service := obj.(*v1.Service) - d, err := device.FindByDisplayName(service.Name, w.LMClient) + d, err := device.FindByDisplayName(fmtServiceDisplayName(service), w.LMClient) if err != nil { log.Errorf("Failed to find service %q: %v", service.Name, err) return @@ -131,6 +133,7 @@ func (w Watcher) DeleteFunc() func(obj interface{}) { err = device.Delete(d, w.LMClient) if err != nil { log.Errorf("Failed to delete service: %v", err) + return } log.Infof("Deleted service %s with id %d", d.DisplayName, d.Id) return @@ -160,10 +163,9 @@ func (w Watcher) DeleteFunc() func(obj interface{}) { func (w Watcher) makeDeviceObject(service *v1.Service) *lm.RestDevice { categories := device.BuildSystemCategoriesFromLabels(constants.ServiceCategory, service.Labels) - fqdn := service.Name + "." + service.Namespace + ".svc.cluster.local" d := &lm.RestDevice{ - Name: fqdn, - DisplayName: fqdn + "-" + string(service.UID), + Name: fmtServiceName(service), + DisplayName: fmtServiceDisplayName(service), DisableAlerting: true, HostGroupIds: "1", PreferredCollectorId: w.Config.PreferredCollector, @@ -197,3 +199,11 @@ func (w Watcher) makeDeviceObject(service *v1.Service) *lm.RestDevice { return d } + +func fmtServiceName(service *v1.Service) string { + return service.Name + "." + service.Namespace + ".svc.cluster.local" +} + +func fmtServiceDisplayName(service *v1.Service) string { + return fmtServiceName(service) + "-" + string(service.UID) +} diff --git a/scripts/test.sh b/scripts/test.sh index 455c4b89a..3b82e5ec8 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -24,8 +24,7 @@ test_packages() { lint_packages() { echo "Linting packages" - # Use the --debug flag to keep Travis from thinking the build has stalled. - gometalinter --debug --vendor --enable-all --disable=gas --disable=gotype --disable=lll --disable=safesql --deadline=600s ./... + gometalinter --aggregate --vendor --enable-all --disable=gas --disable=gotype --disable=lll --disable=safesql --deadline=600s ./... } format_files() { @@ -37,8 +36,8 @@ format_files() { fi } -test_packages lint_packages format_files +test_packages exit 0