gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/runtime/kubernetes/client/client.go (about) 1 package client 2 3 import ( 4 "bytes" 5 "crypto/tls" 6 "errors" 7 "io/ioutil" 8 "net/http" 9 "os" 10 "path" 11 12 "gitee.com/liuxuezhan/go-micro-v1.18.0/runtime/kubernetes/client/api" 13 "gitee.com/liuxuezhan/go-micro-v1.18.0/util/log" 14 ) 15 16 var ( 17 // path to kubernetes service account token 18 serviceAccountPath = "/var/run/secrets/kubernetes.io/serviceaccount" 19 // ErrReadNamespace is returned when the names could not be read from service account 20 ErrReadNamespace = errors.New("Could not read namespace from service account secret") 21 ) 22 23 // Client ... 24 type client struct { 25 opts *api.Options 26 } 27 28 // NewClientInCluster creates a Kubernetes client for use from within a k8s pod. 29 func NewClientInCluster() *client { 30 host := "https://" + os.Getenv("KUBERNETES_SERVICE_HOST") + ":" + os.Getenv("KUBERNETES_SERVICE_PORT") 31 32 s, err := os.Stat(serviceAccountPath) 33 if err != nil { 34 log.Fatal(err) 35 } 36 if s == nil || !s.IsDir() { 37 log.Fatal(errors.New("service account not found")) 38 } 39 40 token, err := ioutil.ReadFile(path.Join(serviceAccountPath, "token")) 41 if err != nil { 42 log.Fatal(err) 43 } 44 t := string(token) 45 46 ns, err := detectNamespace() 47 if err != nil { 48 log.Fatal(err) 49 } 50 51 crt, err := CertPoolFromFile(path.Join(serviceAccountPath, "ca.crt")) 52 if err != nil { 53 log.Fatal(err) 54 } 55 56 c := &http.Client{ 57 Transport: &http.Transport{ 58 TLSClientConfig: &tls.Config{ 59 RootCAs: crt, 60 }, 61 DisableCompression: true, 62 }, 63 } 64 65 return &client{ 66 opts: &api.Options{ 67 Client: c, 68 Host: host, 69 Namespace: ns, 70 BearerToken: &t, 71 }, 72 } 73 } 74 75 func detectNamespace() (string, error) { 76 nsPath := path.Join(serviceAccountPath, "namespace") 77 78 // Make sure it's a file and we can read it 79 if s, e := os.Stat(nsPath); e != nil { 80 return "", e 81 } else if s.IsDir() { 82 return "", ErrReadNamespace 83 } 84 85 // Read the file, and cast to a string 86 if ns, e := ioutil.ReadFile(nsPath); e != nil { 87 return string(ns), e 88 } else { 89 return string(ns), nil 90 } 91 } 92 93 // Create creates new API object 94 func (c *client) Create(r *Resource) error { 95 b := new(bytes.Buffer) 96 if err := renderTemplate(r.Kind, b, r.Value); err != nil { 97 return err 98 } 99 100 return api.NewRequest(c.opts). 101 Post(). 102 SetHeader("Content-Type", "application/yaml"). 103 Resource(r.Kind). 104 Body(b). 105 Do(). 106 Error() 107 } 108 109 // Get queries API objects and stores the result in r 110 func (c *client) Get(r *Resource, labels map[string]string) error { 111 return api.NewRequest(c.opts). 112 Get(). 113 Resource(r.Kind). 114 Params(&api.Params{LabelSelector: labels}). 115 Do(). 116 Into(r.Value) 117 } 118 119 // Update updates API object 120 func (c *client) Update(r *Resource) error { 121 req := api.NewRequest(c.opts). 122 Patch(). 123 SetHeader("Content-Type", "application/strategic-merge-patch+json"). 124 Resource(r.Kind). 125 Name(r.Name) 126 127 switch r.Kind { 128 case "service": 129 req.Body(r.Value.(*Service)) 130 case "deployment": 131 req.Body(r.Value.(*Deployment)) 132 default: 133 return errors.New("unsupported resource") 134 } 135 136 return req.Do().Error() 137 } 138 139 // Delete removes API object 140 func (c *client) Delete(r *Resource) error { 141 return api.NewRequest(c.opts). 142 Delete(). 143 Resource(r.Kind). 144 Name(r.Name). 145 Do(). 146 Error() 147 } 148 149 // List lists API objects and stores the result in r 150 func (c *client) List(r *Resource) error { 151 labels := map[string]string{ 152 "micro": "service", 153 } 154 return c.Get(r, labels) 155 }