github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/cmd/step/step_link_services.go (about) 1 package step 2 3 import ( 4 "fmt" 5 6 "github.com/olli-ai/jx/v2/pkg/cmd/opts/step" 7 8 "github.com/olli-ai/jx/v2/pkg/cmd/helper" 9 10 "github.com/jenkins-x/jx-logging/pkg/log" 11 "github.com/olli-ai/jx/v2/pkg/cmd/opts" 12 "github.com/olli-ai/jx/v2/pkg/cmd/templates" 13 "github.com/olli-ai/jx/v2/pkg/util" 14 "github.com/spf13/cobra" 15 corev1 "k8s.io/api/core/v1" 16 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 17 ) 18 19 const ( 20 fromNamespace = "from-namespace" 21 toNamespace = "to-namespace" 22 includes = "includes" 23 excludes = "excludes" 24 ) 25 26 var ( 27 StepLinkServicesLong = templates.LongDesc(` 28 This pipeline step helps to link microservices from different namespaces like staging/production onto a preview environment 29 `) 30 31 StepLinkServicesExample = templates.Examples(` 32 #Link services from jx-staging namespace to the current namespace 33 jx step link services --from-namespace jx-staging 34 35 #Link services from jx-staging namespace to the jx-prod namespace 36 jx step link services --from-namespace jx-staging --to-namespace jx-prod 37 38 #Link services from jx-staging namespace to the jx-prod namespace including all but the ones starting with the characters 'cheese' 39 jx step link services --from-namespace jx-staging --to-namespace jx-prod --includes * --excludes cheese* 40 `) 41 ) 42 43 // StepLinkServicesOptions contains the command line flags 44 type StepLinkServicesOptions struct { 45 step.StepOptions 46 FromNamespace string 47 ToNamespace string 48 Includes []string 49 Excludes []string 50 } 51 52 // NewCmdStepLinkServices Creates a new Command object 53 func NewCmdStepLinkServices(commonOpts *opts.CommonOptions) *cobra.Command { 54 options := &StepLinkServicesOptions{ 55 StepOptions: step.StepOptions{ 56 CommonOptions: commonOpts, 57 }, 58 } 59 60 cmd := &cobra.Command{ 61 Use: "link services", 62 Short: "achieve service linking in preview environments", 63 Long: StepLinkServicesLong, 64 Example: StepLinkServicesExample, 65 Run: func(cmd *cobra.Command, args []string) { 66 options.Cmd = cmd 67 options.Args = args 68 err := options.Run() 69 helper.CheckErr(err) 70 }, 71 } 72 73 cmd.Flags().StringVarP(&options.FromNamespace, fromNamespace, "f", "", "The source namespace from which the linking would happen") 74 cmd.Flags().StringVarP(&options.ToNamespace, toNamespace, "t", "", "The destination namespace to which the linking would happen") 75 cmd.Flags().StringArrayVarP(&options.Includes, includes, "i", []string{}, "What services from source namespace to include in the linking process") 76 cmd.Flags().StringArrayVarP(&options.Excludes, excludes, "e", []string{}, "What services from the source namespace to exclude from the linking process") 77 return cmd 78 } 79 80 // Run implements this command 81 func (o *StepLinkServicesOptions) Run() error { 82 fromNs := o.FromNamespace 83 if fromNs == "" { 84 return util.MissingOption(fromNamespace) 85 } 86 kubeClient, currentNs, err := o.KubeClientAndNamespace() 87 if err != nil { 88 return err 89 } 90 targetNamespace := o.ToNamespace 91 if targetNamespace == "" { 92 //to-namespace wasn't supplied, let's assume it is current namespace 93 targetNamespace = currentNs 94 } 95 if targetNamespace == "" { 96 //We don't want to continue if we still can't derive to-namespace 97 return util.MissingOption(toNamespace) 98 } else { 99 serviceList, err := kubeClient.CoreV1().Services(fromNs).List(metav1.ListOptions{}) 100 if err != nil { 101 return err 102 } else { 103 for _, service := range serviceList.Items { 104 name := service.GetName() 105 if util.StringMatchesAny(name, o.Includes, o.Excludes) { 106 targetService, err := kubeClient.CoreV1().Services(targetNamespace).Get(name, metav1.GetOptions{}) 107 create := false 108 if err != nil { 109 copy := corev1.Service{} 110 targetService = © 111 create = true 112 } 113 targetService.Name = name 114 targetService.Namespace = targetNamespace 115 targetService.Annotations = service.Annotations 116 targetService.Labels = service.Labels 117 targetService.Spec = corev1.ServiceSpec{ 118 Type: corev1.ServiceTypeExternalName, 119 ExternalName: fmt.Sprintf("%s.%s.svc.cluster.local", name, fromNs), 120 } 121 122 if create { 123 _, err := kubeClient.CoreV1().Services(targetNamespace).Create(targetService) 124 if err != nil { 125 log.Logger().Warnf("Failed to create the service '%s' in target namespace '%s'. Error: %s", 126 name, targetNamespace, err) 127 } 128 } else { 129 _, err := kubeClient.CoreV1().Services(targetNamespace).Update(targetService) 130 if err != nil { 131 log.Logger().Warnf("Failed to update the service '%s' in target namespace '%s'. Error: %s", 132 name, targetNamespace, err) 133 } 134 } 135 } 136 } 137 } 138 } 139 return nil 140 }