github.com/jenkins-x/jx/v2@v2.1.155/pkg/cmd/create/create_addon_pipeline_events.go (about)

     1  package create
     2  
     3  import (
     4  	"strings"
     5  	"time"
     6  
     7  	"github.com/jenkins-x/jx/v2/pkg/cmd/create/options"
     8  
     9  	"github.com/jenkins-x/jx/v2/pkg/cmd/helper"
    10  
    11  	"github.com/jenkins-x/jx/v2/pkg/helm"
    12  
    13  	"github.com/jenkins-x/jx/v2/pkg/kube/services"
    14  
    15  	"github.com/pkg/errors"
    16  	"github.com/spf13/cobra"
    17  	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    18  
    19  	"fmt"
    20  
    21  	"github.com/jenkins-x/jx-logging/pkg/log"
    22  	"github.com/jenkins-x/jx/v2/pkg/cmd/opts"
    23  	"github.com/jenkins-x/jx/v2/pkg/cmd/templates"
    24  	"github.com/jenkins-x/jx/v2/pkg/kube"
    25  	"github.com/jenkins-x/jx/v2/pkg/util"
    26  )
    27  
    28  const (
    29  	defaultPEName        = "pipeline-events"
    30  	defaultPENamespace   = "pipeline-events"
    31  	defaultPEReleaseName = "jx-pipeline-events"
    32  	defaultPEVersion     = "0.0.11"
    33  	kibanaServiceName    = "jx-pipeline-events-kibana"
    34  	kibanaDeploymentName = "jx-pipeline-events-kibana"
    35  	esDeploymentName     = "jx-pipeline-events-elasticsearch-client"
    36  )
    37  
    38  var (
    39  	createAddonPipelineEventsLong = templates.LongDesc(`
    40  		Creates the Jenkins X pipeline events addon
    41  `)
    42  
    43  	createAddonPipelineEventsExample = templates.Examples(`
    44  		# Create the pipeline-events addon
    45  		jx create addon pipeline-events
    46  
    47  		# Create the pipeline-events addon in a custom namespace
    48  		jx create addon pipeline-events -n mynamespace
    49  	`)
    50  )
    51  
    52  // CreateAddonPipelineEventsOptions the options for the create spring command
    53  type CreateAddonPipelineEventsOptions struct {
    54  	CreateAddonOptions
    55  	Password string
    56  }
    57  
    58  // NewCmdCreateAddonPipelineEvents creates a command object for the "create" command
    59  func NewCmdCreateAddonPipelineEvents(commonOpts *opts.CommonOptions) *cobra.Command {
    60  	options := &CreateAddonPipelineEventsOptions{
    61  		CreateAddonOptions: CreateAddonOptions{
    62  			CreateOptions: options.CreateOptions{
    63  				CommonOptions: commonOpts,
    64  			},
    65  		},
    66  	}
    67  
    68  	cmd := &cobra.Command{
    69  		Use:     "pipeline-events",
    70  		Short:   "Create the pipeline events addon",
    71  		Aliases: []string{"pe"},
    72  		Long:    createAddonPipelineEventsLong,
    73  		Example: createAddonPipelineEventsExample,
    74  		Run: func(cmd *cobra.Command, args []string) {
    75  			options.Cmd = cmd
    76  			options.Args = args
    77  			err := options.Run()
    78  			helper.CheckErr(err)
    79  		},
    80  	}
    81  
    82  	options.addFlags(cmd, defaultPENamespace, defaultPEReleaseName, defaultPEVersion)
    83  
    84  	cmd.Flags().StringVarP(&options.Password, "password", "p", "", "Password to access pipeline-events services such as Kibana and Elasticsearch.  Defaults to default Jenkins X admin password.")
    85  	return cmd
    86  }
    87  
    88  // Run implements the command
    89  func (o *CreateAddonPipelineEventsOptions) Run() error {
    90  
    91  	if o.ReleaseName == "" {
    92  		return util.MissingOption(optionRelease)
    93  	}
    94  
    95  	err := o.EnsureHelm()
    96  	if err != nil {
    97  		return errors.Wrap(err, "failed to ensure that helm is present")
    98  	}
    99  	client, err := o.KubeClient()
   100  	if err != nil {
   101  		return err
   102  	}
   103  
   104  	_, devNamespace, err := o.KubeClientAndDevNamespace()
   105  	if err != nil {
   106  		return fmt.Errorf("cannot find a dev team namespace to get existing exposecontroller config from. %v", err)
   107  	}
   108  
   109  	log.Logger().Infof("found dev namespace %s", devNamespace)
   110  
   111  	setValues := strings.Split(o.SetValues, ",")
   112  	helmOptions := helm.InstallChartOptions{
   113  		Chart:       o.Chart,
   114  		ReleaseName: o.ReleaseName,
   115  		Version:     o.Version,
   116  		Ns:          o.Namespace,
   117  		SetValues:   setValues,
   118  	}
   119  	err = o.InstallChartWithOptions(helmOptions)
   120  	if err != nil {
   121  		return fmt.Errorf("elasticsearch deployment failed: %v", err)
   122  	}
   123  
   124  	log.Logger().Info("waiting for elasticsearch deployment to be ready, this can take a few minutes")
   125  
   126  	err = kube.WaitForDeploymentToBeReady(client, esDeploymentName, o.Namespace, 10*time.Minute)
   127  	if err != nil {
   128  		return err
   129  	}
   130  	log.Logger().Info("waiting for kibana deployment to be ready, this can take a few minutes")
   131  
   132  	err = kube.WaitForDeploymentToBeReady(client, kibanaDeploymentName, o.Namespace, 10*time.Minute)
   133  	if err != nil {
   134  		return err
   135  	}
   136  
   137  	// annotate the kibana and elasticsearch services so exposecontroller can create an ingress rule
   138  	err = o.addExposecontrollerAnnotations(kibanaServiceName)
   139  	if err != nil {
   140  		return err
   141  	}
   142  
   143  	esServiceName := kube.AddonServices[defaultPEName]
   144  	err = o.addExposecontrollerAnnotations(esServiceName)
   145  	if err != nil {
   146  		return err
   147  	}
   148  
   149  	if o.Password == "" {
   150  		o.Password, err = o.GetDefaultAdminPassword(devNamespace)
   151  		if err != nil {
   152  			return err
   153  		}
   154  	}
   155  	// create the ingress rule
   156  	err = o.Expose(devNamespace, o.Namespace, o.Password)
   157  	if err != nil {
   158  		return err
   159  	}
   160  
   161  	// get the external services URL
   162  	kIng, err := services.GetServiceURLFromName(client, kibanaServiceName, o.Namespace)
   163  	if err != nil {
   164  		return fmt.Errorf("failed to get external URL for service %s: %v", kibanaServiceName, err)
   165  	}
   166  
   167  	// get the external services URL
   168  	esIng, err := services.GetServiceURLFromName(client, esServiceName, o.Namespace)
   169  	if err != nil {
   170  		return fmt.Errorf("failed to get external URL for service %s: %v", kibanaServiceName, err)
   171  	}
   172  
   173  	// create the local addonAuth.yaml file so `jx get cve` commands work
   174  	tokenOptions := CreateTokenAddonOptions{
   175  		Password: o.Password,
   176  		Username: "admin",
   177  		ServerFlags: opts.ServerFlags{
   178  			ServerURL:  esIng,
   179  			ServerName: esDeploymentName,
   180  		},
   181  		Kind: kube.ValueKindPipelineEvent,
   182  		CreateOptions: options.CreateOptions{
   183  			CommonOptions: o.CommonOptions,
   184  		},
   185  	}
   186  	err = tokenOptions.Run()
   187  	if err != nil {
   188  		return fmt.Errorf("failed to create addonAuth.yaml error: %v", err)
   189  	}
   190  
   191  	_, currentNamespace, err := o.KubeClientAndNamespace()
   192  	if err != nil {
   193  		return errors.Wrap(err, "getting current namespace")
   194  	}
   195  	_, err = client.CoreV1().Services(currentNamespace).Get(esServiceName, meta_v1.GetOptions{})
   196  	if err != nil {
   197  		// create a services link
   198  		err = services.CreateServiceLink(client, currentNamespace, o.Namespace, esServiceName, esIng)
   199  		if err != nil {
   200  			return fmt.Errorf("failed creating a service link for %s in target namespace %s", esServiceName, o.Namespace)
   201  		}
   202  	}
   203  
   204  	log.Logger().Infof("kibana is available and running %s", kIng)
   205  	return nil
   206  }
   207  func (o *CreateAddonPipelineEventsOptions) addExposecontrollerAnnotations(serviceName string) error {
   208  	client, err := o.KubeClient()
   209  	if err != nil {
   210  		return err
   211  	}
   212  
   213  	svc, err := client.CoreV1().Services(o.Namespace).Get(serviceName, meta_v1.GetOptions{})
   214  	if err != nil {
   215  		return fmt.Errorf("failed to get Service %s: %v", serviceName, err)
   216  	}
   217  	if svc.Annotations == nil {
   218  		svc.Annotations = map[string]string{}
   219  	}
   220  
   221  	annotationsUpdated := false
   222  	if svc.Annotations[kube.AnnotationExpose] == "" {
   223  		svc.Annotations[kube.AnnotationExpose] = "true"
   224  		annotationsUpdated = true
   225  	}
   226  	if svc.Annotations[kube.AnnotationIngress] == "" {
   227  		svc.Annotations[kube.AnnotationIngress] = "nginx.ingress.kubernetes.io/auth-type: basic\nnginx.ingress.kubernetes.io/auth-secret: jx-basic-auth"
   228  		annotationsUpdated = true
   229  	}
   230  	if annotationsUpdated {
   231  		svc, err = client.CoreV1().Services(o.Namespace).Update(svc)
   232  		if err != nil {
   233  			return fmt.Errorf("failed to update service %s/%s", o.Namespace, serviceName)
   234  		}
   235  	}
   236  	return nil
   237  }