github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/cmd/create/create_addon_gloo.go (about) 1 package create 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/olli-ai/jx/v2/pkg/cmd/create/options" 8 9 "github.com/olli-ai/jx/v2/pkg/cmd/edit" 10 "github.com/olli-ai/jx/v2/pkg/packages" 11 12 "github.com/olli-ai/jx/v2/pkg/cmd/helper" 13 14 "github.com/jenkins-x/jx-logging/pkg/log" 15 "github.com/olli-ai/jx/v2/pkg/util" 16 "github.com/pkg/errors" 17 "github.com/spf13/cobra" 18 "k8s.io/client-go/kubernetes" 19 20 "github.com/olli-ai/jx/v2/pkg/cmd/opts" 21 "github.com/olli-ai/jx/v2/pkg/cmd/templates" 22 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 ) 24 25 const ( 26 glooNamespace = "gloo-system" 27 glooClusterIngressProxy = "clusteringress-proxy" 28 knativeServeNamespace = "knative-serving" 29 knativeServeConfig = "config-domain" 30 ) 31 32 var ( 33 createAddonGlooLong = templates.LongDesc(` 34 Create a Gloo and Knative Serve addon for creating serverless applications 35 `) 36 37 createAddonGlooExample = templates.Examples(` 38 # Create the Gloo addon 39 jx create addon gloo 40 `) 41 ) 42 43 // CreateAddonGlooOptions the options for the create spring command 44 type CreateAddonGlooOptions struct { 45 CreateAddonOptions 46 47 GlooNamespace string 48 ClusterIngressProxy string 49 KnativeServeNamespace string 50 KnativeServeConfigMap string 51 } 52 53 // NewCmdCreateAddonGloo creates a command object for the "create" command 54 func NewCmdCreateAddonGloo(commonOpts *opts.CommonOptions) *cobra.Command { 55 options := &CreateAddonGlooOptions{ 56 CreateAddonOptions: CreateAddonOptions{ 57 CreateOptions: options.CreateOptions{ 58 CommonOptions: commonOpts, 59 }, 60 }, 61 } 62 63 cmd := &cobra.Command{ 64 Use: "gloo", 65 Short: "Create a Gloo and Knative Serve addon for creating serverless applications", 66 Aliases: []string{"knative-serve"}, 67 Long: createAddonGlooLong, 68 Example: createAddonGlooExample, 69 Run: func(cmd *cobra.Command, args []string) { 70 options.Cmd = cmd 71 options.Args = args 72 err := options.Run() 73 helper.CheckErr(err) 74 }, 75 } 76 cmd.Flags().StringVarP(&options.GlooNamespace, "namespace", "n", glooNamespace, "The gloo system namespace") 77 cmd.Flags().StringVarP(&options.ClusterIngressProxy, "ingress", "i", glooClusterIngressProxy, "The name of the gloo cluster ingress proxy Service") 78 cmd.Flags().StringVarP(&options.KnativeServeNamespace, "knative-namespace", "k", knativeServeNamespace, "The knative serving namespace") 79 cmd.Flags().StringVarP(&options.KnativeServeConfigMap, "knative-configmap", "c", knativeServeConfig, "The knative serving ConfigMap name") 80 81 return cmd 82 } 83 84 // Run implements the command 85 func (o *CreateAddonGlooOptions) Run() error { 86 if o.GlooNamespace == "" { 87 o.GlooNamespace = glooNamespace 88 } 89 if o.ClusterIngressProxy == "" { 90 o.ClusterIngressProxy = glooClusterIngressProxy 91 } 92 if o.KnativeServeNamespace == "" { 93 o.KnativeServeNamespace = knativeServeNamespace 94 } 95 if o.KnativeServeConfigMap == "" { 96 o.KnativeServeConfigMap = knativeServeConfig 97 } 98 99 // lets ensure glooctl is installed 100 shouldInstall, err := packages.ShouldInstallBinary("glooctl") 101 if err != nil { 102 return errors.Wrapf(err, "failed to check if we need to install glooctl") 103 } 104 105 if shouldInstall { 106 log.Logger().Infof("installing %s", util.ColorInfo("glooctl")) 107 err = o.InstallGlooctl() 108 if err != nil { 109 return errors.Wrapf(err, "failed to install glooctl") 110 } 111 } 112 113 kubeClient, err := o.KubeClient() 114 if err != nil { 115 return err 116 } 117 118 // lets try load the gloo cluster service 119 _, err = kubeClient.CoreV1().Services(o.GlooNamespace).Get(o.ClusterIngressProxy, metav1.GetOptions{}) 120 if err != nil { 121 // we may not have installed gloo yet so lets do that now... 122 err = o.RunCommandVerbose("glooctl", "install", "knative") 123 if err != nil { 124 return errors.Wrapf(err, "failed to install gloo") 125 } 126 } 127 128 ip, err := o.getGlooDomain(kubeClient) 129 if err != nil { 130 return err 131 } 132 if ip == "" { 133 return fmt.Errorf("failed to find the external LoadBalancer IP of the Gloo cluster ingress proxy service %s in namespace %s", o.ClusterIngressProxy, o.GlooNamespace) 134 } 135 externalDomain := ip + ".nip.io" 136 err = o.updateKnativeServeDomain(kubeClient, externalDomain) 137 if err != nil { 138 return errors.Wrapf(err, "failed to update the gloo domain") 139 } 140 141 eo := &edit.EditDeployKindOptions{} 142 eo.CommonOptions = o.CommonOptions 143 eo.Team = true 144 eo.Kind = opts.DeployKindKnative 145 return eo.Run() 146 } 147 148 func (o *CreateAddonGlooOptions) getGlooDomain(kubeClient kubernetes.Interface) (string, error) { 149 loggedWait := false 150 ip := "" 151 fn := func() (bool, error) { 152 svc, err := kubeClient.CoreV1().Services(o.GlooNamespace).Get(o.ClusterIngressProxy, metav1.GetOptions{}) 153 if err != nil { 154 return false, err 155 } 156 157 // lets get the gloo ingress service 158 for _, lb := range svc.Status.LoadBalancer.Ingress { 159 ip = lb.IP 160 if ip != "" { 161 return true, nil 162 } 163 } 164 165 if !loggedWait { 166 loggedWait = true 167 log.Logger().Infof("waiting for external IP on Gloo cluster ingress proxy service %s in namespace %s ...", o.ClusterIngressProxy, o.GlooNamespace) 168 } 169 return false, nil 170 } 171 err := o.RetryUntilTrueOrTimeout(time.Minute*5, time.Second*3, fn) 172 if ip == "" || err != nil { 173 return "", err 174 } 175 log.Logger().Infof("using external IP of gloo LoadBalancer: %s", util.ColorInfo(ip)) 176 return ip, nil 177 } 178 179 func (o *CreateAddonGlooOptions) updateKnativeServeDomain(kubeClient kubernetes.Interface, domain string) error { 180 // lets get the knative serving ConfigMap 181 knativeConfigMaps := kubeClient.CoreV1().ConfigMaps(o.KnativeServeNamespace) 182 cm, err := knativeConfigMaps.Get(o.KnativeServeConfigMap, metav1.GetOptions{}) 183 if err != nil { 184 return errors.Wrapf(err, "failed to load the Knative Serve ConfigMap %s in namespace %s", o.KnativeServeConfigMap, o.KnativeServeNamespace) 185 } 186 cm.Data = map[string]string{ 187 domain: "", 188 } 189 _, err = knativeConfigMaps.Update(cm) 190 if err != nil { 191 return errors.Wrapf(err, "failed to save the Knative Serve ConfigMap %s in namespace %s", o.KnativeServeConfigMap, o.KnativeServeNamespace) 192 } 193 return nil 194 }