From 972c9480abd21c881d775837fcbabae1507e2f1e Mon Sep 17 00:00:00 2001 From: Michael Hammer Date: Fri, 3 Apr 2020 12:00:44 -0400 Subject: [PATCH] [initial opssight CRUD] --- pkg/opssight/configmap.go | 138 ------- pkg/opssight/controller.go | 164 -------- pkg/opssight/crdinstaller.go | 207 ---------- pkg/opssight/create_test.go | 36 -- pkg/opssight/creater.go | 285 ------------- pkg/opssight/creater_test.go | 358 ----------------- pkg/opssight/ctl_opssight.go | 420 +++++++------------- pkg/opssight/ctl_opssight_test.go | 596 ++-------------------------- pkg/opssight/handler.go | 209 ---------- pkg/opssight/opssight_suite_test.go | 37 -- pkg/opssight/perceivers.go | 406 ------------------- pkg/opssight/perceptor.go | 234 ----------- pkg/opssight/plugins.go | 311 --------------- pkg/opssight/prometheus.go | 271 ------------- pkg/opssight/scanner.go | 308 -------------- pkg/opssight/skyfire.go | 218 ---------- pkg/opssight/specconfig.go | 477 ---------------------- pkg/synopsysctl/CRDPrint.go | 12 - pkg/synopsysctl/cmd_create.go | 136 +++---- pkg/synopsysctl/cmd_delete.go | 34 +- pkg/synopsysctl/cmd_edit.go | 33 -- pkg/synopsysctl/cmd_get.go | 28 +- pkg/synopsysctl/cmd_start.go | 54 ++- pkg/synopsysctl/cmd_stop.go | 58 ++- pkg/synopsysctl/cmd_update.go | 141 +++++-- pkg/synopsysctl/constants.go | 7 + pkg/synopsysctl/opssight_migrate.go | 211 ++++++++++ 27 files changed, 641 insertions(+), 4748 deletions(-) delete mode 100644 pkg/opssight/configmap.go delete mode 100644 pkg/opssight/controller.go delete mode 100644 pkg/opssight/crdinstaller.go delete mode 100644 pkg/opssight/create_test.go delete mode 100644 pkg/opssight/creater.go delete mode 100644 pkg/opssight/creater_test.go delete mode 100644 pkg/opssight/handler.go delete mode 100644 pkg/opssight/opssight_suite_test.go delete mode 100644 pkg/opssight/perceivers.go delete mode 100644 pkg/opssight/perceptor.go delete mode 100644 pkg/opssight/plugins.go delete mode 100644 pkg/opssight/prometheus.go delete mode 100644 pkg/opssight/scanner.go delete mode 100644 pkg/opssight/skyfire.go delete mode 100644 pkg/opssight/specconfig.go create mode 100644 pkg/synopsysctl/opssight_migrate.go diff --git a/pkg/opssight/configmap.go b/pkg/opssight/configmap.go deleted file mode 100644 index 1e3c17a54..000000000 --- a/pkg/opssight/configmap.go +++ /dev/null @@ -1,138 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -import ( - "encoding/json" - - horizonapi "github.com/blackducksoftware/horizon/pkg/api" - "github.com/blackducksoftware/horizon/pkg/components" - "github.com/juju/errors" -) - -// PerceiverConfig stores the Perceiver configuration -type PerceiverConfig struct { - Certificate string - CertificateKey string - AnnotationIntervalSeconds int - DumpIntervalMinutes int - Port int - Pod *PodPerceiverConfig - Image *ImagePerceiverConfig - Artifactory *ArtifactoryPerceiverConfig -} - -// ImagePerceiverConfig stores the Image Perceiver configuration -type ImagePerceiverConfig struct{} - -// ArtifactoryPerceiverConfig stores the Artifactory Perceiver configuration -type ArtifactoryPerceiverConfig struct { - Dumper bool -} - -// PodPerceiverConfig stores the Pod Perceiver configuration -type PodPerceiverConfig struct { - NamespaceFilter string -} - -// BlackDuckConfig stores the Black Duck configuration -type BlackDuckConfig struct { - ConnectionsEnvironmentVariableName string - TLSVerification bool -} - -// PerceptorTimingsConfig stores the Perceptor configuration -type PerceptorTimingsConfig struct { - CheckForStalledScansPauseHours int - StalledScanClientTimeoutHours int - ModelMetricsPauseSeconds int - UnknownImagePauseMilliseconds int - ClientTimeoutMilliseconds int -} - -// PerceptorConfig stores the Perceptor configuration -type PerceptorConfig struct { - Timings *PerceptorTimingsConfig - UseMockMode bool - Host string - Port int -} - -// ScannerConfig stores the Perceptor Scanner configuration -type ScannerConfig struct { - Port int - ImageDirectory string - BlackDuckClientTimeoutSeconds int -} - -// ImageFacadeConfig stores the Perceptor Image Facade configuration -type ImageFacadeConfig struct { - Host string - Port int - ImagePullerType string - CreateImagesOnly bool -} - -// SkyfireConfig stores the Skyfire configuration -type SkyfireConfig struct { - UseInClusterConfig bool - Port int - PrometheusPort int - BlackDuckClientTimeoutSeconds int - KubeDumpIntervalSeconds int - PerceptorDumpIntervalSeconds int - BlackDuckDumpPauseSeconds int -} - -// MainOpssightConfigMap stores the opssight configmap -type MainOpssightConfigMap struct { - Perceiver *PerceiverConfig - BlackDuck *BlackDuckConfig - Perceptor *PerceptorConfig - Scanner *ScannerConfig - ImageFacade *ImageFacadeConfig - Skyfire *SkyfireConfig - LogLevel string -} - -func (cm *MainOpssightConfigMap) jsonString() (string, error) { - bytes, err := json.MarshalIndent(cm, "", " ") - if err != nil { - return "", errors.Annotate(err, "unable to serialize to json") - } - return string(bytes), nil -} - -func (cm *MainOpssightConfigMap) horizonConfigMap(name string, namespace string, filename string) (*components.ConfigMap, error) { - configMap := components.NewConfigMap(horizonapi.ConfigMapConfig{ - Name: name, - Namespace: namespace, - }) - configMapString, err := cm.jsonString() - if err != nil { - return nil, errors.Trace(err) - } - configMap.AddLabels(map[string]string{"component": name, "app": "opssight"}) - configMap.AddData(map[string]string{filename: configMapString}) - - return configMap, nil -} diff --git a/pkg/opssight/controller.go b/pkg/opssight/controller.go deleted file mode 100644 index c351e4d58..000000000 --- a/pkg/opssight/controller.go +++ /dev/null @@ -1,164 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -import ( - "fmt" - "time" - - opssightclientset "github.com/blackducksoftware/synopsys-operator/pkg/opssight/client/clientset/versioned" - log "github.com/sirupsen/logrus" - "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/cache" - "k8s.io/client-go/util/workqueue" -) - -// Controller will store the controller configuration -type Controller struct { - Logger *log.Entry - Clientset kubernetes.Interface - Queue workqueue.RateLimitingInterface - Informer cache.SharedIndexInformer - Handler HandlerInterface - OpsSightClientset *opssightclientset.Clientset - Namespace string -} - -// NewController will contain the controller specification -func NewController(config interface{}) *Controller { - return config.(*Controller) -} - -// Run will be executed to create the informers or controllers -func (c *Controller) Run(threadiness int, stopCh <-chan struct{}) { - // handle a panic with logging and exiting - defer runtime.HandleCrash() - - // ignore new items in the queue but when all goroutines - // have completed existing items then shutdown - defer c.Queue.ShutDown() - - c.Logger.Info("Initiating controller") - - // run the informer to start listing and watching resources - go c.Informer.Run(stopCh) - - // do the initial synchronization (one time) to populate resources - if !cache.WaitForCacheSync(stopCh, c.HasSynced) { - runtime.HandleError(fmt.Errorf("Error syncing cache")) - return - } - c.Logger.Info("Controller cache sync complete") - - for i := 0; i < threadiness; i++ { - // run the runWorker method every second with a stop channel - go wait.Until(c.runWorker, time.Second, stopCh) - } - - // Wait until we're told to stop - <-stopCh -} - -// HasSynced will check for informer sync -func (c *Controller) HasSynced() bool { - return c.Informer.HasSynced() -} - -// runWorker executes the loop to process new items added to the queue -func (c *Controller) runWorker() { - log.Debug("Controller.runWorker: starting") - - // invoke processNextItem to fetch and consume the next change - // to a watched or listed resource - for c.processNextItem() { - log.Info("Controller.runWorker: processing next item") - } - - log.Debug("Controller.runWorker: completed") -} - -// processNextItem retrieves each queued item and takes the -// necessary handler action based off of if the item was -// created or deleted -func (c *Controller) processNextItem() bool { - log.Info("Controller.processNextItem: start") - - // fetch the next item (blocking) from the queue to process or - // if a shutdown is requested then return out of this to stop - // processing - key, quit := c.Queue.Get() - - // stop the worker loop from running as this indicates we - // have sent a shutdown message that the queue has indicated - // from the Get method - if quit { - return false - } - - defer c.Queue.Done(key) - - // assert the string out of the key (format `namespace/name`) - keyRaw := key.(string) - - // take the string key and get the object out of the indexer - // - // item will contain the complex object for the resource and - // exists is a bool that'll indicate whether or not the - // resource was created (true) or deleted (false) - // - // if there is an error in getting the key from the index - // then we want to retry this particular queue key a certain - // number of times (5 here) before we forget the queue key - // and throw an error - item, exists, err := c.Informer.GetIndexer().GetByKey(keyRaw) - if err != nil { - if c.Queue.NumRequeues(key) < 5 { - c.Logger.Errorf("Controller.processNextItem: Failed processing item with key %s with error %v, retrying", key, err) - c.Queue.AddRateLimited(key) - } else { - c.Logger.Errorf("Controller.processNextItem: Failed processing item with key %s with error %v, no more retries", key, err) - c.Queue.Forget(key) - runtime.HandleError(err) - } - } - - // if the item doesn't exist then it was deleted and we need to fire off the handler's - // ObjectDeleted method. but if the object does exist that indicates that the object - // was created (or updated) so run the ObjectCreated method - // - // after both instances, we want to forget the key from the queue, as this indicates - // a code path of successful queue key processing - if !exists { - c.Logger.Debugf("Controller.processNextItem: object deleted detected: %s: %+v", keyRaw, item) - c.Handler.ObjectDeleted(keyRaw) - c.Queue.Forget(key) - } else { - c.Logger.Debugf("Controller.processNextItem: object created detected: %s: %+v", keyRaw, item) - c.Handler.ObjectCreated(item) - c.Queue.Forget(key) - } - - // keep the worker loop running by returning true - return true -} diff --git a/pkg/opssight/crdinstaller.go b/pkg/opssight/crdinstaller.go deleted file mode 100644 index 6b619e8c7..000000000 --- a/pkg/opssight/crdinstaller.go +++ /dev/null @@ -1,207 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -import ( - "reflect" - "strings" - "time" - - opssightapi "github.com/blackducksoftware/synopsys-operator/pkg/api/opssight/v1" - hubclient "github.com/blackducksoftware/synopsys-operator/pkg/blackduck/client/clientset/versioned" - opssightclientset "github.com/blackducksoftware/synopsys-operator/pkg/opssight/client/clientset/versioned" - opssightinformer "github.com/blackducksoftware/synopsys-operator/pkg/opssight/client/informers/externalversions/opssight/v1" - "github.com/blackducksoftware/synopsys-operator/pkg/protoform" - "github.com/blackducksoftware/synopsys-operator/pkg/util" - "github.com/juju/errors" - securityclient "github.com/openshift/client-go/security/clientset/versioned/typed/security/v1" - log "github.com/sirupsen/logrus" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/cache" - "k8s.io/client-go/util/workqueue" -) - -// CRDInstaller defines the specification -type CRDInstaller struct { - config *protoform.Config - kubeConfig *rest.Config - kubeClient *kubernetes.Clientset - defaults interface{} - resyncPeriod time.Duration - indexers cache.Indexers - informer cache.SharedIndexInformer - queue workqueue.RateLimitingInterface - handler *Handler - controller *Controller - opssightclient *opssightclientset.Clientset - stopCh <-chan struct{} -} - -// NewCRDInstaller will create a controller configuration -func NewCRDInstaller(config *protoform.Config, kubeConfig *rest.Config, kubeClient *kubernetes.Clientset, defaults interface{}, stopCh <-chan struct{}) *CRDInstaller { - crdInstaller := &CRDInstaller{config: config, kubeConfig: kubeConfig, kubeClient: kubeClient, defaults: defaults, stopCh: stopCh} - log.Debugf("resync period: %d", config.ResyncIntervalInSeconds) - crdInstaller.resyncPeriod = time.Duration(config.ResyncIntervalInSeconds) * time.Second - crdInstaller.indexers = cache.Indexers{} - return crdInstaller -} - -// CreateClientSet will create the CRD client -func (c *CRDInstaller) CreateClientSet() error { - opssightClient, err := opssightclientset.NewForConfig(c.kubeConfig) - if err != nil { - return errors.Annotate(err, "Unable to create OpsSight informer client") - } - c.opssightclient = opssightClient - return nil -} - -// Deploy will deploy the CRD -func (c *CRDInstaller) Deploy() error { - // Any new, pluggable maintainance stuff should go in here... - blackDuckClient, err := hubclient.NewForConfig(c.kubeConfig) - if err != nil { - return errors.Trace(err) - } - crdUpdater := NewUpdater(c.config, c.kubeClient, blackDuckClient, c.opssightclient) - go crdUpdater.Run(c.stopCh) - return nil -} - -// PostDeploy will initialize before deploying the CRD -func (c *CRDInstaller) PostDeploy() { -} - -// CreateInformer will create a informer for the CRD -func (c *CRDInstaller) CreateInformer() { - c.informer = opssightinformer.NewOpsSightInformer( - c.opssightclient, - c.config.CrdNamespace, - c.resyncPeriod, - c.indexers, - ) -} - -// CreateQueue will create a queue to process the CRD -func (c *CRDInstaller) CreateQueue() { - // create a new queue so that when the informer gets a resource that is either - // a result of listing or watching, we can add an idenfitying key to the queue - // so that it can be handled in the handler - c.queue = workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) -} - -// AddInformerEventHandler will add the event handlers for the informers -func (c *CRDInstaller) AddInformerEventHandler() { - c.informer.AddEventHandler(cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - // convert the resource object into a key (in this case - // we are just doing it in the format of 'namespace/name') - key, err := cache.MetaNamespaceKeyFunc(obj) - log.Infof("add opssight: %s", key) - if err == nil { - // add the key to the queue for the handler to get - c.queue.Add(key) - } else { - log.Errorf("unable to add OpsSight: %v", err) - } - }, - UpdateFunc: func(oldObj, newObj interface{}) { - old := oldObj.(*opssightapi.OpsSight) - new := newObj.(*opssightapi.OpsSight) - if strings.EqualFold(old.Status.State, string(Running)) || !reflect.DeepEqual(old.Spec, new.Spec) || !reflect.DeepEqual(old.Status.InternalHosts, new.Status.InternalHosts) { - key, err := cache.MetaNamespaceKeyFunc(newObj) - log.Infof("update opssight: %s", key) - if err == nil { - c.queue.Add(key) - } else { - log.Errorf("unable to update OpsSight: %v", err) - } - } - }, - DeleteFunc: func(obj interface{}) { - // DeletionHandlingMetaNamespaceKeyFunc is a helper function that allows - // us to check the DeletedFinalStateUnknown existence in the event that - // a resource was deleted but it is still contained in the index - // - // this then in turn calls MetaNamespaceKeyFunc - key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) - log.Infof("delete opssight: %s: %+v", key, obj) - - if err == nil { - c.queue.Add(key) - } else { - log.Errorf("unable to delete OpsSight: %v", err) - } - }, - }) -} - -// CreateHandler will create a CRD handler -func (c *CRDInstaller) CreateHandler() { - hubClient, err := hubclient.NewForConfig(c.kubeConfig) - if err != nil { - log.Errorf("unable to create the hub client for opssight: %+v", err) - return - } - - c.handler = &Handler{ - Config: c.config, - KubeConfig: c.kubeConfig, - KubeClient: c.kubeClient, - OpsSightClient: c.opssightclient, - Namespace: c.config.Namespace, - Defaults: c.defaults.(*opssightapi.OpsSightSpec), - HubClient: hubClient, - } - - if util.IsOpenshift(c.kubeClient) { - c.handler.RouteClient = util.GetRouteClient(c.kubeConfig, c.kubeClient, c.config.Namespace) - if c.handler.OSSecurityClient, err = securityclient.NewForConfig(c.kubeConfig); err != nil { - log.Errorf("error in creating the OpenShift security client due to %+v", err) - return - } - } -} - -// CreateController will create a CRD controller -func (c *CRDInstaller) CreateController() { - c.controller = NewController( - &Controller{ - Logger: log.NewEntry(log.New()), - Clientset: c.kubeClient, - Queue: c.queue, - Informer: c.informer, - Handler: c.handler, - OpsSightClientset: c.opssightclient, - Namespace: c.config.Namespace, - }) -} - -// Run will run the CRD controller -func (c *CRDInstaller) Run() { - go c.controller.Run(c.config.Threadiness, c.stopCh) -} - -// PostRun will run post CRD controller execution -func (c *CRDInstaller) PostRun() { -} diff --git a/pkg/opssight/create_test.go b/pkg/opssight/create_test.go deleted file mode 100644 index c1812f4a7..000000000 --- a/pkg/opssight/create_test.go +++ /dev/null @@ -1,36 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func RunCreaterTests() { - Describe("Creater", func() { - It("should instantiate without crashing", func() { - creater := NewCreater(nil, nil, nil, nil, nil, nil, nil, false) - Expect(creater).ToNot(BeNil()) - }) - }) -} diff --git a/pkg/opssight/creater.go b/pkg/opssight/creater.go deleted file mode 100644 index 05f74d0fd..000000000 --- a/pkg/opssight/creater.go +++ /dev/null @@ -1,285 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -import ( - "fmt" - "strings" - - "github.com/blackducksoftware/synopsys-operator/pkg/api" - blackduckapi "github.com/blackducksoftware/synopsys-operator/pkg/api/blackduck/v1" - opssightapi "github.com/blackducksoftware/synopsys-operator/pkg/api/opssight/v1" - hubclientset "github.com/blackducksoftware/synopsys-operator/pkg/blackduck/client/clientset/versioned" - "github.com/blackducksoftware/synopsys-operator/pkg/crdupdater" - opssightclientset "github.com/blackducksoftware/synopsys-operator/pkg/opssight/client/clientset/versioned" - "github.com/blackducksoftware/synopsys-operator/pkg/protoform" - "github.com/blackducksoftware/synopsys-operator/pkg/util" - "github.com/juju/errors" - routeclient "github.com/openshift/client-go/route/clientset/versioned/typed/route/v1" - securityclient "github.com/openshift/client-go/security/clientset/versioned/typed/security/v1" - log "github.com/sirupsen/logrus" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" -) - -// Creater will store the configuration to create OpsSight -type Creater struct { - config *protoform.Config - kubeConfig *rest.Config - kubeClient *kubernetes.Clientset - opssightClient *opssightclientset.Clientset - osSecurityClient *securityclient.SecurityV1Client - routeClient *routeclient.RouteV1Client - hubClient *hubclientset.Clientset - isBlackDuckClusterScope bool -} - -// NewCreater will instantiate the Creater -func NewCreater(config *protoform.Config, kubeConfig *rest.Config, kubeClient *kubernetes.Clientset, opssightClient *opssightclientset.Clientset, osSecurityClient *securityclient.SecurityV1Client, routeClient *routeclient.RouteV1Client, hubClient *hubclientset.Clientset, isBlackDuckClusterScope bool) *Creater { - return &Creater{ - config: config, - kubeConfig: kubeConfig, - kubeClient: kubeClient, - opssightClient: opssightClient, - osSecurityClient: osSecurityClient, - routeClient: routeClient, - hubClient: hubClient, - isBlackDuckClusterScope: isBlackDuckClusterScope, - } -} - -// DeleteOpsSight will delete the OpsSight -func (ac *Creater) DeleteOpsSight(name string) error { - log.Infof("deleting a %s OpsSight instance", name) - values := strings.SplitN(name, "/", 2) - var namespace string - if len(values) == 0 { - return fmt.Errorf("invalid name to delete the OpsSight instance") - } else if len(values) == 1 { - name = values[0] - namespace = values[0] - ns, err := util.ListNamespaces(ac.kubeClient, fmt.Sprintf("synopsys.com/%s.%s", util.OpsSightName, name)) - if err != nil { - log.Errorf("unable to list %s OpsSight instance namespaces %s due to %+v", name, namespace, err) - } - if len(ns.Items) > 0 { - namespace = ns.Items[0].Name - } else { - return fmt.Errorf("unable to find %s OpsSight instance namespace", name) - } - } else { - name = values[1] - namespace = values[0] - } - - // delete the OpsSight instance - commonConfig := crdupdater.NewCRUDComponents(ac.kubeConfig, ac.kubeClient, ac.config.DryRun, false, namespace, "", - &api.ComponentList{}, fmt.Sprintf("app=%s,name=%s", util.OpsSightName, name), true) - _, crudErrors := commonConfig.CRUDComponents() - if len(crudErrors) > 0 { - return fmt.Errorf("unable to delete the %s OpsSight instance in %s namespace due to %+v", name, namespace, crudErrors) - } - - // delete namespace and if other apps are running, remove the Synopsys app label from the namespace - var delErr error - // if cluster scope, if no other instance running in Synopsys Operator namespace, delete the namespace or delete the Synopsys labels in the namespace - if ac.config.IsClusterScoped { - delErr = util.DeleteResourceNamespace(ac.kubeClient, util.OpsSightName, namespace, name, false) - } else { - // if namespace scope, delete the label from the namespace - _, delErr = util.CheckAndUpdateNamespace(ac.kubeClient, util.OpsSightName, namespace, name, "", true) - } - if delErr != nil { - return delErr - } - - return nil -} - -// CreateOpsSight will create the Black Duck OpsSight -func (ac *Creater) CreateOpsSight(opssight *opssightapi.OpsSight) error { - // log.Debugf("create OpsSight details for %s: %+v", opssight.Namespace, opssight) - opssightSpec := &opssight.Spec - // get the registry auth credentials for default OpenShift internal docker registries - if !ac.config.DryRun { - ac.addRegistryAuth(opssightSpec) - } - - spec := NewSpecConfig(ac.config, ac.kubeClient, ac.opssightClient, ac.hubClient, opssight, ac.config.DryRun, ac.isBlackDuckClusterScope) - - components, err := spec.GetComponents() - if err != nil { - return errors.Annotatef(err, "unable to get opssight components for %s", opssight.Spec.Namespace) - } - - if !ac.config.DryRun { - // call the CRUD updater to create or update opssight - commonConfig := crdupdater.NewCRUDComponents(ac.kubeConfig, ac.kubeClient, ac.config.DryRun, false, opssightSpec.Namespace, "2.2.5", - components, fmt.Sprintf("app=%s,name=%s", util.OpsSightName, opssight.Name), true) - _, errs := commonConfig.CRUDComponents() - - if len(errs) > 0 { - return fmt.Errorf("update components errors: %+v", errs) - } - - // if OpenShift, add a privileged role to scanner account - err = ac.postDeploy(spec, opssightSpec.Namespace) - if err != nil { - return errors.Annotatef(err, "post deploy") - } - - err = ac.deployHub(opssightSpec) - if err != nil { - return errors.Annotatef(err, "deploy hub") - } - } - - return nil -} - -// StopOpsSight will stop the Black Duck OpsSight -func (ac *Creater) StopOpsSight(opssight *opssightapi.OpsSightSpec) error { - rcl, err := util.ListReplicationControllers(ac.kubeClient, opssight.Namespace, "app=opssight") - for _, rc := range rcl.Items { - if util.Int32ToInt(rc.Spec.Replicas) > 0 { - _, err := util.PatchReplicationControllerForReplicas(ac.kubeClient, &rc, util.IntToInt32(0)) - if err != nil { - return fmt.Errorf("unable to patch %s replication controller with replicas %d in %s namespace because %+v", rc.Name, 0, opssight.Namespace, err) - } - } - } - - dpl, err := util.ListDeployments(ac.kubeClient, opssight.Namespace, "app=opssight") - for _, dp := range dpl.Items { - if util.Int32ToInt(dp.Spec.Replicas) > 0 { - _, err := util.PatchDeploymentForReplicas(ac.kubeClient, &dp, util.IntToInt32(0)) - if err != nil { - return fmt.Errorf("unable to patch %s deployment with replicas %d in %s namespace because %+v", dp.Name, 0, opssight.Namespace, err) - } - } - } - return err -} - -// UpdateOpsSight will update the Black Duck OpsSight -func (ac *Creater) UpdateOpsSight(opssight *opssightapi.OpsSight) error { - return ac.CreateOpsSight(opssight) -} - -func (ac *Creater) addRegistryAuth(opsSightSpec *opssightapi.OpsSightSpec) { - // if OpenShift, get the registry auth informations - if ac.routeClient == nil { - return - } - - internalRegistries := []*string{} - - // Adding default image registry routes - routes := map[string]string{"default": "docker-registry", "openshift-image-registry": "image-registry"} - for namespace, name := range routes { - route, err := util.GetRoute(ac.routeClient, namespace, name) - if err != nil { - continue - } - internalRegistries = append(internalRegistries, &route.Spec.Host) - routeHostPort := fmt.Sprintf("%s:443", route.Spec.Host) - internalRegistries = append(internalRegistries, &routeHostPort) - } - - // Adding default OpenShift internal Docker/image registry service - labelSelectors := []string{"docker-registry=default", "router in (router,router-default)"} - for _, labelSelector := range labelSelectors { - registrySvcs, err := util.ListServices(ac.kubeClient, "", labelSelector) - if err != nil { - continue - } - for _, registrySvc := range registrySvcs.Items { - if !strings.EqualFold(registrySvc.Spec.ClusterIP, "") { - for _, port := range registrySvc.Spec.Ports { - clusterIPSvc := fmt.Sprintf("%s:%d", registrySvc.Spec.ClusterIP, port.Port) - internalRegistries = append(internalRegistries, &clusterIPSvc) - clusterIPSvcPort := fmt.Sprintf("%s.%s.svc:%d", registrySvc.Name, registrySvc.Namespace, port.Port) - internalRegistries = append(internalRegistries, &clusterIPSvcPort) - } - } - } - } - - file, err := util.ReadFromFile("/var/run/secrets/kubernetes.io/serviceaccount/token") - if err != nil { - log.Errorf("unable to read the service account token file due to %+v", err) - } else { - for _, internalRegistry := range internalRegistries { - opsSightSpec.ScannerPod.ImageFacade.InternalRegistries = append(opsSightSpec.ScannerPod.ImageFacade.InternalRegistries, &opssightapi.RegistryAuth{URL: *internalRegistry, User: "admin", Password: string(file)}) - } - } -} - -func (ac *Creater) postDeploy(spec *SpecConfig, namespace string) error { - // Need to add the perceptor-scanner service account to the privileged scc - if ac.config.IsOpenshift { - scannerServiceAccount := spec.ScannerServiceAccount() - perceiverServiceAccount := spec.PodPerceiverServiceAccount() - serviceAccounts := []string{fmt.Sprintf("system:serviceaccount:%s:%s", namespace, perceiverServiceAccount.GetName())} - if !strings.EqualFold(spec.opssight.Spec.ScannerPod.ImageFacade.ImagePullerType, "skopeo") { - serviceAccounts = append(serviceAccounts, fmt.Sprintf("system:serviceaccount:%s:%s", namespace, scannerServiceAccount.GetName())) - } - return util.UpdateOpenShiftSecurityConstraint(ac.osSecurityClient, serviceAccounts, "privileged") - } - return nil -} - -func (ac *Creater) deployHub(createOpsSight *opssightapi.OpsSightSpec) error { - if createOpsSight.Blackduck.InitialCount > createOpsSight.Blackduck.MaxCount { - createOpsSight.Blackduck.InitialCount = createOpsSight.Blackduck.MaxCount - } - - hubErrs := map[string]error{} - for i := 0; i < createOpsSight.Blackduck.InitialCount; i++ { - name := fmt.Sprintf("%s-%v", createOpsSight.Namespace, i) - - _, err := util.GetNamespace(ac.kubeClient, name) - if err == nil { - continue - } - - ns, err := util.CreateNamespace(ac.kubeClient, name) - log.Debugf("created namespace: %+v", ns) - if err != nil { - log.Errorf("hub[%d]: unable to create the namespace due to %+v", i, err) - hubErrs[name] = fmt.Errorf("unable to create the namespace due to %+v", err) - } - - hubSpec := createOpsSight.Blackduck.BlackduckSpec - hubSpec.Namespace = name - createHub := &blackduckapi.Blackduck{ObjectMeta: metav1.ObjectMeta{Name: name}, Spec: *hubSpec} - log.Debugf("hub[%d]: %+v", i, createHub) - _, err = util.CreateBlackduck(ac.hubClient, name, createHub) - if err != nil { - log.Errorf("hub[%d]: unable to create the hub due to %+v", i, err) - hubErrs[name] = fmt.Errorf("unable to create the hub due to %+v", err) - } - } - - return util.NewMapErrors(hubErrs) -} diff --git a/pkg/opssight/creater_test.go b/pkg/opssight/creater_test.go deleted file mode 100644 index 02035fdc8..000000000 --- a/pkg/opssight/creater_test.go +++ /dev/null @@ -1,358 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -import ( - "fmt" - "strings" - "testing" - - "github.com/blackducksoftware/horizon/pkg/components" - "github.com/blackducksoftware/synopsys-operator/pkg/api" - opssightapi "github.com/blackducksoftware/synopsys-operator/pkg/api/opssight/v1" - "github.com/blackducksoftware/synopsys-operator/pkg/protoform" - "github.com/blackducksoftware/synopsys-operator/pkg/util" - "github.com/google/go-cmp/cmp" -) - -// TestUpstreamPerceptor will test the upstream deployment -func TestUpstreamPerceptor(t *testing.T) { - defaultValues := getOpsSightDefaultValue() - opssight := NewSpecConfig(&protoform.Config{DryRun: true}, nil, nil, nil, defaultValues, true, true) - - // TODO "components, err := opssight.GetComponents()" [add components back with ginko tests] - _, err := opssight.GetComponents() - if err != nil { - t.Errorf("unable to get the opssight components due to %+v", err) - } - - fmt.Printf("TODO: reenable tests with ginkgo\n") - // TODO reenable these with ginkgo [add components back above] - // validateClusterRoleBindings(t, components.ClusterRoleBindings, defaultValues) - // validateClusterRoles(t, components.ClusterRoles, defaultValues) - // validateConfigMaps(t, components.ConfigMaps, defaultValues) - // validateDeployments(t, components.Deployments, defaultValues) - // validateReplicationControllers(t, components.ReplicationControllers, defaultValues) - // validateSecrets(t, components.Secrets, defaultValues) - // validateServiceAccounts(t, components.ServiceAccounts, defaultValues) - // validateServices(t, components.Services, defaultValues) -} - -// TestDownstreamPerceptor will test the downstream deployment -func TestDownstreamPerceptor(t *testing.T) { - defaultValues := getOpsSightDefaultValue() - - opssight := NewSpecConfig(&protoform.Config{DryRun: true}, nil, nil, nil, defaultValues, true, true) - - _, err := opssight.GetComponents() // TODO add components back ", err := opssight.GetComponents()" - fmt.Printf("TODO tests DownStreamPerceptor Components are temporarily disabled -- reenable using ginkgo\n") - - if err != nil { - t.Errorf("unable to get the opssight components due to %+v", err) - } - - // TODO convert to Ginkgo - // validateClusterRoleBindings(t, components.ClusterRoleBindings, defaultValues) - // validateClusterRoles(t, components.ClusterRoles, defaultValues) - // validateConfigMaps(t, components.ConfigMaps, defaultValues) - // validateDeployments(t, components.Deployments, defaultValues) - // validateReplicationControllers(t, components.ReplicationControllers, defaultValues) - // validateSecrets(t, components.Secrets, defaultValues) - // validateServiceAccounts(t, components.ServiceAccounts, defaultValues) - // validateServices(t, components.Services, defaultValues) -} - -func validateClusterRoleBindings(t *testing.T, clusterRoleBindings []*components.ClusterRoleBinding, opssightSpec *opssightapi.OpsSightSpec, opssightSpecConfig *SpecConfig) { - if len(clusterRoleBindings) != 3 { - t.Errorf("cluster role binding length not equal to 3, actual: %d", len(clusterRoleBindings)) - } - scanner := "scanner" - podPerceiver := "pod-processor" - imagePerceiver := "image-processor" - - scannerClusterRoleBinding, _ := opssightSpecConfig.ScannerClusterRoleBinding() - expectedClusterRoleBindings := map[string]*components.ClusterRoleBinding{ - scanner: scannerClusterRoleBinding, - podPerceiver: opssightSpecConfig.PodPerceiverClusterRoleBinding(opssightSpecConfig.PodPerceiverClusterRole()), - imagePerceiver: opssightSpecConfig.ImagePerceiverClusterRoleBinding(opssightSpecConfig.ImagePerceiverClusterRole()), - } - - for _, cb := range clusterRoleBindings { - if !cmp.Equal(cb.ClusterRoleBinding, expectedClusterRoleBindings[cb.GetName()]) { - t.Errorf("cluster role bindings is not equal for %s. Diff: %+v", cb.GetName(), cmp.Diff(cb.ClusterRoleBinding, expectedClusterRoleBindings[cb.GetName()])) - } - } -} - -func validateClusterRoles(t *testing.T, clusterRoles []*components.ClusterRole, opssightSpec *opssightapi.OpsSightSpec, opssightSpecConfig *SpecConfig) { - if len(clusterRoles) != 2 { - t.Errorf("cluster role length not equal to 2, actual: %d", len(clusterRoles)) - } - - podPerceiver := "pod-processor" - imagePerceiver := "image-processor" - expectedClusterRoles := map[string]*components.ClusterRole{ - podPerceiver: opssightSpecConfig.PodPerceiverClusterRole(), - imagePerceiver: opssightSpecConfig.ImagePerceiverClusterRole(), - } - - for _, cr := range clusterRoles { - if !cmp.Equal(cr.ClusterRole, expectedClusterRoles[cr.GetName()]) { - t.Errorf("cluster role is not equal for %s. Diff: %+v", cr.GetName(), cmp.Diff(cr.ClusterRole, expectedClusterRoles[cr.GetName()])) - } - } -} - -func validateConfigMaps(t *testing.T, configMaps []*components.ConfigMap, opssightSpec *opssightapi.OpsSightSpec) { - if len(configMaps) != 6 { - t.Errorf("config maps length not equal to 6, actual: %d", len(configMaps)) - } - - perceptor := "core" - perceptorScanner := "scanner" - perceptorImageFacade := "image-getter" - perceiver := "processor" - prometheus := "prometheus" - - type configMap struct { - name string - fileName string - } - - expectedConfigMaps := map[string]*configMap{ - perceptor: {name: perceptor, fileName: fmt.Sprintf("%s.yaml", perceptor)}, - perceptorScanner: {name: perceptorScanner, fileName: fmt.Sprintf("%s.yaml", perceptorScanner)}, - perceptorImageFacade: {name: perceptorImageFacade, fileName: fmt.Sprintf("%s.json", perceptorImageFacade)}, - perceiver: {name: perceiver, fileName: fmt.Sprintf("%s.yaml", perceiver)}, - prometheus: {name: prometheus}, - } - - for _, cm := range configMaps { - actualConfigMap := expectedConfigMaps[cm.GetName()] - if !strings.EqualFold(cm.Name, actualConfigMap.name) { - t.Errorf("config map name is not equal. Expected: %s, Actual: %s", actualConfigMap.name, cm.Data) - } - - if !strings.EqualFold(cm.GetName(), prometheus) { - if _, ok := cm.Data[actualConfigMap.fileName]; !ok { - t.Errorf("config map file name is not equal. Expected: %s, Actual: %s", actualConfigMap.fileName, cm.Data[actualConfigMap.fileName]) - } - } - } -} - -func validateDeployments(t *testing.T, deployments []*components.Deployment, opssightSpec *opssightapi.OpsSightSpec, opssightSpecConfig *SpecConfig) { - if len(deployments) != 1 { - t.Errorf("deployments length not equal to 1, actual: %d", len(deployments)) - } - - prometheusDeployment, _ := opssightSpecConfig.PerceptorMetricsDeployment() - - expectedDeployment := map[string]*components.Deployment{ - "prometheus": prometheusDeployment, - } - - for _, d := range deployments { - if !cmp.Equal(d.Deployment, expectedDeployment[d.GetName()]) { - t.Errorf("deployment is not equal for %s. Diff: %+v", d.GetName(), cmp.Diff(d.Deployment, expectedDeployment[d.GetName()])) - } - } -} - -func validateReplicationControllers(t *testing.T, replicationControllers []*components.ReplicationController, opssightSpec *opssightapi.OpsSightSpec, opssightSpecConfig *SpecConfig) { - if len(replicationControllers) != 4 { - t.Errorf("replication controllers length not equal to 5, actual: %d", len(replicationControllers)) - } - - perceptor := "core" - scanner := "scanner" - podPerceiver := "pod-processor" - imagePerceiver := "image-processor" - - perceptorRc, _ := opssightSpecConfig.PerceptorReplicationController() - scannerRc, _ := opssightSpecConfig.ScannerReplicationController() - podPerceiverRc, _ := opssightSpecConfig.PodPerceiverReplicationController() - imagePerceiverRc, _ := opssightSpecConfig.ImagePerceiverReplicationController() - expectedReplicationController := map[string]*components.ReplicationController{ - perceptor: perceptorRc, - scanner: scannerRc, - podPerceiver: podPerceiverRc, - imagePerceiver: imagePerceiverRc, - } - - for _, rc := range replicationControllers { - if !cmp.Equal(rc.ReplicationController, expectedReplicationController[rc.GetName()]) { - t.Errorf("replication controller is not equal for %s. Diff: %+v", rc.GetName(), cmp.Diff(rc.ReplicationController, expectedReplicationController[rc.GetName()])) - } - } -} - -func validateSecrets(t *testing.T, secrets []*components.Secret, opssightSpec *opssightapi.OpsSightSpec, opssightSpecConfig *SpecConfig) { - if len(secrets) != 1 { - t.Errorf("secrets length not equal to 1, actual: %d", len(secrets)) - } - - perceptorSecret, err := opssightSpecConfig.PerceptorSecret() - t.Errorf("invalid secret: %s", err) - expectedSecrets := map[string]*components.Secret{ - "opssight": perceptorSecret, - } - - for _, secret := range secrets { - if !cmp.Equal(secret.Secret, expectedSecrets[secret.GetName()]) { - t.Errorf("secret is not equal for %s. Diff: %+v", secret.GetName(), cmp.Diff(secret.Secret, expectedSecrets[secret.GetName()])) - } - } -} - -func validateServiceAccounts(t *testing.T, serviceAccounts []*components.ServiceAccount, opssightSpec *opssightapi.OpsSightSpec, opssightSpecConfig *SpecConfig) { - if len(serviceAccounts) != 3 { - t.Errorf("service account length not equal to 3, actual: %d", len(serviceAccounts)) - } - - scanner := "scanner" - podPerceiver := "pod-processor" - imagePerceiver := "image-processor" - expectedServiceAccounts := map[string]*components.ServiceAccount{ - scanner: opssightSpecConfig.ScannerServiceAccount(), - imagePerceiver: opssightSpecConfig.ImagePerceiverServiceAccount(), - podPerceiver: opssightSpecConfig.PodPerceiverServiceAccount(), - } - - for _, serviceAccount := range serviceAccounts { - if !cmp.Equal(serviceAccount.ServiceAccount, expectedServiceAccounts[serviceAccount.GetName()]) { - t.Errorf("service account is not equal for %s. Diff: %+v", serviceAccount.GetName(), cmp.Diff(serviceAccount.ServiceAccount, expectedServiceAccounts[serviceAccount.GetName()])) - } - } -} - -func validateServices(t *testing.T, services []*components.Service, opssightSpec *opssightapi.OpsSightSpec, opssightSpecConfig *SpecConfig) { - if len(services) != 6 { - t.Errorf("services length not equal to 6, actual: %d", len(services)) - } - - // perceptor - perceptor := "core" - perceptorService, _ := opssightSpecConfig.PerceptorService() - scanner := "scanner" - imageFacade := "image-getter" - podPerceiver := "pod-processor" - imagePerceiver := "image-processor" - - // prometheus - prometheusService, _ := opssightSpecConfig.PerceptorMetricsService() - - expectedServices := map[string]*components.Service{ - perceptor: perceptorService, - scanner: opssightSpecConfig.ScannerService(), - imageFacade: opssightSpecConfig.ImageFacadeService(), - podPerceiver: opssightSpecConfig.PodPerceiverService(), - imagePerceiver: opssightSpecConfig.ImageFacadeService(), - "prometheus": prometheusService, - } - - for _, service := range services { - if !cmp.Equal(service.Service, expectedServices[service.GetName()]) { - t.Errorf("service is not equal for %s. Diff: %+v", service.GetName(), cmp.Diff(service.Service, expectedServices[service.GetName()])) - } - } -} - -func prettyPrintObj(components *api.ComponentList) { - for _, cb := range components.ClusterRoleBindings { - util.PrettyPrint(cb.ClusterRoleBinding) - } - - for _, cr := range components.ClusterRoles { - util.PrettyPrint(cr.ClusterRole) - } - - for _, cm := range components.ConfigMaps { - util.PrettyPrint(cm.ConfigMap) - } - - for _, d := range components.Deployments { - util.PrettyPrint(d.Deployment) - } - - for _, rc := range components.ReplicationControllers { - util.PrettyPrint(rc.ReplicationController) - } - - for _, s := range components.Secrets { - util.PrettyPrint(s.Secret) - } - - for _, sa := range components.ServiceAccounts { - util.PrettyPrint(sa.ServiceAccount) - } - - for _, svc := range components.Services { - util.PrettyPrint(svc.Service) - } -} - -// GetOpsSightDefaultValue creates a perceptor crd configuration object with defaults -func getOpsSightDefaultValue() *opssightapi.OpsSight { - return &opssightapi.OpsSight{ - Spec: opssightapi.OpsSightSpec{ - Perceptor: &opssightapi.Perceptor{ - CheckForStalledScansPauseHours: 999999, - StalledScanClientTimeoutHours: 999999, - ModelMetricsPauseSeconds: 15, - UnknownImagePauseMilliseconds: 15000, - ClientTimeoutMilliseconds: 100000, - }, - Perceiver: &opssightapi.Perceiver{ - EnableImagePerceiver: false, - EnableArtifactoryPerceiver: false, - EnableQuayPerceiver: false, - EnablePodPerceiver: true, - PodPerceiver: &opssightapi.PodPerceiver{}, - AnnotationIntervalSeconds: 30, - DumpIntervalMinutes: 30, - }, - ScannerPod: &opssightapi.ScannerPod{ - ImageFacade: &opssightapi.ImageFacade{ - InternalRegistries: []*opssightapi.RegistryAuth{}, - }, - Scanner: &opssightapi.Scanner{ - ClientTimeoutSeconds: 600, - }, - ReplicaCount: 1, - }, - Prometheus: &opssightapi.Prometheus{}, - Skyfire: &opssightapi.Skyfire{}, - Blackduck: &opssightapi.Blackduck{ - InitialCount: 1, - MaxCount: 1, - DeleteBlackduckThresholdPercentage: 50, - BlackduckSpec: nil, - }, - EnableMetrics: true, - EnableSkyfire: false, - DefaultCPU: "300m", - DefaultMem: "1300Mi", - LogLevel: "debug", - }, - } -} diff --git a/pkg/opssight/ctl_opssight.go b/pkg/opssight/ctl_opssight.go index 25128f157..d6cc9615e 100644 --- a/pkg/opssight/ctl_opssight.go +++ b/pkg/opssight/ctl_opssight.go @@ -26,8 +26,6 @@ import ( "fmt" "strings" - "github.com/blackducksoftware/synopsys-operator/pkg/api" - blackduckapi "github.com/blackducksoftware/synopsys-operator/pkg/api/blackduck/v1" opssightapi "github.com/blackducksoftware/synopsys-operator/pkg/api/opssight/v1" "github.com/blackducksoftware/synopsys-operator/pkg/util" crddefaults "github.com/blackducksoftware/synopsys-operator/pkg/util" @@ -36,16 +34,16 @@ import ( "github.com/spf13/pflag" ) -// CRSpecBuilderFromCobraFlags uses Cobra commands, Cobra flags and other -// values to create an OpsSight CR's Spec. -// -// The fields in the CRSpecBuilderFromCobraFlags represent places where the values of the Cobra flags are stored. -// -// Usage: Use CRSpecBuilderFromCobraFlags to add flags to your Cobra Command for making an OpsSight Spec. -// When flags are used the correspoding value in this struct will by set. You can then -// generate the spec by telling CRSpecBuilderFromCobraFlags what flags were changed. -type CRSpecBuilderFromCobraFlags struct { - opsSightSpec *opssightapi.OpsSightSpec +// HelmValuesFromCobraFlags is a type for converting synopsysctl flags +// to Helm Chart fields and values +// args: map of helm chart field to value +type HelmValuesFromCobraFlags struct { + args map[string]interface{} + flagTree FlagTree +} + +// FlagTree is a set of fields needed to configure the Opssight Helm Chart +type FlagTree struct { IsUpstream string PerceptorExpose string PerceptorCheckForStalledScansPauseHours int @@ -95,137 +93,103 @@ type CRSpecBuilderFromCobraFlags struct { ImageRegistries []string } -// NewCRSpecBuilderFromCobraFlags creates a new CRSpecBuilderFromCobraFlags type -func NewCRSpecBuilderFromCobraFlags() *CRSpecBuilderFromCobraFlags { - return &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, +// NewHelmValuesFromCobraFlags returns an initialized HelmValuesFromCobraFlags +func NewHelmValuesFromCobraFlags() *HelmValuesFromCobraFlags { + return &HelmValuesFromCobraFlags{ + args: make(map[string]interface{}, 0), + flagTree: FlagTree{}, } } -// GetCRSpec returns a pointer to the OpsSightSpec as an interface{} -func (ctl *CRSpecBuilderFromCobraFlags) GetCRSpec() interface{} { - return *ctl.opsSightSpec +// GetArgs returns the map of helm chart fields to values +func (ctl *HelmValuesFromCobraFlags) GetArgs() map[string]interface{} { + return ctl.args } -// SetCRSpec sets the opsSightSpec in the struct -func (ctl *CRSpecBuilderFromCobraFlags) SetCRSpec(spec interface{}) error { - convertedSpec, ok := spec.(opssightapi.OpsSightSpec) - if !ok { - return fmt.Errorf("error setting OpsSight spec") +// SetArgs set the map to values +func (ctl *HelmValuesFromCobraFlags) SetArgs(args map[string]interface{}) { + for key, value := range args { + ctl.args[key] = value } - ctl.opsSightSpec = &convertedSpec - return nil } -// Constants for predefined specs -const ( - EmptySpec string = "empty" - UpstreamSpec string = "upstream" - DefaultSpec string = "default" - DisabledBlackDuckSpec string = "disabledBlackDuck" -) - -// SetPredefinedCRSpec sets the opsSightSpec to a predefined spec -func (ctl *CRSpecBuilderFromCobraFlags) SetPredefinedCRSpec(specType string) error { - switch specType { - case EmptySpec: - ctl.opsSightSpec = &opssightapi.OpsSightSpec{} - case UpstreamSpec: - ctl.opsSightSpec = crddefaults.GetOpsSightUpstream() - ctl.opsSightSpec.Perceiver.EnablePodPerceiver = true - ctl.opsSightSpec.EnableMetrics = true - ctl.opsSightSpec.IsUpstream = true - case DefaultSpec: - ctl.opsSightSpec = crddefaults.GetOpsSightDefault() - ctl.opsSightSpec.Perceiver.EnablePodPerceiver = true - ctl.opsSightSpec.EnableMetrics = true - case DisabledBlackDuckSpec: - ctl.opsSightSpec = crddefaults.GetOpsSightDefaultWithIPV6DisabledBlackDuck() - ctl.opsSightSpec.Perceiver.EnablePodPerceiver = true - ctl.opsSightSpec.EnableMetrics = true - default: - return fmt.Errorf("OpsSight spec type '%s' is not valid", specType) - } - return nil -} - -// AddCRSpecFlagsToCommand adds flags to a Cobra Command that are need for OpsSight's Spec. -// The flags map to fields in the CRSpecBuilderFromCobraFlags struct. -// master - if false, doesn't add flags that all Users shouldn't use -func (ctl *CRSpecBuilderFromCobraFlags) AddCRSpecFlagsToCommand(cmd *cobra.Command, master bool) { - cmd.Flags().StringVar(&ctl.IsUpstream, "is-upstream", ctl.IsUpstream, "If true, Upstream images and names will be used [true|false]") +// AddCobraFlagsToCommand adds flags for the Opssight helm chart to the cmd +// master=true is used to add all flags for creating an instance +// master=false is used to add a subset of flags for updating an instance +func (ctl *HelmValuesFromCobraFlags) AddCobraFlagsToCommand(cmd *cobra.Command, master bool) { + cmd.Flags().StringVar(&ctl.flagTree.IsUpstream, "is-upstream", ctl.flagTree.IsUpstream, "If true, Upstream images and names will be used [true|false]") if master { - cmd.Flags().StringVar(&ctl.PerceptorExpose, "opssight-core-expose", util.NONE, "Type of service for OpsSight's core model [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") + cmd.Flags().StringVar(&ctl.flagTree.PerceptorExpose, "opssight-core-expose", util.NONE, "Type of service for Opssight's core model [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") } else { - cmd.Flags().StringVar(&ctl.PerceptorExpose, "opssight-core-expose", ctl.PerceptorExpose, "Type of service for OpsSight's core model [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") + cmd.Flags().StringVar(&ctl.flagTree.PerceptorExpose, "opssight-core-expose", ctl.flagTree.PerceptorExpose, "Type of service for Opssight's core model [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") } - cmd.Flags().IntVar(&ctl.PerceptorCheckForStalledScansPauseHours, "opssight-core-check-scan-hours", ctl.PerceptorCheckForStalledScansPauseHours, "Hours OpsSight's Core waits between checking for scans") - cmd.Flags().IntVar(&ctl.PerceptorStalledScanClientTimeoutHours, "opssight-core-scan-client-timeout-hours", ctl.PerceptorStalledScanClientTimeoutHours, "Hours until OpsSight's Core stops checking for scans") - cmd.Flags().IntVar(&ctl.PerceptorModelMetricsPauseSeconds, "opssight-core-metrics-pause-seconds", ctl.PerceptorModelMetricsPauseSeconds, "Core metrics pause in seconds") - cmd.Flags().IntVar(&ctl.PerceptorUnknownImagePauseMilliseconds, "opssight-core-unknown-image-pause-milliseconds", ctl.PerceptorUnknownImagePauseMilliseconds, "OpsSight Core's unknown image pause in milliseconds") - cmd.Flags().IntVar(&ctl.PerceptorClientTimeoutMilliseconds, "opssight-core-client-timeout-milliseconds", ctl.PerceptorClientTimeoutMilliseconds, "Seconds for OpsSight Core's timeout for Black Duck Scan Client") - cmd.Flags().IntVar(&ctl.ScannerPodScannerClientTimeoutSeconds, "scanner-client-timeout-seconds", ctl.ScannerPodScannerClientTimeoutSeconds, "Seconds before Scanner times out for Black Duck's Scan Client") - cmd.Flags().StringVar(&ctl.ScannerPodImageFacadeInternalRegistriesFilePath, "image-getter-secure-registries-file-path", ctl.ScannerPodImageFacadeInternalRegistriesFilePath, "Absolute path to a file for secure docker registries credentials to pull the images for scan") - cmd.Flags().StringVar(&ctl.ScannerPodImageFacadeImagePullerType, "image-getter-image-puller-type", ctl.ScannerPodImageFacadeImagePullerType, "Type of Image Getter's Image Puller [docker|skopeo]") - cmd.Flags().IntVar(&ctl.ScannerPodReplicaCount, "scannerpod-replica-count", ctl.ScannerPodReplicaCount, "Number of Containers for scanning") - cmd.Flags().StringVar(&ctl.ScannerPodImageDirectory, "scannerpod-image-directory", ctl.ScannerPodImageDirectory, "Directory in Scanner's pod where images are stored for scanning") - cmd.Flags().StringVar(&ctl.PerceiverEnableImagePerceiver, "enable-image-processor", ctl.PerceiverEnableImagePerceiver, "If true, Image Processor discovers images for scanning [true|false]") - cmd.Flags().StringVar(&ctl.PerceiverEnableArtifactoryPerceiver, "enable-artifactory-processor", ctl.PerceiverEnableArtifactoryPerceiver, "If true, Artifactory Processor discovers artifactory images for scanning [true|false]") - cmd.Flags().StringVar(&ctl.PerceiverEnableArtifactoryPerceiverDumper, "enable-artifactory-processor-dumper", ctl.PerceiverEnableArtifactoryPerceiverDumper, "If true, Artifactory Processor dumps all docker images in an artifactory instance for scanning [true|false]") - cmd.Flags().StringVar(&ctl.PerceiverEnableQuayPerceiver, "enable-quay-processor", ctl.PerceiverEnableQuayPerceiver, "If true, Quay Processor discovers quay images for scanning [true|false]") - cmd.Flags().StringVar(&ctl.PerceiverEnablePodPerceiver, "enable-pod-processor", ctl.PerceiverEnablePodPerceiver, "If true, Pod Processor discovers pods for scanning [true|false]") - cmd.Flags().StringVar(&ctl.PerceiverArtifactoryExpose, "expose-artifactory-processor", ctl.PerceiverArtifactoryExpose, "Type of service for Artifactory processor [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") - cmd.Flags().StringVar(&ctl.PerceiverQuayExpose, "expose-quay-processor", ctl.PerceiverQuayExpose, "Type of service for Quay processor [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") - cmd.Flags().StringVar(&ctl.PerceiverTLSCertificatePath, "processor-TLS-certificate-path", ctl.PerceiverTLSCertificatePath, "Accepts certificate file to start webhook receiver with TLS enabled, works in conjunction with Quay and Artifactory processors") - cmd.Flags().StringVar(&ctl.PerceiverTLSKeyPath, "processor-TLS-key-path", ctl.PerceiverTLSKeyPath, "Accepts key file to sign the TLS certificate, works in conjunction with Quay and Artifactory processors") - cmd.Flags().StringVar(&ctl.PerceiverPodPerceiverNamespaceFilter, "pod-processor-namespace-filter", ctl.PerceiverPodPerceiverNamespaceFilter, "Pod Processor's filter to scan pods by their namespace") - cmd.Flags().IntVar(&ctl.PerceiverAnnotationIntervalSeconds, "processor-annotation-interval-seconds", ctl.PerceiverAnnotationIntervalSeconds, "Refresh interval to get latest scan results and apply to Pods and Images") - cmd.Flags().IntVar(&ctl.PerceiverDumpIntervalMinutes, "processor-dump-interval-minutes", ctl.PerceiverDumpIntervalMinutes, "Minutes Image Processor and Pod Processor wait between creating dumps of data/metrics") - cmd.Flags().StringVar(&ctl.DefaultCPU, "default-cpu", ctl.DefaultCPU, "CPU size of OpsSight") - cmd.Flags().StringVar(&ctl.DefaultMem, "default-memory", ctl.DefaultMem, "Memory size of OpsSight") - cmd.Flags().StringVar(&ctl.ScannerCPU, "scanner-cpu", ctl.ScannerCPU, "CPU size of OpsSight's Scanner") - cmd.Flags().StringVar(&ctl.ScannerMem, "scanner-memory", ctl.ScannerMem, "Memory size of OpsSight's Scanner") - cmd.Flags().StringVar(&ctl.LogLevel, "log-level", ctl.LogLevel, "Log level of OpsSight") - cmd.Flags().StringVar(&ctl.EnableMetrics, "enable-metrics", ctl.EnableMetrics, "If true, OpsSight records Prometheus Metrics [true|false]") + cmd.Flags().IntVar(&ctl.flagTree.PerceptorCheckForStalledScansPauseHours, "opssight-core-check-scan-hours", ctl.flagTree.PerceptorCheckForStalledScansPauseHours, "Hours Opssight's Core waits between checking for scans") + cmd.Flags().IntVar(&ctl.flagTree.PerceptorStalledScanClientTimeoutHours, "opssight-core-scan-client-timeout-hours", ctl.flagTree.PerceptorStalledScanClientTimeoutHours, "Hours until Opssight's Core stops checking for scans") + cmd.Flags().IntVar(&ctl.flagTree.PerceptorModelMetricsPauseSeconds, "opssight-core-metrics-pause-seconds", ctl.flagTree.PerceptorModelMetricsPauseSeconds, "Core metrics pause in seconds") + cmd.Flags().IntVar(&ctl.flagTree.PerceptorUnknownImagePauseMilliseconds, "opssight-core-unknown-image-pause-milliseconds", ctl.flagTree.PerceptorUnknownImagePauseMilliseconds, "Opssight Core's unknown image pause in milliseconds") + cmd.Flags().IntVar(&ctl.flagTree.PerceptorClientTimeoutMilliseconds, "opssight-core-client-timeout-milliseconds", ctl.flagTree.PerceptorClientTimeoutMilliseconds, "Seconds for Opssight Core's timeout for Black Duck Scan Client") + cmd.Flags().IntVar(&ctl.flagTree.ScannerPodScannerClientTimeoutSeconds, "scanner-client-timeout-seconds", ctl.flagTree.ScannerPodScannerClientTimeoutSeconds, "Seconds before Scanner times out for Black Duck's Scan Client") + cmd.Flags().StringVar(&ctl.flagTree.ScannerPodImageFacadeInternalRegistriesFilePath, "image-getter-secure-registries-file-path", ctl.flagTree.ScannerPodImageFacadeInternalRegistriesFilePath, "Absolute path to a file for secure docker registries credentials to pull the images for scan") + cmd.Flags().StringVar(&ctl.flagTree.ScannerPodImageFacadeImagePullerType, "image-getter-image-puller-type", ctl.flagTree.ScannerPodImageFacadeImagePullerType, "Type of Image Getter's Image Puller [docker|skopeo]") + cmd.Flags().IntVar(&ctl.flagTree.ScannerPodReplicaCount, "scannerpod-replica-count", ctl.flagTree.ScannerPodReplicaCount, "Number of Containers for scanning") + cmd.Flags().StringVar(&ctl.flagTree.ScannerPodImageDirectory, "scannerpod-image-directory", ctl.flagTree.ScannerPodImageDirectory, "Directory in Scanner's pod where images are stored for scanning") + cmd.Flags().StringVar(&ctl.flagTree.PerceiverEnableImagePerceiver, "enable-image-processor", ctl.flagTree.PerceiverEnableImagePerceiver, "If true, Image Processor discovers images for scanning [true|false]") + cmd.Flags().StringVar(&ctl.flagTree.PerceiverEnableArtifactoryPerceiver, "enable-artifactory-processor", ctl.flagTree.PerceiverEnableArtifactoryPerceiver, "If true, Artifactory Processor discovers artifactory images for scanning [true|false]") + cmd.Flags().StringVar(&ctl.flagTree.PerceiverEnableArtifactoryPerceiverDumper, "enable-artifactory-processor-dumper", ctl.flagTree.PerceiverEnableArtifactoryPerceiverDumper, "If true, Artifactory Processor dumps all docker images in an artifactory instance for scanning [true|false]") + cmd.Flags().StringVar(&ctl.flagTree.PerceiverEnableQuayPerceiver, "enable-quay-processor", ctl.flagTree.PerceiverEnableQuayPerceiver, "If true, Quay Processor discovers quay images for scanning [true|false]") + cmd.Flags().StringVar(&ctl.flagTree.PerceiverEnablePodPerceiver, "enable-pod-processor", ctl.flagTree.PerceiverEnablePodPerceiver, "If true, Pod Processor discovers pods for scanning [true|false]") + cmd.Flags().StringVar(&ctl.flagTree.PerceiverArtifactoryExpose, "expose-artifactory-processor", ctl.flagTree.PerceiverArtifactoryExpose, "Type of service for Artifactory processor [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") + cmd.Flags().StringVar(&ctl.flagTree.PerceiverQuayExpose, "expose-quay-processor", ctl.flagTree.PerceiverQuayExpose, "Type of service for Quay processor [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") + cmd.Flags().StringVar(&ctl.flagTree.PerceiverTLSCertificatePath, "processor-TLS-certificate-path", ctl.flagTree.PerceiverTLSCertificatePath, "Accepts certificate file to start webhook receiver with TLS enabled, works in conjunction with Quay and Artifactory processors") + cmd.Flags().StringVar(&ctl.flagTree.PerceiverTLSKeyPath, "processor-TLS-key-path", ctl.flagTree.PerceiverTLSKeyPath, "Accepts key file to sign the TLS certificate, works in conjunction with Quay and Artifactory processors") + cmd.Flags().StringVar(&ctl.flagTree.PerceiverPodPerceiverNamespaceFilter, "pod-processor-namespace-filter", ctl.flagTree.PerceiverPodPerceiverNamespaceFilter, "Pod Processor's filter to scan pods by their namespace") + cmd.Flags().IntVar(&ctl.flagTree.PerceiverAnnotationIntervalSeconds, "processor-annotation-interval-seconds", ctl.flagTree.PerceiverAnnotationIntervalSeconds, "Refresh interval to get latest scan results and apply to Pods and Images") + cmd.Flags().IntVar(&ctl.flagTree.PerceiverDumpIntervalMinutes, "processor-dump-interval-minutes", ctl.flagTree.PerceiverDumpIntervalMinutes, "Minutes Image Processor and Pod Processor wait between creating dumps of data/metrics") + cmd.Flags().StringVar(&ctl.flagTree.DefaultCPU, "default-cpu", ctl.flagTree.DefaultCPU, "CPU size of Opssight") + cmd.Flags().StringVar(&ctl.flagTree.DefaultMem, "default-memory", ctl.flagTree.DefaultMem, "Memory size of Opssight") + cmd.Flags().StringVar(&ctl.flagTree.ScannerCPU, "scanner-cpu", ctl.flagTree.ScannerCPU, "CPU size of Opssight's Scanner") + cmd.Flags().StringVar(&ctl.flagTree.ScannerMem, "scanner-memory", ctl.flagTree.ScannerMem, "Memory size of Opssight's Scanner") + cmd.Flags().StringVar(&ctl.flagTree.LogLevel, "log-level", ctl.flagTree.LogLevel, "Log level of Opssight") + cmd.Flags().StringVar(&ctl.flagTree.EnableMetrics, "enable-metrics", ctl.flagTree.EnableMetrics, "If true, Opssight records Prometheus Metrics [true|false]") if master { - cmd.Flags().StringVar(&ctl.PrometheusExpose, "expose-metrics", util.NONE, "Type of service of OpsSight's Prometheus Metrics [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") + cmd.Flags().StringVar(&ctl.flagTree.PrometheusExpose, "expose-metrics", util.NONE, "Type of service of Opssight's Prometheus Metrics [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") } else { - cmd.Flags().StringVar(&ctl.PrometheusExpose, "expose-metrics", ctl.PrometheusExpose, "Type of service of OpsSight's Prometheus Metrics [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") + cmd.Flags().StringVar(&ctl.flagTree.PrometheusExpose, "expose-metrics", ctl.flagTree.PrometheusExpose, "Type of service of Opssight's Prometheus Metrics [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") } - cmd.Flags().StringVar(&ctl.BlackduckExternalHostsFilePath, "blackduck-external-hosts-file-path", ctl.BlackduckExternalHostsFilePath, "Absolute path to a file containing a list of Black Duck External Hosts") - cmd.Flags().StringVar(&ctl.BlackduckTLSVerification, "blackduck-TLS-verification", ctl.BlackduckTLSVerification, "If true, OpsSight performs TLS Verification for Black Duck [true|false]") - cmd.Flags().IntVar(&ctl.BlackduckInitialCount, "blackduck-initial-count", ctl.BlackduckInitialCount, "Initial number of Black Duck instances to create") - cmd.Flags().IntVar(&ctl.BlackduckMaxCount, "blackduck-max-count", ctl.BlackduckMaxCount, "Maximum number of Black Duck instances that can be created") - cmd.Flags().StringVar(&ctl.BlackduckType, "blackduck-type", ctl.BlackduckType, "Type of Black Duck") - cmd.Flags().StringVar(&ctl.BlackduckPassword, "blackduck-password", ctl.BlackduckPassword, "Password to use for all internal Blackduck 'sysadmin' account") - cmd.Flags().StringVar(&ctl.Registry, "registry", ctl.Registry, "Name of the registry to use for images e.g. docker.io/blackducksoftware") - cmd.Flags().StringSliceVar(&ctl.PullSecrets, "pull-secret-name", ctl.PullSecrets, "Only if the registry requires authentication") - cmd.Flags().StringSliceVar(&ctl.ImageRegistries, "image-registries", ctl.ImageRegistries, "List of image registries") + cmd.Flags().StringVar(&ctl.flagTree.BlackduckExternalHostsFilePath, "blackduck-external-hosts-file-path", ctl.flagTree.BlackduckExternalHostsFilePath, "Absolute path to a file containing a list of Black Duck External Hosts") + cmd.Flags().StringVar(&ctl.flagTree.BlackduckTLSVerification, "blackduck-TLS-verification", ctl.flagTree.BlackduckTLSVerification, "If true, Opssight performs TLS Verification for Black Duck [true|false]") + cmd.Flags().IntVar(&ctl.flagTree.BlackduckInitialCount, "blackduck-initial-count", ctl.flagTree.BlackduckInitialCount, "Initial number of Black Duck instances to create") + cmd.Flags().IntVar(&ctl.flagTree.BlackduckMaxCount, "blackduck-max-count", ctl.flagTree.BlackduckMaxCount, "Maximum number of Black Duck instances that can be created") + cmd.Flags().StringVar(&ctl.flagTree.BlackduckType, "blackduck-type", ctl.flagTree.BlackduckType, "Type of Black Duck") + cmd.Flags().StringVar(&ctl.flagTree.BlackduckPassword, "blackduck-password", ctl.flagTree.BlackduckPassword, "Password to use for all internal Blackduck 'sysadmin' account") + cmd.Flags().StringVar(&ctl.flagTree.Registry, "registry", ctl.flagTree.Registry, "Name of the registry to use for images e.g. docker.io/blackducksoftware") + cmd.Flags().StringSliceVar(&ctl.flagTree.PullSecrets, "pull-secret-name", ctl.flagTree.PullSecrets, "Only if the registry requires authentication") + cmd.Flags().StringSliceVar(&ctl.flagTree.ImageRegistries, "image-registries", ctl.flagTree.ImageRegistries, "List of image registries") } // CheckValuesFromFlags returns an error if a value stored in the struct will not be able to be -// used in the opsSightSpec +// used in the opssightSpec func (ctl *CRSpecBuilderFromCobraFlags) CheckValuesFromFlags(flagset *pflag.FlagSet) error { if FlagWasSet(flagset, "opssight-core-expose") { - isValid := util.IsExposeServiceValid(ctl.PerceptorExpose) + isValid := util.IsExposeServiceValid(ctl.flagTree.PerceptorExpose) if !isValid { return fmt.Errorf("opssight core expose must be '%s', '%s', '%s' or '%s'", util.NODEPORT, util.LOADBALANCER, util.OPENSHIFT, util.NONE) } } if FlagWasSet(flagset, "expose-metrics") { - isValid := util.IsExposeServiceValid(ctl.PrometheusExpose) + isValid := util.IsExposeServiceValid(ctl.flagTree.PrometheusExpose) if !isValid { return fmt.Errorf("expose metrics must be '%s', '%s', '%s' or '%s'", util.NODEPORT, util.LOADBALANCER, util.OPENSHIFT, util.NONE) } } if FlagWasSet(flagset, "expose-artifactory-processor") { - isValid := util.IsExposeServiceValid(ctl.PerceiverArtifactoryExpose) + isValid := util.IsExposeServiceValid(ctl.flagTree.PerceiverArtifactoryExpose) if !isValid { return fmt.Errorf("expose metrics must be '%s', '%s', '%s' or '%s'", util.NODEPORT, util.LOADBALANCER, util.OPENSHIFT, util.NONE) } } if FlagWasSet(flagset, "expose-quay-processor") { - isValid := util.IsExposeServiceValid(ctl.PerceiverQuayExpose) + isValid := util.IsExposeServiceValid(ctl.flagTree.PerceiverQuayExpose) if !isValid { return fmt.Errorf("expose metrics must be '%s', '%s', '%s' or '%s'", util.NODEPORT, util.LOADBALANCER, util.OPENSHIFT, util.NONE) } @@ -241,82 +205,43 @@ func FlagWasSet(flagset *pflag.FlagSet, flagName string) bool { return false } -// GenerateCRSpecFromFlags checks if a flag was changed and updates the opsSightSpec with the value that's stored -// in the corresponding struct field -func (ctl *CRSpecBuilderFromCobraFlags) GenerateCRSpecFromFlags(flagset *pflag.FlagSet) (interface{}, error) { - err := ctl.CheckValuesFromFlags(flagset) +// GenerateHelmFlagsFromCobraFlags checks each flag in synopsysctl and updates the map to +// contain the corresponding helm chart field and value +func (ctl *HelmValuesFromCobraFlags) GenerateHelmFlagsFromCobraFlags(flagset *pflag.FlagSet) (map[string]interface{}, error) { + err := ctl.flagTree.CheckValuesFromFlags(flagset) if err != nil { return nil, err } - flagset.VisitAll(ctl.SetCRSpecFieldByFlag) - return *ctl.opsSightSpec, nil -} + flagset.VisitAll(ctl.flagTree.AddHelmValueByCobraFlag) -// InternalRegistryStructs - file format for reading data -type InternalRegistryStructs struct { - Data []opssightapi.RegistryAuth + return ctl.args, nil } -// ExternalHostStructs - file format for reading data -type ExternalHostStructs struct { - Data []opssightapi.Host -} - -// SetCRSpecFieldByFlag updates a field in the opsSightSpec if the flag was set by the user. It gets the -// value from the corresponding struct field -// Note: It should only handle values with a 1 to 1 mapping - struct-field to spec -func (ctl *CRSpecBuilderFromCobraFlags) SetCRSpecFieldByFlag(f *pflag.Flag) { +// AddHelmValueByCobraFlag adds the helm chart field and value based on the flag set +// in synopsysctl +func (ctl *HelmValuesFromCobraFlags) AddHelmValueByCobraFlag(f *pflag.Flag) { if f.Changed { log.Debugf("flag '%s': CHANGED", f.Name) switch f.Name { case "is-upstream": - ctl.opsSightSpec.IsUpstream = strings.ToUpper(ctl.IsUpstream) == "TRUE" + isUpstream := strings.ToUpper(ctl.flagTree.IsUpstream) == "TRUE" + util.SetHelmValueInMap(ctl.args, []string{"isUpstream"}, isUpstream) case "opssight-core-expose": - if ctl.opsSightSpec.Perceptor == nil { - ctl.opsSightSpec.Perceptor = &opssightapi.Perceptor{} - } - ctl.opsSightSpec.Perceptor.Expose = ctl.PerceptorExpose + util.SetHelmValueInMap(ctl.args, []string{"perceptor", "expose"}, ctl.flagTree.PerceptorExpose) case "opssight-core-check-scan-hours": - if ctl.opsSightSpec.Perceptor == nil { - ctl.opsSightSpec.Perceptor = &opssightapi.Perceptor{} - } - ctl.opsSightSpec.Perceptor.CheckForStalledScansPauseHours = ctl.PerceptorCheckForStalledScansPauseHours + util.SetHelmValueInMap(ctl.args, []string{"perceptor", "checkForStalledScansPauseHours"}, ctl.flagTree.PerceptorCheckForStalledScansPauseHours) case "opssight-core-scan-client-timeout-hours": - if ctl.opsSightSpec.Perceptor == nil { - ctl.opsSightSpec.Perceptor = &opssightapi.Perceptor{} - } - ctl.opsSightSpec.Perceptor.StalledScanClientTimeoutHours = ctl.PerceptorStalledScanClientTimeoutHours + util.SetHelmValueInMap(ctl.args, []string{"perceptor", "stalledScanClientTimeoutHours"}, ctl.flagTree.PerceptorStalledScanClientTimeoutHours) case "opssight-core-metrics-pause-seconds": - if ctl.opsSightSpec.Perceptor == nil { - ctl.opsSightSpec.Perceptor = &opssightapi.Perceptor{} - } - ctl.opsSightSpec.Perceptor.ModelMetricsPauseSeconds = ctl.PerceptorModelMetricsPauseSeconds + util.SetHelmValueInMap(ctl.args, []string{"perceptor", "modeMetricsPauseSeconds"}, ctl.flagTree.PerceptorModelMetricsPauseSeconds) case "opssight-core-unknown-image-pause-milliseconds": - if ctl.opsSightSpec.Perceptor == nil { - ctl.opsSightSpec.Perceptor = &opssightapi.Perceptor{} - } - ctl.opsSightSpec.Perceptor.UnknownImagePauseMilliseconds = ctl.PerceptorUnknownImagePauseMilliseconds + util.SetHelmValueInMap(ctl.args, []string{"perceptor", "unknownImagePauseMilliseconds"}, ctl.flagTree.PerceptorUnknownImagePauseMilliseconds) case "opssight-core-client-timeout-milliseconds": - if ctl.opsSightSpec.Perceptor == nil { - ctl.opsSightSpec.Perceptor = &opssightapi.Perceptor{} - } - ctl.opsSightSpec.Perceptor.ClientTimeoutMilliseconds = ctl.PerceptorClientTimeoutMilliseconds + util.SetHelmValueInMap(ctl.args, []string{"perceptor", "clientTimeoutMilliseconds"}, ctl.flagTree.PerceptorClientTimeoutMilliseconds) case "scanner-client-timeout-seconds": - if ctl.opsSightSpec.ScannerPod == nil { - ctl.opsSightSpec.ScannerPod = &opssightapi.ScannerPod{} - } - if ctl.opsSightSpec.ScannerPod.Scanner == nil { - ctl.opsSightSpec.ScannerPod.Scanner = &opssightapi.Scanner{} - } - ctl.opsSightSpec.ScannerPod.Scanner.ClientTimeoutSeconds = ctl.ScannerPodScannerClientTimeoutSeconds + util.SetHelmValueInMap(ctl.args, []string{"scannerPod", "scanner", "clientTimeoutSeconds"}, ctl.flagTree.ScannerPodScannerClientTimeoutSeconds) case "image-getter-secure-registries-file-path": - if ctl.opsSightSpec.ScannerPod == nil { - ctl.opsSightSpec.ScannerPod = &opssightapi.ScannerPod{} - } - if ctl.opsSightSpec.ScannerPod.ImageFacade == nil { - ctl.opsSightSpec.ScannerPod.ImageFacade = &opssightapi.ImageFacade{} - } - data, err := util.ReadFileData(ctl.ScannerPodImageFacadeInternalRegistriesFilePath) + data, err := util.ReadFileData(ctl.flagTree.ScannerPodImageFacadeInternalRegistriesFilePath) if err != nil { log.Fatalf("failed to read internal registries file: %+v", err) } @@ -325,118 +250,67 @@ func (ctl *CRSpecBuilderFromCobraFlags) SetCRSpecFieldByFlag(f *pflag.Flag) { if err != nil { log.Fatalf("failed to unmarshal internal registries: %+v", err) } - ctl.opsSightSpec.ScannerPod.ImageFacade.InternalRegistries = registryStructs + util.SetHelmValueInMap(ctl.args, []string{"scannerPod", "imageFacade", "internalRegistries"}, registryStructs) case "image-getter-image-puller-type": - if ctl.opsSightSpec.ScannerPod == nil { - ctl.opsSightSpec.ScannerPod = &opssightapi.ScannerPod{} - } - if ctl.opsSightSpec.ScannerPod.ImageFacade == nil { - ctl.opsSightSpec.ScannerPod.ImageFacade = &opssightapi.ImageFacade{} - } - ctl.opsSightSpec.ScannerPod.ImageFacade.ImagePullerType = ctl.ScannerPodImageFacadeImagePullerType + util.SetHelmValueInMap(ctl.args, []string{"scannerPod", "imageFacade", "imagePullerType"}, ctl.flagTree.ScannerPodImageFacadeImagePullerType) case "scannerpod-replica-count": - if ctl.opsSightSpec.ScannerPod == nil { - ctl.opsSightSpec.ScannerPod = &opssightapi.ScannerPod{} - } - ctl.opsSightSpec.ScannerPod.ReplicaCount = ctl.ScannerPodReplicaCount + util.SetHelmValueInMap(ctl.args, []string{"scannerPod", "replicaCount"}, ctl.flagTree.ScannerPodReplicaCount) case "scannerpod-image-directory": - if ctl.opsSightSpec.ScannerPod == nil { - ctl.opsSightSpec.ScannerPod = &opssightapi.ScannerPod{} - } - ctl.opsSightSpec.ScannerPod.ImageDirectory = ctl.ScannerPodImageDirectory + util.SetHelmValueInMap(ctl.args, []string{"scannerPod", "imageDirectory"}, ctl.flagTree.ScannerPodImageDirectory) case "enable-image-processor": - if ctl.opsSightSpec.Perceiver == nil { - ctl.opsSightSpec.Perceiver = &opssightapi.Perceiver{} - } - ctl.opsSightSpec.Perceiver.EnableImagePerceiver = strings.ToUpper(ctl.PerceiverEnableImagePerceiver) == "TRUE" + enableImagePerceiver = strings.ToUpper(ctl.flagTree.PerceiverEnableImagePerceiver) == "TRUE" + util.SetHelmValueInMap(ctl.args, []string{"perceiver", "enableImagePerceiver"}, enableImagePerceiver) case "enable-artifactory-processor": - if ctl.opsSightSpec.Perceiver == nil { - ctl.opsSightSpec.Perceiver = &opssightapi.Perceiver{} - } - ctl.opsSightSpec.Perceiver.EnableArtifactoryPerceiver = strings.ToUpper(ctl.PerceiverEnableArtifactoryPerceiver) == "TRUE" + enableArtifactoryPerceiver = strings.ToUpper(ctl.flagTree.PerceiverEnableArtifactoryPerceiver) == "TRUE" + util.SetHelmValueInMap(ctl.args, []string{"perceiver", "enableArtifactoryPerceiver"}, enableArtifactoryPerceiver) case "enable-artifactory-processor-dumper": - if ctl.opsSightSpec.Perceiver == nil { - ctl.opsSightSpec.Perceiver = &opssightapi.Perceiver{} - } - ctl.opsSightSpec.Perceiver.EnableArtifactoryPerceiverDumper = strings.ToUpper(ctl.PerceiverEnableArtifactoryPerceiverDumper) == "TRUE" + enableArtifactoryPerceiverDumper = strings.ToUpper(ctl.flagTree.PerceiverEnableArtifactoryPerceiverDumper) == "TRUE" + util.SetHelmValueInMap(ctl.args, []string{"perceiver", "enableArtifactoryPerceiverDumber"}, enableArtifactoryPerceiverDumper) case "enable-quay-processor": - if ctl.opsSightSpec.Perceiver == nil { - ctl.opsSightSpec.Perceiver = &opssightapi.Perceiver{} - } - ctl.opsSightSpec.Perceiver.EnableQuayPerceiver = strings.ToUpper(ctl.PerceiverEnableQuayPerceiver) == "TRUE" + enableQuayPerceiver = strings.ToUpper(ctl.flagTree.PerceiverEnableQuayPerceiver) == "TRUE" + util.SetHelmValueInMap(ctl.args, []string{"perceiver", "enableQuayPerceiver"}, enableQuayPerceiver) case "expose-artifactory-processor": - if ctl.opsSightSpec.Perceiver == nil { - ctl.opsSightSpec.Perceiver = &opssightapi.Perceiver{} - } - ctl.opsSightSpec.Perceiver.Expose = ctl.PerceiverArtifactoryExpose + util.SetHelmValueInMap(ctl.args, []string{"perceiver", "expose"}, ctl.flagTree.PerceiverArtifactoryExpose) case "expose-quay-processor": - if ctl.opsSightSpec.Perceiver == nil { - ctl.opsSightSpec.Perceiver = &opssightapi.Perceiver{} - } - ctl.opsSightSpec.Perceiver.Expose = ctl.PerceiverQuayExpose + util.SetHelmValueInMap(ctl.args, []string{""}, ctl.flagTree.PerceiverQuayExpose) case "processor-TLS-certificate-path": - if ctl.opsSightSpec.Perceiver == nil { - ctl.opsSightSpec.Perceiver = &opssightapi.Perceiver{} - } - data, err := util.ReadFileData(ctl.PerceiverTLSCertificatePath) + data, err := util.ReadFileData(ctl.flagTree.PerceiverTLSCertificatePath) if err != nil { log.Fatalf("failed to read certificate file: %+v", err) } - ctl.opsSightSpec.Perceiver.Certificate = data + util.SetHelmValueInMap(ctl.args, []string{"perceiver", "certificate"}, data) case "processor-TLS-key-path": - if ctl.opsSightSpec.Perceiver == nil { - ctl.opsSightSpec.Perceiver = &opssightapi.Perceiver{} - } - data, err := util.ReadFileData(ctl.PerceiverTLSKeyPath) + data, err := util.ReadFileData(ctl.flagTree.PerceiverTLSKeyPath) if err != nil { log.Fatalf("failed to read certificate file: %+v", err) } - ctl.opsSightSpec.Perceiver.CertificateKey = data + util.SetHelmValueInMap(ctl.args, []string{"perceiver", "certificateKey"}, data) case "enable-pod-processor": - if ctl.opsSightSpec.Perceiver == nil { - ctl.opsSightSpec.Perceiver = &opssightapi.Perceiver{} - } - ctl.opsSightSpec.Perceiver.EnablePodPerceiver = strings.ToUpper(ctl.PerceiverEnablePodPerceiver) == "TRUE" + enablePodPerceiver = strings.ToUpper(ctl.flagTree.PerceiverEnablePodPerceiver) == "TRUE" + util.SetHelmValueInMap(ctl.args, []string{"perceiver", "enablePodPerceiver"}, enablePodPerceiver) case "pod-processor-namespace-filter": - if ctl.opsSightSpec.Perceiver == nil { - ctl.opsSightSpec.Perceiver = &opssightapi.Perceiver{} - } - if ctl.opsSightSpec.Perceiver.PodPerceiver == nil { - ctl.opsSightSpec.Perceiver.PodPerceiver = &opssightapi.PodPerceiver{} - } - ctl.opsSightSpec.Perceiver.PodPerceiver.NamespaceFilter = ctl.PerceiverPodPerceiverNamespaceFilter + util.SetHelmValueInMap(ctl.args, []string{"perceiver", "podPerceiver", "namespaceFilter"}, ctl.flagTree.PerceiverPodPerceiverNamespaceFilter) case "processor-annotation-interval-seconds": - if ctl.opsSightSpec.Perceiver == nil { - ctl.opsSightSpec.Perceiver = &opssightapi.Perceiver{} - } - ctl.opsSightSpec.Perceiver.AnnotationIntervalSeconds = ctl.PerceiverAnnotationIntervalSeconds + util.SetHelmValueInMap(ctl.args, []string{"perceiver", "annotationIntervalSeconds"}, ctl.flagTree.PerceiverAnnotationIntervalSeconds) case "processor-dump-interval-minutes": - if ctl.opsSightSpec.Perceiver == nil { - ctl.opsSightSpec.Perceiver = &opssightapi.Perceiver{} - } - ctl.opsSightSpec.Perceiver.DumpIntervalMinutes = ctl.PerceiverDumpIntervalMinutes + util.SetHelmValueInMap(ctl.args, []string{"perceiver", "dumpIntervalMinutes"}, ctl.flagTree.PerceiverDumpIntervalMinutes) case "default-cpu": - ctl.opsSightSpec.DefaultCPU = ctl.DefaultCPU + util.SetHelmValueInMap(ctl.args, []string{"defaultCPU"}, ctl.flagTree.DefaultCPU) case "default-memory": - ctl.opsSightSpec.DefaultMem = ctl.DefaultMem + util.SetHelmValueInMap(ctl.args, []string{"defaultMem"}, ctl.flagTree.DefaultMem) case "scanner-cpu": - ctl.opsSightSpec.ScannerCPU = ctl.ScannerCPU + util.SetHelmValueInMap(ctl.args, []string{"scannerCPU"}, ctl.flagTree.ScannerCPU) case "scanner-memory": - ctl.opsSightSpec.ScannerMem = ctl.ScannerMem + util.SetHelmValueInMap(ctl.args, []string{"scannerMem"}, ctl.flagTree.ScannerMem) case "log-level": - ctl.opsSightSpec.LogLevel = ctl.LogLevel + util.SetHelmValueInMap(ctl.args, []string{"logLevel"}, ctl.flagTree.LogLevel) case "enable-metrics": - ctl.opsSightSpec.EnableMetrics = strings.ToUpper(ctl.EnableMetrics) == "TRUE" + enableMetrics = strings.ToUpper(ctl.flagTree.EnableMetrics) == "TRUE" + util.SetHelmValueInMap(ctl.args, []string{"enableMetrics"}, enableMetrics) case "expose-metrics": - if ctl.opsSightSpec.Prometheus == nil { - ctl.opsSightSpec.Prometheus = &opssightapi.Prometheus{} - } - ctl.opsSightSpec.Prometheus.Expose = ctl.PrometheusExpose + util.SetHelmValueInMap(ctl.args, []string{"prometheus", "expose"}, ctl.flagTree.PrometheusExpose) case "blackduck-external-hosts-file-path": - if ctl.opsSightSpec.Blackduck == nil { - ctl.opsSightSpec.Blackduck = &opssightapi.Blackduck{} - } - data, err := util.ReadFileData(ctl.BlackduckExternalHostsFilePath) + data, err := util.ReadFileData(ctl.flagTree.BlackduckExternalHostsFilePath) if err != nil { log.Fatalf("failed to read external hosts file: %+v", err) } @@ -445,50 +319,24 @@ func (ctl *CRSpecBuilderFromCobraFlags) SetCRSpecFieldByFlag(f *pflag.Flag) { if err != nil { log.Fatalf("failed to unmarshal internal registry structs: %+v", err) } - ctl.opsSightSpec.Blackduck.ExternalHosts = hostStructs + util.SetHelmValueInMap(ctl.args, []string{"blackduck", "externalHosts"}, hostStructs) case "blackduck-TLS-verification": - if ctl.opsSightSpec.Blackduck == nil { - ctl.opsSightSpec.Blackduck = &opssightapi.Blackduck{} - } - ctl.opsSightSpec.Blackduck.TLSVerification = strings.ToUpper(ctl.BlackduckTLSVerification) == "TRUE" + enalbeTLSVerification = strings.ToUpper(ctl.flagTree.BlackduckTLSVerification) == "TRUE" + util.SetHelmValueInMap(ctl.args, []string{"blackduck", "tlsVerification"}, enalbeTLSVerification) case "blackduck-initial-count": - if ctl.opsSightSpec.Blackduck == nil { - ctl.opsSightSpec.Blackduck = &opssightapi.Blackduck{} - } - ctl.opsSightSpec.Blackduck.InitialCount = ctl.BlackduckInitialCount + util.SetHelmValueInMap(ctl.args, []string{"blackduck", "initialCount"}, ctl.flagTree.BlackduckInitialCount) case "blackduck-max-count": - if ctl.opsSightSpec.Blackduck == nil { - ctl.opsSightSpec.Blackduck = &opssightapi.Blackduck{} - } - ctl.opsSightSpec.Blackduck.MaxCount = ctl.BlackduckMaxCount + util.SetHelmValueInMap(ctl.args, []string{"blackduck", "maxCount"}, ctl.flagTree.BlackduckMaxCount) case "blackduck-type": - if ctl.opsSightSpec.Blackduck == nil { - ctl.opsSightSpec.Blackduck = &opssightapi.Blackduck{} - } - if ctl.opsSightSpec.Blackduck.BlackduckSpec == nil { - ctl.opsSightSpec.Blackduck.BlackduckSpec = &blackduckapi.BlackduckSpec{} - } - ctl.opsSightSpec.Blackduck.BlackduckSpec.Type = ctl.BlackduckType + util.SetHelmValueInMap(ctl.args, []string{"blackduck", "blackduckSpec", "type"}, ctl.flagTree.BlackduckType) case "blackduck-password": - if ctl.opsSightSpec.Blackduck == nil { - ctl.opsSightSpec.Blackduck = &opssightapi.Blackduck{} - } - if ctl.opsSightSpec.Blackduck.BlackduckSpec == nil { - ctl.opsSightSpec.Blackduck.BlackduckSpec = &blackduckapi.BlackduckSpec{} - } - ctl.opsSightSpec.Blackduck.BlackduckPassword = crddefaults.Base64Encode([]byte(ctl.BlackduckPassword)) + util.SetHelmValueInMap(ctl.args, []string{"blackduck", "blackduckPassword"}, crddefaults.Base64Encode([]byte(ctl.flagTree.BlackduckPassword))) case "registry": - if ctl.opsSightSpec.RegistryConfiguration == nil { - ctl.opsSightSpec.RegistryConfiguration = &api.RegistryConfiguration{} - } - ctl.opsSightSpec.RegistryConfiguration.Registry = ctl.Registry + util.SetHelmValueInMap(ctl.args, []string{"registryConfiguration", "registry"}, ctl.flagTree.Registry) case "pull-secret-name": - if ctl.opsSightSpec.RegistryConfiguration == nil { - ctl.opsSightSpec.RegistryConfiguration = &api.RegistryConfiguration{} - } - ctl.opsSightSpec.RegistryConfiguration.PullSecrets = ctl.PullSecrets + util.SetHelmValueInMap(ctl.args, []string{"registryConfiguration", "pullSecrets"}, ctl.flagTree.PullSecrets) case "image-registries": - ctl.opsSightSpec.ImageRegistries = ctl.ImageRegistries + util.SetHelmValueInMap(ctl.args, []string{"imageRegistries"}, ctl.flagTree.ImageRegistries) default: log.Debugf("flag '%s': NOT FOUND", f.Name) } diff --git a/pkg/opssight/ctl_opssight_test.go b/pkg/opssight/ctl_opssight_test.go index d3ff590bb..a68775e7a 100644 --- a/pkg/opssight/ctl_opssight_test.go +++ b/pkg/opssight/ctl_opssight_test.go @@ -21,206 +21,40 @@ package opssight import ( "testing" - "github.com/blackducksoftware/synopsys-operator/pkg/api" - blackduckapi "github.com/blackducksoftware/synopsys-operator/pkg/api/blackduck/v1" - opssightapi "github.com/blackducksoftware/synopsys-operator/pkg/api/opssight/v1" - "github.com/blackducksoftware/synopsys-operator/pkg/util" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/stretchr/testify/assert" ) -func TestNewCRSpecBuilderFromCobraFlags(t *testing.T) { +func TestNewHelmValuesFromCobraFlags(t *testing.T) { assert := assert.New(t) - opsSightCobraHelper := NewCRSpecBuilderFromCobraFlags() - assert.Equal(&CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - }, opsSightCobraHelper) + opssightCobraHelper := NewHelmValuesFromCobraFlags() + assert.Equal(&HelmValuesFromCobraFlags{ + args: map[string]interface{}{}, + flagTree: FlagTree{}, + }, opssightCobraHelper) } -func TestGetCRSpec(t *testing.T) { +func TestGetArgs(t *testing.T) { assert := assert.New(t) - opsSightCobraHelper := NewCRSpecBuilderFromCobraFlags() - assert.Equal(opssightapi.OpsSightSpec{}, opsSightCobraHelper.GetCRSpec()) + opssightCobraHelper := NewHelmValuesFromCobraFlags() + assert.Equal(map[string]interface{}{}, opssightCobraHelper.GetArgs()) } -func TestSetCRSpec(t *testing.T) { +func TestGenerateHelmFlagsFromCobraFlags(t *testing.T) { assert := assert.New(t) - opsSightCobraHelper := NewCRSpecBuilderFromCobraFlags() - specToSet := opssightapi.OpsSightSpec{Namespace: "test"} - opsSightCobraHelper.SetCRSpec(specToSet) - assert.Equal(specToSet, opsSightCobraHelper.GetCRSpec()) - // check for error - assert.Error(opsSightCobraHelper.SetCRSpec("")) -} - -func TestCheckValuesFromFlags(t *testing.T) { - assert := assert.New(t) - opsSightCobraHelper := NewCRSpecBuilderFromCobraFlags() - opsSightCobraHelper.PerceptorExpose = util.NONE - opsSightCobraHelper.PrometheusExpose = util.NONE - opsSightCobraHelper.PerceiverArtifactoryExpose = util.NONE + opssightCobraHelper := NewHelmValuesFromCobraFlags() cmd := &cobra.Command{} - specFlags := opsSightCobraHelper.CheckValuesFromFlags(cmd.Flags()) - assert.Nil(specFlags) - - var tests = []struct { - input *CRSpecBuilderFromCobraFlags - flagNameToTest string - flagValue string - }{ - // invalid opssight core expose case - {input: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceptorExpose: "", - PrometheusExpose: util.NONE, - PerceiverArtifactoryExpose: util.NONE, - PerceiverQuayExpose: util.NONE, - }, - flagNameToTest: "opssight-core-expose", - flagValue: "", - }, - // invalid prometheus metrics expose case - {input: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceptorExpose: util.NONE, - PerceiverArtifactoryExpose: util.NONE, - PerceiverQuayExpose: util.NONE, - PrometheusExpose: "", - }, - flagNameToTest: "expose-metrics", - flagValue: "", - }, - // invalid artifactory metrics expose case - {input: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceptorExpose: util.NONE, - PrometheusExpose: util.NONE, - PerceiverQuayExpose: util.NONE, - PerceiverArtifactoryExpose: "", - }, - flagNameToTest: "expose-artifactory-processor", - flagValue: "", - }, - // invalid quay metrics expose case - {input: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceptorExpose: util.NONE, - PrometheusExpose: util.NONE, - PerceiverQuayExpose: "", - PerceiverArtifactoryExpose: util.NONE, - }, - flagNameToTest: "expose-quay-processor", - flagValue: "", - }, - } - - for _, test := range tests { - cmd := &cobra.Command{} - opsSightCobraHelper.AddCRSpecFlagsToCommand(cmd, true) - flagset := cmd.Flags() - flagset.Set(test.flagNameToTest, test.flagValue) - err := test.input.CheckValuesFromFlags(flagset) - if err == nil { - t.Errorf("Expected an error but got nil, test: %+v", test) - } - } -} - -func TestSetPredefinedCRSpec(t *testing.T) { - assert := assert.New(t) - opsSightCobraHelper := NewCRSpecBuilderFromCobraFlags() - defaultSpec := util.GetOpsSightDefault() - defaultSpec.Perceiver.EnablePodPerceiver = true - defaultSpec.EnableMetrics = true - - var tests = []struct { - input string - expected *opssightapi.OpsSightSpec - }{ - {input: EmptySpec, expected: &opssightapi.OpsSightSpec{}}, - {input: UpstreamSpec, expected: util.GetOpsSightUpstream()}, - {input: DefaultSpec, expected: defaultSpec}, - {input: DisabledBlackDuckSpec, expected: util.GetOpsSightDefaultWithIPV6DisabledBlackDuck()}, - } - - // test cases: "empty", "default", "disabledBlackduck" - for _, test := range tests { - assert.Nil(opsSightCobraHelper.SetPredefinedCRSpec(test.input)) - assert.Equal(*test.expected, opsSightCobraHelper.GetCRSpec()) - } - - // test cases: default - createOpsSightSpecType := "" - assert.Error(opsSightCobraHelper.SetPredefinedCRSpec(createOpsSightSpecType)) - -} - -func TestAddCRSpecFlagsToCommand(t *testing.T) { - assert := assert.New(t) - - ctl := NewCRSpecBuilderFromCobraFlags() - actualCmd := &cobra.Command{} - ctl.AddCRSpecFlagsToCommand(actualCmd, true) - - cmd := &cobra.Command{} - cmd.Flags().StringVar(&ctl.IsUpstream, "is-upstream", ctl.IsUpstream, "If true, Upstream images and names will be used [true|false]") - cmd.Flags().StringVar(&ctl.PerceptorExpose, "opssight-core-expose", ctl.PerceptorExpose, "Type of service for OpsSight's core model [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") - cmd.Flags().IntVar(&ctl.PerceptorCheckForStalledScansPauseHours, "opssight-core-check-scan-hours", ctl.PerceptorCheckForStalledScansPauseHours, "Hours OpsSight's Core waits between checking for scans") - cmd.Flags().IntVar(&ctl.PerceptorStalledScanClientTimeoutHours, "opssight-core-scan-client-timeout-hours", ctl.PerceptorStalledScanClientTimeoutHours, "Hours until OpsSight's Core stops checking for scans") - cmd.Flags().IntVar(&ctl.PerceptorModelMetricsPauseSeconds, "opssight-core-metrics-pause-seconds", ctl.PerceptorModelMetricsPauseSeconds, "Core metrics pause in seconds") - cmd.Flags().IntVar(&ctl.PerceptorUnknownImagePauseMilliseconds, "opssight-core-unknown-image-pause-milliseconds", ctl.PerceptorUnknownImagePauseMilliseconds, "OpsSight Core's unknown image pause in milliseconds") - cmd.Flags().IntVar(&ctl.PerceptorClientTimeoutMilliseconds, "opssight-core-client-timeout-milliseconds", ctl.PerceptorClientTimeoutMilliseconds, "Seconds for OpsSight Core's timeout for Black Duck Scan Client") - cmd.Flags().IntVar(&ctl.ScannerPodScannerClientTimeoutSeconds, "scanner-client-timeout-seconds", ctl.ScannerPodScannerClientTimeoutSeconds, "Seconds before Scanner times out for Black Duck's Scan Client") - cmd.Flags().StringVar(&ctl.ScannerPodImageFacadeInternalRegistriesFilePath, "image-getter-secure-registries-file-path", ctl.ScannerPodImageFacadeInternalRegistriesFilePath, "Absolute path to a file for secure docker registries credentials to pull the images for scan") - cmd.Flags().StringVar(&ctl.ScannerPodImageFacadeImagePullerType, "image-getter-image-puller-type", ctl.ScannerPodImageFacadeImagePullerType, "Type of Image Getter's Image Puller [docker|skopeo]") - cmd.Flags().IntVar(&ctl.ScannerPodReplicaCount, "scannerpod-replica-count", ctl.ScannerPodReplicaCount, "Number of Containers for scanning") - cmd.Flags().StringVar(&ctl.ScannerPodImageDirectory, "scannerpod-image-directory", ctl.ScannerPodImageDirectory, "Directory in Scanner's pod where images are stored for scanning") - cmd.Flags().StringVar(&ctl.PerceiverEnableImagePerceiver, "enable-image-processor", ctl.PerceiverEnableImagePerceiver, "If true, Image Processor discovers images for scanning [true|false]") - cmd.Flags().StringVar(&ctl.PerceiverEnableArtifactoryPerceiver, "enable-artifactory-processor", ctl.PerceiverEnableArtifactoryPerceiver, "If true, Artifactory Processor discovers artifactory images for scanning [true|false]") - cmd.Flags().StringVar(&ctl.PerceiverEnableArtifactoryPerceiverDumper, "enable-artifactory-processor-dumper", ctl.PerceiverEnableArtifactoryPerceiverDumper, "If true, Artifactory Processor dumps all docker images in an artifactory instance for scanning [true|false]") - cmd.Flags().StringVar(&ctl.PerceiverEnableQuayPerceiver, "enable-quay-processor", ctl.PerceiverEnableQuayPerceiver, "If true, Quay Processor discovers quay images for scanning [true|false]") - cmd.Flags().StringVar(&ctl.PerceiverEnablePodPerceiver, "enable-pod-processor", ctl.PerceiverEnablePodPerceiver, "If true, Pod Processor discovers pods for scanning [true|false]") - cmd.Flags().StringVar(&ctl.PerceiverArtifactoryExpose, "expose-artifactory-processor", ctl.PerceiverArtifactoryExpose, "Type of service for Artifactory processor [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") - cmd.Flags().StringVar(&ctl.PerceiverQuayExpose, "expose-quay-processor", ctl.PerceiverQuayExpose, "Type of service for Quay processor [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") - cmd.Flags().StringVar(&ctl.PerceiverTLSCertificatePath, "processor-TLS-certificate-path", ctl.PerceiverTLSCertificatePath, "Accepts certificate file to start webhook receiver with TLS enabled, works in conjunction with Quay and Artifactory processors") - cmd.Flags().StringVar(&ctl.PerceiverTLSKeyPath, "processor-TLS-key-path", ctl.PerceiverTLSKeyPath, "Accepts key file to sign the TLS certificate, works in conjunction with Quay and Artifactory processors") - cmd.Flags().StringVar(&ctl.PerceiverPodPerceiverNamespaceFilter, "pod-processor-namespace-filter", ctl.PerceiverPodPerceiverNamespaceFilter, "Pod Processor's filter to scan pods by their namespace") - cmd.Flags().IntVar(&ctl.PerceiverAnnotationIntervalSeconds, "processor-annotation-interval-seconds", ctl.PerceiverAnnotationIntervalSeconds, "Refresh interval to get latest scan results and apply to Pods and Images") - cmd.Flags().IntVar(&ctl.PerceiverDumpIntervalMinutes, "processor-dump-interval-minutes", ctl.PerceiverDumpIntervalMinutes, "Minutes Image Processor and Pod Processor wait between creating dumps of data/metrics") - cmd.Flags().StringVar(&ctl.DefaultCPU, "default-cpu", ctl.DefaultCPU, "CPU size of OpsSight") - cmd.Flags().StringVar(&ctl.DefaultMem, "default-memory", ctl.DefaultMem, "Memory size of OpsSight") - cmd.Flags().StringVar(&ctl.ScannerCPU, "scanner-cpu", ctl.ScannerCPU, "CPU size of OpsSight's Scanner") - cmd.Flags().StringVar(&ctl.ScannerMem, "scanner-memory", ctl.ScannerMem, "Memory size of OpsSight's Scanner") - cmd.Flags().StringVar(&ctl.LogLevel, "log-level", ctl.LogLevel, "Log level of OpsSight") - cmd.Flags().StringVar(&ctl.EnableMetrics, "enable-metrics", ctl.EnableMetrics, "If true, OpsSight records Prometheus Metrics [true|false]") - cmd.Flags().StringVar(&ctl.PrometheusExpose, "expose-metrics", ctl.PrometheusExpose, "Type of service of OpsSight's Prometheus Metrics [NODEPORT|LOADBALANCER|OPENSHIFT|NONE]") - cmd.Flags().StringVar(&ctl.BlackduckExternalHostsFilePath, "blackduck-external-hosts-file-path", ctl.BlackduckExternalHostsFilePath, "Absolute path to a file containing a list of Black Duck External Hosts") - cmd.Flags().StringVar(&ctl.BlackduckTLSVerification, "blackduck-TLS-verification", ctl.BlackduckTLSVerification, "If true, OpsSight performs TLS Verification for Black Duck [true|false]") - cmd.Flags().IntVar(&ctl.BlackduckInitialCount, "blackduck-initial-count", ctl.BlackduckInitialCount, "Initial number of Black Duck instances to create") - cmd.Flags().IntVar(&ctl.BlackduckMaxCount, "blackduck-max-count", ctl.BlackduckMaxCount, "Maximum number of Black Duck instances that can be created") - cmd.Flags().StringVar(&ctl.BlackduckType, "blackduck-type", ctl.BlackduckType, "Type of Black Duck") - cmd.Flags().StringVar(&ctl.BlackduckPassword, "blackduck-password", ctl.BlackduckPassword, "Password to use for all internal Blackduck 'sysadmin' account") - cmd.Flags().StringVar(&ctl.Registry, "registry", ctl.Registry, "Name of the registry to use for images e.g. docker.io/blackducksoftware") - cmd.Flags().StringSliceVar(&ctl.PullSecrets, "pull-secret-name", ctl.PullSecrets, "Only if the registry requires authentication") - cmd.Flags().StringSliceVar(&ctl.ImageRegistries, "image-registries", ctl.ImageRegistries, "List of image registries") - - assert.Equal(cmd.Flags(), actualCmd.Flags()) - -} + opssightCobraHelper.AddCobraFlagsToCommand(cmd, true) + flagset := cmd.Flags() + // Set flags here... -func TestGenerateCRSpecFromFlags(t *testing.T) { - assert := assert.New(t) + opssightCobraHelper.GenerateHelmFlagsFromCobraFlags(flagset) - actualCtl := NewCRSpecBuilderFromCobraFlags() - cmd := &cobra.Command{} - actualCtl.AddCRSpecFlagsToCommand(cmd, true) - actualCtl.GenerateCRSpecFromFlags(cmd.Flags()) + expectedArgs := map[string]interface{}{} - expCtl := NewCRSpecBuilderFromCobraFlags() - - assert.Equal(expCtl.opsSightSpec, actualCtl.opsSightSpec) + assert.Equal(expectedArgs, opssightCobraHelper.GetArgs()) } @@ -229,403 +63,49 @@ func TestSetCRSpecFieldByFlag(t *testing.T) { var tests = []struct { flagName string - initialCtl *CRSpecBuilderFromCobraFlags - changedCtl *CRSpecBuilderFromCobraFlags - changedSpec *opssightapi.OpsSightSpec + initialCtl *HelmValuesFromCobraFlags + changedCtl *HelmValuesFromCobraFlags + changedArgs map[string]interface{} }{ // case { - flagName: "opssight-core-expose", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceptorExpose: "changed", - }, - changedSpec: &opssightapi.OpsSightSpec{Perceptor: &opssightapi.Perceptor{Expose: "changed"}}, - }, - // case - { - flagName: "expose-artifactory-processor", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceiverArtifactoryExpose: "changed", - }, - changedSpec: &opssightapi.OpsSightSpec{Perceiver: &opssightapi.Perceiver{Expose: "changed"}}, - }, - // case - { - flagName: "expose-quay-processor", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceiverQuayExpose: "changed", - }, - changedSpec: &opssightapi.OpsSightSpec{Perceiver: &opssightapi.Perceiver{Expose: "changed"}}, - }, - // case - { - flagName: "opssight-core-check-scan-hours", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceptorCheckForStalledScansPauseHours: 10, - }, - changedSpec: &opssightapi.OpsSightSpec{Perceptor: &opssightapi.Perceptor{CheckForStalledScansPauseHours: 10}}, - }, - // case - { - flagName: "opssight-core-scan-client-timeout-hours", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceptorStalledScanClientTimeoutHours: 10, - }, - changedSpec: &opssightapi.OpsSightSpec{Perceptor: &opssightapi.Perceptor{StalledScanClientTimeoutHours: 10}}, - }, - // case - { - flagName: "opssight-core-metrics-pause-seconds", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceptorModelMetricsPauseSeconds: 10, - }, - changedSpec: &opssightapi.OpsSightSpec{Perceptor: &opssightapi.Perceptor{ModelMetricsPauseSeconds: 10}}, - }, - // case - { - flagName: "opssight-core-unknown-image-pause-milliseconds", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceptorUnknownImagePauseMilliseconds: 10, - }, - changedSpec: &opssightapi.OpsSightSpec{Perceptor: &opssightapi.Perceptor{UnknownImagePauseMilliseconds: 10}}, - }, - // case - { - flagName: "opssight-core-client-timeout-milliseconds", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceptorClientTimeoutMilliseconds: 10, - }, - changedSpec: &opssightapi.OpsSightSpec{Perceptor: &opssightapi.Perceptor{ClientTimeoutMilliseconds: 10}}, - }, - // case - { - flagName: "scanner-client-timeout-seconds", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - ScannerPodScannerClientTimeoutSeconds: 10, - }, - changedSpec: &opssightapi.OpsSightSpec{ScannerPod: &opssightapi.ScannerPod{Scanner: &opssightapi.Scanner{ClientTimeoutSeconds: 10}}}, - }, - // case - { - flagName: "image-getter-secure-registries-file-path", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - ScannerPodImageFacadeInternalRegistriesFilePath: "../../examples/synopsysctl/imageGetterSecureRegistries.json", - }, - changedSpec: &opssightapi.OpsSightSpec{ScannerPod: &opssightapi.ScannerPod{ImageFacade: &opssightapi.ImageFacade{InternalRegistries: []*opssightapi.RegistryAuth{ - { - URL: "url", - User: "user", - Password: "password", - }, - }}}}, - }, - // case - { - flagName: "image-getter-image-puller-type", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - ScannerPodImageFacadeImagePullerType: "changed", - }, - changedSpec: &opssightapi.OpsSightSpec{ScannerPod: &opssightapi.ScannerPod{ImageFacade: &opssightapi.ImageFacade{ImagePullerType: "changed"}}}, - }, - // case - { - flagName: "scannerpod-replica-count", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - ScannerPodReplicaCount: 10, - }, - changedSpec: &opssightapi.OpsSightSpec{ScannerPod: &opssightapi.ScannerPod{ReplicaCount: 10}}, - }, - // case - { - flagName: "scannerpod-image-directory", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - ScannerPodImageDirectory: "changed", - }, - changedSpec: &opssightapi.OpsSightSpec{ScannerPod: &opssightapi.ScannerPod{ImageDirectory: "changed"}}, - }, - // case - { - flagName: "enable-pod-processor", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceiverEnablePodPerceiver: "false", - }, - changedSpec: &opssightapi.OpsSightSpec{Perceiver: &opssightapi.Perceiver{EnablePodPerceiver: false}}, - }, - // case - { - flagName: "enable-pod-processor", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceiverEnablePodPerceiver: "true", - }, - changedSpec: &opssightapi.OpsSightSpec{Perceiver: &opssightapi.Perceiver{EnablePodPerceiver: true}}, - }, - // case - { - flagName: "pod-processor-namespace-filter", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceiverPodPerceiverNamespaceFilter: "changed", - }, - changedSpec: &opssightapi.OpsSightSpec{Perceiver: &opssightapi.Perceiver{PodPerceiver: &opssightapi.PodPerceiver{NamespaceFilter: "changed"}}}, - }, - // case - { - flagName: "processor-annotation-interval-seconds", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceiverAnnotationIntervalSeconds: 10, - }, - changedSpec: &opssightapi.OpsSightSpec{Perceiver: &opssightapi.Perceiver{AnnotationIntervalSeconds: 10}}, - }, - // case - { - flagName: "processor-dump-interval-minutes", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PerceiverDumpIntervalMinutes: 10, - }, - changedSpec: &opssightapi.OpsSightSpec{Perceiver: &opssightapi.Perceiver{DumpIntervalMinutes: 10}}, - }, - // case - { - flagName: "default-cpu", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - DefaultCPU: "changed", - }, - changedSpec: &opssightapi.OpsSightSpec{DefaultCPU: "changed"}, - }, - // case - { - flagName: "default-memory", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - DefaultMem: "changed", - }, - changedSpec: &opssightapi.OpsSightSpec{DefaultMem: "changed"}, - }, - // case - { - flagName: "scanner-cpu", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - ScannerCPU: "changed", - }, - changedSpec: &opssightapi.OpsSightSpec{ScannerCPU: "changed"}, - }, - // case - { - flagName: "scanner-memory", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - ScannerMem: "changed", - }, - changedSpec: &opssightapi.OpsSightSpec{ScannerMem: "changed"}, - }, - // case - { - flagName: "log-level", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - LogLevel: "changed", - }, - changedSpec: &opssightapi.OpsSightSpec{LogLevel: "changed"}, - }, - // case - { - flagName: "enable-metrics", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - EnableMetrics: "false", - }, - changedSpec: &opssightapi.OpsSightSpec{EnableMetrics: false}, - }, - // case - { - flagName: "enable-metrics", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - EnableMetrics: "true", - }, - changedSpec: &opssightapi.OpsSightSpec{EnableMetrics: true}, - }, - // case - { - flagName: "expose-metrics", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PrometheusExpose: "changed", - }, - changedSpec: &opssightapi.OpsSightSpec{Prometheus: &opssightapi.Prometheus{Expose: "changed"}}, - }, - // case - { - flagName: "blackduck-external-hosts-file-path", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - BlackduckExternalHostsFilePath: "../../examples/synopsysctl/blackduckExternalHosts.json", - }, - changedSpec: &opssightapi.OpsSightSpec{Blackduck: &opssightapi.Blackduck{ExternalHosts: []*opssightapi.Host{ - { - Scheme: "scheme", - Domain: "domain", - Port: 99, - User: "user", - Password: "password", - ConcurrentScanLimit: 88, + flagName: "isUpstream", + changedCtl: &HelmValuesFromCobraFlags{ + flagTree: FlagTree{ + IsUpstream: true, }, - }}}, - }, - // case - { - flagName: "blackduck-TLS-verification", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - BlackduckTLSVerification: "false", }, - changedSpec: &opssightapi.OpsSightSpec{Blackduck: &opssightapi.Blackduck{TLSVerification: false}}, - }, - // case - { - flagName: "blackduck-TLS-verification", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - BlackduckTLSVerification: "true", - }, - changedSpec: &opssightapi.OpsSightSpec{Blackduck: &opssightapi.Blackduck{TLSVerification: true}}, - }, - // case - { - flagName: "blackduck-initial-count", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - BlackduckInitialCount: 10, - }, - changedSpec: &opssightapi.OpsSightSpec{Blackduck: &opssightapi.Blackduck{InitialCount: 10}}, - }, - // case - { - flagName: "blackduck-max-count", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - BlackduckMaxCount: 10, - }, - changedSpec: &opssightapi.OpsSightSpec{Blackduck: &opssightapi.Blackduck{MaxCount: 10}}, - }, - // case - { - flagName: "blackduck-type", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - BlackduckType: "changed", - }, - changedSpec: &opssightapi.OpsSightSpec{Blackduck: &opssightapi.Blackduck{BlackduckSpec: &blackduckapi.BlackduckSpec{Type: "changed"}}}, - }, - // case - { - flagName: "registry", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - Registry: "changed", - }, - changedSpec: &opssightapi.OpsSightSpec{RegistryConfiguration: &api.RegistryConfiguration{Registry: "changed"}}, - }, - // case - { - flagName: "pull-secret-name", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - PullSecrets: []string{"changed"}, - }, - changedSpec: &opssightapi.OpsSightSpec{RegistryConfiguration: &api.RegistryConfiguration{PullSecrets: []string{"changed"}}}, - }, - // case - { - flagName: "image-registries", - initialCtl: NewCRSpecBuilderFromCobraFlags(), - changedCtl: &CRSpecBuilderFromCobraFlags{ - opsSightSpec: &opssightapi.OpsSightSpec{}, - ImageRegistries: []string{"changed"}, + changedArgs: map[string]interface{}{ + "isUpstream": true, }, - changedSpec: &opssightapi.OpsSightSpec{ImageRegistries: []string{"changed"}}, }, + // TODO: More test cases ... } - // get the CRSpecBuilderFromCobraFlags's flags + // get the flagset cmd := &cobra.Command{} - actualCtl := NewCRSpecBuilderFromCobraFlags() - actualCtl.AddCRSpecFlagsToCommand(cmd, true) + opssightCobraHelper := NewHelmValuesFromCobraFlags() + opssightCobraHelper.AddCobraFlagsToCommand(cmd, true) flagset := cmd.Flags() for _, test := range tests { - actualCtl = NewCRSpecBuilderFromCobraFlags() // check the Flag exists foundFlag := flagset.Lookup(test.flagName) if foundFlag == nil { t.Errorf("flag %s is not in the spec", test.flagName) } - // check the correct CRSpecBuilderFromCobraFlags is used - assert.Equal(test.initialCtl, actualCtl) - actualCtl = test.changedCtl - // test setting a flag + // test setting the flag f := &pflag.Flag{Changed: true, Name: test.flagName} - actualCtl.SetCRSpecFieldByFlag(f) - assert.Equal(test.changedSpec, actualCtl.opsSightSpec) + opssightCobraHelper = test.changedCtl + opssightCobraHelper.args = map[string]interface{}{} + opssightCobraHelper.AddHelmValueByCobraFlag(f) + assert.Equal(test.changedArgs, opssightCobraHelper.GetArgs()) } // case: nothing set if flag doesn't exist - actualCtl = NewCRSpecBuilderFromCobraFlags() + opssightCobraHelper = NewHelmValuesFromCobraFlags() f := &pflag.Flag{Changed: true, Name: "bad-flag"} - actualCtl.SetCRSpecFieldByFlag(f) - assert.Equal(&opssightapi.OpsSightSpec{}, actualCtl.opsSightSpec) + opssightCobraHelper.AddHelmValueByCobraFlag(f) + assert.Equal(map[string]interface{}{}, opssightCobraHelper.GetArgs()) } diff --git a/pkg/opssight/handler.go b/pkg/opssight/handler.go deleted file mode 100644 index f2c9f9d1f..000000000 --- a/pkg/opssight/handler.go +++ /dev/null @@ -1,209 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -import ( - "fmt" - "reflect" - "strings" - - opssightapi "github.com/blackducksoftware/synopsys-operator/pkg/api/opssight/v1" - hubclientset "github.com/blackducksoftware/synopsys-operator/pkg/blackduck/client/clientset/versioned" - opssightclientset "github.com/blackducksoftware/synopsys-operator/pkg/opssight/client/clientset/versioned" - "github.com/blackducksoftware/synopsys-operator/pkg/protoform" - "github.com/blackducksoftware/synopsys-operator/pkg/util" - "github.com/imdario/mergo" - "github.com/juju/errors" - routeclient "github.com/openshift/client-go/route/clientset/versioned/typed/route/v1" - securityclient "github.com/openshift/client-go/security/clientset/versioned/typed/security/v1" - log "github.com/sirupsen/logrus" - "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" -) - -// HandlerInterface contains the methods that are required -// ... not really sure why we have this type -type HandlerInterface interface { - ObjectCreated(obj interface{}) - ObjectDeleted(obj string) - ObjectUpdated(objOld, objNew interface{}) -} - -// State contains the state of the OpsSight -type State string - -// DesiredState contains the desired state of the OpsSight -type DesiredState string - -const ( - // Running is used when OpsSight is running - Running State = "Running" - // Stopped is used when OpsSight to be stopped - Stopped State = "Stopped" - // Error is used when OpsSight deployment errored out - Error State = "Error" - - // Start is used when OpsSight deployment to be created or updated - Start DesiredState = "" - // Stop is used when OpsSight deployment to be stopped - Stop DesiredState = "Stop" -) - -// Handler will store the configuration that is required to initiantiate the informers callback -type Handler struct { - Config *protoform.Config - KubeConfig *rest.Config - KubeClient *kubernetes.Clientset - OpsSightClient *opssightclientset.Clientset - IsBlackDuckClusterScope bool - Defaults *opssightapi.OpsSightSpec - Namespace string - OSSecurityClient *securityclient.SecurityV1Client - RouteClient *routeclient.RouteV1Client - HubClient *hubclientset.Clientset -} - -// ObjectCreated will be called for create opssight events -func (h *Handler) ObjectCreated(obj interface{}) { - if err := h.handleObjectCreated(obj); err != nil { - log.Errorf("handle opssight: %s", err.Error()) - } -} - -func (h *Handler) handleObjectCreated(obj interface{}) error { - h.ObjectUpdated(nil, obj) - return nil -} - -// ObjectDeleted will be called for delete opssight events -func (h *Handler) ObjectDeleted(name string) { - log.Debugf("objectDeleted: %+v", name) - - // if cluster scope, then check whether the OpsSight CRD exist. If not exist, then don't delete the instance - if h.Config.IsClusterScoped { - apiClientset, err := clientset.NewForConfig(h.KubeConfig) - crd, err := apiClientset.ApiextensionsV1beta1().CustomResourceDefinitions().Get(util.OpsSightCRDName, metav1.GetOptions{}) - if err != nil || crd.DeletionTimestamp != nil { - // We do not delete the OpsSight instance if the CRD doesn't exist or that it is in the process of being deleted - log.Warnf("Ignoring request to delete %s because the %s CRD doesn't exist or is being deleted", name, util.OpsSightCRDName) - return - } - } - - opssightCreator := NewCreater(h.Config, h.KubeConfig, h.KubeClient, h.OpsSightClient, h.OSSecurityClient, h.RouteClient, h.HubClient, h.IsBlackDuckClusterScope) - err := opssightCreator.DeleteOpsSight(name) - if err != nil { - log.Errorf("unable to delete opssight: %v", err) - } -} - -// ObjectUpdated will be called for update opssight events -func (h *Handler) ObjectUpdated(objOld, objNew interface{}) { - // log.Debugf("objectUpdated: %+v", objNew) - opssight, ok := objNew.(*opssightapi.OpsSight) - if !ok { - log.Error("Unable to cast OpsSight object") - return - } - - var err error - if _, ok = opssight.Annotations["synopsys.com/created.by"]; !ok { - opssight.Annotations = util.InitAnnotations(opssight.Annotations) - opssight.Annotations["synopsys.com/created.by"] = h.Config.Version - opssight, err = util.UpdateOpsSight(h.OpsSightClient, h.Config.CrdNamespace, opssight) - if err != nil { - log.Errorf("couldn't update the annotation for %s OpsSight instance in %s namespace due to %+v", opssight.Name, opssight.Spec.Namespace, err) - return - } - } - - newSpec := opssight.Spec - defaultSpec := h.Defaults - err = mergo.Merge(&newSpec, defaultSpec) - if err != nil { - h.updateState(Error, err.Error(), opssight) - log.Errorf("unable to merge default and new objects due to %+v", err) - return - } - - opssight.Spec = newSpec - - switch strings.ToUpper(opssight.Spec.DesiredState) { - case "STOP": - opssightCreator := NewCreater(h.Config, h.KubeConfig, h.KubeClient, h.OpsSightClient, h.OSSecurityClient, h.RouteClient, h.HubClient, h.IsBlackDuckClusterScope) - err = opssightCreator.StopOpsSight(&opssight.Spec) - if err != nil { - h.updateState(Error, err.Error(), opssight) - log.Errorf("handle object stop: %s", err.Error()) - return - } - - _, err = h.updateState(Stopped, "", opssight) - if err != nil { - log.Error(errors.Annotate(err, "unable to update stopped state")) - return - } - case "": - opssightCreator := NewCreater(h.Config, h.KubeConfig, h.KubeClient, h.OpsSightClient, h.OSSecurityClient, h.RouteClient, h.HubClient, h.IsBlackDuckClusterScope) - err = opssightCreator.UpdateOpsSight(opssight) - if err != nil { - h.updateState(Error, err.Error(), opssight) - log.Errorf("handle object update: %s", err.Error()) - return - } - - if !strings.EqualFold(opssight.Status.State, string(Running)) { - _, err = h.updateState(Running, "", opssight) - if err != nil { - log.Error(errors.Annotate(err, "unable to update running state")) - return - } - } - default: - log.Errorf("unable to handle object update due to %+v", fmt.Errorf("desired state value is not expected")) - return - } -} - -func (h *Handler) updateState(state State, errorMessage string, opssight *opssightapi.OpsSight) (*opssightapi.OpsSight, error) { - newOpssight, err := util.GetOpsSight(h.OpsSightClient, h.Config.CrdNamespace, opssight.Name, metav1.GetOptions{}) - if err != nil { - return nil, errors.Annotate(err, "unable to get the opssight to update the state of opssight object") - } - - if !reflect.DeepEqual(newOpssight.Status.State, string(state)) || !reflect.DeepEqual(newOpssight.Status.ErrorMessage, errorMessage) { - newOpssight.Spec = opssight.Spec - newOpssight.Status.State = string(state) - newOpssight.Status.ErrorMessage = errorMessage - newOpssight, err = h.updateOpsSightObject(newOpssight) - if err != nil { - return nil, errors.Annotate(err, "unable to update the state of opssight object") - } - } - return newOpssight, nil -} - -func (h *Handler) updateOpsSightObject(obj *opssightapi.OpsSight) (*opssightapi.OpsSight, error) { - return util.UpdateOpsSight(h.OpsSightClient, h.Config.CrdNamespace, obj) -} diff --git a/pkg/opssight/opssight_suite_test.go b/pkg/opssight/opssight_suite_test.go deleted file mode 100644 index 4e99dd917..000000000 --- a/pkg/opssight/opssight_suite_test.go +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - log "github.com/sirupsen/logrus" -) - -func TestOpsSight(t *testing.T) { - RegisterFailHandler(Fail) - log.SetLevel(log.DebugLevel) - RunCreaterTests() - RunSpecs(t, "opssight suite") -} diff --git a/pkg/opssight/perceivers.go b/pkg/opssight/perceivers.go deleted file mode 100644 index dd50bb711..000000000 --- a/pkg/opssight/perceivers.go +++ /dev/null @@ -1,406 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -import ( - "fmt" - "strings" - - horizonapi "github.com/blackducksoftware/horizon/pkg/api" - "github.com/blackducksoftware/horizon/pkg/components" - "github.com/blackducksoftware/synopsys-operator/pkg/api" - "github.com/blackducksoftware/synopsys-operator/pkg/util" - "github.com/juju/errors" - routev1 "github.com/openshift/api/route/v1" -) - -// PodPerceiverReplicationController creates a replication controller for the pod perceiver -func (p *SpecConfig) PodPerceiverReplicationController() (*components.ReplicationController, error) { - name := p.names["pod-perceiver"] - image := p.images["pod-perceiver"] - - rc := p.perceiverReplicationController(name, 1) - - pod, err := p.perceiverPod(name, image, util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceiver-service-account"])) - if err != nil { - return nil, errors.Annotate(err, "failed to create pod perceiver pod") - } - rc.AddPod(pod) - - return rc, nil -} - -// ImagePerceiverReplicationController creates a replication controller for the image perceiver -func (p *SpecConfig) ImagePerceiverReplicationController() (*components.ReplicationController, error) { - name := p.names["image-perceiver"] - image := p.images["image-perceiver"] - - rc := p.perceiverReplicationController(name, 1) - - pod, err := p.perceiverPod(name, image, util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceiver-service-account"])) - if err != nil { - return nil, errors.Annotate(err, "failed to create image perceiver pod") - } - rc.AddPod(pod) - - return rc, nil -} - -// ArtifactoryPerceiverReplicationController creates a replication controller for the artifactory perceiver -func (p *SpecConfig) ArtifactoryPerceiverReplicationController() (*components.ReplicationController, error) { - name := p.names["artifactory-perceiver"] - image := p.images["artifactory-perceiver"] - - rc := p.perceiverReplicationController(name, 1) - - pod, err := p.perceiverPod(name, image, "") - if err != nil { - return nil, errors.Annotate(err, "failed to create artifactory perceiver pod") - } - rc.AddPod(pod) - return rc, nil -} - -// QuayPerceiverReplicationController creates a replication controller for the quay perceiver -func (p *SpecConfig) QuayPerceiverReplicationController() (*components.ReplicationController, error) { - name := p.names["quay-perceiver"] - image := p.images["quay-perceiver"] - - rc := p.perceiverReplicationController(name, 1) - - pod, err := p.perceiverPod(name, image, "") - if err != nil { - return nil, errors.Annotate(err, "failed to create quay perceiver pod") - } - rc.AddPod(pod) - return rc, nil -} - -func (p *SpecConfig) perceiverReplicationController(name string, replicas int32) *components.ReplicationController { - rc := components.NewReplicationController(horizonapi.ReplicationControllerConfig{ - Replicas: &replicas, - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, name), - Namespace: p.opssight.Spec.Namespace, - }) - rc.AddSelectors(map[string]string{"component": name, "app": "opssight", "name": p.opssight.Name}) - rc.AddLabels(map[string]string{"component": name, "app": "opssight", "name": p.opssight.Name}) - return rc -} - -func (p *SpecConfig) perceiverPod(name string, image string, account string) (*components.Pod, error) { - pod := components.NewPod(horizonapi.PodConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, name), - ServiceAccount: account, - }) - - pod.AddLabels(map[string]string{"component": name, "app": "opssight", "name": p.opssight.Name}) - container, err := p.perceiverContainer(name, image) - if err != nil { - return nil, errors.Trace(err) - } - pod.AddContainer(container) - - vols, err := p.perceiverVolumes(name) - - if err != nil { - return nil, errors.Annotate(err, "unable to create volumes") - } - - for _, v := range vols { - err = pod.AddVolume(v) - if err != nil { - return nil, errors.Annotate(err, "unable to add volume to pod") - } - } - - if p.opssight.Spec.RegistryConfiguration != nil && len(p.opssight.Spec.RegistryConfiguration.PullSecrets) > 0 { - pod.AddImagePullSecrets(p.opssight.Spec.RegistryConfiguration.PullSecrets) - } - - return pod, nil -} - -func (p *SpecConfig) perceiverContainer(name string, image string) (*components.Container, error) { - cmd := fmt.Sprintf("./%s", name) - if strings.Contains(name, "processor") { - cmd = fmt.Sprintf("./opssight-%s", name) - } - container, err := components.NewContainer(horizonapi.ContainerConfig{ - Name: name, - Image: image, - Command: []string{cmd}, - Args: []string{fmt.Sprintf("/etc/%s/%s.json", name, p.names["configmap"])}, - MinCPU: p.opssight.Spec.DefaultCPU, - MinMem: p.opssight.Spec.DefaultMem, - }) - if err != nil { - return nil, errors.Trace(err) - } - - container.AddPort(horizonapi.PortConfig{ - ContainerPort: int32(3002), - Protocol: horizonapi.ProtocolTCP, - }) - - err = container.AddVolumeMount(horizonapi.VolumeMountConfig{ - Name: name, - MountPath: fmt.Sprintf("/etc/%s", name), - }) - if err != nil { - return nil, errors.Trace(err) - } - - err = container.AddVolumeMount(horizonapi.VolumeMountConfig{ - Name: "logs", - MountPath: "/tmp", - }) - if err != nil { - return nil, errors.Annotatef(err, "unable to add the volume mount to %s container", name) - } - - if strings.Contains(name, "artifactory") || strings.Contains(name, "quay") { - container.AddEnv(horizonapi.EnvConfig{Type: horizonapi.EnvFromSecret, FromName: util.GetResourceName(p.opssight.Name, util.OpsSightName, "blackduck")}) - } - return container, nil -} - -func (p *SpecConfig) perceiverVolumes(name string) ([]*components.Volume, error) { - vols := []*components.Volume{p.configMapVolume(name)} - - vol, err := components.NewEmptyDirVolume(horizonapi.EmptyDirVolumeConfig{ - VolumeName: "logs", - Medium: horizonapi.StorageMediumDefault, - }) - - if err != nil { - return nil, errors.Annotate(err, "failed to create empty dir volume") - } - vols = append(vols, vol) - - return vols, nil -} - -// PerceiverNodePortService creates a nodeport service for perceiver -func (p *SpecConfig) PerceiverNodePortService(perceiverName string) (*components.Service, error) { - name := fmt.Sprintf("%s-exposed", p.names[fmt.Sprintf("%s-perceiver", perceiverName)]) - service := components.NewService(horizonapi.ServiceConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, name), - Namespace: p.opssight.Spec.Namespace, - Type: horizonapi.ServiceTypeNodePort, - }) - - err := service.AddPort(horizonapi.ServicePortConfig{ - Port: int32(3002), - TargetPort: fmt.Sprintf("%d", 3002), - Protocol: horizonapi.ProtocolTCP, - Name: fmt.Sprintf("port-%s", name), - }) - if err != nil { - return nil, errors.Trace(err) - } - - service.AddLabels(map[string]string{"component": p.names[fmt.Sprintf("%s-perceiver", perceiverName)], "app": "opssight", "name": p.opssight.Name}) - service.AddSelectors(map[string]string{"component": p.names[fmt.Sprintf("%s-perceiver", perceiverName)], "app": "opssight", "name": p.opssight.Name}) - - return service, nil -} - -// PerceiverLoadBalancerService creates a loadbalancer service for perceiver -func (p *SpecConfig) PerceiverLoadBalancerService(perceiverName string) (*components.Service, error) { - name := fmt.Sprintf("%s-exposed", p.names[fmt.Sprintf("%s-perceiver", perceiverName)]) - service := components.NewService(horizonapi.ServiceConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, name), - Namespace: p.opssight.Spec.Namespace, - Type: horizonapi.ServiceTypeLoadBalancer, - }) - - err := service.AddPort(horizonapi.ServicePortConfig{ - Port: int32(3002), - TargetPort: fmt.Sprintf("%d", 3002), - Protocol: horizonapi.ProtocolTCP, - Name: fmt.Sprintf("port-%s", name), - }) - if err != nil { - return nil, errors.Trace(err) - - } - - service.AddLabels(map[string]string{"component": p.names[fmt.Sprintf("%s-perceiver", perceiverName)], "app": "opssight", "name": p.opssight.Name}) - service.AddSelectors(map[string]string{"component": p.names[fmt.Sprintf("%s-perceiver", perceiverName)], "app": "opssight", "name": p.opssight.Name}) - - return service, nil -} - -// GetPerceiverOpenShiftRoute creates the OpenShift route component for the perceiver model -func (p *SpecConfig) GetPerceiverOpenShiftRoute(perceiverName string, secure bool) *api.Route { - perceiverName = fmt.Sprintf("%s-perceiver", perceiverName) - name := p.names[perceiverName] - namespace := p.opssight.Spec.Namespace - if strings.ToUpper(p.opssight.Spec.Perceiver.Expose) == util.OPENSHIFT { - route := &api.Route{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, name), - Namespace: namespace, - Kind: "Service", - ServiceName: util.GetResourceName(p.opssight.Name, util.OpsSightName, name), - PortName: fmt.Sprintf("port-%s", name), - Labels: map[string]string{"app": "opssight", "name": p.opssight.Name, "component": fmt.Sprintf("%s-exposed", name)}, - } - if secure { - route.TLSTerminationType = routev1.TLSTerminationPassthrough - } - return route - } - return nil -} - -func (p *SpecConfig) perceiverService(name string) *components.Service { - service := components.NewService(horizonapi.ServiceConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, name), - Namespace: p.opssight.Spec.Namespace, - Type: horizonapi.ServiceTypeServiceIP, - }) - - service.AddPort(horizonapi.ServicePortConfig{ - Port: int32(3002), - TargetPort: fmt.Sprintf("%d", 3002), - Protocol: horizonapi.ProtocolTCP, - Name: fmt.Sprintf("port-%s", name), - }) - - service.AddLabels(map[string]string{"component": name, "app": "opssight", "name": p.opssight.Name}) - service.AddSelectors(map[string]string{"component": name, "app": "opssight", "name": p.opssight.Name}) - - return service -} - -// PodPerceiverService creates a service for the pod perceiver -func (p *SpecConfig) PodPerceiverService() *components.Service { - return p.perceiverService(p.names["pod-perceiver"]) -} - -// ImagePerceiverService creates a service for the image perceiver -func (p *SpecConfig) ImagePerceiverService() *components.Service { - return p.perceiverService(p.names["image-perceiver"]) -} - -// ArtifactoryPerceiverService creates a service for the Artifactory perceiver -func (p *SpecConfig) ArtifactoryPerceiverService() *components.Service { - return p.perceiverService(p.names["artifactory-perceiver"]) -} - -// QuayPerceiverService creates a service for the Quay perceiver -func (p *SpecConfig) QuayPerceiverService() *components.Service { - return p.perceiverService(p.names["quay-perceiver"]) -} - -func (p *SpecConfig) perceiverServiceAccount(name string) *components.ServiceAccount { - serviceAccount := components.NewServiceAccount(horizonapi.ServiceAccountConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, name), - Namespace: p.opssight.Spec.Namespace, - }) - serviceAccount.AddLabels(map[string]string{"component": name, "app": "opssight", "name": p.opssight.Name}) - return serviceAccount -} - -// PodPerceiverServiceAccount creates a service account for the pod perceiver -func (p *SpecConfig) PodPerceiverServiceAccount() *components.ServiceAccount { - return p.perceiverServiceAccount(p.names["perceiver-service-account"]) -} - -// ImagePerceiverServiceAccount creates a service account for the image perceiver -func (p *SpecConfig) ImagePerceiverServiceAccount() *components.ServiceAccount { - return p.perceiverServiceAccount(p.names["perceiver-service-account"]) -} - -// PodPerceiverClusterRole creates a cluster role for the pod perceiver -func (p *SpecConfig) PodPerceiverClusterRole() *components.ClusterRole { - clusterRole := components.NewClusterRole(horizonapi.ClusterRoleConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["pod-perceiver"]), - APIVersion: "rbac.authorization.k8s.io/v1", - }) - clusterRole.AddPolicyRule(horizonapi.PolicyRuleConfig{ - APIGroups: []string{""}, - Resources: []string{"pods"}, - Verbs: []string{"get", "watch", "list", "update"}, - }) - clusterRole.AddLabels(map[string]string{"component": p.names["pod-perceiver"], "app": "opssight", "name": p.opssight.Name}) - - return clusterRole -} - -// ImagePerceiverClusterRole creates a cluster role for the image perceiver -func (p *SpecConfig) ImagePerceiverClusterRole() *components.ClusterRole { - clusterRole := components.NewClusterRole(horizonapi.ClusterRoleConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["image-perceiver"]), - APIVersion: "rbac.authorization.k8s.io/v1", - }) - clusterRole.AddPolicyRule(horizonapi.PolicyRuleConfig{ - APIGroups: []string{"image.openshift.io"}, - Resources: []string{"images"}, - Verbs: []string{"get", "watch", "list", "update"}, - }) - clusterRole.AddLabels(map[string]string{"component": p.names["image-perceiver"], "app": "opssight", "name": p.opssight.Name}) - - return clusterRole -} - -// PodPerceiverClusterRoleBinding creates a cluster role binding for the pod perceiver -func (p *SpecConfig) PodPerceiverClusterRoleBinding(clusterRole *components.ClusterRole) *components.ClusterRoleBinding { - clusterRoleBinding := components.NewClusterRoleBinding(horizonapi.ClusterRoleBindingConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["pod-perceiver"]), - APIVersion: "rbac.authorization.k8s.io/v1", - }) - clusterRoleBinding.AddSubject(horizonapi.SubjectConfig{ - Kind: "ServiceAccount", - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceiver-service-account"]), - Namespace: p.opssight.Spec.Namespace, - }) - clusterRoleBinding.AddRoleRef(horizonapi.RoleRefConfig{ - APIGroup: "", - Kind: "ClusterRole", - Name: clusterRole.GetName(), - }) - clusterRoleBinding.AddLabels(map[string]string{"component": p.names["pod-perceiver"], "app": "opssight", "name": p.opssight.Name}) - - return clusterRoleBinding -} - -// ImagePerceiverClusterRoleBinding creates a cluster role binding for the image perceiver -func (p *SpecConfig) ImagePerceiverClusterRoleBinding(clusterRole *components.ClusterRole) *components.ClusterRoleBinding { - clusterRoleBinding := components.NewClusterRoleBinding(horizonapi.ClusterRoleBindingConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["image-perceiver"]), - APIVersion: "rbac.authorization.k8s.io/v1", - }) - clusterRoleBinding.AddSubject(horizonapi.SubjectConfig{ - Kind: "ServiceAccount", - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceiver-service-account"]), - Namespace: p.opssight.Spec.Namespace, - }) - clusterRoleBinding.AddRoleRef(horizonapi.RoleRefConfig{ - APIGroup: "", - Kind: "ClusterRole", - Name: clusterRole.GetName(), - }) - clusterRoleBinding.AddLabels(map[string]string{"component": p.names["image-perceiver"], "app": "opssight", "name": p.opssight.Name}) - - return clusterRoleBinding -} diff --git a/pkg/opssight/perceptor.go b/pkg/opssight/perceptor.go deleted file mode 100644 index 17a8789e9..000000000 --- a/pkg/opssight/perceptor.go +++ /dev/null @@ -1,234 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -import ( - "encoding/json" - "fmt" - "strings" - - horizonapi "github.com/blackducksoftware/horizon/pkg/api" - "github.com/blackducksoftware/horizon/pkg/components" - "github.com/blackducksoftware/synopsys-operator/pkg/api" - opssightapi "github.com/blackducksoftware/synopsys-operator/pkg/api/opssight/v1" - "github.com/blackducksoftware/synopsys-operator/pkg/util" - "github.com/juju/errors" - routev1 "github.com/openshift/api/route/v1" -) - -// PerceptorReplicationController creates a replication controller for perceptor -func (p *SpecConfig) PerceptorReplicationController() (*components.ReplicationController, error) { - replicas := int32(1) - rc := components.NewReplicationController(horizonapi.ReplicationControllerConfig{ - Replicas: &replicas, - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceptor"]), - Namespace: p.opssight.Spec.Namespace, - }) - pod, err := p.perceptorPod() - if err != nil { - return nil, errors.Trace(err) - } - rc.AddPod(pod) - rc.AddSelectors(map[string]string{"component": p.names["perceptor"], "app": "opssight", "name": p.opssight.Name}) - rc.AddLabels(map[string]string{"component": p.names["perceptor"], "app": "opssight", "name": p.opssight.Name}) - return rc, nil -} - -func (p *SpecConfig) perceptorPod() (*components.Pod, error) { - pod := components.NewPod(horizonapi.PodConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceptor"]), - }) - pod.AddLabels(map[string]string{"component": p.names["perceptor"], "app": "opssight", "name": p.opssight.Name}) - cont, err := p.perceptorContainer() - if err != nil { - return nil, errors.Trace(err) - } - - err = pod.AddContainer(cont) - if err != nil { - return nil, errors.Trace(err) - } - err = pod.AddVolume(p.configMapVolume(p.names["perceptor"])) - if err != nil { - return nil, errors.Trace(err) - } - - if p.opssight.Spec.RegistryConfiguration != nil && len(p.opssight.Spec.RegistryConfiguration.PullSecrets) > 0 { - pod.AddImagePullSecrets(p.opssight.Spec.RegistryConfiguration.PullSecrets) - } - - return pod, nil -} - -func (p *SpecConfig) perceptorContainer() (*components.Container, error) { - name := p.names["perceptor"] - command := name - if name == "core" { - command = fmt.Sprintf("opssight-%s", name) - } - container, err := components.NewContainer(horizonapi.ContainerConfig{ - Name: name, - Image: p.images["perceptor"], - Command: []string{fmt.Sprintf("./%s", command)}, - Args: []string{fmt.Sprintf("/etc/%s/%s.json", name, p.names["configmap"])}, - MinCPU: p.opssight.Spec.DefaultCPU, - MinMem: p.opssight.Spec.DefaultMem, - }) - if err != nil { - return nil, errors.Trace(err) - } - - container.AddPort(horizonapi.PortConfig{ - ContainerPort: int32(3001), - Protocol: horizonapi.ProtocolTCP, - }) - err = container.AddVolumeMount(horizonapi.VolumeMountConfig{ - Name: name, - MountPath: fmt.Sprintf("/etc/%s", name), - }) - if err != nil { - return nil, errors.Trace(err) - } - - container.AddEnv(horizonapi.EnvConfig{Type: horizonapi.EnvFromSecret, FromName: util.GetResourceName(p.opssight.Name, util.OpsSightName, "blackduck")}) - - return container, nil -} - -// PerceptorService creates a service for perceptor -func (p *SpecConfig) PerceptorService() (*components.Service, error) { - service := components.NewService(horizonapi.ServiceConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceptor"]), - Namespace: p.opssight.Spec.Namespace, - Type: horizonapi.ServiceTypeServiceIP, - }) - - err := service.AddPort(horizonapi.ServicePortConfig{ - Port: int32(3001), - TargetPort: fmt.Sprintf("%d", 3001), - Protocol: horizonapi.ProtocolTCP, - Name: fmt.Sprintf("port-%s", p.names["perceptor"]), - }) - if err != nil { - return nil, errors.Trace(err) - } - - service.AddLabels(map[string]string{"component": p.names["perceptor"], "app": "opssight", "name": p.opssight.Name}) - service.AddSelectors(map[string]string{"component": p.names["perceptor"], "app": "opssight", "name": p.opssight.Name}) - - return service, nil -} - -// PerceptorNodePortService creates a nodeport service for perceptor -func (p *SpecConfig) PerceptorNodePortService() (*components.Service, error) { - name := fmt.Sprintf("%s-exposed", p.names["perceptor"]) - service := components.NewService(horizonapi.ServiceConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, name), - Namespace: p.opssight.Spec.Namespace, - Type: horizonapi.ServiceTypeNodePort, - }) - - err := service.AddPort(horizonapi.ServicePortConfig{ - Port: int32(3001), - TargetPort: fmt.Sprintf("%d", 3001), - Protocol: horizonapi.ProtocolTCP, - Name: fmt.Sprintf("port-%s", name), - }) - if err != nil { - return nil, errors.Trace(err) - } - - service.AddLabels(map[string]string{"component": p.names["perceptor"], "app": "opssight", "name": p.opssight.Name}) - service.AddSelectors(map[string]string{"component": p.names["perceptor"], "app": "opssight", "name": p.opssight.Name}) - - return service, nil -} - -// PerceptorLoadBalancerService creates a loadbalancer service for perceptor -func (p *SpecConfig) PerceptorLoadBalancerService() (*components.Service, error) { - name := fmt.Sprintf("%s-exposed", p.names["perceptor"]) - service := components.NewService(horizonapi.ServiceConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, name), - Namespace: p.opssight.Spec.Namespace, - Type: horizonapi.ServiceTypeLoadBalancer, - }) - - err := service.AddPort(horizonapi.ServicePortConfig{ - Port: int32(3001), - TargetPort: fmt.Sprintf("%d", 3001), - Protocol: horizonapi.ProtocolTCP, - Name: fmt.Sprintf("port-%s", name), - }) - if err != nil { - return nil, errors.Trace(err) - } - - service.AddLabels(map[string]string{"component": p.names["perceptor"], "app": "opssight", "name": p.opssight.Name}) - service.AddSelectors(map[string]string{"component": p.names["perceptor"], "app": "opssight", "name": p.opssight.Name}) - - return service, nil -} - -// PerceptorSecret create a secret for perceptor -func (p *SpecConfig) PerceptorSecret() (*components.Secret, error) { - secretConfig := horizonapi.SecretConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, "blackduck"), - Namespace: p.opssight.Spec.Namespace, - Type: horizonapi.SecretTypeOpaque, - } - secret := components.NewSecret(secretConfig) - - // empty data fields that will be overwritten - emptyHosts := make(map[string]*opssightapi.Host) - bytes, err := json.Marshal(emptyHosts) - if err != nil { - return nil, fmt.Errorf("unable to marshal OpsSight's Host struct: %+v", err) - } - secret.AddData(map[string][]byte{p.opssight.Spec.Blackduck.ConnectionsEnvironmentVariableName: bytes}) - - emptySecuredRegistries := make(map[string]*opssightapi.RegistryAuth) - bytes, err = json.Marshal(emptySecuredRegistries) - if err != nil { - return nil, fmt.Errorf("unable to marshal secured registries struct: %+v", err) - } - secret.AddData(map[string][]byte{"securedRegistries.json": bytes}) - - secret.AddLabels(map[string]string{"component": "blackduck", "app": "opssight", "name": p.opssight.Name}) - return secret, nil -} - -// GetPerceptorOpenShiftRoute creates the OpenShift route component for the perceptor model -func (p *SpecConfig) GetPerceptorOpenShiftRoute() *api.Route { - namespace := p.opssight.Spec.Namespace - if strings.ToUpper(p.opssight.Spec.Perceptor.Expose) == util.OPENSHIFT { - return &api.Route{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceptor"]), - Namespace: namespace, - Kind: "Service", - ServiceName: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceptor"]), - PortName: fmt.Sprintf("port-%s", p.names["perceptor"]), - Labels: map[string]string{"app": "opssight", "name": p.opssight.Name, "component": fmt.Sprintf("%s-ui", p.names["perceptor"])}, - TLSTerminationType: routev1.TLSTerminationEdge, - } - } - return nil -} diff --git a/pkg/opssight/plugins.go b/pkg/opssight/plugins.go deleted file mode 100644 index 8d58646dc..000000000 --- a/pkg/opssight/plugins.go +++ /dev/null @@ -1,311 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownershia. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -// This is a controller that deletes the hub based on the delete threshold - -import ( - "fmt" - "strings" - "time" - - blackduckapi "github.com/blackducksoftware/synopsys-operator/pkg/api/blackduck/v1" - opssightapi "github.com/blackducksoftware/synopsys-operator/pkg/api/opssight/v1" - hubclient "github.com/blackducksoftware/synopsys-operator/pkg/blackduck/client/clientset/versioned" - opssightclientset "github.com/blackducksoftware/synopsys-operator/pkg/opssight/client/clientset/versioned" - "github.com/blackducksoftware/synopsys-operator/pkg/protoform" - "github.com/blackducksoftware/synopsys-operator/pkg/util" - "github.com/juju/errors" - log "github.com/sirupsen/logrus" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/cache" -) - -var logger *log.Entry - -func init() { - logger = log.WithField("subsystem", "opssight-plugins") -} - -// This is a controller that updates the secret in perceptor periodically. -// It is assumed that the secret in perceptor will roll over any time this is updated, and -// if not, that there is a problem in the orchestration environment. - -// Updater stores the opssight updater configuration -type Updater struct { - config *protoform.Config - kubeClient *kubernetes.Clientset - hubClient *hubclient.Clientset - opssightClient *opssightclientset.Clientset -} - -// NewUpdater returns the opssight updater configuration -func NewUpdater(config *protoform.Config, kubeClient *kubernetes.Clientset, hubClient *hubclient.Clientset, opssightClient *opssightclientset.Clientset) *Updater { - return &Updater{ - config: config, - kubeClient: kubeClient, - hubClient: hubClient, - opssightClient: opssightClient, - } -} - -// Run watches for Black Duck and OpsSight events and update the internal Black Duck hosts in Perceptor secret and -// then patch the corresponding replication controller -func (p *Updater) Run(ch <-chan struct{}) { - logger.Infof("Starting controller for blackduck<->opssight-core updates... this blocks, so running in a go func.") - - go func() { - for { - select { - case <-ch: - // stop - return - default: - syncFunc := func() { - err := p.updateAllHubs() - if len(err) > 0 { - logger.Errorf("unable to update Black Ducks because %+v", err) - } - } - - // watch for Black Duck events to update an OpsSight internal host only if Black Duck crd is enabled - if strings.Contains(p.config.CrdNames, util.BlackDuckCRDName) { - log.Debugf("watch for Black Duck events to update an OpsSight internal hosts") - syncFunc() - - hubListWatch := &cache.ListWatch{ - ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { - return p.hubClient.SynopsysV1().Blackducks(p.config.CrdNamespace).List(options) - }, - WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { - return p.hubClient.SynopsysV1().Blackducks(p.config.CrdNamespace).Watch(options) - }, - } - _, hubController := cache.NewInformer(hubListWatch, - &blackduckapi.Blackduck{}, - 2*time.Second, - cache.ResourceEventHandlerFuncs{ - // TODO kinda dumb, we just do a complete re-list of all hubs, - // every time an event happens... But thats all we need to do, so its good enough. - DeleteFunc: func(obj interface{}) { - logger.Debugf("updater - blackduck deleted event ! %v ", obj) - syncFunc() - }, - - AddFunc: func(obj interface{}) { - logger.Debugf("updater - blackduck added event! %v ", obj) - running := p.isBlackDuckRunning(obj) - if !running { - syncFunc() - } - }, - }, - ) - - // make sure this is called from a go func -- it blocks! - go hubController.Run(ch) - <-ch - } else { - time.Sleep(5 * time.Second) - } - } - } - }() -} - -// isBlackDuckRunning return whether the Black Duck instance is in running state -func (p *Updater) isBlackDuckRunning(obj interface{}) bool { - blackduck, _ := obj.(*blackduckapi.Blackduck) - if strings.EqualFold(blackduck.Status.State, "Running") { - return true - } - return false -} - -// updateAllHubs will update the Black Duck instances in opssight resources -func (p *Updater) updateAllHubs() []error { - opssights, err := util.ListOpsSights(p.opssightClient, p.config.CrdNamespace, metav1.ListOptions{}) - if err != nil { - return []error{errors.Annotatef(err, "unable to list opssight in namespace %s", p.config.Namespace)} - } - - if len(opssights.Items) == 0 { - return nil - } - - errList := []error{} - for _, opssight := range opssights.Items { - err = p.updateOpsSight(&opssight) - if err != nil { - errList = append(errList, errors.Annotate(err, "unable to update opssight")) - } - } - return errList -} - -// updateOpsSight will update the opssight resource with latest Black Duck instances -func (p *Updater) updateOpsSight(opssight *opssightapi.OpsSight) error { - var err error - if !strings.EqualFold(opssight.Status.State, "stopped") && !strings.EqualFold(opssight.Status.State, "error") { - for j := 0; j < 20; j++ { - if strings.EqualFold(opssight.Status.State, "running") { - break - } - logger.Debugf("waiting for opssight %s to be up.....", opssight.Name) - time.Sleep(10 * time.Second) - - opssight, err = util.GetOpsSight(p.opssightClient, p.config.CrdNamespace, opssight.Name, metav1.GetOptions{}) - if err != nil { - return fmt.Errorf("unable to get opssight %s due to %+v", opssight.Name, err) - } - } - err = p.update(opssight) - } - return err -} - -// update will list all Black Ducks in the cluster, and send them to opssight as scan targets. -func (p *Updater) update(opssight *opssightapi.OpsSight) error { - hubType := opssight.Spec.Blackduck.BlackduckSpec.Type - - blackduckPassword, err := util.Base64Decode(opssight.Spec.Blackduck.BlackduckPassword) - if err != nil { - return errors.Annotate(err, "unable to decode blackduckPassword") - } - - allHubs := p.getAllHubs(hubType, blackduckPassword) - - err = p.updateOpsSightCRD(opssight, allHubs) - if err != nil { - return errors.Annotate(err, "unable to update opssight CRD") - } - return nil -} - -// getAllHubs get only the internal Black Duck instances from the cluster -func (p *Updater) getAllHubs(hubType string, blackduckPassword string) []*opssightapi.Host { - hosts := []*opssightapi.Host{} - hubsList, err := util.ListBlackduck(p.hubClient, p.config.CrdNamespace, metav1.ListOptions{}) - if err != nil { - log.Errorf("unable to list blackducks due to %+v", err) - } - for _, hub := range hubsList.Items { - if strings.EqualFold(hub.Spec.Type, hubType) { - var concurrentScanLimit int - switch strings.ToUpper(hub.Spec.Size) { - case "MEDIUM": - concurrentScanLimit = 3 - case "LARGE": - concurrentScanLimit = 4 - case "X-LARGE": - concurrentScanLimit = 6 - default: - concurrentScanLimit = 2 - } - host := &opssightapi.Host{ - Domain: fmt.Sprintf("%s.%s.svc", util.GetResourceName(hub.Name, util.BlackDuckName, "webserver"), hub.Spec.Namespace), - ConcurrentScanLimit: concurrentScanLimit, - Scheme: "https", - User: "sysadmin", - Port: 443, - Password: blackduckPassword, - } - hosts = append(hosts, host) - } - } - log.Debugf("total no of Black Duck's for type %s is %d", hubType, len(hosts)) - return hosts -} - -// updateOpsSightCRD will update the opssight CRD -func (p *Updater) updateOpsSightCRD(opsSight *opssightapi.OpsSight, hubs []*opssightapi.Host) error { - opssightName := opsSight.Name - opsSightNamespace := opsSight.Spec.Namespace - logger.WithField("opssight", opssightName).Info("update opssight: looking for opssight") - opssight, err := util.GetOpsSight(p.opssightClient, p.config.CrdNamespace, opssightName, metav1.GetOptions{}) - if err != nil { - return errors.Annotatef(err, "unable to get opssight %s in %s namespace", opssightName, opsSightNamespace) - } - - opssight.Status.InternalHosts = p.appendBlackDuckHosts(opssight.Status.InternalHosts, hubs) - - _, err = util.UpdateOpsSight(p.opssightClient, p.config.CrdNamespace, opsSight) - if err != nil { - return errors.Annotatef(err, "unable to update opssight %s in %s", opssightName, opsSightNamespace) - } - return nil -} - -// appendBlackDuckHosts will append the old and new internal Black Duck hosts -func (p *Updater) appendBlackDuckHosts(oldBlackDucks []*opssightapi.Host, newBlackDucks []*opssightapi.Host) []*opssightapi.Host { - existingBlackDucks := make(map[string]*opssightapi.Host) - for _, oldBlackDuck := range oldBlackDucks { - existingBlackDucks[oldBlackDuck.Domain] = oldBlackDuck - } - - finalBlackDucks := []*opssightapi.Host{} - for _, newBlackDuck := range newBlackDucks { - if existingBlackduck, ok := existingBlackDucks[newBlackDuck.Domain]; ok { - // add the existing internal Black Duck from the final Black Duck list - finalBlackDucks = append(finalBlackDucks, existingBlackduck) - } else { - // add the new internal Black Duck to the final Black Duck list - finalBlackDucks = append(finalBlackDucks, newBlackDuck) - } - } - - return finalBlackDucks -} - -// appendBlackDuckSecrets will append the secrets of external and internal Black Duck -func (p *Updater) appendBlackDuckSecrets(existingExternalBlackDucks map[string]*opssightapi.Host, oldInternalBlackDucks []*opssightapi.Host, newInternalBlackDucks []*opssightapi.Host) map[string]*opssightapi.Host { - existingInternalBlackducks := make(map[string]*opssightapi.Host) - for _, oldInternalBlackDuck := range oldInternalBlackDucks { - existingInternalBlackducks[oldInternalBlackDuck.Domain] = oldInternalBlackDuck - } - - currentInternalBlackducks := make(map[string]*opssightapi.Host) - for _, newInternalBlackDuck := range newInternalBlackDucks { - currentInternalBlackducks[newInternalBlackDuck.Domain] = newInternalBlackDuck - } - - for _, currentInternalBlackduck := range currentInternalBlackducks { - // check if external host contains the internal host - if _, ok := existingExternalBlackDucks[currentInternalBlackduck.Domain]; ok { - // if internal host contains an external host, then check whether it is already part of status, - // if yes replace it with existing internal host else with new internal host - if existingInternalBlackduck, ok1 := existingInternalBlackducks[currentInternalBlackduck.Domain]; ok1 { - existingExternalBlackDucks[currentInternalBlackduck.Domain] = existingInternalBlackduck - } else { - existingExternalBlackDucks[currentInternalBlackduck.Domain] = currentInternalBlackduck - } - } else { - // add new internal Black Duck - existingExternalBlackDucks[currentInternalBlackduck.Domain] = currentInternalBlackduck - } - } - - return existingExternalBlackDucks -} diff --git a/pkg/opssight/prometheus.go b/pkg/opssight/prometheus.go deleted file mode 100644 index 190d8af83..000000000 --- a/pkg/opssight/prometheus.go +++ /dev/null @@ -1,271 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -import ( - "encoding/json" - "fmt" - "strings" - - horizonapi "github.com/blackducksoftware/horizon/pkg/api" - "github.com/blackducksoftware/horizon/pkg/components" - "github.com/blackducksoftware/synopsys-operator/pkg/api" - "github.com/blackducksoftware/synopsys-operator/pkg/util" - "github.com/juju/errors" - routev1 "github.com/openshift/api/route/v1" -) - -// PerceptorMetricsDeployment creates a deployment for perceptor metrics -func (p *SpecConfig) PerceptorMetricsDeployment() (*components.Deployment, error) { - replicas := int32(1) - deployment := components.NewDeployment(horizonapi.DeploymentConfig{ - Replicas: &replicas, - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, "prometheus"), - Namespace: p.opssight.Spec.Namespace, - }) - deployment.AddLabels(map[string]string{"component": "prometheus", "app": "opssight", "name": p.opssight.Name}) - deployment.AddMatchLabelsSelectors(map[string]string{"component": "prometheus", "app": "opssight", "name": p.opssight.Name}) - - pod, err := p.perceptorMetricsPod() - if err != nil { - return nil, errors.Annotate(err, "failed to create metrics pod") - } - deployment.AddPod(pod) - - return deployment, nil -} - -func (p *SpecConfig) perceptorMetricsPod() (*components.Pod, error) { - pod := components.NewPod(horizonapi.PodConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, "prometheus"), - }) - pod.AddLabels(map[string]string{"component": "prometheus", "app": "opssight", "name": p.opssight.Name}) - container, err := p.perceptorMetricsContainer() - if err != nil { - return nil, errors.Trace(err) - } - pod.AddContainer(container) - - vols, err := p.perceptorMetricsVolumes() - if err != nil { - return nil, errors.Annotate(err, "error creating metrics volumes") - } - for _, v := range vols { - pod.AddVolume(v) - } - - if p.opssight.Spec.RegistryConfiguration != nil && len(p.opssight.Spec.RegistryConfiguration.PullSecrets) > 0 { - pod.AddImagePullSecrets(p.opssight.Spec.RegistryConfiguration.PullSecrets) - } - - return pod, nil -} - -func (p *SpecConfig) perceptorMetricsContainer() (*components.Container, error) { - container, err := components.NewContainer(horizonapi.ContainerConfig{ - Name: p.names["prometheus"], - Image: p.images["prometheus"], - Args: []string{"--log.level=debug", "--config.file=/etc/prometheus/prometheus.yml", "--storage.tsdb.path=/tmp/data/", "--storage.tsdb.retention=120d", "--web.listen-address=:3006"}, - }) - if err != nil { - return nil, errors.Trace(err) - } - - container.AddPort(horizonapi.PortConfig{ - ContainerPort: int32(3006), - Protocol: horizonapi.ProtocolTCP, - Name: "web", - }) - - err = container.AddVolumeMount(horizonapi.VolumeMountConfig{ - Name: "data", - MountPath: "/data", - }) - if err != nil { - return nil, errors.Trace(err) - } - err = container.AddVolumeMount(horizonapi.VolumeMountConfig{ - Name: "prometheus", - MountPath: "/etc/prometheus", - }) - if err != nil { - return nil, errors.Trace(err) - } - - return container, nil -} - -func (p *SpecConfig) perceptorMetricsVolumes() ([]*components.Volume, error) { - vols := []*components.Volume{} - vols = append(vols, components.NewConfigMapVolume(horizonapi.ConfigMapOrSecretVolumeConfig{ - VolumeName: "prometheus", - MapOrSecretName: util.GetResourceName(p.opssight.Name, util.OpsSightName, "prometheus"), - DefaultMode: util.IntToInt32(420), - })) - - vol, err := components.NewEmptyDirVolume(horizonapi.EmptyDirVolumeConfig{ - VolumeName: "data", - Medium: horizonapi.StorageMediumDefault, - }) - if err != nil { - return nil, errors.Annotate(err, "failed to create empty dir volume") - } - vols = append(vols, vol) - - return vols, nil -} - -// PerceptorMetricsService creates a service for perceptor metrics -func (p *SpecConfig) PerceptorMetricsService() (*components.Service, error) { - service := components.NewService(horizonapi.ServiceConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, "prometheus"), - Namespace: p.opssight.Spec.Namespace, - Type: horizonapi.ServiceTypeServiceIP, - }) - - err := service.AddPort(horizonapi.ServicePortConfig{ - Port: 3006, - TargetPort: "3006", - Protocol: horizonapi.ProtocolTCP, - Name: fmt.Sprintf("port-%s", "prometheus"), - }) - - service.AddAnnotations(map[string]string{"prometheus.io/scrape": "true"}) - service.AddLabels(map[string]string{"component": "prometheus", "app": "opssight", "name": p.opssight.Name}) - service.AddSelectors(map[string]string{"component": "prometheus", "app": "opssight", "name": p.opssight.Name}) - - return service, err -} - -// PerceptorMetricsNodePortService creates a nodeport service for perceptor metrics -func (p *SpecConfig) PerceptorMetricsNodePortService() (*components.Service, error) { - service := components.NewService(horizonapi.ServiceConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, "prometheus-exposed"), - Namespace: p.opssight.Spec.Namespace, - Type: horizonapi.ServiceTypeNodePort, - }) - - err := service.AddPort(horizonapi.ServicePortConfig{ - Port: 3006, - TargetPort: "3006", - Protocol: horizonapi.ProtocolTCP, - Name: fmt.Sprintf("port-%s", "prometheus-exposed"), - }) - - service.AddAnnotations(map[string]string{"prometheus.io/scrape": "true"}) - service.AddLabels(map[string]string{"component": "prometheus", "app": "opssight", "name": p.opssight.Name}) - service.AddSelectors(map[string]string{"component": "prometheus", "app": "opssight", "name": p.opssight.Name}) - - return service, err -} - -// PerceptorMetricsLoadBalancerService creates a loadbalancer service for perceptor metrics -func (p *SpecConfig) PerceptorMetricsLoadBalancerService() (*components.Service, error) { - service := components.NewService(horizonapi.ServiceConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, "prometheus-exposed"), - Namespace: p.opssight.Spec.Namespace, - Type: horizonapi.ServiceTypeLoadBalancer, - }) - - err := service.AddPort(horizonapi.ServicePortConfig{ - Port: 3006, - TargetPort: "3006", - Protocol: horizonapi.ProtocolTCP, - Name: fmt.Sprintf("port-%s", "prometheus-exposed"), - }) - - service.AddAnnotations(map[string]string{"prometheus.io/scrape": "true"}) - service.AddLabels(map[string]string{"component": "prometheus", "app": "opssight", "name": p.opssight.Name}) - service.AddSelectors(map[string]string{"component": "prometheus", "app": "opssight", "name": p.opssight.Name}) - - return service, err -} - -// PerceptorMetricsConfigMap creates a config map for perceptor metrics -func (p *SpecConfig) PerceptorMetricsConfigMap() (*components.ConfigMap, error) { - configMap := components.NewConfigMap(horizonapi.ConfigMapConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, "prometheus"), - Namespace: p.opssight.Spec.Namespace, - }) - - targets := []string{ - fmt.Sprintf("%s:%d", util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceptor"]), 3001), - fmt.Sprintf("%s:%d", util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["scanner"]), 3003), - fmt.Sprintf("%s:%d", util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceptor-imagefacade"]), 3004), - } - if p.opssight.Spec.Perceiver.EnableImagePerceiver { - targets = append(targets, fmt.Sprintf("%s:%d", util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["image-perceiver"]), 3002)) - } - if p.opssight.Spec.Perceiver.EnableArtifactoryPerceiver { - targets = append(targets, fmt.Sprintf("%s:%d", util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["artifactory-perceiver"]), 3007)) - } - if p.opssight.Spec.Perceiver.EnableQuayPerceiver { - targets = append(targets, fmt.Sprintf("%s:%d", util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["quay-perceiver"]), 3008)) - } - if p.opssight.Spec.Perceiver.EnablePodPerceiver { - targets = append(targets, fmt.Sprintf("%s:%d", util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["pod-perceiver"]), 3002)) - } - if p.opssight.Spec.EnableSkyfire { - targets = append(targets, fmt.Sprintf("%s:%d", util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["skyfire"]), 3005)) - } - data := map[string]interface{}{ - "global": map[string]interface{}{ - "scrape_interval": "5s", - }, - "scrape_configs": []interface{}{ - map[string]interface{}{ - "job_name": "perceptor-scrape", - "scrape_interval": "5s", - "static_configs": []interface{}{ - map[string]interface{}{ - "targets": targets, - }, - }, - }, - }, - } - bytes, err := json.Marshal(data) - if err != nil { - return nil, errors.Trace(err) - } - configMap.AddLabels(map[string]string{"app": "opssight", "name": p.opssight.Name, "component": "prometheus"}) - configMap.AddData(map[string]string{"prometheus.yml": string(bytes)}) - - return configMap, nil -} - -// GetPrometheusOpenShiftRoute creates the OpenShift route component for the prometheus metrics -func (p *SpecConfig) GetPrometheusOpenShiftRoute() *api.Route { - namespace := p.opssight.Spec.Namespace - if strings.ToUpper(p.opssight.Spec.Prometheus.Expose) == util.OPENSHIFT { - return &api.Route{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, fmt.Sprintf("%s-metrics", p.names["prometheus"])), - Namespace: namespace, - Kind: "Service", - ServiceName: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["prometheus"]), - PortName: fmt.Sprintf("port-%s", p.names["prometheus"]), - Labels: map[string]string{"app": "opssight", "name": p.opssight.Name, "component": "prometheus-metrics"}, - TLSTerminationType: routev1.TLSTerminationEdge, - } - } - return nil -} diff --git a/pkg/opssight/scanner.go b/pkg/opssight/scanner.go deleted file mode 100644 index 19c36b17e..000000000 --- a/pkg/opssight/scanner.go +++ /dev/null @@ -1,308 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -import ( - "fmt" - "strings" - - horizonapi "github.com/blackducksoftware/horizon/pkg/api" - "github.com/blackducksoftware/horizon/pkg/components" - "github.com/blackducksoftware/synopsys-operator/pkg/util" - "github.com/juju/errors" -) - -// ScannerReplicationController creates a replication controller for the perceptor scanner -func (p *SpecConfig) ScannerReplicationController() (*components.ReplicationController, error) { - replicas := int32(p.opssight.Spec.ScannerPod.ReplicaCount) - rc := components.NewReplicationController(horizonapi.ReplicationControllerConfig{ - Replicas: &replicas, - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["scanner"]), - Namespace: p.opssight.Spec.Namespace, - }) - - rc.AddSelectors(map[string]string{"component": p.names["scanner"], "app": "opssight", "name": p.opssight.Name}) - rc.AddLabels(map[string]string{"component": p.names["scanner"], "app": "opssight", "name": p.opssight.Name}) - pod, err := p.scannerPod() - if err != nil { - return nil, errors.Annotate(err, "failed to create scanner pod") - } - rc.AddPod(pod) - - return rc, nil -} - -func (p *SpecConfig) scannerPod() (*components.Pod, error) { - pod := components.NewPod(horizonapi.PodConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["scanner"]), - ServiceAccount: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceptor-imagefacade"]), - }) - pod.AddLabels(map[string]string{"component": p.names["scanner"], "app": "opssight", "name": p.opssight.Name}) - - cont, err := p.scannerContainer() - if err != nil { - return nil, errors.Trace(err) - } - pod.AddContainer(cont) - - facadecont, err := p.imageFacadeContainer() - if err != nil { - return nil, errors.Trace(err) - } - pod.AddContainer(facadecont) - - vols, err := p.scannerVolumes() - if err != nil { - return nil, errors.Annotate(err, "error creating scanner volumes") - } - - newVols, err := p.imageFacadeVolumes() - if err != nil { - return nil, errors.Annotate(err, "error creating image facade volumes") - } - for _, v := range append(vols, newVols...) { - pod.AddVolume(v) - } - - if p.opssight.Spec.RegistryConfiguration != nil && len(p.opssight.Spec.RegistryConfiguration.PullSecrets) > 0 { - pod.AddImagePullSecrets(p.opssight.Spec.RegistryConfiguration.PullSecrets) - } - - return pod, nil -} - -func (p *SpecConfig) scannerContainer() (*components.Container, error) { - priv := false - name := p.names["scanner"] - command := name - if name == "scanner" { - command = fmt.Sprintf("opssight-%s", name) - } - container, err := components.NewContainer(horizonapi.ContainerConfig{ - Name: name, - Image: p.images["scanner"], - Command: []string{fmt.Sprintf("./%s", command)}, - Args: []string{fmt.Sprintf("/etc/%s/%s.json", name, p.names["configmap"])}, - MinCPU: p.opssight.Spec.ScannerCPU, - MinMem: p.opssight.Spec.ScannerMem, - Privileged: &priv, - }) - if err != nil { - return nil, errors.Trace(err) - } - - container.AddPort(horizonapi.PortConfig{ - ContainerPort: int32(3003), - Protocol: horizonapi.ProtocolTCP, - }) - - err = container.AddVolumeMount(horizonapi.VolumeMountConfig{ - Name: name, - MountPath: fmt.Sprintf("/etc/%s", name), - }) - if err != nil { - return nil, errors.Trace(err) - } - - err = container.AddVolumeMount(horizonapi.VolumeMountConfig{ - Name: "var-images", - MountPath: "/var/images", - }) - if err != nil { - return nil, errors.Trace(err) - } - - container.AddEnv(horizonapi.EnvConfig{Type: horizonapi.EnvFromSecret, FromName: util.GetResourceName(p.opssight.Name, util.OpsSightName, "blackduck")}) - - return container, nil -} - -func (p *SpecConfig) imageFacadeContainer() (*components.Container, error) { - priv := false - if !strings.EqualFold(p.opssight.Spec.ScannerPod.ImageFacade.ImagePullerType, "skopeo") { - priv = true - } - - name := p.names["perceptor-imagefacade"] - command := name - if name == "image-getter" { - command = fmt.Sprintf("opssight-%s", name) - } - container, err := components.NewContainer(horizonapi.ContainerConfig{ - Name: name, - Image: p.images["perceptor-imagefacade"], - Command: []string{fmt.Sprintf("./%s", command)}, - Args: []string{fmt.Sprintf("/etc/%s/%s.json", name, p.names["configmap"])}, - MinCPU: p.opssight.Spec.ScannerCPU, - MinMem: p.opssight.Spec.ScannerMem, - Privileged: &priv, - }) - if err != nil { - return nil, errors.Trace(err) - } - - container.AddPort(horizonapi.PortConfig{ - ContainerPort: int32(3004), - Protocol: horizonapi.ProtocolTCP, - }) - - err = container.AddVolumeMount(horizonapi.VolumeMountConfig{ - Name: name, - MountPath: fmt.Sprintf("/etc/%s", name), - }) - if err != nil { - return nil, errors.Trace(err) - } - err = container.AddVolumeMount(horizonapi.VolumeMountConfig{ - Name: "var-images", - MountPath: "/var/images", - }) - if err != nil { - return nil, errors.Trace(err) - } - - if !strings.EqualFold(p.opssight.Spec.ScannerPod.ImageFacade.ImagePullerType, "skopeo") { - err = container.AddVolumeMount(horizonapi.VolumeMountConfig{ - Name: "dir-docker-socket", - MountPath: "/var/run/docker.sock", - }) - if err != nil { - return nil, errors.Trace(err) - } - } - - container.AddEnv(horizonapi.EnvConfig{Type: horizonapi.EnvFromSecret, FromName: util.GetResourceName(p.opssight.Name, util.OpsSightName, "blackduck")}) - - return container, nil -} - -func (p *SpecConfig) scannerVolumes() ([]*components.Volume, error) { - vols := []*components.Volume{p.configMapVolume(p.names["scanner"])} - - vol, err := components.NewEmptyDirVolume(horizonapi.EmptyDirVolumeConfig{ - VolumeName: "var-images", - Medium: horizonapi.StorageMediumDefault, - }) - - if err != nil { - return nil, errors.Annotate(err, "failed to create empty dir volume") - } - vols = append(vols, vol) - - return vols, nil -} - -func (p *SpecConfig) imageFacadeVolumes() ([]*components.Volume, error) { - vols := []*components.Volume{p.configMapVolume(p.names["perceptor-imagefacade"])} - - vol, err := components.NewEmptyDirVolume(horizonapi.EmptyDirVolumeConfig{ - VolumeName: "var-images", - Medium: horizonapi.StorageMediumDefault, - }) - - if err != nil { - return nil, errors.Annotate(err, "failed to create empty dir volume") - } - vols = append(vols, vol) - - if !strings.EqualFold(p.opssight.Spec.ScannerPod.ImageFacade.ImagePullerType, "skopeo") { - vols = append(vols, components.NewHostPathVolume(horizonapi.HostPathVolumeConfig{ - VolumeName: "dir-docker-socket", - Path: "/var/run/docker.sock", - })) - } - - return vols, nil -} - -// ScannerService creates a service for perceptor scanner -func (p *SpecConfig) ScannerService() *components.Service { - service := components.NewService(horizonapi.ServiceConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["scanner"]), - Namespace: p.opssight.Spec.Namespace, - Type: horizonapi.ServiceTypeServiceIP, - }) - service.AddLabels(map[string]string{"component": p.names["scanner"], "app": "opssight", "name": p.opssight.Name}) - service.AddSelectors(map[string]string{"component": p.names["scanner"], "app": "opssight", "name": p.opssight.Name}) - - service.AddPort(horizonapi.ServicePortConfig{ - Port: int32(3003), - TargetPort: fmt.Sprintf("%d", 3003), - Protocol: horizonapi.ProtocolTCP, - Name: fmt.Sprintf("port-%s", p.names["scanner"]), - }) - - return service -} - -// ImageFacadeService creates a service for perceptor image-facade -func (p *SpecConfig) ImageFacadeService() *components.Service { - service := components.NewService(horizonapi.ServiceConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceptor-imagefacade"]), - Namespace: p.opssight.Spec.Namespace, - Type: horizonapi.ServiceTypeServiceIP, - }) - // TODO verify that this hits the *perceptor-scanner pod* !!! - service.AddLabels(map[string]string{"component": p.names["scanner"], "app": "opssight", "name": p.opssight.Name}) - service.AddSelectors(map[string]string{"component": p.names["scanner"], "app": "opssight", "name": p.opssight.Name}) - - service.AddPort(horizonapi.ServicePortConfig{ - Port: int32(3004), - TargetPort: fmt.Sprintf("%d", 3004), - Protocol: horizonapi.ProtocolTCP, - Name: fmt.Sprintf("port-%s", p.names["perceptor-imagefacade"]), - }) - - return service -} - -// ScannerServiceAccount creates a service account for the perceptor scanner -func (p *SpecConfig) ScannerServiceAccount() *components.ServiceAccount { - serviceAccount := components.NewServiceAccount(horizonapi.ServiceAccountConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceptor-imagefacade"]), - Namespace: p.opssight.Spec.Namespace, - }) - serviceAccount.AddLabels(map[string]string{"component": p.names["perceptor-imagefacade"], "app": "opssight", "name": p.opssight.Name}) - return serviceAccount -} - -// ScannerClusterRoleBinding creates a cluster role binding for the perceptor scanner -func (p *SpecConfig) ScannerClusterRoleBinding() (*components.ClusterRoleBinding, error) { - scannerCRB := components.NewClusterRoleBinding(horizonapi.ClusterRoleBindingConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["scanner"]), - APIVersion: "rbac.authorization.k8s.io/v1", - }) - - scannerCRB.AddSubject(horizonapi.SubjectConfig{ - Kind: "ServiceAccount", - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["perceptor-imagefacade"]), - Namespace: p.opssight.Spec.Namespace, - }) - scannerCRB.AddRoleRef(horizonapi.RoleRefConfig{ - APIGroup: "", - Kind: "ClusterRole", - Name: "system:image-puller", - }) - scannerCRB.AddLabels(map[string]string{"component": p.names["scanner"], "app": "opssight", "name": p.opssight.Name}) - - return scannerCRB, nil -} diff --git a/pkg/opssight/skyfire.go b/pkg/opssight/skyfire.go deleted file mode 100644 index a492241a8..000000000 --- a/pkg/opssight/skyfire.go +++ /dev/null @@ -1,218 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -import ( - "fmt" - - horizonapi "github.com/blackducksoftware/horizon/pkg/api" - "github.com/blackducksoftware/horizon/pkg/components" - "github.com/blackducksoftware/synopsys-operator/pkg/util" - "github.com/juju/errors" -) - -// PerceptorSkyfireReplicationController creates a replication controller for perceptor skyfire -func (p *SpecConfig) PerceptorSkyfireReplicationController() (*components.ReplicationController, error) { - replicas := int32(1) - rc := components.NewReplicationController(horizonapi.ReplicationControllerConfig{ - Replicas: &replicas, - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["skyfire"]), - Namespace: p.opssight.Spec.Namespace, - }) - rc.AddSelectors(map[string]string{"component": p.names["skyfire"], "app": "opssight", "name": p.opssight.Name}) - rc.AddLabels(map[string]string{"component": p.names["skyfire"], "app": "opssight", "name": p.opssight.Name}) - pod, err := p.perceptorSkyfirePod() - if err != nil { - return nil, errors.Annotate(err, "failed to create skyfire volumes") - } - rc.AddPod(pod) - - return rc, nil -} - -func (p *SpecConfig) perceptorSkyfirePod() (*components.Pod, error) { - pod := components.NewPod(horizonapi.PodConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["skyfire"]), - ServiceAccount: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["skyfire"]), - }) - pod.AddLabels(map[string]string{"component": p.names["skyfire"], "app": "opssight", "name": p.opssight.Name}) - - cont, err := p.perceptorSkyfireContainer() - if err != nil { - return nil, err - } - err = pod.AddContainer(cont) - if err != nil { - return nil, errors.Annotate(err, "unable to add skyfire container") - } - - vols, err := p.perceptorSkyfireVolumes() - if err != nil { - return nil, errors.Annotate(err, "error creating skyfire volumes") - } - for _, v := range vols { - err = pod.AddVolume(v) - if err != nil { - return nil, errors.Annotate(err, "error add pod volume") - } - } - - if p.opssight.Spec.RegistryConfiguration != nil && len(p.opssight.Spec.RegistryConfiguration.PullSecrets) > 0 { - pod.AddImagePullSecrets(p.opssight.Spec.RegistryConfiguration.PullSecrets) - } - - return pod, nil -} - -func (p *SpecConfig) pyfireContainer() (*components.Container, error) { - return components.NewContainer(horizonapi.ContainerConfig{ - Name: "skyfire", - Image: p.images["skyfire"], - Command: []string{"python3"}, - Args: []string{ - "src/main.py", - fmt.Sprintf("/etc/skyfire/%s.json", p.names["configmap"]), - }, - MinCPU: p.opssight.Spec.DefaultCPU, - MinMem: p.opssight.Spec.DefaultMem, - }) -} - -func (p *SpecConfig) perceptorSkyfireContainer() (*components.Container, error) { - container, err := p.pyfireContainer() - if err != nil { - return nil, errors.Trace(err) - } - - container.AddPort(horizonapi.PortConfig{ - ContainerPort: int32(3005), - Protocol: horizonapi.ProtocolTCP, - }) - - err = container.AddVolumeMount(horizonapi.VolumeMountConfig{ - Name: "skyfire", - MountPath: "/etc/skyfire", - }) - if err != nil { - return nil, err - } - err = container.AddVolumeMount(horizonapi.VolumeMountConfig{ - Name: "logs", - MountPath: "/tmp", - }) - if err != nil { - return nil, err - } - - container.AddEnv(horizonapi.EnvConfig{Type: horizonapi.EnvFromSecret, FromName: util.GetResourceName(p.opssight.Name, util.OpsSightName, "blackduck")}) - - return container, nil -} - -func (p *SpecConfig) perceptorSkyfireVolumes() ([]*components.Volume, error) { - vols := []*components.Volume{p.configMapVolume("skyfire")} - - vol, err := components.NewEmptyDirVolume(horizonapi.EmptyDirVolumeConfig{ - VolumeName: "logs", - Medium: horizonapi.StorageMediumDefault, - }) - if err != nil { - return nil, errors.Annotate(err, "failed to create empty dir volume") - } - vols = append(vols, vol) - - return vols, nil -} - -// PerceptorSkyfireService creates a service for perceptor skyfire -func (p *SpecConfig) PerceptorSkyfireService() *components.Service { - service := components.NewService(horizonapi.ServiceConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["skyfire"]), - Namespace: p.opssight.Spec.Namespace, - Type: horizonapi.ServiceTypeServiceIP, - }) - - service.AddPort(horizonapi.ServicePortConfig{ - Port: int32(3005), - TargetPort: fmt.Sprintf("%d", 3005), - Protocol: horizonapi.ProtocolTCP, - Name: "main-skyfire", - }) - service.AddPort(horizonapi.ServicePortConfig{ - Port: int32(3006), - TargetPort: fmt.Sprintf("%d", 3006), - Protocol: horizonapi.ProtocolTCP, - Name: "skyfire-prometheus", - }) - - service.AddLabels(map[string]string{"component": p.names["skyfire"], "app": "opssight", "name": p.opssight.Name}) - service.AddSelectors(map[string]string{"component": p.names["skyfire"], "app": "opssight", "name": p.opssight.Name}) - - return service -} - -// PerceptorSkyfireServiceAccount creates a service account for perceptor skyfire -func (p *SpecConfig) PerceptorSkyfireServiceAccount() *components.ServiceAccount { - serviceAccount := components.NewServiceAccount(horizonapi.ServiceAccountConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, "skyfire"), - Namespace: p.opssight.Spec.Namespace, - }) - serviceAccount.AddLabels(map[string]string{"component": "skyfire", "app": "opssight", "name": p.opssight.Name}) - return serviceAccount -} - -// PerceptorSkyfireClusterRole creates a cluster role for perceptor skyfire -func (p *SpecConfig) PerceptorSkyfireClusterRole() *components.ClusterRole { - clusterRole := components.NewClusterRole(horizonapi.ClusterRoleConfig{ - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, "skyfire"), - APIVersion: "rbac.authorization.k8s.io/v1", - }) - clusterRole.AddPolicyRule(horizonapi.PolicyRuleConfig{ - APIGroups: []string{"*"}, - Resources: []string{"pods", "nodes", "namespaces"}, - Verbs: []string{"get", "watch", "list", "create", "delete"}, - }) - clusterRole.AddLabels(map[string]string{"component": "skyfire", "app": "opssight", "name": p.opssight.Name}) - - return clusterRole -} - -// PerceptorSkyfireClusterRoleBinding creates a cluster role binding for perceptor skyfire -func (p *SpecConfig) PerceptorSkyfireClusterRoleBinding(clusterRole *components.ClusterRole) *components.ClusterRoleBinding { - clusterRoleBinding := components.NewClusterRoleBinding(horizonapi.ClusterRoleBindingConfig{ - Name: "skyfire", - APIVersion: "rbac.authorization.k8s.io/v1", - }) - clusterRoleBinding.AddSubject(horizonapi.SubjectConfig{ - Kind: "ServiceAccount", - Name: util.GetResourceName(p.opssight.Name, util.OpsSightName, "skyfire"), - Namespace: p.opssight.Spec.Namespace, - }) - clusterRoleBinding.AddRoleRef(horizonapi.RoleRefConfig{ - APIGroup: "", - Kind: "ClusterRole", - Name: clusterRole.GetName(), - }) - clusterRoleBinding.AddLabels(map[string]string{"component": "skyfire", "app": "opssight", "name": p.opssight.Name}) - - return clusterRoleBinding -} diff --git a/pkg/opssight/specconfig.go b/pkg/opssight/specconfig.go deleted file mode 100644 index 6728d88d0..000000000 --- a/pkg/opssight/specconfig.go +++ /dev/null @@ -1,477 +0,0 @@ -/* -Copyright (C) 2018 Synopsys, Inc. - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownershia. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -package opssight - -import ( - "encoding/json" - "fmt" - "strings" - - horizonapi "github.com/blackducksoftware/horizon/pkg/api" - "github.com/blackducksoftware/horizon/pkg/components" - "github.com/blackducksoftware/synopsys-operator/pkg/api" - opssightapi "github.com/blackducksoftware/synopsys-operator/pkg/api/opssight/v1" - appsutil "github.com/blackducksoftware/synopsys-operator/pkg/apps/util" - hubclientset "github.com/blackducksoftware/synopsys-operator/pkg/blackduck/client/clientset/versioned" - opssightclientset "github.com/blackducksoftware/synopsys-operator/pkg/opssight/client/clientset/versioned" - "github.com/blackducksoftware/synopsys-operator/pkg/protoform" - "github.com/blackducksoftware/synopsys-operator/pkg/util" - "github.com/juju/errors" - "k8s.io/client-go/kubernetes" -) - -// SpecConfig will contain the specification of OpsSight -type SpecConfig struct { - config *protoform.Config - kubeClient *kubernetes.Clientset - opssightClient *opssightclientset.Clientset - hubClient *hubclientset.Clientset - opssight *opssightapi.OpsSight - configMap *MainOpssightConfigMap - names map[string]string - images map[string]string - isBlackDuckClusterScope bool - dryRun bool -} - -// NewSpecConfig will create the OpsSight object -func NewSpecConfig(config *protoform.Config, kubeClient *kubernetes.Clientset, opssightClient *opssightclientset.Clientset, hubClient *hubclientset.Clientset, opssight *opssightapi.OpsSight, isBlackDuckClusterScope bool, dryRun bool) *SpecConfig { - opssightSpec := &opssight.Spec - name := opssight.Name - names := map[string]string{ - "perceptor": "core", - "pod-perceiver": "pod-processor", - "image-perceiver": "image-processor", - "artifactory-perceiver": "artifactory-processor", - "quay-perceiver": "quay-processor", - "scanner": "scanner", - "perceptor-imagefacade": "image-getter", - "skyfire": "skyfire", - "prometheus": "prometheus", - "configmap": "opssight", - "perceiver-service-account": "processor", - } - baseImageURL := "docker.io/blackducksoftware" - version := "2.2.5" - images := map[string]string{ - "perceptor": fmt.Sprintf("%s/opssight-core:%s", baseImageURL, version), - "pod-perceiver": fmt.Sprintf("%s/opssight-pod-processor:%s", baseImageURL, version), - "image-perceiver": fmt.Sprintf("%s/opssight-image-processor:%s", baseImageURL, version), - "artifactory-perceiver": fmt.Sprintf("%s/opssight-artifactory-processor:%s", baseImageURL, version), - "quay-perceiver": fmt.Sprintf("%s/opssight-quay-processor:%s", baseImageURL, version), - "scanner": fmt.Sprintf("%s/opssight-scanner:%s", baseImageURL, version), - "perceptor-imagefacade": fmt.Sprintf("%s/opssight-image-getter:%s", baseImageURL, version), - "skyfire": "gcr.io/saas-hub-stg/blackducksoftware/pyfire:master", - "prometheus": "docker.io/prom/prometheus:v2.1.0", - } - if opssightSpec.IsUpstream { - names = map[string]string{ - "perceptor": "perceptor", - "pod-perceiver": "pod-perceiver", - "image-perceiver": "image-perceiver", - "artifactory-perceiver": "artifactory-perceiver", - "quay-perceiver": "quay-perceiver", - "scanner": "scanner", - "perceptor-imagefacade": "image-facade", - "skyfire": "skyfire", - "prometheus": "prometheus", - "configmap": "perceptor", - "perceiver-service-account": "perceiver", - } - baseImageURL = "gcr.io/saas-hub-stg/blackducksoftware" - version = "master" - images = map[string]string{ - "perceptor": fmt.Sprintf("%s/perceptor:%s", baseImageURL, version), - "pod-perceiver": fmt.Sprintf("%s/pod-perceiver:%s", baseImageURL, version), - "image-perceiver": fmt.Sprintf("%s/image-perceiver:%s", baseImageURL, version), - "artifactory-perceiver": fmt.Sprintf("%s/artifactory-perceiver:%s", baseImageURL, version), - "quay-perceiver": fmt.Sprintf("%s/quay-perceiver:%s", baseImageURL, version), - "scanner": fmt.Sprintf("%s/perceptor-scanner:%s", baseImageURL, version), - "perceptor-imagefacade": fmt.Sprintf("%s/perceptor-imagefacade:%s", baseImageURL, version), - "skyfire": "gcr.io/saas-hub-stg/blackducksoftware/pyfire:master", - "prometheus": "docker.io/prom/prometheus:v2.1.0"} - } - - for componentName, componentImage := range images { - image := appsutil.GenerateImageTag(componentImage, opssightSpec.ImageRegistries, opssightSpec.RegistryConfiguration) - images[componentName] = image - } - - configMap := &MainOpssightConfigMap{ - LogLevel: opssightSpec.LogLevel, - BlackDuck: &BlackDuckConfig{ - ConnectionsEnvironmentVariableName: opssightSpec.Blackduck.ConnectionsEnvironmentVariableName, - TLSVerification: opssightSpec.Blackduck.TLSVerification, - }, - ImageFacade: &ImageFacadeConfig{ - CreateImagesOnly: false, - Host: "localhost", - Port: 3004, - ImagePullerType: opssightSpec.ScannerPod.ImageFacade.ImagePullerType, - }, - Perceiver: &PerceiverConfig{ - Certificate: opssightSpec.Perceiver.Certificate, - CertificateKey: opssightSpec.Perceiver.CertificateKey, - Image: &ImagePerceiverConfig{}, - Pod: &PodPerceiverConfig{ - NamespaceFilter: opssightSpec.Perceiver.PodPerceiver.NamespaceFilter, - }, - Artifactory: &ArtifactoryPerceiverConfig{ - Dumper: opssightSpec.Perceiver.EnableArtifactoryPerceiverDumper, - }, - AnnotationIntervalSeconds: opssightSpec.Perceiver.AnnotationIntervalSeconds, - DumpIntervalMinutes: opssightSpec.Perceiver.DumpIntervalMinutes, - Port: 3002, - }, - Perceptor: &PerceptorConfig{ - Timings: &PerceptorTimingsConfig{ - CheckForStalledScansPauseHours: opssightSpec.Perceptor.CheckForStalledScansPauseHours, - ClientTimeoutMilliseconds: opssightSpec.Perceptor.ClientTimeoutMilliseconds, - ModelMetricsPauseSeconds: opssightSpec.Perceptor.ModelMetricsPauseSeconds, - StalledScanClientTimeoutHours: opssightSpec.Perceptor.StalledScanClientTimeoutHours, - UnknownImagePauseMilliseconds: opssightSpec.Perceptor.UnknownImagePauseMilliseconds, - }, - Host: util.GetResourceName(name, util.OpsSightName, names["perceptor"]), - Port: 3001, - UseMockMode: false, - }, - Scanner: &ScannerConfig{ - BlackDuckClientTimeoutSeconds: opssightSpec.ScannerPod.Scanner.ClientTimeoutSeconds, - ImageDirectory: opssightSpec.ScannerPod.ImageDirectory, - Port: 3003, - }, - Skyfire: &SkyfireConfig{ - BlackDuckClientTimeoutSeconds: opssightSpec.Skyfire.HubClientTimeoutSeconds, - BlackDuckDumpPauseSeconds: opssightSpec.Skyfire.HubDumpPauseSeconds, - KubeDumpIntervalSeconds: opssightSpec.Skyfire.KubeDumpIntervalSeconds, - PerceptorDumpIntervalSeconds: opssightSpec.Skyfire.PerceptorDumpIntervalSeconds, - Port: 3005, - PrometheusPort: 3006, - UseInClusterConfig: true, - }, - } - return &SpecConfig{ - config: config, - kubeClient: kubeClient, - opssightClient: opssightClient, - hubClient: hubClient, - opssight: opssight, - configMap: configMap, - isBlackDuckClusterScope: isBlackDuckClusterScope, - dryRun: dryRun, - names: names, - images: images, - } -} - -func (p *SpecConfig) configMapVolume(volumeName string) *components.Volume { - return components.NewConfigMapVolume(horizonapi.ConfigMapOrSecretVolumeConfig{ - VolumeName: volumeName, - MapOrSecretName: util.GetResourceName(p.opssight.Name, util.OpsSightName, p.names["configmap"]), - DefaultMode: util.IntToInt32(420), - }) -} - -// GetComponents will return the list of components -func (p *SpecConfig) GetComponents() (*api.ComponentList, error) { - components := &api.ComponentList{} - name := p.opssight.Name - // Add config map - cm, err := p.configMap.horizonConfigMap(util.GetResourceName(name, util.OpsSightName, p.names["configmap"]), p.opssight.Spec.Namespace, fmt.Sprintf("%s.json", p.names["configmap"])) - if err != nil { - return nil, errors.Trace(err) - } - cm.AddLabels(map[string]string{"name": name}) - components.ConfigMaps = append(components.ConfigMaps, cm) - - // Add Perceptor - rc, err := p.PerceptorReplicationController() - if err != nil { - return nil, errors.Trace(err) - } - components.ReplicationControllers = append(components.ReplicationControllers, rc) - service, err := p.PerceptorService() - if err != nil { - return nil, errors.Trace(err) - } - components.Services = append(components.Services, service) - perceptorSvc, err := p.getPerceptorExposeService() - if err != nil { - return nil, errors.Annotate(err, "failed to create perceptor service") - } - if perceptorSvc != nil { - components.Services = append(components.Services, perceptorSvc) - } - secret, err := p.PerceptorSecret() - if err != nil { - return nil, errors.Trace(err) - } - if !p.dryRun { - p.addSecretData(secret) - } - components.Secrets = append(components.Secrets, secret) - - route := p.GetPerceptorOpenShiftRoute() - if route != nil { - components.Routes = append(components.Routes, route) - } - - // Add Perceptor Scanner - scannerRC, err := p.ScannerReplicationController() - if err != nil { - return nil, errors.Annotate(err, "failed to create scanner replication controller") - } - components.ReplicationControllers = append(components.ReplicationControllers, scannerRC) - components.Services = append(components.Services, p.ScannerService(), p.ImageFacadeService()) - - components.ServiceAccounts = append(components.ServiceAccounts, p.ScannerServiceAccount()) - if p.config.IsOpenshift && p.opssight.Spec.Perceiver.EnableImagePerceiver { - clusterRoleBinding, err := p.ScannerClusterRoleBinding() - if err != nil { - return nil, errors.Annotate(err, "failed to create scanner cluster role binding") - } - components.ClusterRoleBindings = append(components.ClusterRoleBindings, clusterRoleBinding) - } - - // Add Pod Perceiver - if p.opssight.Spec.Perceiver.EnablePodPerceiver { - rc, err = p.PodPerceiverReplicationController() - if err != nil { - return nil, errors.Annotate(err, "failed to create pod perceiver") - } - components.ReplicationControllers = append(components.ReplicationControllers, rc) - components.Services = append(components.Services, p.PodPerceiverService()) - podClusterRole := p.PodPerceiverClusterRole() - components.ClusterRoles = append(components.ClusterRoles, podClusterRole) - components.ClusterRoleBindings = append(components.ClusterRoleBindings, p.PodPerceiverClusterRoleBinding(podClusterRole)) - } - - // Add Image Perceiver - if p.opssight.Spec.Perceiver.EnableImagePerceiver { - rc, err = p.ImagePerceiverReplicationController() - if err != nil { - return nil, errors.Annotate(err, "failed to create image perceiver") - } - components.ReplicationControllers = append(components.ReplicationControllers, rc) - components.Services = append(components.Services, p.ImagePerceiverService()) - imageClusterRole := p.ImagePerceiverClusterRole() - components.ClusterRoles = append(components.ClusterRoles, imageClusterRole) - components.ClusterRoleBindings = append(components.ClusterRoleBindings, p.ImagePerceiverClusterRoleBinding(imageClusterRole)) - } - - // Add Artifactory Perceiver if enabled - if p.opssight.Spec.Perceiver.EnableArtifactoryPerceiver { - rc, err = p.ArtifactoryPerceiverReplicationController() - if err != nil { - return nil, errors.Annotate(err, "failed to create artifactory perceiver") - } - - components.ReplicationControllers = append(components.ReplicationControllers, rc) - perceiverSvc, err := p.getPerceiverExposeService("artifactory") - if err != nil { - return nil, errors.Annotate(err, "failed to create artifactory perceiver service") - } - if perceiverSvc != nil { - components.Services = append(components.Services, perceiverSvc) - } - secure := false - if len(p.opssight.Spec.Perceiver.Certificate) > 0 && len(p.opssight.Spec.Perceiver.CertificateKey) > 0 { - secure = true - } - route := p.GetPerceiverOpenShiftRoute("artifactory", secure) - if route != nil { - components.Services = append(components.Services, p.ArtifactoryPerceiverService()) - components.Routes = append(components.Routes, route) - } - } - - // Add Quay Perceiver if enabled - if p.opssight.Spec.Perceiver.EnableQuayPerceiver { - rc, err = p.QuayPerceiverReplicationController() - if err != nil { - return nil, errors.Annotate(err, "failed to create quay perceiver") - } - - components.ReplicationControllers = append(components.ReplicationControllers, rc) - perceiverSvc, err := p.getPerceiverExposeService("quay") - if err != nil { - return nil, errors.Annotate(err, "failed to create quay perceiver service") - } - if perceiverSvc != nil { - components.Services = append(components.Services, perceiverSvc) - } - secure := false - if len(p.opssight.Spec.Perceiver.Certificate) > 0 && len(p.opssight.Spec.Perceiver.CertificateKey) > 0 { - secure = true - } - route := p.GetPerceiverOpenShiftRoute("quay", secure) - if route != nil { - components.Services = append(components.Services, p.QuayPerceiverService()) - components.Routes = append(components.Routes, route) - } - } - - if p.opssight.Spec.Perceiver.EnablePodPerceiver || p.opssight.Spec.Perceiver.EnableImagePerceiver { - // Use the same service account - //components.ServiceAccounts = append(components.ServiceAccounts, p.PodPerceiverServiceAccount()) - components.ServiceAccounts = append(components.ServiceAccounts, p.ImagePerceiverServiceAccount()) - } - - // Add skyfire - if p.opssight.Spec.EnableSkyfire { - skyfireRC, err := p.PerceptorSkyfireReplicationController() - if err != nil { - return nil, errors.Annotate(err, "failed to create skyfire") - } - components.ReplicationControllers = append(components.ReplicationControllers, skyfireRC) - components.Services = append(components.Services, p.PerceptorSkyfireService()) - components.ServiceAccounts = append(components.ServiceAccounts, p.PerceptorSkyfireServiceAccount()) - skyfireClusterRole := p.PerceptorSkyfireClusterRole() - components.ClusterRoles = append(components.ClusterRoles, skyfireClusterRole) - components.ClusterRoleBindings = append(components.ClusterRoleBindings, p.PerceptorSkyfireClusterRoleBinding(skyfireClusterRole)) - } - - // Add Metrics - if p.opssight.Spec.EnableMetrics { - // deployments - dep, err := p.PerceptorMetricsDeployment() - if err != nil { - return nil, errors.Annotate(err, "failed to create metrics") - } - components.Deployments = append(components.Deployments, dep) - - // services - prometheusService, err := p.PerceptorMetricsService() - if err != nil { - return nil, errors.Annotate(err, "failed to create prometheus metrics service") - } - components.Services = append(components.Services, prometheusService) - prometheusSvc, err := p.getPerceptorMetricsExposeService() - if err != nil { - return nil, errors.Annotate(err, "failed to create prometheus metrics exposed service") - } - if prometheusSvc != nil { - components.Services = append(components.Services, prometheusSvc) - } - - // config map - perceptorCm, err := p.PerceptorMetricsConfigMap() - if err != nil { - return nil, errors.Annotate(err, "failed to create perceptor config map") - } - components.ConfigMaps = append(components.ConfigMaps, perceptorCm) - - route := p.GetPrometheusOpenShiftRoute() - if route != nil { - components.Routes = append(components.Routes, route) - } - } - - return components, nil -} - -func (p *SpecConfig) getPerceiverExposeService(perceiverName string) (*components.Service, error) { - var svc *components.Service - var err error - switch strings.ToUpper(p.opssight.Spec.Perceiver.Expose) { - case util.NODEPORT: - svc, err = p.PerceiverNodePortService(perceiverName) - break - case util.LOADBALANCER: - svc, err = p.PerceiverLoadBalancerService(perceiverName) - break - default: - } - return svc, err -} - -func (p *SpecConfig) getPerceptorExposeService() (*components.Service, error) { - var svc *components.Service - var err error - switch strings.ToUpper(p.opssight.Spec.Perceptor.Expose) { - case util.NODEPORT: - svc, err = p.PerceptorNodePortService() - break - case util.LOADBALANCER: - svc, err = p.PerceptorLoadBalancerService() - break - default: - } - return svc, err -} - -func (p *SpecConfig) getPerceptorMetricsExposeService() (*components.Service, error) { - var svc *components.Service - var err error - switch strings.ToUpper(p.opssight.Spec.Prometheus.Expose) { - case util.NODEPORT: - svc, err = p.PerceptorMetricsNodePortService() - break - case util.LOADBALANCER: - svc, err = p.PerceptorMetricsLoadBalancerService() - break - default: - } - return svc, err -} - -func (p *SpecConfig) addSecretData(secret *components.Secret) error { - blackduckHosts := make(map[string]*opssightapi.Host) - // adding External Black Duck credentials - for _, host := range p.opssight.Spec.Blackduck.ExternalHosts { - blackduckHosts[host.Domain] = host - } - - // adding Internal Black Duck credentials - secretEditor := NewUpdater(p.config, p.kubeClient, p.hubClient, p.opssightClient) - hubType := p.opssight.Spec.Blackduck.BlackduckSpec.Type - blackduckPassword, err := util.Base64Decode(p.opssight.Spec.Blackduck.BlackduckPassword) - if err != nil { - return errors.Annotatef(err, "unable to decode blackduckPassword") - } - - allHubs := secretEditor.getAllHubs(hubType, blackduckPassword) - blackduckPasswords := secretEditor.appendBlackDuckSecrets(blackduckHosts, p.opssight.Status.InternalHosts, allHubs) - - // marshal the blackduck credentials to bytes - bytes, err := json.Marshal(blackduckPasswords) - if err != nil { - return errors.Annotatef(err, "unable to marshal blackduck passwords") - } - secret.AddData(map[string][]byte{p.opssight.Spec.Blackduck.ConnectionsEnvironmentVariableName: bytes}) - - // adding Secured registries credentials - securedRegistries := make(map[string]*opssightapi.RegistryAuth) - for _, internalRegistry := range p.opssight.Spec.ScannerPod.ImageFacade.InternalRegistries { - securedRegistries[internalRegistry.URL] = internalRegistry - } - // marshal the Secured registries credentials to bytes - bytes, err = json.Marshal(securedRegistries) - if err != nil { - return errors.Annotatef(err, "unable to marshal secured registries") - } - secret.AddData(map[string][]byte{"securedRegistries.json": bytes}) - - // add internal hosts to status - p.opssight.Status.InternalHosts = secretEditor.appendBlackDuckHosts(p.opssight.Status.InternalHosts, allHubs) - return nil -} diff --git a/pkg/synopsysctl/CRDPrint.go b/pkg/synopsysctl/CRDPrint.go index 82293bebb..98726ff89 100644 --- a/pkg/synopsysctl/CRDPrint.go +++ b/pkg/synopsysctl/CRDPrint.go @@ -33,10 +33,8 @@ import ( "github.com/blackducksoftware/horizon/pkg/components" "github.com/blackducksoftware/synopsys-operator/pkg/api" alertapi "github.com/blackducksoftware/synopsys-operator/pkg/api/alert/v1" - opssightapi "github.com/blackducksoftware/synopsys-operator/pkg/api/opssight/v1" "github.com/blackducksoftware/synopsys-operator/pkg/apps" alertapp "github.com/blackducksoftware/synopsys-operator/pkg/apps/alert" - "github.com/blackducksoftware/synopsys-operator/pkg/opssight" "github.com/blackducksoftware/synopsys-operator/pkg/protoform" "github.com/blackducksoftware/synopsys-operator/pkg/soperator" ) @@ -93,16 +91,6 @@ func PrintResource(crd interface{}, format string, printKubeComponents bool) err if err != nil { return fmt.Errorf("failed to get components: %s", err) } - case reflect.TypeOf(opssightapi.OpsSight{}): - pc := &protoform.Config{} - pc.SelfSetDefaults() - pc.DryRun = true - opsSight := crd.(opssightapi.OpsSight) - sc := opssight.NewSpecConfig(pc, kubeClient, opsSightClient, blackDuckClient, &opsSight, true, pc.DryRun) - cList, err = sc.GetComponents() - if err != nil { - return fmt.Errorf("failed to get components: %s", err) - } default: return fmt.Errorf("cannot print a resource with the format: %+v", crd) } diff --git a/pkg/synopsysctl/cmd_create.go b/pkg/synopsysctl/cmd_create.go index 332f84575..43dbc4c4a 100644 --- a/pkg/synopsysctl/cmd_create.go +++ b/pkg/synopsysctl/cmd_create.go @@ -32,7 +32,6 @@ import ( "github.com/blackducksoftware/synopsys-operator/pkg/alert" "github.com/blackducksoftware/synopsys-operator/pkg/api" alertv1 "github.com/blackducksoftware/synopsys-operator/pkg/api/alert/v1" - opssightv1 "github.com/blackducksoftware/synopsys-operator/pkg/api/opssight/v1" "github.com/blackducksoftware/synopsys-operator/pkg/apps" alertapp "github.com/blackducksoftware/synopsys-operator/pkg/apps/alert" "github.com/blackducksoftware/synopsys-operator/pkg/blackduck" @@ -49,7 +48,7 @@ import ( // Create Command CRSpecBuilderFromCobraFlagsInterface var createAlertCobraHelper CRSpecBuilderFromCobraFlagsInterface var createBlackDuckCobraHelper blackduck.HelmValuesFromCobraFlags -var createOpsSightCobraHelper CRSpecBuilderFromCobraFlagsInterface +var createOpsSightCobraHelper opssight.HelmValuesFromCobraFlags var createPolarisCobraHelper polaris.HelmValuesFromCobraFlags var createPolarisReportingCobraHelper polarisreporting.HelmValuesFromCobraFlags var createBDBACobraHelper bdba.HelmValuesFromCobraFlags @@ -367,49 +366,10 @@ var createBlackDuckNativeCmd = &cobra.Command{ Create OpsSight Commands */ -var createOpsSightPreRun = func(cmd *cobra.Command, args []string) error { - // Set the base spec - if !cmd.Flags().Lookup("template").Changed { - baseOpsSightSpec = defaultBaseOpsSightSpec - } - log.Debugf("setting OpsSight's base spec to '%s'", baseOpsSightSpec) - err := createOpsSightCobraHelper.SetPredefinedCRSpec(baseOpsSightSpec) - if err != nil { - cmd.Help() - return err - } - return nil -} - -func updateOpsSightSpecWithFlags(cmd *cobra.Command, opsSightName string, opsSightNamespace string) (*opssightv1.OpsSight, error) { - // Update Spec with user's flags - log.Debugf("updating spec with user's flags") - opsSightInterface, err := createOpsSightCobraHelper.GenerateCRSpecFromFlags(cmd.Flags()) - if err != nil { - return nil, err - } - - // Set Namespace in Spec - opsSightSpec, _ := opsSightInterface.(opssightv1.OpsSightSpec) - opsSightSpec.Namespace = opsSightNamespace - - // Create and Deploy OpsSight CRD - opsSight := &opssightv1.OpsSight{ - ObjectMeta: metav1.ObjectMeta{ - Name: opsSightName, - Namespace: opsSightNamespace, - }, - Spec: opsSightSpec, - } - opsSight.Kind = "OpsSight" - opsSight.APIVersion = "synopsys.com/v1" - return opsSight, nil -} - // createOpsSightCmd creates an OpsSight instance var createOpsSightCmd = &cobra.Command{ - Use: "opssight NAME", - Example: "synopsysctl create opssight \nsynopsysctl create opssight -n \nsynopsysctl create opssight --mock json", + Use: "opssight NAME -n NAMESPACE", + Example: "synopsysctl create opssight -n ", Short: "Create an OpsSight instance", SilenceUsage: true, SilenceErrors: true, @@ -417,45 +377,54 @@ var createOpsSightCmd = &cobra.Command{ // Check the Number of Arguments if len(args) != 1 { cmd.Help() - return fmt.Errorf("this command takes 1 arguments") + return fmt.Errorf("this command takes 1 argument, but got %+v", args) } return nil }, - PreRunE: createOpsSightPreRun, RunE: func(cmd *cobra.Command, args []string) error { - mockMode := cmd.Flags().Lookup("mock").Changed - opsSightName := args[0] - opsSightNamespace, crdNamespace, _, err := getInstanceInfo(mockMode, util.OpsSightCRDName, "", namespace, opsSightName) + opssightName := args[0] + + // Get the flags to set Helm values + helmValuesMap, err := createOpssightReportingCobraHelper.GenerateHelmFlagsFromCobraFlags(cmd.Flags()) if err != nil { return err } - opsSight, err := updateOpsSightSpecWithFlags(cmd, opsSightName, opsSightNamespace) - if err != nil { - return err + + // Update the Helm Chart Location + // TODO: allow user to specify --version and --chart-location + chartLocationFlag := cmd.Flag("chart-location-path") + if chartLocationFlag.Changed { + opssightReportingChartRepository = chartLocationFlag.Value.String() + } else { + versionFlag := cmd.Flag("version") + if versionFlag.Changed { + opssightReportingChartRepository = fmt.Sprintf("%s/charts/opssight-%s.tgz", baseChartRepository, versionFlag.Value.String()) + } } - // If mock mode, return and don't create resources - if mockMode { - log.Debugf("generating CRD for OpsSight '%s' in namespace '%s'...", opsSightName, opsSightNamespace) - return PrintResource(*opsSight, mockFormat, false) + // Check Dry Run before deploying any resources + err = util.CreateWithHelm3(opssightName, namespace, opssightReportingChartRepository, helmValuesMap, kubeConfigPath, true) + if err != nil { + return fmt.Errorf("failed to create OpsSight resources: %+v", err) } - log.Infof("creating OpsSight '%s' in namespace '%s'...", opsSightName, opsSightNamespace) + // TODO Create any initial opssight resources ... - // Deploy the OpsSight instance - _, err = util.CreateOpsSight(opsSightClient, crdNamespace, opsSight) + // Deploy OpsSight Resources + err = util.CreateWithHelm3(opssightName, namespace, opssightReportingChartRepository, helmValuesMap, kubeConfigPath, false) if err != nil { - return fmt.Errorf("error creating the OpsSight '%s' in namespace '%s' due to %+v", opsSightName, opsSightNamespace, err) + return fmt.Errorf("failed to create OpsSight resources: %+v", err) } - log.Infof("successfully submitted OpsSight '%s' into namespace '%s'", opsSightName, opsSightNamespace) + + log.Infof("OpsSight has been successfully Created!") return nil }, } // createOpsSightNativeCmd prints the Kubernetes resources for creating an OpsSight instance var createOpsSightNativeCmd = &cobra.Command{ - Use: "native NAME", - Example: "synopsysctl create opssight native \nsynopsysctl create opssight native -n \nsynopsysctl create opssight native -o yaml", + Use: "native NAME -n NAMESPACE", + Example: "synopsysctl create opssight native -n ", Short: "Print the Kubernetes resources for creating an OpsSight instance", SilenceUsage: true, SilenceErrors: true, @@ -463,24 +432,43 @@ var createOpsSightNativeCmd = &cobra.Command{ // Check the Number of Arguments if len(args) != 1 { cmd.Help() - return fmt.Errorf("this command takes 1 argument") + return fmt.Errorf("this command takes 1 argument, but got %+v", args) } return nil }, PreRunE: createOpsSightPreRun, RunE: func(cmd *cobra.Command, args []string) error { - opsSightName := args[0] - opsSightNamespace, _, _, err := getInstanceInfo(true, util.OpsSightCRDName, "", namespace, opsSightName) + opssightName := args[0] + + // Get the flags to set Helm values + helmValuesMap, err := createOpssightCobraHelper.GenerateHelmFlagsFromCobraFlags(cmd.Flags()) if err != nil { return err } - opsSight, err := updateOpsSightSpecWithFlags(cmd, opsSightName, opsSightNamespace) + + // Update the Helm Chart Location + chartLocationFlag := cmd.Flag("chart-location-path") + if chartLocationFlag.Changed { + opssightChartRepository = chartLocationFlag.Value.String() + } else { + versionFlag := cmd.Flag("version") + if versionFlag.Changed { + opssightChartRepository = fmt.Sprintf("%s/charts/opssight-%s.tgz", baseChartRepository, versionFlag.Value.String()) + } + } + + // // TODO Print any initial resources... + // for _, obj := range gcpServiceAccountSecrets { + // PrintComponent(obj, "YAML") // helm only supports yaml + // } + + // Print OpsSight Resources + err = util.TemplateWithHelm3(opssightName, namespace, opssightChartRepository, helmValuesMap) if err != nil { - return err + return fmt.Errorf("failed to generate OpsSight resources: %+v", err) } - log.Debugf("generating Kubernetes resources for OpsSight '%s' in namespace '%s'...", opsSightName, opsSightNamespace) - return PrintResource(*opsSight, nativeFormat, true) + return nil }, } @@ -825,7 +813,7 @@ func init() { // initialize global resource ctl structs for commands to use createAlertCobraHelper = alert.NewCRSpecBuilderFromCobraFlags() createBlackDuckCobraHelper = *blackduck.NewHelmValuesFromCobraFlags() - createOpsSightCobraHelper = opssight.NewCRSpecBuilderFromCobraFlags() + createOpsSightCobraHelper = *opssight.NewHelmValuesFromCobraFlags() createPolarisCobraHelper = *polaris.NewHelmValuesFromCobraFlags() createPolarisReportingCobraHelper = *polarisreporting.NewHelmValuesFromCobraFlags() createBDBACobraHelper = *bdba.NewHelmValuesFromCobraFlags() @@ -860,12 +848,14 @@ func init() { // Add OpsSight Command createOpsSightCmd.PersistentFlags().StringVar(&baseOpsSightSpec, "template", baseOpsSightSpec, "Base resource configuration to modify with flags [empty|upstream|default|disabledBlackDuck]") createOpsSightCmd.PersistentFlags().StringVarP(&namespace, "namespace", "n", namespace, "Namespace of the instance(s)") - createOpsSightCobraHelper.AddCRSpecFlagsToCommand(createOpsSightCmd, true) + cobra.MarkFlagRequired(createOpsSightCmd.PersistentFlags(), "namespace") + addChartLocationPathFlag(createOpsSightCmd) + createOpsSightCobraHelper.AddCobraFlagsToCommand(createOpsSightCmd, true) addMockFlag(createOpsSightCmd) createCmd.AddCommand(createOpsSightCmd) - createOpsSightCobraHelper.AddCRSpecFlagsToCommand(createOpsSightNativeCmd, true) - addNativeFormatFlag(createOpsSightNativeCmd) + createOpsSightCobraHelper.AddCobraFlagsToCommand(createOpsSightNativeCmd, true) + addChartLocationPathFlag(createOpsSightNativeCmd) createOpsSightCmd.AddCommand(createOpsSightNativeCmd) // Add Polaris commands diff --git a/pkg/synopsysctl/cmd_delete.go b/pkg/synopsysctl/cmd_delete.go index 496de76c5..1a7997e2d 100644 --- a/pkg/synopsysctl/cmd_delete.go +++ b/pkg/synopsysctl/cmd_delete.go @@ -23,6 +23,7 @@ package synopsysctl import ( "fmt" + k8serrors "k8s.io/apimachinery/pkg/api/errors" polarisreporting "github.com/blackducksoftware/synopsys-operator/pkg/polaris-reporting" @@ -104,33 +105,31 @@ var deleteBlackDuckCmd = &cobra.Command{ }, } -// deleteOpsSightCmd deletes OpsSight instances from the cluster +// deleteOpsSightCmd deletes an OpsSight instance from the cluster var deleteOpsSightCmd = &cobra.Command{ - Use: "opssight NAME...", - Example: "synopsysctl delete opssight \nsynopsysctl delete opssight \nsynopsysctl delete opssight -n \nsynopsysctl delete opssight -n ", - Short: "Delete one or many OpsSight instances", + Use: "opssight NAME -n NAMESPACE", + Example: "synopsysctl delete opssight -n ", + Short: "Delete an OpsSight instances", SilenceUsage: true, SilenceErrors: true, Args: func(cmd *cobra.Command, args []string) error { - if len(args) == 0 { + if len(args) != 1 { cmd.Help() - return fmt.Errorf("this command takes 1 or more arguments") + return fmt.Errorf("this command takes 1 argument but got %+v", len(args)) } return nil }, RunE: func(cmd *cobra.Command, args []string) error { - for _, opsSightName := range args { - opsSightNamespace, crdNamespace, _, err := getInstanceInfo(false, util.OpsSightCRDName, util.OpsSightName, namespace, opsSightName) - if err != nil { - return err - } - log.Infof("deleting OpsSight '%s' in namespace '%s'...", opsSightName, opsSightNamespace) - err = util.DeleteOpsSight(opsSightClient, opsSightName, crdNamespace, &metav1.DeleteOptions{}) - if err != nil { - return fmt.Errorf("error deleting OpsSight '%s' in namespace '%s' due to '%s'", opsSightName, opsSightNamespace, err) - } - log.Infof("successfully submitted delete OpsSight '%s' in namespace '%s'", opsSightName, opsSightNamespace) + opssightName := args[0] + // TODO Delete any initial resources... + + // Delete Opssight Resources + err = util.DeleteWithHelm3(opssightName, namespace, kubeConfigPath) + if err != nil { + return fmt.Errorf("failed to delete OpsSight resources: %+v", err) } + + log.Infof("OpsSight has been successfully Deleted!") return nil }, } @@ -244,6 +243,7 @@ func init() { // Add Delete OpsSight Command deleteOpsSightCmd.Flags().StringVarP(&namespace, "namespace", "n", namespace, "Namespace of the instance(s)") + cobra.MarkFlagRequired(deleteBDBACmd.Flags(), "namespace") deleteCmd.AddCommand(deleteOpsSightCmd) // Add Delete Polaris Command diff --git a/pkg/synopsysctl/cmd_edit.go b/pkg/synopsysctl/cmd_edit.go index 82658da82..641c41243 100644 --- a/pkg/synopsysctl/cmd_edit.go +++ b/pkg/synopsysctl/cmd_edit.go @@ -68,42 +68,9 @@ var editAlertCmd = &cobra.Command{ }, } -// editOpsSightCmd edits an OpsSight instance by using the kube/oc editor -var editOpsSightCmd = &cobra.Command{ - Use: "opssight NAME", - Example: "synopsysctl edit opssight \nsynopsysctl edit opssight -n ", - Short: "Edit an OpsSight instance", - SilenceUsage: true, - SilenceErrors: true, - Args: func(cmd *cobra.Command, args []string) error { - if len(args) != 1 { - cmd.Help() - return fmt.Errorf("this command takes 1 argument") - } - return nil - }, - RunE: func(cmd *cobra.Command, args []string) error { - opsSightName := args[0] - opsSightNamespace, _, _, err := getInstanceInfo(false, util.OpsSightCRDName, util.OpsSightName, namespace, opsSightName) - if err != nil { - return err - } - log.Infof("editing OpsSight '%s' in namespace '%s'...", opsSightName, opsSightNamespace) - err = RunKubeEditorCmd(restconfig, kubeClient, "edit", "opssight", opsSightName, "-n", opsSightNamespace) - if err != nil { - return fmt.Errorf("error editing OpsSight '%s' in namespace '%s' due to %+v", opsSightName, opsSightNamespace, err) - } - log.Infof("successfully edited OpsSight '%s' in namespace '%s'...", opsSightName, opsSightNamespace) - return nil - }, -} - func init() { rootCmd.AddCommand(editCmd) editAlertCmd.Flags().StringVarP(&namespace, "namespace", "n", namespace, "Namespace of the instance(s)") editCmd.AddCommand(editAlertCmd) - - editOpsSightCmd.Flags().StringVarP(&namespace, "namespace", "n", namespace, "Namespace of the instance(s)") - editCmd.AddCommand(editOpsSightCmd) } diff --git a/pkg/synopsysctl/cmd_get.go b/pkg/synopsysctl/cmd_get.go index 5c40412e3..06b9564dc 100644 --- a/pkg/synopsysctl/cmd_get.go +++ b/pkg/synopsysctl/cmd_get.go @@ -24,12 +24,13 @@ package synopsysctl import ( "encoding/base64" "fmt" - "github.com/blackducksoftware/synopsys-operator/pkg/util" - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" "io/ioutil" "os" "path/filepath" + + "github.com/blackducksoftware/synopsys-operator/pkg/util" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" ) // Get Command flag for -output functionality @@ -173,24 +174,29 @@ func getBlackDuckMasterKey(namespace string, name string, filePath string) error return nil } -// getOpsSightCmd display one or many OpsSight instances +// getOpsSightCmd display an OpsSight instance var getOpsSightCmd = &cobra.Command{ - Use: "opssight [NAME...]", - Example: "synopsysctl get opssights\nsynopsysctl get opssight \nsynopsysctl get opssights ", + Use: "opssight NAME -n NAMESPACE", + Example: "synopsysctl get opssight -n ", Aliases: []string{"opssights"}, - Short: "Display one or many OpsSight instances", + Short: "Display an OpsSight instance", SilenceUsage: true, SilenceErrors: true, Args: func(cmd *cobra.Command, args []string) error { + if len(args) != 1 { + cmd.Help() + return fmt.Errorf("this command takes 1 argument, but got %+v", args) + } return nil }, RunE: func(cmd *cobra.Command, args []string) error { - log.Debugf("getting OpsSight instances...") - out, err := RunKubeCmd(restconfig, kubeClient, generateKubectlGetCommand("opssights", args)...) + opssightName := args[0] + helmRelease, err := util.GetWithHelm3(opssightName, namespace, kubeConfigPath) if err != nil { - return fmt.Errorf("error getting OpsSight instances due to %+v - %s", out, err) + return fmt.Errorf("failed to get OpsSight values: %+v", err) } - fmt.Printf("%+v", out) + helmSetValues := helmRelease.Config + PrintComponent(helmSetValues, "YAML") return nil }, } diff --git a/pkg/synopsysctl/cmd_start.go b/pkg/synopsysctl/cmd_start.go index bdd639d60..8f8d3ce07 100644 --- a/pkg/synopsysctl/cmd_start.go +++ b/pkg/synopsysctl/cmd_start.go @@ -23,6 +23,7 @@ package synopsysctl import ( "fmt" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/blackducksoftware/synopsys-operator/pkg/util" @@ -130,48 +131,39 @@ var startBlackDuckCmd = &cobra.Command{ // startOpsSightCmd starts an OpsSight instance var startOpsSightCmd = &cobra.Command{ - Use: "opssight NAME", - Example: "synopsysctl start opssight \nsynopsysctl start opssight ", + Use: "opssight NAME -n NAMESPACE", + Example: "synopsysctl start opssight -n ", Short: "Start an OpsSight instance", SilenceUsage: true, SilenceErrors: true, Args: func(cmd *cobra.Command, args []string) error { - if len(args) == 0 { + if len(args) != 1 { cmd.Help() - return fmt.Errorf("this command takes one or more arguments") + return fmt.Errorf("this command takes 1 argument, but got %+v", args) } return nil }, RunE: func(cmd *cobra.Command, args []string) error { - errors := []error{} - for _, opsSightName := range args { - opsSightNamespace, crdNamespace, _, err := getInstanceInfo(false, util.OpsSightCRDName, util.OpsSightName, namespace, opsSightName) - if err != nil { - errors = append(errors, err) - continue - } - log.Infof("starting OpsSight '%s' in namespace '%s'...", opsSightName, opsSightNamespace) + opssightName := args[0] + instance, err := util.GetWithHelm3(opssightName, namespace, kubeConfigPath) + if err != nil { + return fmt.Errorf("couldn't find instance %s in namespace %s", opssightName, namespace) + } - // Get the OpsSight - currOpsSight, err := util.GetOpsSight(opsSightClient, crdNamespace, opsSightName, metav1.GetOptions{}) - if err != nil { - errors = append(errors, fmt.Errorf("error getting OpsSight '%s' in namespace '%s' due to %+v", opsSightName, opsSightNamespace, err)) - continue - } + // Update the Helm Chart Location + chartLocationFlag := cmd.Flag("chart-location-path") + if chartLocationFlag.Changed { + opssightChartRepository = chartLocationFlag.Value.String() + } else { + opssightChartRepository = fmt.Sprintf("%s/charts/opssight-%s.tgz", baseChartRepository, instance.Chart.Values["imageTag"]) // TODO fix getting version + } - // Make changes to Spec - currOpsSight.Spec.DesiredState = "" - // Update OpsSight - _, err = util.UpdateOpsSight(opsSightClient, crdNamespace, currOpsSight) - if err != nil { - errors = append(errors, fmt.Errorf("error starting OpsSight '%s' in namespace '%s' due to %+v", opsSightName, opsSightNamespace, err)) - continue - } + helmValuesMap := make(map[string]interface{}) + util.SetHelmValueInMap(helmValuesMap, []string{"status"}, "Running") - log.Infof("successfully submitted start OpsSight '%s' in namespace '%s'", opsSightName, opsSightNamespace) - } - if len(errors) > 0 { - return fmt.Errorf("%v", errors) + err = util.UpdateWithHelm3(opssightName, namespace, opssightChartRepository, helmValuesMap, kubeConfigPath) + if err != nil { + return fmt.Errorf("failed to create OpsSight resources: %+v", err) } return nil }, @@ -188,5 +180,7 @@ func init() { addChartLocationPathFlag(startBlackDuckCmd) startOpsSightCmd.Flags().StringVarP(&namespace, "namespace", "n", namespace, "Namespace of the instance(s)") + cobra.MarkFlagRequired(startOpsSightCmd.PersistentFlags(), "namespace") + addChartLocationPathFlag(startOpsSightCmd) startCmd.AddCommand(startOpsSightCmd) } diff --git a/pkg/synopsysctl/cmd_stop.go b/pkg/synopsysctl/cmd_stop.go index edb22735c..cc89b70c8 100644 --- a/pkg/synopsysctl/cmd_stop.go +++ b/pkg/synopsysctl/cmd_stop.go @@ -135,52 +135,39 @@ var stopBlackDuckCmd = &cobra.Command{ // stopOpsSightCmd stops an OpsSight instance var stopOpsSightCmd = &cobra.Command{ - Use: "opssight NAME", - Example: "synopsysctl stop opssight \nsynopsysctl stop opssight ", + Use: "opssight NAME -n NAMESPACE", + Example: "synopsysctl stop opssight -n ", Short: "Stop an OpsSight instance", SilenceUsage: true, SilenceErrors: true, Args: func(cmd *cobra.Command, args []string) error { - if len(args) == 0 { + if len(args) != 1 { cmd.Help() - return fmt.Errorf("this command takes one or more arguments") + return fmt.Errorf("this command takes 1 argument, but got %+v", args) } return nil }, RunE: func(cmd *cobra.Command, args []string) error { - errors := []error{} - for _, opsSightName := range args { - opsSightNamespace, crdNamespace, scope, err := getInstanceInfo(false, util.OpsSightCRDName, util.OpsSightName, namespace, opsSightName) - if err != nil { - if len(opsSightNamespace) == 0 && scope == apiextensions.ClusterScoped { - err = fmt.Errorf("%s %s doesn't appear to be running: %v", util.OpsSightName, opsSightName, err) - } - errors = append(errors, err) - continue - } - log.Infof("stopping OpsSight '%s' in namespace '%s'...", opsSightName, opsSightNamespace) + opssightName := args[0] + instance, err := util.GetWithHelm3(opssightName, namespace, kubeConfigPath) + if err != nil { + return fmt.Errorf("couldn't find instance %s in namespace %s", opssightName, namespace) + } - // Get the OpsSight - currOpsSight, err := util.GetOpsSight(opsSightClient, crdNamespace, opsSightName, metav1.GetOptions{}) - if err != nil { - errors = append(errors, fmt.Errorf("error getting OpsSight '%s' in namespace '%s' due to %+v", opsSightName, opsSightNamespace, err)) - continue - } + // Update the Helm Chart Location + chartLocationFlag := cmd.Flag("chart-location-path") + if chartLocationFlag.Changed { + opssightChartRepository = chartLocationFlag.Value.String() + } else { + opssightChartRepository = fmt.Sprintf("%s/charts/opssight-%s.tgz", baseChartRepository, instance.Chart.Values["imageTag"]) // TODO fix getting version + } - // Make changes to Spec - currOpsSight.Spec.DesiredState = "STOP" - // Update OpsSight - _, err = util.UpdateOpsSight(opsSightClient, - currOpsSight.Spec.Namespace, currOpsSight) - if err != nil { - errors = append(errors, fmt.Errorf("error stopping OpsSight '%s' in namespace '%s' due to %+v", opsSightName, opsSightNamespace, err)) - continue - } + helmValuesMap := make(map[string]interface{}) + util.SetHelmValueInMap(helmValuesMap, []string{"status"}, "Stopped") - log.Infof("successfully submitted stop OpsSight '%s' in namespace '%s'", opsSightName, opsSightNamespace) - } - if len(errors) > 0 { - return fmt.Errorf("%v", errors) + err = util.UpdateWithHelm3(opssightName, namespace, opssightChartRepository, helmValuesMap, kubeConfigPath) + if err != nil { + return fmt.Errorf("failed to create OpsSight resources: %+v", err) } return nil }, @@ -196,5 +183,8 @@ func init() { stopCmd.AddCommand(stopBlackDuckCmd) addChartLocationPathFlag(stopBlackDuckCmd) + stopOpsSightCmd.Flags().StringVarP(&namespace, "namespace", "n", namespace, "Namespace of the instance(s)") + cobra.MarkFlagRequired(stopOpsSightCmd.PersistentFlags(), "namespace") + addChartLocationPathFlag(stopOpsSightCmd) stopCmd.AddCommand(stopOpsSightCmd) } diff --git a/pkg/synopsysctl/cmd_update.go b/pkg/synopsysctl/cmd_update.go index ed72502d2..598aee29c 100644 --- a/pkg/synopsysctl/cmd_update.go +++ b/pkg/synopsysctl/cmd_update.go @@ -543,55 +543,118 @@ func updateOpsSight(ops *opssightapi.OpsSight, flagset *pflag.FlagSet) (*opssigh // updateOpsSightCmd updates an OpsSight instance var updateOpsSightCmd = &cobra.Command{ - Use: "opssight NAME", - Example: "synopsyctl update opssight --blackduck-max-count 2\nsynopsyctl update opssight --blackduck-max-count 2 -n \nsynopsyctl update opssight --blackduck-max-count 2 --mock json", + Use: "opssight NAME -n NAMESPACE", + Example: "synopsyctl update opssight -n --blackduck-max-count 2", Short: "Update an OpsSight instance", SilenceUsage: true, SilenceErrors: true, Args: func(cmd *cobra.Command, args []string) error { if len(args) != 1 { cmd.Help() - return fmt.Errorf("this command takes 1 argument") + return fmt.Errorf("this command takes 1 argument, but got %+v", args) } return nil }, RunE: func(cmd *cobra.Command, args []string) error { - mockMode := cmd.Flags().Lookup("mock").Changed - opsSightName := args[0] - opsSightNamespace, crdnamespace, _, err := getInstanceInfo(false, util.OpsSightCRDName, util.OpsSightName, namespace, opsSightName) - if err != nil { - return err + opssightName := args[0] + + // Update the Helm Chart Location + chartLocationFlag := cmd.Flag("chart-location-path") + if chartLocationFlag.Changed { + opssightChartRepository = chartLocationFlag.Value.String() + } else { + versionFlag := cmd.Flag("version") + if versionFlag.Changed { + opssightChartRepository = fmt.Sprintf("%s/charts/opssight-%s.tgz", baseChartRepository, versionFlag.Value.String()) + } } - currOpsSight, err := util.GetOpsSight(opsSightClient, crdnamespace, opsSightName, metav1.GetOptions{}) + + // TODO verity we can download the chart + isOperatorBased := false + instance, err := util.GetWithHelm3(alertName, namespace, kubeConfigPath) if err != nil { - return fmt.Errorf("error getting OpsSight '%s' in namespace '%s' due to %+v", opsSightName, opsSightNamespace, err) + isOperatorBased = true + } + + if !isOperatorBased && instance != nil { + err = updateOpssightHelmBased(cmd, alertName) + } else if isOperatorBased { + if !cmd.Flag("version").Changed { + return fmt.Errorf("you must upgrade this OpsSight version with --version to use this synopsysctl binary") + } + err = updateOpsSightOperatorBased(cmd, alertName) } - newOpsSight, err := updateOpsSight(currOpsSight, cmd.Flags()) if err != nil { return err } - // update the namespace label if the version of the app got changed - // TODO: when opssight versioning PR is merged, the hard coded 2.2.5 version to be replaced with OpsSight - _, err = util.CheckAndUpdateNamespace(kubeClient, util.OpsSightName, opsSightNamespace, opsSightName, "2.2.5", false) + log.Infof("OpsSight has been successfully updated in namespace '%s'!", namespace) + + return nil + }, +} + +func updateOpssightHelmBased(cmd *cobra.Command, opssightName string) error { + mockMode := cmd.Flags().Lookup("mock").Changed + + // Set flags from the current release in the updateOpsSightCobraHelper + helmRelease, err := util.GetWithHelm3(opssightName, namespace, kubeConfigPath) + if err != nil { + return fmt.Errorf("failed to get previous user defined values: %+v", err) + } + updateOpsSightCobraHelper.SetArgs(helmRelease.Config) + + // Update Helm Values with flags + helmValuesMap, err := updateOpsSightCobraHelper.GenerateHelmFlagsFromCobraFlags(cmd.Flags()) + if err != nil { + return err + } + + // If mock mode, return and don't create resources + if mockMode { + _, err = PrintComponent(helmValuesMap, "YAML") + return err + } + + // Update any initial resources that were created... + + // Update OpsSight Resources + err = util.UpdateWithHelm3(opssightName, namespace, alertChartRepository, helmValuesMap, kubeConfigPath) + if err != nil { + return fmt.Errorf("failed to update OpsSight resources due to %+v", err) + } + return nil +} + +func updateOpsSightOperatorBased(cmd *cobra.Command, opssightName string) error { + operatorNamespace := namespace + isClusterScoped := util.GetClusterScope(apiExtensionClient) + if isClusterScoped { + opNamespace, err := util.GetOperatorNamespace(kubeClient, metav1.NamespaceAll) if err != nil { return err } - - // If mock mode, return and don't create resources - if mockMode { - log.Debugf("generating updates to the CRD for OpsSight '%s' in namespace '%s'...", opsSightName, opsSightNamespace) - return PrintResource(*newOpsSight, mockFormat, false) + if len(opNamespace) > 1 { + return fmt.Errorf("more than 1 Synopsys Operator found in your cluster") } + operatorNamespace = opNamespace[0] + } - log.Infof("updating OpsSight '%s' in namespace '%s'...", opsSightName, opsSightNamespace) - _, err = util.UpdateOpsSight(opsSightClient, crdnamespace, newOpsSight) - if err != nil { - return fmt.Errorf("error updating OpsSight '%s' due to %+v", newOpsSight.Name, err) - } - log.Infof("successfully submitted updates to OpsSight '%s' in namespace '%s'", opsSightName, opsSightNamespace) - return nil - }, + crdNamespace := namespace + if isClusterScoped { + crdNamespace = metav1.NamespaceAll + } + + currOpssight, err := util.GetOpsSight(opsSightClient, crdNamespace, opssightName, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("error getting OpsSight '%s' in namespace '%s' due to %+v", opssightName, crdNamespace, err) + } + + if err := migrateOpssight(currOpssight, operatorNamespace, cmd.Flags()); err != nil { + // TODO restart operator if migration failed? + return err + } + return nil } func updateOpsSightExternalHost(ops *opssightapi.OpsSight, scheme, domain, port, user, pass, scanLimit string) (*opssightapi.OpsSight, error) { @@ -617,8 +680,8 @@ func updateOpsSightExternalHost(ops *opssightapi.OpsSight, scheme, domain, port, // updateOpsSightExternalHostCmd updates an external host for an OpsSight intance's component var updateOpsSightExternalHostCmd = &cobra.Command{ - Use: "externalhost NAME SCHEME DOMAIN PORT USER PASSWORD SCANLIMIT", - Example: "synopsysctl update opssight externalhost scheme domain 80 user pass 50\nsynopsysctl update opssight externalhost scheme domain 80 user pass 50 -n ", + Use: "externalhost NAME SCHEME DOMAIN PORT USER PASSWORD SCANLIMIT -n NAMESPACE", + Example: "synopsysctl update opssight externalhost scheme domain 80 user pass 50 -n ", Short: "Update an external host for an OpsSight intance's component", SilenceUsage: true, SilenceErrors: true, @@ -640,6 +703,8 @@ var updateOpsSightExternalHostCmd = &cobra.Command{ return nil }, RunE: func(cmd *cobra.Command, args []string) error { + // TODO - convert to update for Helm + // In order to call this function they must have already upgraded to use helm (add a check) mockMode := cmd.Flags().Lookup("mock").Changed opsSightName := args[0] opsSightNamespace, crdnamespace, _, err := getInstanceInfo(false, util.OpsSightCRDName, util.OpsSightName, namespace, opsSightName) @@ -673,8 +738,8 @@ var updateOpsSightExternalHostCmd = &cobra.Command{ // updateOpsSightExternalHostNativeCmd prints the Kubernetes resources with updates to an external host for an OpsSight intance's component var updateOpsSightExternalHostNativeCmd = &cobra.Command{ - Use: "externalhost NAME SCHEME DOMAIN PORT USER PASSWORD SCANLIMIT", - Example: "synopsysctl update opssight externalhost native scheme domain 80 user pass 50\nsynopsysctl update opssight externalhost native scheme domain 80 user pass 50 -n ", + Use: "externalhost NAME SCHEME DOMAIN PORT USER PASSWORD SCANLIMIT -n NAMESPACE", + Example: "synopsysctl update opssight externalhost native scheme domain 80 user pass 50 -n ", Short: "Print the Kubernetes resources with updates to an external host for an OpsSight intance's component", SilenceUsage: true, SilenceErrors: true, @@ -696,6 +761,8 @@ var updateOpsSightExternalHostNativeCmd = &cobra.Command{ return nil }, RunE: func(cmd *cobra.Command, args []string) error { + // TODO - convert to update for Helm + // In order to call this function they must have already upgraded to use helm (add a check) opsSightName := args[0] opsSightNamespace, crdnamespace, _, err := getInstanceInfo(false, util.OpsSightCRDName, util.OpsSightName, namespace, opsSightName) if err != nil { @@ -727,8 +794,8 @@ func updateOpsSightAddRegistry(ops *opssightapi.OpsSight, url, user, pass string // updateOpsSightAddRegistryCmd adds an internal registry to an OpsSight instance's ImageFacade var updateOpsSightAddRegistryCmd = &cobra.Command{ - Use: "registry NAME URL USER PASSWORD", - Example: "synopsysctl update opssight registry reg_url reg_username reg_password\nsynopsysctl update opssight registry reg_url reg_username reg_password -n ", + Use: "registry NAME URL USER PASSWORD -n NAMESPACE", + Example: "synopsysctl update opssight registry reg_url reg_username reg_password -n ", Short: "Add an internal registry to an OpsSight instance's ImageFacade", SilenceUsage: true, SilenceErrors: true, @@ -740,6 +807,8 @@ var updateOpsSightAddRegistryCmd = &cobra.Command{ return nil }, RunE: func(cmd *cobra.Command, args []string) error { + // TODO - convert to update for Helm + // In order to call this function they must have already upgraded to use helm (add a check) mockMode := cmd.Flags().Lookup("mock").Changed opsSightName := args[0] opsSightNamespace, crdnamespace, _, err := getInstanceInfo(false, util.OpsSightCRDName, util.OpsSightName, namespace, opsSightName) @@ -773,8 +842,8 @@ var updateOpsSightAddRegistryCmd = &cobra.Command{ // updateOpsSightAddRegistryNativeCmd prints the Kubernetes resources with updates from adding an internal registry to an OpsSight instance's ImageFacade var updateOpsSightAddRegistryNativeCmd = &cobra.Command{ - Use: "native NAME URL USER PASSWORD", - Example: "synopsysctl update opssight registry native reg_url reg_username reg_password\nsynopsysctl update opssight registry native reg_url reg_username reg_password -n ", + Use: "native NAME URL USER PASSWORD -n NAMESPACE", + Example: "synopsysctl update opssight registry native reg_url reg_username reg_password -n ", Short: "Print the Kubernetes resources with updates from adding an internal registry to an OpsSight instance's ImageFacade", SilenceUsage: true, SilenceErrors: true, @@ -786,6 +855,8 @@ var updateOpsSightAddRegistryNativeCmd = &cobra.Command{ return nil }, RunE: func(cmd *cobra.Command, args []string) error { + // TODO - convert to update for Helm + // In order to call this function they must have already upgraded to use helm (add a check) opsSightName := args[0] opsSightNamespace, crdnamespace, _, err := getInstanceInfo(false, util.OpsSightCRDName, util.OpsSightName, namespace, opsSightName) if err != nil { diff --git a/pkg/synopsysctl/constants.go b/pkg/synopsysctl/constants.go index 1d8f6b8f0..b320fa1f0 100644 --- a/pkg/synopsysctl/constants.go +++ b/pkg/synopsysctl/constants.go @@ -55,7 +55,14 @@ var baseURL = "https://raw.githubusercontent.com/blackducksoftware/releases/mast var baseChartRepository = "https://chartmuseum.cloudnative.sig-clops.synopsys.com" +// Black Duck Constants var blackduckChartRepository = fmt.Sprintf("%s/charts/blackduck-2020.4.0.tgz", baseChartRepository) + +// Opssight Constants +var opssightVersion = "0.0.0" +var opssightChartRepository = fmt.Sprintf("%s/charts/opssight-%s.tgz", baseChartRepository, opssightVersion) + +// Polaris Constants var polarisName = "polaris" var polarisChartRepository = fmt.Sprintf("%s/charts/polaris-helmchart-2020.03.tgz", baseChartRepository) diff --git a/pkg/synopsysctl/opssight_migrate.go b/pkg/synopsysctl/opssight_migrate.go new file mode 100644 index 000000000..5baede64d --- /dev/null +++ b/pkg/synopsysctl/opssight_migrate.go @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2020 Synopsys, Inc. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package synopsysctl + +import ( + "fmt" + + v1 "github.com/blackducksoftware/synopsys-operator/pkg/api/opssight/v1" + "github.com/blackducksoftware/synopsys-operator/pkg/util" + log "github.com/sirupsen/logrus" + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func migrateOpssight(opssight *v1.OpsSight, operatorNamespace string, flags *pflag.FlagSet) error { + // TODO ensure operator is installed and running a recent version that doesn't require additional migration + + log.Debug("Stopping Operator") + soOperatorDeploy, err := util.GetDeployment(kubeClient, operatorNamespace, "synopsys-operator") + if err != nil { + return err + } + + soOperatorDeploy, err = util.PatchDeploymentForReplicas(kubeClient, soOperatorDeploy, util.IntToInt32(0)) + if err != nil { + return err + } + + // Generate Helm values for the current CR Instance + helmValuesMap, err := OpssightV1ToHelmValues(opssight, operatorNamespace) + if err != nil { + return err + } + + // Put helm values into the CobraHelper + updateOpsSightCobraHelper.SetArgs(helmValuesMap) + + // Get Helm Values if User updated more than just the version + updatedHelmValuesMapFromFlags, err := updateOpssightCobraHelper.GenerateHelmFlagsFromCobraFlags(flags) + if err != nil { + return err + } + + log.Info("Upgrading OpsSight") + + // Delete the Current Instance's Resources (except PVCs) + log.Debug("Cleaning Current OpsSight resources") + // TODO wait for resources to be deleted + if err := deleteOpssightComponents(opssight.Namespace, opssight.Name); err != nil { + return err + } + + // Update the Helm Chart Location + chartLocationFlag := flags.Lookup("chart-location-path") + if chartLocationFlag.Changed { + opssightChartRepository = chartLocationFlag.Value.String() + } else { + versionFlag := flags.Lookup("version") + if versionFlag.Changed { + opssightChartRepository = fmt.Sprintf("%s/charts/opssight-%s.tgz", baseChartRepository, versionFlag.Value.String()) + } + } + + // Verify Opssight can be created with Dry-Run before creating resources + err = util.CreateWithHelm3(opssight.Name, opssight.Spec.Namespace, opssightChartRepository, helmValuesMap, kubeConfigPath, true) + if err != nil { + return fmt.Errorf("failed to update OpsSight resources: %+v", err) + } + + // Update any resources not created by Helm... + + // Deploy new Resources + err = util.CreateWithHelm3(opssight.Name, opssight.Spec.Namespace, opssightChartRepository, helmValuesMap, kubeConfigPath, false) + if err != nil { + return fmt.Errorf("failed to update OpsSight resources: %+v", err) + } + + log.Debug("Removing CR") + if err := util.DeleteOpssight(opsSightClient, opssight.Name, opssight.Namespace, &metav1.DeleteOptions{}); err != nil { + return err + } + + log.Debug("Starting Operator") + if _, err := util.PatchDeploymentForReplicas(kubeClient, soOperatorDeploy, util.IntToInt32(1)); err != nil { + return err + } + + return nil +} + +// OpssightV1ToHelmValues converts an Opssight v1 Spec to a Helm Values Map +func OpssightV1ToHelmValues(opssight *v1.Opssight, operatorNamespace string) (map[string]interface{}, error) { + helmValuesMap := make(map[string]interface{}) + + // util.SetHelmValueInMap(helmValuesMap, []string{"opssight", "imageTag"}, opssight.Spec.Version) + + // TODO... + + return helmValuesMap, nil +} + +// deleteOpssightComponents deletes Opssight's resources besides PVCs +// deletes: Deployments, Replication Controllers, Services, ConfigMaps, Secrets, Service Accounts +func deleteOpssightComponents(namespace, name string) error { + appName := "opssight" + + // Deployments + deploy, err := kubeClient.AppsV1().Deployments(namespace).List(metav1.ListOptions{ + LabelSelector: fmt.Sprintf("app=%s, name=%s", appName, name), + }) + if err != nil { + return err + } + for _, v := range deploy.Items { + propagationPolicy := metav1.DeletePropagationBackground + if err := kubeClient.AppsV1().Deployments(namespace).Delete(v.Name, &metav1.DeleteOptions{ + PropagationPolicy: &propagationPolicy, + }); err != nil { + return err + } + } + + // Replication Controllers + rc, err := kubeClient.CoreV1().ReplicationControllers(namespace).List(metav1.ListOptions{ + LabelSelector: fmt.Sprintf("app=%s, name=%s", appName, name), + }) + if err != nil { + return err + } + for _, v := range rc.Items { + propagationPolicy := metav1.DeletePropagationBackground + if err := kubeClient.CoreV1().ReplicationControllers(namespace).Delete(v.Name, &metav1.DeleteOptions{ + PropagationPolicy: &propagationPolicy, + }); err != nil { + return err + } + } + + // Services + svc, err := kubeClient.CoreV1().Services(namespace).List(metav1.ListOptions{ + LabelSelector: fmt.Sprintf("app=%s, name=%s", appName, name), + }) + if err != nil { + return err + } + for _, v := range svc.Items { + if err := kubeClient.CoreV1().Services(namespace).Delete(v.Name, &metav1.DeleteOptions{}); err != nil { + return err + } + } + + // ConfigMaps + cm, err := kubeClient.CoreV1().ConfigMaps(namespace).List(metav1.ListOptions{ + LabelSelector: fmt.Sprintf("app=%s, name=%s", appName, name), + }) + if err != nil { + return err + } + for _, v := range cm.Items { + if err := kubeClient.CoreV1().ConfigMaps(namespace).Delete(v.Name, &metav1.DeleteOptions{}); err != nil { + return err + } + } + + // Secrets + secret, err := kubeClient.CoreV1().Secrets(namespace).List(metav1.ListOptions{ + LabelSelector: fmt.Sprintf("app=%s, name=%s", appName, name), + }) + if err != nil { + return err + } + for _, v := range secret.Items { + if err := kubeClient.CoreV1().Secrets(namespace).Delete(v.Name, &metav1.DeleteOptions{}); err != nil { + return err + } + } + + // Service Accounts + serviceAccounts, err := kubeClient.CoreV1().ServiceAccounts(namespace).List(metav1.ListOptions{ + LabelSelector: fmt.Sprintf("app=%s, name=%s", appName, name), + }) + if err != nil { + return err + } + for _, v := range serviceAccounts.Items { + if err := kubeClient.CoreV1().ServiceAccounts(namespace).Delete(v.Name, &metav1.DeleteOptions{}); err != nil { + return err + } + } + + return nil +}