github.com/deemoprobe/k8s-first-commit@v0.0.0-20230430165612-a541f1982be3/pkg/client/client.go (about)

     1  /*
     2  Copyright 2014 Google Inc. All rights reserved.
     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  // A client for the Kubernetes cluster management API
    18  // There are three fundamental objects
    19  //   Task - A single running container
    20  //   TaskForce - A set of co-scheduled Task(s)
    21  //   ReplicationController - A manager for replicating TaskForces
    22  package client
    23  
    24  import (
    25  	"bytes"
    26  	"crypto/tls"
    27  	"encoding/json"
    28  	"fmt"
    29  	"io"
    30  	"io/ioutil"
    31  	"log"
    32  	"net/http"
    33  	"net/url"
    34  	"strings"
    35  
    36  	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
    37  )
    38  
    39  // ClientInterface holds the methods for clients of Kubenetes, an interface to allow mock testing
    40  type ClientInterface interface {
    41  	ListTasks(labelQuery map[string]string) (api.TaskList, error)
    42  	GetTask(name string) (api.Task, error)
    43  	DeleteTask(name string) error
    44  	CreateTask(api.Task) (api.Task, error)
    45  	UpdateTask(api.Task) (api.Task, error)
    46  
    47  	GetReplicationController(name string) (api.ReplicationController, error)
    48  	CreateReplicationController(api.ReplicationController) (api.ReplicationController, error)
    49  	UpdateReplicationController(api.ReplicationController) (api.ReplicationController, error)
    50  	DeleteReplicationController(string) error
    51  
    52  	GetService(name string) (api.Service, error)
    53  	CreateService(api.Service) (api.Service, error)
    54  	UpdateService(api.Service) (api.Service, error)
    55  	DeleteService(string) error
    56  }
    57  
    58  // AuthInfo is used to store authorization information
    59  type AuthInfo struct {
    60  	User     string
    61  	Password string
    62  }
    63  
    64  // Client is the actual implementation of a Kubernetes client.
    65  // Host is the http://... base for the URL
    66  type Client struct {
    67  	Host       string
    68  	Auth       *AuthInfo
    69  	httpClient *http.Client
    70  }
    71  
    72  // Underlying base implementation of performing a request.
    73  // method is the HTTP method (e.g. "GET")
    74  // path is the path on the host to hit
    75  // requestBody is the body of the request. Can be nil.
    76  // target the interface to marshal the JSON response into.  Can be nil.
    77  func (client Client) rawRequest(method, path string, requestBody io.Reader, target interface{}) ([]byte, error) {
    78  	request, err := http.NewRequest(method, client.makeURL(path), requestBody)
    79  	if err != nil {
    80  		return []byte{}, err
    81  	}
    82  	if client.Auth != nil {
    83  		request.SetBasicAuth(client.Auth.User, client.Auth.Password)
    84  	}
    85  	tr := &http.Transport{
    86  		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    87  	}
    88  	var httpClient *http.Client
    89  	if client.httpClient != nil {
    90  		httpClient = client.httpClient
    91  	} else {
    92  		httpClient = &http.Client{Transport: tr}
    93  	}
    94  	response, err := httpClient.Do(request)
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  	if response.StatusCode != 200 {
    99  		return nil, fmt.Errorf("request [%s %s] failed (%d) %s", method, client.makeURL(path), response.StatusCode, response.Status)
   100  	}
   101  	defer response.Body.Close()
   102  	body, err := ioutil.ReadAll(response.Body)
   103  	if err != nil {
   104  		return body, err
   105  	}
   106  	if target != nil {
   107  		err = json.Unmarshal(body, target)
   108  	}
   109  	if err != nil {
   110  		log.Printf("Failed to parse: %s\n", string(body))
   111  		// FIXME: no need to return err here?
   112  	}
   113  	return body, err
   114  }
   115  
   116  func (client Client) makeURL(path string) string {
   117  	return client.Host + "/api/v1beta1/" + path
   118  }
   119  
   120  func EncodeLabelQuery(labelQuery map[string]string) string {
   121  	query := make([]string, 0, len(labelQuery))
   122  	for key, value := range labelQuery {
   123  		query = append(query, key+"="+value)
   124  	}
   125  	return url.QueryEscape(strings.Join(query, ","))
   126  }
   127  
   128  func DecodeLabelQuery(labelQuery string) map[string]string {
   129  	result := map[string]string{}
   130  	if len(labelQuery) == 0 {
   131  		return result
   132  	}
   133  	parts := strings.Split(labelQuery, ",")
   134  	for _, part := range parts {
   135  		pieces := strings.Split(part, "=")
   136  		if len(pieces) == 2 {
   137  			result[pieces[0]] = pieces[1]
   138  		} else {
   139  			log.Printf("Invalid label query: %s", labelQuery)
   140  		}
   141  	}
   142  	return result
   143  }
   144  
   145  // ListTasks takes a label query, and returns the list of tasks that match that query
   146  func (client Client) ListTasks(labelQuery map[string]string) (api.TaskList, error) {
   147  	path := "tasks"
   148  	if labelQuery != nil && len(labelQuery) > 0 {
   149  		path += "?labels=" + EncodeLabelQuery(labelQuery)
   150  	}
   151  	var result api.TaskList
   152  	_, err := client.rawRequest("GET", path, nil, &result)
   153  	return result, err
   154  }
   155  
   156  // GetTask takes the name of the task, and returns the corresponding Task object, and an error if it occurs
   157  func (client Client) GetTask(name string) (api.Task, error) {
   158  	var result api.Task
   159  	_, err := client.rawRequest("GET", "tasks/"+name, nil, &result)
   160  	return result, err
   161  }
   162  
   163  // DeleteTask takes the name of the task, and returns an error if one occurs
   164  func (client Client) DeleteTask(name string) error {
   165  	_, err := client.rawRequest("DELETE", "tasks/"+name, nil, nil)
   166  	return err
   167  }
   168  
   169  // CreateTask takes the representation of a task.  Returns the server's representation of the task, and an error, if it occurs
   170  func (client Client) CreateTask(task api.Task) (api.Task, error) {
   171  	var result api.Task
   172  	body, err := json.Marshal(task)
   173  	if err == nil {
   174  		_, err = client.rawRequest("POST", "tasks", bytes.NewBuffer(body), &result)
   175  	}
   176  	return result, err
   177  }
   178  
   179  // UpdateTask takes the representation of a task to update.  Returns the server's representation of the task, and an error, if it occurs
   180  func (client Client) UpdateTask(task api.Task) (api.Task, error) {
   181  	var result api.Task
   182  	body, err := json.Marshal(task)
   183  	if err == nil {
   184  		_, err = client.rawRequest("PUT", "tasks/"+task.ID, bytes.NewBuffer(body), &result)
   185  	}
   186  	return result, err
   187  }
   188  
   189  // GetReplicationController returns information about a particular replication controller
   190  func (client Client) GetReplicationController(name string) (api.ReplicationController, error) {
   191  	var result api.ReplicationController
   192  	_, err := client.rawRequest("GET", "replicationControllers/"+name, nil, &result)
   193  	return result, err
   194  }
   195  
   196  // CreateReplicationController creates a new replication controller
   197  func (client Client) CreateReplicationController(controller api.ReplicationController) (api.ReplicationController, error) {
   198  	var result api.ReplicationController
   199  	body, err := json.Marshal(controller)
   200  	if err == nil {
   201  		_, err = client.rawRequest("POST", "replicationControllers", bytes.NewBuffer(body), &result)
   202  	}
   203  	return result, err
   204  }
   205  
   206  // UpdateReplicationController updates an existing replication controller
   207  func (client Client) UpdateReplicationController(controller api.ReplicationController) (api.ReplicationController, error) {
   208  	var result api.ReplicationController
   209  	body, err := json.Marshal(controller)
   210  	if err == nil {
   211  		_, err = client.rawRequest("PUT", "replicationControllers/"+controller.ID, bytes.NewBuffer(body), &result)
   212  	}
   213  	return result, err
   214  }
   215  
   216  func (client Client) DeleteReplicationController(name string) error {
   217  	_, err := client.rawRequest("DELETE", "replicationControllers/"+name, nil, nil)
   218  	return err
   219  }
   220  
   221  // GetReplicationController returns information about a particular replication controller
   222  func (client Client) GetService(name string) (api.Service, error) {
   223  	var result api.Service
   224  	_, err := client.rawRequest("GET", "services/"+name, nil, &result)
   225  	return result, err
   226  }
   227  
   228  // CreateReplicationController creates a new replication controller
   229  func (client Client) CreateService(svc api.Service) (api.Service, error) {
   230  	var result api.Service
   231  	body, err := json.Marshal(svc)
   232  	if err == nil {
   233  		_, err = client.rawRequest("POST", "services", bytes.NewBuffer(body), &result)
   234  	}
   235  	return result, err
   236  }
   237  
   238  // UpdateReplicationController updates an existing replication controller
   239  func (client Client) UpdateService(svc api.Service) (api.Service, error) {
   240  	var result api.Service
   241  	body, err := json.Marshal(svc)
   242  	if err == nil {
   243  		_, err = client.rawRequest("PUT", "services/"+svc.ID, bytes.NewBuffer(body), &result)
   244  	}
   245  	return result, err
   246  }
   247  
   248  func (client Client) DeleteService(name string) error {
   249  	_, err := client.rawRequest("DELETE", "services/"+name, nil, nil)
   250  	return err
   251  }