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  }