github.com/jenkins-x/jx/v2@v2.1.155/pkg/kube/git_services.go (about) 1 package kube 2 3 import ( 4 "fmt" 5 "io" 6 "net/url" 7 "strings" 8 9 "github.com/jenkins-x/jx-logging/pkg/log" 10 "github.com/jenkins-x/jx/v2/pkg/auth" 11 "github.com/jenkins-x/jx/v2/pkg/kube/naming" 12 13 "github.com/pkg/errors" 14 15 v1 "github.com/jenkins-x/jx-api/pkg/apis/jenkins.io/v1" 16 "github.com/jenkins-x/jx-api/pkg/client/clientset/versioned" 17 "github.com/jenkins-x/jx/v2/pkg/gits" 18 "k8s.io/client-go/kubernetes" 19 20 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 ) 22 23 // EnsureGitServiceExistsForHost ensures that there is a GitService CRD for the given host and kind 24 func EnsureGitServiceExistsForHost(jxClient versioned.Interface, devNs string, kind string, name string, gitUrl string, out io.Writer) error { 25 if kind == "" || (kind == "github" && gitUrl == gits.GitHubURL) || gitUrl == "" { 26 return nil 27 } 28 29 gitServices := jxClient.JenkinsV1().GitServices(devNs) 30 list, err := gitServices.List(metav1.ListOptions{}) 31 if err != nil { 32 return errors.Wrap(err, "failed to list git services") 33 } 34 for _, g := range list.Items { 35 gs := g 36 if gitUrlsEqual(gs.Spec.URL, gitUrl) { 37 oldKind := gs.Spec.GitKind 38 if oldKind != kind { 39 fmt.Fprintf(out, "Updating GitService %s as the kind has changed from %s to %s\n", gs.Name, oldKind, kind) 40 gs.Spec.GitKind = kind 41 _, err = gitServices.PatchUpdate(&gs) 42 if err != nil { 43 return fmt.Errorf("Failed to update kind on GitService with name %s: %s", gs.Name, err) 44 } 45 return errors.Wrap(err, "failed to PatchUpdate") 46 } else { 47 log.Logger().Infof("already has GitService %s in namespace %s for URL %s", gs.Name, devNs, gitUrl) 48 return nil 49 } 50 } 51 } 52 if name == "" { 53 u, err := url.Parse(gitUrl) 54 if err != nil { 55 return errors.Wrapf(err, "no name supplied and could not parse URL %s", u) 56 } 57 name = u.Host 58 } 59 60 // not found so lets create a new GitService 61 gitSvc := &v1.GitService{ 62 ObjectMeta: metav1.ObjectMeta{ 63 Name: naming.ToValidNameWithDots(name), 64 }, 65 Spec: v1.GitServiceSpec{ 66 Name: name, 67 URL: gitUrl, 68 GitKind: kind, 69 }, 70 } 71 current, err := gitServices.Get(name, metav1.GetOptions{}) 72 if err != nil { 73 _, err = gitServices.Create(gitSvc) 74 if err != nil { 75 return errors.Wrapf(err, "failed to create GitService with name %s", gitSvc.Name) 76 } 77 log.Logger().Infof("GitService %s created in namespace %s for URL %s", gitSvc.Name, devNs, gitUrl) 78 } else if current != nil { 79 if current.Spec.URL != gitSvc.Spec.URL || current.Spec.GitKind != gitSvc.Spec.GitKind { 80 current.Spec.URL = gitSvc.Spec.URL 81 current.Spec.GitKind = gitSvc.Spec.GitKind 82 83 _, err = gitServices.PatchUpdate(current) 84 if err != nil { 85 return errors.Wrapf(err, "failed to PatchUpdate GitService with name %s", gitSvc.Name) 86 } 87 log.Logger().Infof("GitService %s updated in namespace %s for URL %s", gitSvc.Name, devNs, gitUrl) 88 } 89 } 90 return nil 91 } 92 93 // GetGitServiceKind returns the kind of the given host if one can be found or "" 94 func GetGitServiceKind(jxClient versioned.Interface, kubeClient kubernetes.Interface, devNs string, clusterAuthConfig *auth.AuthConfig, gitServiceURL string) (string, error) { 95 answer := gits.SaasGitKind(gitServiceURL) 96 if answer != "" { 97 return answer, nil 98 } 99 100 if clusterAuthConfig != nil { 101 clusterServer := clusterAuthConfig.GetServer(gitServiceURL) 102 if clusterServer != nil { 103 return clusterServer.Kind, nil 104 } 105 } 106 107 answer, err := GetServiceKindFromSecrets(kubeClient, devNs, gitServiceURL) 108 if err == nil && answer != "" { 109 return answer, nil 110 } 111 112 return getServiceKindFromGitServices(jxClient, devNs, gitServiceURL) 113 } 114 115 // GetServiceKindFromSecrets gets the kind of service from secrets 116 func GetServiceKindFromSecrets(kubeClient kubernetes.Interface, ns string, gitServiceURL string) (string, error) { 117 secretList, err := kubeClient.CoreV1().Secrets(ns).List(metav1.ListOptions{}) 118 if err != nil { 119 return "", errors.Wrap(err, "failed to list the secrets") 120 } 121 122 // note sometimes the Git secret is just called 'jx-pipeline-git' if its created as part of 123 // 'jx create cluster --git-provider-url' - so lets handle the missing - on the name 124 secretNamePrefix := strings.TrimSuffix(SecretJenkinsPipelineGitCredentials, "-") 125 126 for _, secret := range secretList.Items { 127 if strings.HasPrefix(secret.GetName(), secretNamePrefix) { 128 annotations := secret.GetAnnotations() 129 url, ok := annotations[AnnotationURL] 130 if !ok { 131 continue 132 } 133 if gitUrlsEqual(url, gitServiceURL) { 134 labels := secret.GetLabels() 135 serviceKind, ok := labels[LabelServiceKind] 136 if !ok { 137 return "", fmt.Errorf("no service kind label found on secret '%s' for Git service '%s'", 138 secret.GetName(), gitServiceURL) 139 } 140 if serviceKind == "" { 141 kind := labels[LabelKind] 142 if kind == "git" { 143 serviceKind = gits.SaasGitKind(gitServiceURL) 144 if serviceKind == "" { 145 // lets default to github? 146 serviceKind = gits.KindGitHub 147 } 148 } 149 } 150 return serviceKind, nil 151 } 152 } 153 } 154 return "", fmt.Errorf("no secret found with configuration for '%s' Git service", gitServiceURL) 155 } 156 157 func getServiceKindFromGitServices(jxClient versioned.Interface, ns string, gitServiceURL string) (string, error) { 158 gitServices := jxClient.JenkinsV1().GitServices(ns) 159 list, err := gitServices.List(metav1.ListOptions{}) 160 if err == nil { 161 for _, gs := range list.Items { 162 if gitUrlsEqual(gs.Spec.URL, gitServiceURL) { 163 return gs.Spec.GitKind, nil 164 } 165 } 166 } 167 return "", fmt.Errorf("no Git service resource found with URL '%s' in namespace %s", gitServiceURL, ns) 168 } 169 170 func gitUrlsEqual(url1 string, url2 string) bool { 171 return url1 == url2 || strings.TrimSuffix(url1, "/") == strings.TrimSuffix(url2, "/") 172 }