diff --git a/pkg/monitor/resourcewatch/cmd/resourcewatch.go b/pkg/monitor/resourcewatch/cmd/resourcewatch.go index 49c2d07d86d1..a95a807daeb3 100644 --- a/pkg/monitor/resourcewatch/cmd/resourcewatch.go +++ b/pkg/monitor/resourcewatch/cmd/resourcewatch.go @@ -1,6 +1,8 @@ package cmd import ( + "context" + "github.com/spf13/cobra" "github.com/openshift/library-go/pkg/controller/controllercmd" @@ -12,9 +14,18 @@ import ( func NewRunResourceWatchCommand() *cobra.Command { cmd := controllercmd. NewControllerCommandConfig("run-resourcewatch", version.Get(), operator.RunOperator). - NewCommand() + NewCommandWithContext(context.TODO()) cmd.Use = "run-resourcewatch" - cmd.Short = "Run watching resource changes" + cmd.Short = "Run watch for resource changes and commit each to a git repository" + cmd.Long = ` +Watches specific resources using the given kubeconfig for create/update/delete, +and commits the latest state of the resource to a git repo. This allows you to +see precisely how a resource changed over time. +By default /repository will be used, specify REPOSITORY_PATH env var to +override. +Sample invocation against an external cluster: + $ REPOSITORY_PATH="/tmp/resource-watch-repo" openshift-tests run-resourcewatch --kubeconfig /path/to/kubeconfig --namespace default +` return cmd } diff --git a/pkg/monitor/resourcewatch/controller/clusteroperatormetric/controller.go b/pkg/monitor/resourcewatch/controller/clusteroperatormetric/controller.go index aa1fc289c048..3e443dad3859 100644 --- a/pkg/monitor/resourcewatch/controller/clusteroperatormetric/controller.go +++ b/pkg/monitor/resourcewatch/controller/clusteroperatormetric/controller.go @@ -32,11 +32,15 @@ type ClusterOperatorMetricController struct { clusterOperatorClient configv1client.ClusterOperatorsGetter } -func NewClusterOperatorMetricController(clusterOperatorInformer cache.SharedInformer, clusterOperatorGetter configv1client.ClusterOperatorsGetter, recorder events.Recorder) factory.Controller { +func NewClusterOperatorMetricController( + clusterOperatorInformer cache.SharedInformer, + clusterOperatorGetter configv1client.ClusterOperatorsGetter, + recorder events.Recorder) factory.Controller { c := &ClusterOperatorMetricController{ clusterOperatorClient: clusterOperatorGetter, } - return factory.New().WithInformers(clusterOperatorInformer).WithSync(c.sync).ResyncEvery(1*time.Minute).ToController("ClusterOperatorMetricController", recorder.WithComponentSuffix("cluster-operator-metric")) + return factory.New().WithInformers(clusterOperatorInformer).WithSync(c.sync).ResyncEvery(1*time.Minute). + ToController("ClusterOperatorMetricController", recorder.WithComponentSuffix("cluster-operator-metric")) } func (c *ClusterOperatorMetricController) sync(ctx context.Context, syncCtx factory.SyncContext) error { @@ -46,7 +50,8 @@ func (c *ClusterOperatorMetricController) sync(ctx context.Context, syncCtx fact } for _, operator := range clusterOperators.Items { for _, condition := range operator.Status.Conditions { - clusterOperatorStateMetric.WithLabelValues(operator.Name, string(condition.Type), string(condition.Status)).Set(float64(condition.LastTransitionTime.Unix())) + clusterOperatorStateMetric.WithLabelValues(operator.Name, string(condition.Type), + string(condition.Status)).Set(float64(condition.LastTransitionTime.Unix())) } } return nil diff --git a/pkg/monitor/resourcewatch/controller/configmonitor/crd_controller.go b/pkg/monitor/resourcewatch/controller/configmonitor/crd_controller.go index a4be6bcf4160..a51d2ca8e002 100644 --- a/pkg/monitor/resourcewatch/controller/configmonitor/crd_controller.go +++ b/pkg/monitor/resourcewatch/controller/configmonitor/crd_controller.go @@ -26,13 +26,16 @@ var ( ) type ConfigObserverController struct { - crdLister apiextensionsv1lister.CustomResourceDefinitionLister - crdInformer cache.SharedIndexInformer - dynamicClient dynamic.Interface - dynamicInformers []*dynamicConfigInformer - cachedDiscovery discovery.CachedDiscoveryInterface - monitoredResources []schema.GroupVersion - storageHandler cache.ResourceEventHandler + crdLister apiextensionsv1lister.CustomResourceDefinitionLister + crdInformer cache.SharedIndexInformer + dynamicClient dynamic.Interface + dynamicInformers []*dynamicConfigInformer + cachedDiscovery discovery.CachedDiscoveryInterface + // monitoredResourceGVs are group+versions we want to monitor all resources beneath. + monitoredResourceGVs []schema.GroupVersion + // monitoredResourceGVKs are specific group+version+kinds we want to monitor for. (as opposed to everything in the group) + monitoredResourceGVKs []schema.GroupVersionKind + storageHandler cache.ResourceEventHandler } func NewConfigObserverController( @@ -40,22 +43,25 @@ func NewConfigObserverController( crdInformer cache.SharedIndexInformer, discoveryClient *discovery.DiscoveryClient, configStorage cache.ResourceEventHandler, - monitoredResources []schema.GroupVersion, + monitoredResourceGVs []schema.GroupVersion, + monitoredResourceGVKs []schema.GroupVersionKind, recorder events.Recorder, ) factory.Controller { c := &ConfigObserverController{ - dynamicClient: dynamicClient, - crdInformer: crdInformer, - storageHandler: configStorage, - monitoredResources: monitoredResources, - cachedDiscovery: memory.NewMemCacheClient(discoveryClient), + dynamicClient: dynamicClient, + crdInformer: crdInformer, + storageHandler: configStorage, + monitoredResourceGVs: monitoredResourceGVs, + monitoredResourceGVKs: monitoredResourceGVKs, + cachedDiscovery: memory.NewMemCacheClient(discoveryClient), } c.crdLister = apiextensionsv1lister.NewCustomResourceDefinitionLister(c.crdInformer.GetIndexer()) return factory.New().WithInformers(c.crdInformer).ResyncEvery(defaultResyncDuration).WithSync(c.sync).ToController("ConfigObserverController", recorder.WithComponentSuffix("config-observer-controller")) } -// currentResourceKinds returns list of group version configKind for OpenShift configuration types. +// currentResourceKinds returns list of group version kind for each resource we want to watch currently. +// We may be watching for CRDs which do not initially exist, thus why this is "current" resource kinds. func (c *ConfigObserverController) currentResourceKinds() ([]schema.GroupVersionKind, error) { observedCrds, err := c.crdLister.List(labels.Everything()) if err != nil { @@ -66,7 +72,7 @@ func (c *ConfigObserverController) currentResourceKinds() ([]schema.GroupVersion currentKinds = sets.NewString() ) for _, crd := range observedCrds { - for _, gv := range c.monitoredResources { + for _, gv := range c.monitoredResourceGVs { if !strings.HasSuffix(crd.GetName(), "."+gv.Group) { continue } @@ -86,24 +92,31 @@ func (c *ConfigObserverController) currentResourceKinds() ([]schema.GroupVersion currentConfigResources = append(currentConfigResources, gvk) } } - + for _, gvk := range c.monitoredResourceGVKs { + if currentKinds.Has(gvk.Kind) { + continue + } + currentKinds.Insert(gvk.Kind) + currentConfigResources = append(currentConfigResources, gvk) + } } return currentConfigResources, nil } func (c *ConfigObserverController) sync(ctx context.Context, syncCtx factory.SyncContext) error { - current, err := c.currentResourceKinds() + currentResourcesToMonitor, err := c.currentResourceKinds() if err != nil { return err } - // TODO: The CRD delete case is not handled + // TODO: The CRD delete case is not handled. This would require shutting down an observer on a GVK that + // no longer exists? var ( currentList []string needObserverList []string kindNeedObserver []schema.GroupVersionKind ) - for _, configKind := range current { + for _, configKind := range currentResourcesToMonitor { currentList = append(currentList, configKind.String()) hasObserver := false for _, o := range c.dynamicInformers { diff --git a/pkg/monitor/resourcewatch/operator/starter.go b/pkg/monitor/resourcewatch/operator/starter.go index 9e2788bccdb4..82af97c3ddc2 100644 --- a/pkg/monitor/resourcewatch/operator/starter.go +++ b/pkg/monitor/resourcewatch/operator/starter.go @@ -66,6 +66,33 @@ func RunOperator(ctx context.Context, controllerCtx *controllercmd.ControllerCon Version: "v1", }, }, + []schema.GroupVersionKind{ + { + Group: "apps", + Version: "v1", + Kind: "Deployment", + }, + { + Group: "apps", + Version: "v1", + Kind: "DaemonSet", + }, + { + Group: "", + Version: "v1", + Kind: "Event", + }, + { + Group: "", + Version: "v1", + Kind: "Pod", + }, + { + Group: "", + Version: "v1", + Kind: "Node", + }, + }, controllerCtx.EventRecorder, ) diff --git a/pkg/monitor/resourcewatch/storage/git_store.go b/pkg/monitor/resourcewatch/storage/git_store.go index 2166dda36187..cb2eb9ea151a 100644 --- a/pkg/monitor/resourcewatch/storage/git_store.go +++ b/pkg/monitor/resourcewatch/storage/git_store.go @@ -139,7 +139,11 @@ func decodeUnstructuredObject(objUnstructured *unstructured.Unstructured) (strin // resourceFilename extracts the filename out from the group version kind func resourceFilename(name string, gvk schema.GroupVersionKind) string { - return strings.ToLower(fmt.Sprintf("%s.%s.%s-%s.yaml", gvk.Kind, gvk.Version, gvk.Group, name)) + groupStr := "" + if gvk.Group != "" { + groupStr = fmt.Sprintf(".%s", gvk.Group) + } + return strings.ToLower(fmt.Sprintf("%s.%s%s-%s.yaml", gvk.Kind, gvk.Version, groupStr, name)) } // commit handle different git operators on repository