github.com/GoogleContainerTools/skaffold/v2@v2.13.2/pkg/webhook/kubernetes/service.go (about) 1 /* 2 Copyright 2019 The Skaffold Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package kubernetes 18 19 import ( 20 "context" 21 "fmt" 22 "time" 23 24 "github.com/google/go-github/github" 25 v1 "k8s.io/api/core/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/util/wait" 28 29 kubernetesclient "github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/kubernetes/client" 30 "github.com/GoogleContainerTools/skaffold/v2/pkg/webhook/constants" 31 "github.com/GoogleContainerTools/skaffold/v2/pkg/webhook/labels" 32 ) 33 34 // CreateService creates a service for the deployment to bind to 35 // and returns the external IP of the service 36 func CreateService(pr *github.PullRequestEvent) (*v1.Service, error) { 37 client, err := kubernetesclient.DefaultClient() 38 if err != nil { 39 return nil, fmt.Errorf("getting Kubernetes client: %w", err) 40 } 41 42 l := labels.GenerateLabelsFromPR(pr.GetNumber()) 43 key, val := labels.RetrieveLabel(pr.GetNumber()) 44 selector := map[string]string{key: val} 45 46 svc := &v1.Service{ 47 ObjectMeta: metav1.ObjectMeta{ 48 Name: serviceName(pr.GetNumber()), 49 Labels: l, 50 }, 51 Spec: v1.ServiceSpec{ 52 Type: v1.ServiceTypeLoadBalancer, 53 Ports: []v1.ServicePort{ 54 { 55 Port: constants.HugoPort, 56 }, 57 }, 58 Selector: selector, 59 }, 60 } 61 return client.CoreV1().Services(constants.Namespace).Create(context.Background(), svc, metav1.CreateOptions{}) 62 } 63 64 // GetExternalIP polls the service until an external IP is available and returns it 65 func GetExternalIP(s *v1.Service) (string, error) { 66 var ip string 67 err := wait.PollImmediate(time.Second*5, time.Minute*5, func() (bool, error) { 68 svc, err := getService(s) 69 if err != nil { 70 return false, nil 71 } 72 if len(svc.Status.LoadBalancer.Ingress) > 0 { 73 ip = svc.Status.LoadBalancer.Ingress[0].IP 74 return true, nil 75 } 76 return false, nil 77 }) 78 return ip, err 79 } 80 81 func serviceName(prNumber int) string { 82 return fmt.Sprintf("docs-controller-svc-%d", prNumber) 83 } 84 85 func getService(svc *v1.Service) (*v1.Service, error) { 86 client, err := kubernetesclient.DefaultClient() 87 if err != nil { 88 return nil, fmt.Errorf("getting Kubernetes client: %w", err) 89 } 90 91 return client.CoreV1().Services(svc.Namespace).Get(context.Background(), svc.Name, metav1.GetOptions{}) 92 }