mirror of https://github.com/k3s-io/k3s
commit
40c71e8292
|
@ -33,7 +33,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
etcd_servers = flag.String("etcd_servers", "", "Servers for the etcd (http://ip:port).")
|
etcdServers = flag.String("etcd_servers", "", "Servers for the etcd (http://ip:port).")
|
||||||
master = flag.String("master", "", "The address of the Kubernetes API server")
|
master = flag.String("master", "", "The address of the Kubernetes API server")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ func main() {
|
||||||
util.InitLogs()
|
util.InitLogs()
|
||||||
defer util.FlushLogs()
|
defer util.FlushLogs()
|
||||||
|
|
||||||
if len(*etcd_servers) == 0 || len(*master) == 0 {
|
if len(*etcdServers) == 0 || len(*master) == 0 {
|
||||||
glog.Fatal("usage: controller-manager -etcd_servers <servers> -master <master>")
|
glog.Fatal("usage: controller-manager -etcd_servers <servers> -master <master>")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ func main() {
|
||||||
etcd.SetLogger(util.NewLogger("etcd "))
|
etcd.SetLogger(util.NewLogger("etcd "))
|
||||||
|
|
||||||
controllerManager := controller.MakeReplicationManager(
|
controllerManager := controller.MakeReplicationManager(
|
||||||
etcd.NewClient([]string{*etcd_servers}),
|
etcd.NewClient([]string{*etcdServers}),
|
||||||
client.New("http://"+*master, nil))
|
client.New("http://"+*master, nil))
|
||||||
|
|
||||||
controllerManager.Run(10 * time.Second)
|
controllerManager.Run(10 * time.Second)
|
||||||
|
|
|
@ -76,10 +76,10 @@ func startComponents(manifestURL string) (apiServerURL string) {
|
||||||
m := master.New(servers, machineList, fakePodInfoGetter{}, nil, "")
|
m := master.New(servers, machineList, fakePodInfoGetter{}, nil, "")
|
||||||
apiserver := httptest.NewServer(m.ConstructHandler("/api/v1beta1"))
|
apiserver := httptest.NewServer(m.ConstructHandler("/api/v1beta1"))
|
||||||
|
|
||||||
kClient := client.New(apiserver.URL, nil)
|
cl := client.New(apiserver.URL, nil)
|
||||||
kClient.PollPeriod = time.Second * 1
|
cl.PollPeriod = time.Second * 1
|
||||||
kClient.Sync = true
|
cl.Sync = true
|
||||||
controllerManager := controller.MakeReplicationManager(etcd.NewClient(servers), kClient)
|
controllerManager := controller.MakeReplicationManager(etcd.NewClient(servers), cl)
|
||||||
|
|
||||||
controllerManager.Run(1 * time.Second)
|
controllerManager.Run(1 * time.Second)
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ func main() {
|
||||||
glog.Infof("OK - found created pods: %#v", createdPods.List())
|
glog.Infof("OK - found created pods: %#v", createdPods.List())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serve a file for kubelet to read.
|
// ServeCachedManifestFile serves a file for kubelet to read.
|
||||||
func ServeCachedManifestFile() (servingAddress string) {
|
func ServeCachedManifestFile() (servingAddress string) {
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.URL.Path == "/manifest" {
|
if r.URL.Path == "/manifest" {
|
||||||
|
|
|
@ -32,7 +32,8 @@ import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
const APP_VERSION = "0.1"
|
// AppVersion is the current version of kubecfg.
|
||||||
|
const AppVersion = "0.1"
|
||||||
|
|
||||||
// The flag package provides a default help printer via -h switch
|
// The flag package provides a default help printer via -h switch
|
||||||
var (
|
var (
|
||||||
|
@ -97,7 +98,7 @@ func main() {
|
||||||
defer util.FlushLogs()
|
defer util.FlushLogs()
|
||||||
|
|
||||||
if *versionFlag {
|
if *versionFlag {
|
||||||
fmt.Println("Version:", APP_VERSION)
|
fmt.Println("Version:", AppVersion)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,11 +111,11 @@ func main() {
|
||||||
} else {
|
} else {
|
||||||
masterServer = "http://localhost:8080"
|
masterServer = "http://localhost:8080"
|
||||||
}
|
}
|
||||||
parsedUrl, err := url.Parse(masterServer)
|
parsedURL, err := url.Parse(masterServer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatalf("Unable to parse %v as a URL\n", err)
|
glog.Fatalf("Unable to parse %v as a URL\n", err)
|
||||||
}
|
}
|
||||||
if parsedUrl.Scheme != "" && parsedUrl.Scheme != "https" {
|
if parsedURL.Scheme != "" && parsedURL.Scheme != "https" {
|
||||||
secure = false
|
secure = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ var (
|
||||||
syncFrequency = flag.Duration("sync_frequency", 10*time.Second, "Max period between synchronizing running containers and config")
|
syncFrequency = flag.Duration("sync_frequency", 10*time.Second, "Max period between synchronizing running containers and config")
|
||||||
fileCheckFrequency = flag.Duration("file_check_frequency", 20*time.Second, "Duration between checking config files for new data")
|
fileCheckFrequency = flag.Duration("file_check_frequency", 20*time.Second, "Duration between checking config files for new data")
|
||||||
httpCheckFrequency = flag.Duration("http_check_frequency", 20*time.Second, "Duration between checking http for new data")
|
httpCheckFrequency = flag.Duration("http_check_frequency", 20*time.Second, "Duration between checking http for new data")
|
||||||
manifestUrl = flag.String("manifest_url", "", "URL for accessing the container manifest")
|
manifestURL = flag.String("manifest_url", "", "URL for accessing the container manifest")
|
||||||
address = flag.String("address", "127.0.0.1", "The address for the info server to serve on")
|
address = flag.String("address", "127.0.0.1", "The address for the info server to serve on")
|
||||||
port = flag.Uint("port", 10250, "The port for the info server to serve on")
|
port = flag.Uint("port", 10250, "The port for the info server to serve on")
|
||||||
hostnameOverride = flag.String("hostname_override", "", "If non-empty, will use this string as identification instead of the actual hostname.")
|
hostnameOverride = flag.String("hostname_override", "", "If non-empty, will use this string as identification instead of the actual hostname.")
|
||||||
|
@ -80,12 +80,12 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
my_kubelet := kubelet.Kubelet{
|
k := kubelet.Kubelet{
|
||||||
Hostname: string(hostname),
|
Hostname: string(hostname),
|
||||||
DockerClient: dockerClient,
|
DockerClient: dockerClient,
|
||||||
FileCheckFrequency: *fileCheckFrequency,
|
FileCheckFrequency: *fileCheckFrequency,
|
||||||
SyncFrequency: *syncFrequency,
|
SyncFrequency: *syncFrequency,
|
||||||
HTTPCheckFrequency: *httpCheckFrequency,
|
HTTPCheckFrequency: *httpCheckFrequency,
|
||||||
}
|
}
|
||||||
my_kubelet.RunKubelet(*dockerEndpoint, *config, *manifestUrl, *etcdServers, *address, *port)
|
k.RunKubelet(*dockerEndpoint, *config, *manifestURL, *etcdServers, *address, *port)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
config_file = flag.String("configfile", "/tmp/proxy_config", "Configuration file for the proxy")
|
configFile = flag.String("configfile", "/tmp/proxy_config", "Configuration file for the proxy")
|
||||||
etcd_servers = flag.String("etcd_servers", "http://10.240.10.57:4001", "Servers for the etcd cluster (http://ip:port).")
|
etcdServers = flag.String("etcd_servers", "http://10.240.10.57:4001", "Servers for the etcd cluster (http://ip:port).")
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -39,18 +39,18 @@ func main() {
|
||||||
// Set up logger for etcd client
|
// Set up logger for etcd client
|
||||||
etcd.SetLogger(util.NewLogger("etcd "))
|
etcd.SetLogger(util.NewLogger("etcd "))
|
||||||
|
|
||||||
glog.Infof("Using configuration file %s and etcd_servers %s", *config_file, *etcd_servers)
|
glog.Infof("Using configuration file %s and etcd_servers %s", *configFile, *etcdServers)
|
||||||
|
|
||||||
proxyConfig := config.NewServiceConfig()
|
proxyConfig := config.NewServiceConfig()
|
||||||
|
|
||||||
// Create a configuration source that handles configuration from etcd.
|
// Create a configuration source that handles configuration from etcd.
|
||||||
etcdClient := etcd.NewClient([]string{*etcd_servers})
|
etcdClient := etcd.NewClient([]string{*etcdServers})
|
||||||
config.NewConfigSourceEtcd(etcdClient,
|
config.NewConfigSourceEtcd(etcdClient,
|
||||||
proxyConfig.GetServiceConfigurationChannel("etcd"),
|
proxyConfig.GetServiceConfigurationChannel("etcd"),
|
||||||
proxyConfig.GetEndpointsConfigurationChannel("etcd"))
|
proxyConfig.GetEndpointsConfigurationChannel("etcd"))
|
||||||
|
|
||||||
// And create a configuration source that reads from a local file
|
// And create a configuration source that reads from a local file
|
||||||
config.NewConfigSourceFile(*config_file,
|
config.NewConfigSourceFile(*configFile,
|
||||||
proxyConfig.GetServiceConfigurationChannel("file"),
|
proxyConfig.GetServiceConfigurationChannel("file"),
|
||||||
proxyConfig.GetEndpointsConfigurationChannel("file"))
|
proxyConfig.GetEndpointsConfigurationChannel("file"))
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,8 @@ func init() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddKnownTypes registers the types of the arguments to the marshaller of the package api.
|
||||||
|
// Encode() refuses the object unless its type is registered with AddKnownTypes.
|
||||||
func AddKnownTypes(types ...interface{}) {
|
func AddKnownTypes(types ...interface{}) {
|
||||||
for _, obj := range types {
|
for _, obj := range types {
|
||||||
t := reflect.TypeOf(obj)
|
t := reflect.TypeOf(obj)
|
||||||
|
@ -49,14 +51,14 @@ func AddKnownTypes(types ...interface{}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes an arbitary api type, returns pointer to its JSONBase field.
|
// FindJSONBase takes an arbitary api type, returns pointer to its JSONBase field.
|
||||||
// obj must be a pointer to an api type.
|
// obj must be a pointer to an api type.
|
||||||
func FindJSONBase(obj interface{}) (*JSONBase, error) {
|
func FindJSONBase(obj interface{}) (*JSONBase, error) {
|
||||||
_, jsonBase, err := nameAndJSONBase(obj)
|
_, jsonBase, err := nameAndJSONBase(obj)
|
||||||
return jsonBase, err
|
return jsonBase, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Takes an arbitary api type, return a copy of its JSONBase field.
|
// FindJSONBaseRO takes an arbitary api type, return a copy of its JSONBase field.
|
||||||
// obj may be a pointer to an api type, or a non-pointer struct api type.
|
// obj may be a pointer to an api type, or a non-pointer struct api type.
|
||||||
func FindJSONBaseRO(obj interface{}) (JSONBase, error) {
|
func FindJSONBaseRO(obj interface{}) (JSONBase, error) {
|
||||||
v := reflect.ValueOf(obj)
|
v := reflect.ValueOf(obj)
|
||||||
|
@ -141,7 +143,7 @@ func Decode(data []byte) (interface{}, error) {
|
||||||
// yaml is a superset of json, so we use it to decode here. That way, we understand both.
|
// yaml is a superset of json, so we use it to decode here. That way, we understand both.
|
||||||
err := yaml.Unmarshal(data, &findKind)
|
err := yaml.Unmarshal(data, &findKind)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Couldn't get kind: %#v", err)
|
return nil, fmt.Errorf("couldn't get kind: %#v", err)
|
||||||
}
|
}
|
||||||
objType, found := knownTypes[findKind.Kind]
|
objType, found := knownTypes[findKind.Kind]
|
||||||
if !found {
|
if !found {
|
||||||
|
|
|
@ -153,8 +153,10 @@ type JSONBase struct {
|
||||||
ResourceVersion uint64 `json:"resourceVersion,omitempty" yaml:"resourceVersion,omitempty"`
|
ResourceVersion uint64 `json:"resourceVersion,omitempty" yaml:"resourceVersion,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PodStatus represents a status of a pod.
|
||||||
type PodStatus string
|
type PodStatus string
|
||||||
|
|
||||||
|
// These are the valid statuses of pods.
|
||||||
const (
|
const (
|
||||||
PodRunning PodStatus = "Running"
|
PodRunning PodStatus = "Running"
|
||||||
PodPending PodStatus = "Pending"
|
PodPending PodStatus = "Pending"
|
||||||
|
@ -179,6 +181,7 @@ type PodState struct {
|
||||||
Info PodInfo `json:"info,omitempty" yaml:"info,omitempty"`
|
Info PodInfo `json:"info,omitempty" yaml:"info,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PodList is a list of Pods.
|
||||||
type PodList struct {
|
type PodList struct {
|
||||||
JSONBase `json:",inline" yaml:",inline"`
|
JSONBase `json:",inline" yaml:",inline"`
|
||||||
Items []Pod `json:"items" yaml:"items,omitempty"`
|
Items []Pod `json:"items" yaml:"items,omitempty"`
|
||||||
|
@ -199,6 +202,7 @@ type ReplicationControllerState struct {
|
||||||
PodTemplate PodTemplate `json:"podTemplate,omitempty" yaml:"podTemplate,omitempty"`
|
PodTemplate PodTemplate `json:"podTemplate,omitempty" yaml:"podTemplate,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReplicationControllerList is a collection of replication controllers.
|
||||||
type ReplicationControllerList struct {
|
type ReplicationControllerList struct {
|
||||||
JSONBase `json:",inline" yaml:",inline"`
|
JSONBase `json:",inline" yaml:",inline"`
|
||||||
Items []ReplicationController `json:"items,omitempty" yaml:"items,omitempty"`
|
Items []ReplicationController `json:"items,omitempty" yaml:"items,omitempty"`
|
||||||
|
@ -223,7 +227,7 @@ type ServiceList struct {
|
||||||
Items []Service `json:"items" yaml:"items"`
|
Items []Service `json:"items" yaml:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defines a service abstraction by a name (for example, mysql) consisting of local port
|
// Service is a named abstraction of software service (for example, mysql) consisting of local port
|
||||||
// (for example 3306) that the proxy listens on, and the selector that determines which pods
|
// (for example 3306) that the proxy listens on, and the selector that determines which pods
|
||||||
// will answer requests sent through the proxy.
|
// will answer requests sent through the proxy.
|
||||||
type Service struct {
|
type Service struct {
|
||||||
|
@ -238,22 +242,22 @@ type Service struct {
|
||||||
CreateExternalLoadBalancer bool `json:"createExternalLoadBalancer,omitempty" yaml:"createExternalLoadBalancer,omitempty"`
|
CreateExternalLoadBalancer bool `json:"createExternalLoadBalancer,omitempty" yaml:"createExternalLoadBalancer,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defines the endpoints that implement the actual service, for example:
|
// Endpoints is a collection of endpoints that implement the actual service, for example:
|
||||||
// Name: "mysql", Endpoints: ["10.10.1.1:1909", "10.10.2.2:8834"]
|
// Name: "mysql", Endpoints: ["10.10.1.1:1909", "10.10.2.2:8834"]
|
||||||
type Endpoints struct {
|
type Endpoints struct {
|
||||||
Name string
|
Name string
|
||||||
Endpoints []string
|
Endpoints []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Information about a single Minion; the name of the minion according to etcd
|
// Minion is a worker node in Kubernetenes.
|
||||||
// is in JSONBase.ID.
|
// The name of the minion according to etcd is in JSONBase.ID.
|
||||||
type Minion struct {
|
type Minion struct {
|
||||||
JSONBase `json:",inline" yaml:",inline"`
|
JSONBase `json:",inline" yaml:",inline"`
|
||||||
// Queried from cloud provider, if available.
|
// Queried from cloud provider, if available.
|
||||||
HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"`
|
HostIP string `json:"hostIP,omitempty" yaml:"hostIP,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// A list of minions.
|
// MinionList is a list of minions.
|
||||||
type MinionList struct {
|
type MinionList struct {
|
||||||
JSONBase `json:",inline" yaml:",inline"`
|
JSONBase `json:",inline" yaml:",inline"`
|
||||||
Items []Minion `json:"minions,omitempty" yaml:"minions,omitempty"`
|
Items []Minion `json:"minions,omitempty" yaml:"minions,omitempty"`
|
||||||
|
@ -282,12 +286,12 @@ const (
|
||||||
StatusWorking = "working"
|
StatusWorking = "working"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Operation information, as delivered to API clients.
|
// ServerOp is an operation delivered to API clients.
|
||||||
type ServerOp struct {
|
type ServerOp struct {
|
||||||
JSONBase `yaml:",inline" json:",inline"`
|
JSONBase `yaml:",inline" json:",inline"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Operation list, as delivered to API clients.
|
// ServerOpList is a list of operations, as delivered to API clients.
|
||||||
type ServerOpList struct {
|
type ServerOpList struct {
|
||||||
JSONBase `yaml:",inline" json:",inline"`
|
JSONBase `yaml:",inline" json:",inline"`
|
||||||
Items []ServerOp `yaml:"items,omitempty" json:"items,omitempty"`
|
Items []ServerOp `yaml:"items,omitempty" json:"items,omitempty"`
|
||||||
|
|
|
@ -24,19 +24,20 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
supportedManifestVersions util.StringSet = util.NewStringSet("v1beta1", "v1beta2")
|
supportedManifestVersions = util.NewStringSet("v1beta1", "v1beta2")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Validation errors.
|
// ValidationErrorEnum is a type of validation error.
|
||||||
type ValidationErrorEnum string
|
type ValidationErrorEnum string
|
||||||
|
|
||||||
|
// These are known errors of validation.
|
||||||
const (
|
const (
|
||||||
ErrTypeInvalid ValidationErrorEnum = "invalid value"
|
ErrTypeInvalid ValidationErrorEnum = "invalid value"
|
||||||
ErrTypeNotSupported ValidationErrorEnum = "unsupported value"
|
ErrTypeNotSupported ValidationErrorEnum = "unsupported value"
|
||||||
ErrTypeDuplicate ValidationErrorEnum = "duplicate value"
|
ErrTypeDuplicate ValidationErrorEnum = "duplicate value"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Implements the 'error' interface.
|
// ValidationError is an implementation of the 'error' interface, which represents an error of validation.
|
||||||
type ValidationError struct {
|
type ValidationError struct {
|
||||||
ErrorType ValidationErrorEnum
|
ErrorType ValidationErrorEnum
|
||||||
ErrorField string
|
ErrorField string
|
||||||
|
|
|
@ -76,24 +76,24 @@ func MakeAsync(fn WorkFunc) <-chan interface{} {
|
||||||
return channel
|
return channel
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApiServer is an HTTPHandler that delegates to RESTStorage objects.
|
// APIServer is an HTTPHandler that delegates to RESTStorage objects.
|
||||||
// It handles URLs of the form:
|
// It handles URLs of the form:
|
||||||
// ${prefix}/${storage_key}[/${object_name}]
|
// ${prefix}/${storage_key}[/${object_name}]
|
||||||
// Where 'prefix' is an arbitrary string, and 'storage_key' points to a RESTStorage object stored in storage.
|
// Where 'prefix' is an arbitrary string, and 'storage_key' points to a RESTStorage object stored in storage.
|
||||||
//
|
//
|
||||||
// TODO: consider migrating this to go-restful which is a more full-featured version of the same thing.
|
// TODO: consider migrating this to go-restful which is a more full-featured version of the same thing.
|
||||||
type ApiServer struct {
|
type APIServer struct {
|
||||||
prefix string
|
prefix string
|
||||||
storage map[string]RESTStorage
|
storage map[string]RESTStorage
|
||||||
ops *Operations
|
ops *Operations
|
||||||
logserver http.Handler
|
logserver http.Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new ApiServer object.
|
// New creates a new APIServer object.
|
||||||
// 'storage' contains a map of handlers.
|
// 'storage' contains a map of handlers.
|
||||||
// 'prefix' is the hosting path prefix.
|
// 'prefix' is the hosting path prefix.
|
||||||
func New(storage map[string]RESTStorage, prefix string) *ApiServer {
|
func New(storage map[string]RESTStorage, prefix string) *APIServer {
|
||||||
return &ApiServer{
|
return &APIServer{
|
||||||
storage: storage,
|
storage: storage,
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
ops: NewOperations(),
|
ops: NewOperations(),
|
||||||
|
@ -101,7 +101,7 @@ func New(storage map[string]RESTStorage, prefix string) *ApiServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *ApiServer) handleIndex(w http.ResponseWriter) {
|
func (server *APIServer) handleIndex(w http.ResponseWriter) {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
// TODO: serve this out of a file?
|
// TODO: serve this out of a file?
|
||||||
data := "<html><body>Welcome to Kubernetes</body></html>"
|
data := "<html><body>Welcome to Kubernetes</body></html>"
|
||||||
|
@ -109,12 +109,12 @@ func (server *ApiServer) handleIndex(w http.ResponseWriter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTP Handler interface
|
// HTTP Handler interface
|
||||||
func (server *ApiServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
func (server *APIServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if x := recover(); x != nil {
|
if x := recover(); x != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
fmt.Fprint(w, "apiserver panic. Look in log for details.")
|
fmt.Fprint(w, "apiserver panic. Look in log for details.")
|
||||||
glog.Infof("ApiServer panic'd on %v %v: %#v\n%s\n", req.Method, req.RequestURI, x, debug.Stack())
|
glog.Infof("APIServer panic'd on %v %v: %#v\n%s\n", req.Method, req.RequestURI, x, debug.Stack())
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
defer MakeLogged(req, &w).StacktraceWhen(
|
defer MakeLogged(req, &w).StacktraceWhen(
|
||||||
|
@ -155,17 +155,17 @@ func (server *ApiServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
LogOf(w).Addf("'%v' has no storage object", requestParts[0])
|
LogOf(w).Addf("'%v' has no storage object", requestParts[0])
|
||||||
server.notFound(req, w)
|
server.notFound(req, w)
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
server.handleREST(requestParts, url, req, w, storage)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *ApiServer) notFound(req *http.Request, w http.ResponseWriter) {
|
server.handleREST(requestParts, url, req, w, storage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *APIServer) notFound(req *http.Request, w http.ResponseWriter) {
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
fmt.Fprintf(w, "Not Found: %#v", req)
|
fmt.Fprintf(w, "Not Found: %#v", req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *ApiServer) write(statusCode int, object interface{}, w http.ResponseWriter) {
|
func (server *APIServer) write(statusCode int, object interface{}, w http.ResponseWriter) {
|
||||||
w.WriteHeader(statusCode)
|
w.WriteHeader(statusCode)
|
||||||
output, err := api.Encode(object)
|
output, err := api.Encode(object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -175,19 +175,19 @@ func (server *ApiServer) write(statusCode int, object interface{}, w http.Respon
|
||||||
w.Write(output)
|
w.Write(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *ApiServer) error(err error, w http.ResponseWriter) {
|
func (server *APIServer) error(err error, w http.ResponseWriter) {
|
||||||
w.WriteHeader(500)
|
w.WriteHeader(500)
|
||||||
fmt.Fprintf(w, "Internal Error: %#v", err)
|
fmt.Fprintf(w, "Internal Error: %#v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *ApiServer) readBody(req *http.Request) ([]byte, error) {
|
func (server *APIServer) readBody(req *http.Request) ([]byte, error) {
|
||||||
defer req.Body.Close()
|
defer req.Body.Close()
|
||||||
return ioutil.ReadAll(req.Body)
|
return ioutil.ReadAll(req.Body)
|
||||||
}
|
}
|
||||||
|
|
||||||
// finishReq finishes up a request, waiting until the operation finishes or, after a timeout, creating an
|
// finishReq finishes up a request, waiting until the operation finishes or, after a timeout, creating an
|
||||||
// Operation to recieve the result and returning its ID down the writer.
|
// Operation to recieve the result and returning its ID down the writer.
|
||||||
func (server *ApiServer) finishReq(out <-chan interface{}, sync bool, timeout time.Duration, w http.ResponseWriter) {
|
func (server *APIServer) finishReq(out <-chan interface{}, sync bool, timeout time.Duration, w http.ResponseWriter) {
|
||||||
op := server.ops.NewOperation(out)
|
op := server.ops.NewOperation(out)
|
||||||
if sync {
|
if sync {
|
||||||
op.WaitFor(timeout)
|
op.WaitFor(timeout)
|
||||||
|
@ -236,14 +236,14 @@ func parseTimeout(str string) time.Duration {
|
||||||
// sync=[false|true] Synchronous request (only applies to create, update, delete operations)
|
// sync=[false|true] Synchronous request (only applies to create, update, delete operations)
|
||||||
// timeout=<duration> Timeout for synchronous requests, only applies if sync=true
|
// timeout=<duration> Timeout for synchronous requests, only applies if sync=true
|
||||||
// labels=<label-selector> Used for filtering list operations
|
// labels=<label-selector> Used for filtering list operations
|
||||||
func (server *ApiServer) handleREST(parts []string, requestUrl *url.URL, req *http.Request, w http.ResponseWriter, storage RESTStorage) {
|
func (server *APIServer) handleREST(parts []string, requestURL *url.URL, req *http.Request, w http.ResponseWriter, storage RESTStorage) {
|
||||||
sync := requestUrl.Query().Get("sync") == "true"
|
sync := requestURL.Query().Get("sync") == "true"
|
||||||
timeout := parseTimeout(requestUrl.Query().Get("timeout"))
|
timeout := parseTimeout(requestURL.Query().Get("timeout"))
|
||||||
switch req.Method {
|
switch req.Method {
|
||||||
case "GET":
|
case "GET":
|
||||||
switch len(parts) {
|
switch len(parts) {
|
||||||
case 1:
|
case 1:
|
||||||
selector, err := labels.ParseSelector(requestUrl.Query().Get("labels"))
|
selector, err := labels.ParseSelector(requestURL.Query().Get("labels"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.error(err, w)
|
server.error(err, w)
|
||||||
return
|
return
|
||||||
|
@ -325,7 +325,7 @@ func (server *ApiServer) handleREST(parts []string, requestUrl *url.URL, req *ht
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *ApiServer) handleOperationRequest(parts []string, w http.ResponseWriter, req *http.Request) {
|
func (server *APIServer) handleOperationRequest(parts []string, w http.ResponseWriter, req *http.Request) {
|
||||||
if req.Method != "GET" {
|
if req.Method != "GET" {
|
||||||
server.notFound(req, w)
|
server.notFound(req, w)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Return true if a stacktrace should be logged for this status
|
// StacktracePred returns true if a stacktrace should be logged for this status
|
||||||
type StacktracePred func(httpStatus int) (logStacktrace bool)
|
type StacktracePred func(httpStatus int) (logStacktrace bool)
|
||||||
|
|
||||||
// Add a layer on top of ResponseWriter, so we can track latency and error
|
// Add a layer on top of ResponseWriter, so we can track latency and error
|
||||||
|
@ -42,6 +42,7 @@ type respLogger struct {
|
||||||
logStacktracePred StacktracePred
|
logStacktracePred StacktracePred
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultStacktracePred is the default implementation of StacktracePred.
|
||||||
func DefaultStacktracePred(status int) bool {
|
func DefaultStacktracePred(status int) bool {
|
||||||
return status != http.StatusOK && status != http.StatusAccepted
|
return status != http.StatusOK && status != http.StatusAccepted
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ type Operations struct {
|
||||||
ops map[string]*Operation
|
ops map[string]*Operation
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a new Operations repository.
|
// NewOperations returns a new Operations repository.
|
||||||
func NewOperations() *Operations {
|
func NewOperations() *Operations {
|
||||||
ops := &Operations{
|
ops := &Operations{
|
||||||
ops: map[string]*Operation{},
|
ops: map[string]*Operation{},
|
||||||
|
@ -56,7 +56,7 @@ func NewOperations() *Operations {
|
||||||
return ops
|
return ops
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a new operation. Lock-free.
|
// NewOperation adds a new operation. It is lock-free.
|
||||||
func (ops *Operations) NewOperation(from <-chan interface{}) *Operation {
|
func (ops *Operations) NewOperation(from <-chan interface{}) *Operation {
|
||||||
id := atomic.AddInt64(&ops.lastID, 1)
|
id := atomic.AddInt64(&ops.lastID, 1)
|
||||||
op := &Operation{
|
op := &Operation{
|
||||||
|
@ -93,7 +93,7 @@ func (ops *Operations) List() api.ServerOpList {
|
||||||
return ol
|
return ol
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the operation with the given ID, or nil
|
// Get returns the operation with the given ID, or nil
|
||||||
func (ops *Operations) Get(id string) *Operation {
|
func (ops *Operations) Get(id string) *Operation {
|
||||||
ops.lock.Lock()
|
ops.lock.Lock()
|
||||||
defer ops.lock.Unlock()
|
defer ops.lock.Unlock()
|
||||||
|
@ -131,7 +131,7 @@ func (op *Operation) wait() {
|
||||||
op.notify <- true
|
op.notify <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the specified duration, or until the operation finishes,
|
// WaitFor waits for the specified duration, or until the operation finishes,
|
||||||
// whichever happens first.
|
// whichever happens first.
|
||||||
func (op *Operation) WaitFor(timeout time.Duration) {
|
func (op *Operation) WaitFor(timeout time.Duration) {
|
||||||
select {
|
select {
|
||||||
|
@ -153,7 +153,7 @@ func (op *Operation) expired(limitTime time.Time) bool {
|
||||||
return op.finished.Before(limitTime)
|
return op.finished.Before(limitTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return status information or the result of the operation if it is complete,
|
// StatusOrResult returns status information or the result of the operation if it is complete,
|
||||||
// with a bool indicating true in the latter case.
|
// with a bool indicating true in the latter case.
|
||||||
func (op *Operation) StatusOrResult() (description interface{}, finished bool) {
|
func (op *Operation) StatusOrResult() (description interface{}, finished bool) {
|
||||||
op.lock.Lock()
|
op.lock.Lock()
|
||||||
|
|
|
@ -75,7 +75,7 @@ type Client struct {
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new client object.
|
// New creates a new client object.
|
||||||
func New(host string, auth *AuthInfo) *Client {
|
func New(host string, auth *AuthInfo) *Client {
|
||||||
return &Client{
|
return &Client{
|
||||||
auth: auth,
|
auth: auth,
|
||||||
|
@ -159,79 +159,81 @@ func (c *Client) rawRequest(method, path string, requestBody io.Reader, target i
|
||||||
return body, err
|
return body, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) makeURL(path string) string {
|
func (c *Client) makeURL(path string) string {
|
||||||
return client.host + "/api/v1beta1/" + path
|
return c.host + "/api/v1beta1/" + path
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListPods takes a selector, and returns the list of pods that match that selector
|
// ListPods takes a selector, and returns the list of pods that match that selector
|
||||||
func (client *Client) ListPods(selector labels.Selector) (result api.PodList, err error) {
|
func (c *Client) ListPods(selector labels.Selector) (result api.PodList, err error) {
|
||||||
err = client.Get().Path("pods").Selector(selector).Do().Into(&result)
|
err = c.Get().Path("pods").Selector(selector).Do().Into(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPod takes the name of the pod, and returns the corresponding Pod object, and an error if it occurs
|
// GetPod takes the name of the pod, and returns the corresponding Pod object, and an error if it occurs
|
||||||
func (client *Client) GetPod(name string) (result api.Pod, err error) {
|
func (c *Client) GetPod(name string) (result api.Pod, err error) {
|
||||||
err = client.Get().Path("pods").Path(name).Do().Into(&result)
|
err = c.Get().Path("pods").Path(name).Do().Into(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletePod takes the name of the pod, and returns an error if one occurs
|
// DeletePod takes the name of the pod, and returns an error if one occurs
|
||||||
func (client *Client) DeletePod(name string) error {
|
func (c *Client) DeletePod(name string) error {
|
||||||
return client.Delete().Path("pods").Path(name).Do().Error()
|
return c.Delete().Path("pods").Path(name).Do().Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatePod takes the representation of a pod. Returns the server's representation of the pod, and an error, if it occurs
|
// CreatePod takes the representation of a pod. Returns the server's representation of the pod, and an error, if it occurs
|
||||||
func (client *Client) CreatePod(pod api.Pod) (result api.Pod, err error) {
|
func (c *Client) CreatePod(pod api.Pod) (result api.Pod, err error) {
|
||||||
err = client.Post().Path("pods").Body(pod).Do().Into(&result)
|
err = c.Post().Path("pods").Body(pod).Do().Into(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatePod takes the representation of a pod to update. Returns the server's representation of the pod, and an error, if it occurs
|
// UpdatePod takes the representation of a pod to update. Returns the server's representation of the pod, and an error, if it occurs
|
||||||
func (client *Client) UpdatePod(pod api.Pod) (result api.Pod, err error) {
|
func (c *Client) UpdatePod(pod api.Pod) (result api.Pod, err error) {
|
||||||
err = client.Put().Path("pods").Path(pod.ID).Body(pod).Do().Into(&result)
|
err = c.Put().Path("pods").Path(pod.ID).Body(pod).Do().Into(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetReplicationController returns information about a particular replication controller
|
// GetReplicationController returns information about a particular replication controller
|
||||||
func (client *Client) GetReplicationController(name string) (result api.ReplicationController, err error) {
|
func (c *Client) GetReplicationController(name string) (result api.ReplicationController, err error) {
|
||||||
err = client.Get().Path("replicationControllers").Path(name).Do().Into(&result)
|
err = c.Get().Path("replicationControllers").Path(name).Do().Into(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateReplicationController creates a new replication controller
|
// CreateReplicationController creates a new replication controller
|
||||||
func (client *Client) CreateReplicationController(controller api.ReplicationController) (result api.ReplicationController, err error) {
|
func (c *Client) CreateReplicationController(controller api.ReplicationController) (result api.ReplicationController, err error) {
|
||||||
err = client.Post().Path("replicationControllers").Body(controller).Do().Into(&result)
|
err = c.Post().Path("replicationControllers").Body(controller).Do().Into(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateReplicationController updates an existing replication controller
|
// UpdateReplicationController updates an existing replication controller
|
||||||
func (client *Client) UpdateReplicationController(controller api.ReplicationController) (result api.ReplicationController, err error) {
|
func (c *Client) UpdateReplicationController(controller api.ReplicationController) (result api.ReplicationController, err error) {
|
||||||
err = client.Put().Path("replicationControllers").Path(controller.ID).Body(controller).Do().Into(&result)
|
err = c.Put().Path("replicationControllers").Path(controller.ID).Body(controller).Do().Into(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) DeleteReplicationController(name string) error {
|
// DeleteReplicationController deletes an existing replication controller.
|
||||||
return client.Delete().Path("replicationControllers").Path(name).Do().Error()
|
func (c *Client) DeleteReplicationController(name string) error {
|
||||||
|
return c.Delete().Path("replicationControllers").Path(name).Do().Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetReplicationController returns information about a particular replication controller
|
// GetService returns information about a particular service.
|
||||||
func (client *Client) GetService(name string) (result api.Service, err error) {
|
func (c *Client) GetService(name string) (result api.Service, err error) {
|
||||||
err = client.Get().Path("services").Path(name).Do().Into(&result)
|
err = c.Get().Path("services").Path(name).Do().Into(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateReplicationController creates a new replication controller
|
// CreateService creates a new service.
|
||||||
func (client *Client) CreateService(svc api.Service) (result api.Service, err error) {
|
func (c *Client) CreateService(svc api.Service) (result api.Service, err error) {
|
||||||
err = client.Post().Path("services").Body(svc).Do().Into(&result)
|
err = c.Post().Path("services").Body(svc).Do().Into(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateReplicationController updates an existing replication controller
|
// UpdateService updates an existing service.
|
||||||
func (client *Client) UpdateService(svc api.Service) (result api.Service, err error) {
|
func (c *Client) UpdateService(svc api.Service) (result api.Service, err error) {
|
||||||
err = client.Put().Path("services").Path(svc.ID).Body(svc).Do().Into(&result)
|
err = c.Put().Path("services").Path(svc.ID).Body(svc).Do().Into(&result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) DeleteService(name string) error {
|
// DeleteService deletes an existing service.
|
||||||
return client.Delete().Path("services").Path(name).Do().Error()
|
func (c *Client) DeleteService(name string) error {
|
||||||
|
return c.Delete().Path("services").Path(name).Do().Error()
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ import (
|
||||||
// TODO: Move this to a common place, it's needed in multiple tests.
|
// TODO: Move this to a common place, it's needed in multiple tests.
|
||||||
var apiPath = "/api/v1beta1"
|
var apiPath = "/api/v1beta1"
|
||||||
|
|
||||||
func makeUrl(suffix string) string {
|
func makeURL(suffix string) string {
|
||||||
return apiPath + suffix
|
return apiPath + suffix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +326,7 @@ func (c *testClient) Validate(t *testing.T, received interface{}, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
requestBody := body(c.Request.Body, c.Request.RawBody)
|
requestBody := body(c.Request.Body, c.Request.RawBody)
|
||||||
c.handler.ValidateRequest(t, makeUrl(c.Request.Path), c.Request.Method, requestBody)
|
c.handler.ValidateRequest(t, makeURL(c.Request.Path), c.Request.Method, requestBody)
|
||||||
for key, values := range c.Request.Query {
|
for key, values := range c.Request.Query {
|
||||||
validator, ok := c.QueryValidator[key]
|
validator, ok := c.QueryValidator[key]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -35,12 +35,13 @@ type PodInfoGetter interface {
|
||||||
GetPodInfo(host, podID string) (api.PodInfo, error)
|
GetPodInfo(host, podID string) (api.PodInfo, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The default implementation, accesses the kubelet over HTTP
|
// HTTPPodInfoGetter is the default implementation of PodInfoGetter, accesses the kubelet over HTTP
|
||||||
type HTTPPodInfoGetter struct {
|
type HTTPPodInfoGetter struct {
|
||||||
Client *http.Client
|
Client *http.Client
|
||||||
Port uint
|
Port uint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPodInfo gets information about the specified pod.
|
||||||
func (c *HTTPPodInfoGetter) GetPodInfo(host, podID string) (api.PodInfo, error) {
|
func (c *HTTPPodInfoGetter) GetPodInfo(host, podID string) (api.PodInfo, error) {
|
||||||
request, err := http.NewRequest(
|
request, err := http.NewRequest(
|
||||||
"GET",
|
"GET",
|
||||||
|
@ -70,12 +71,13 @@ func (c *HTTPPodInfoGetter) GetPodInfo(host, podID string) (api.PodInfo, error)
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Useful for testing.
|
// FakePodInfoGetter is a fake implementation of PodInfoGetter. It is useful for testing.
|
||||||
type FakePodInfoGetter struct {
|
type FakePodInfoGetter struct {
|
||||||
data api.PodInfo
|
data api.PodInfo
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPodInfo is a fake implementation of PodInfoGetter.GetPodInfo.
|
||||||
func (c *FakePodInfoGetter) GetPodInfo(host, podID string) (api.PodInfo, error) {
|
func (c *FakePodInfoGetter) GetPodInfo(host, podID string) (api.PodInfo, error) {
|
||||||
return c.data, c.err
|
return c.data, c.err
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,9 @@ func TestHTTPPodInfoGetter(t *testing.T) {
|
||||||
}
|
}
|
||||||
testServer := httptest.NewServer(&fakeHandler)
|
testServer := httptest.NewServer(&fakeHandler)
|
||||||
|
|
||||||
hostUrl, err := url.Parse(testServer.URL)
|
hostURL, err := url.Parse(testServer.URL)
|
||||||
expectNoError(t, err)
|
expectNoError(t, err)
|
||||||
parts := strings.Split(hostUrl.Host, ":")
|
parts := strings.Split(hostURL.Host, ":")
|
||||||
|
|
||||||
port, err := strconv.Atoi(parts[1])
|
port, err := strconv.Atoi(parts[1])
|
||||||
expectNoError(t, err)
|
expectNoError(t, err)
|
||||||
|
|
|
@ -40,7 +40,7 @@ import (
|
||||||
// Do()
|
// Do()
|
||||||
// list, ok := resp.(api.PodList)
|
// list, ok := resp.(api.PodList)
|
||||||
|
|
||||||
// Begin a request with a verb (GET, POST, PUT, DELETE)
|
// Verb begins a request with a verb (GET, POST, PUT, DELETE)
|
||||||
func (c *Client) Verb(verb string) *Request {
|
func (c *Client) Verb(verb string) *Request {
|
||||||
return &Request{
|
return &Request{
|
||||||
verb: verb,
|
verb: verb,
|
||||||
|
@ -52,29 +52,29 @@ func (c *Client) Verb(verb string) *Request {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin a POST request.
|
// Post begins a POST request.
|
||||||
func (c *Client) Post() *Request {
|
func (c *Client) Post() *Request {
|
||||||
return c.Verb("POST")
|
return c.Verb("POST")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin a PUT request.
|
// Put begins a PUT request.
|
||||||
func (c *Client) Put() *Request {
|
func (c *Client) Put() *Request {
|
||||||
return c.Verb("PUT")
|
return c.Verb("PUT")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin a GET request.
|
// Get begins a GET request.
|
||||||
func (c *Client) Get() *Request {
|
func (c *Client) Get() *Request {
|
||||||
return c.Verb("GET")
|
return c.Verb("GET")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin a DELETE request.
|
// Delete begins a DELETE request.
|
||||||
func (c *Client) Delete() *Request {
|
func (c *Client) Delete() *Request {
|
||||||
return c.Verb("DELETE")
|
return c.Verb("DELETE")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a request to do a single poll of the completion of the given operation.
|
// PollFor makes a request to do a single poll of the completion of the given operation.
|
||||||
func (c *Client) PollFor(operationId string) *Request {
|
func (c *Client) PollFor(operationID string) *Request {
|
||||||
return c.Get().Path("operations").Path(operationId).Sync(false).PollPeriod(0)
|
return c.Get().Path("operations").Path(operationID).Sync(false).PollPeriod(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request allows for building up a request to a server in a chained fashion.
|
// Request allows for building up a request to a server in a chained fashion.
|
||||||
|
@ -92,7 +92,7 @@ type Request struct {
|
||||||
pollPeriod time.Duration
|
pollPeriod time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append an item to the request path. You must call Path at least once.
|
// Path appends an item to the request path. You must call Path at least once.
|
||||||
func (r *Request) Path(item string) *Request {
|
func (r *Request) Path(item string) *Request {
|
||||||
if r.err != nil {
|
if r.err != nil {
|
||||||
return r
|
return r
|
||||||
|
@ -101,7 +101,7 @@ func (r *Request) Path(item string) *Request {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sync/async call status.
|
// Sync sets sync/async call status.
|
||||||
func (r *Request) Sync(sync bool) *Request {
|
func (r *Request) Sync(sync bool) *Request {
|
||||||
if r.err != nil {
|
if r.err != nil {
|
||||||
return r
|
return r
|
||||||
|
@ -110,7 +110,7 @@ func (r *Request) Sync(sync bool) *Request {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overwrite an existing path with the path parameter.
|
// AbsPath overwrites an existing path with the path parameter.
|
||||||
func (r *Request) AbsPath(path string) *Request {
|
func (r *Request) AbsPath(path string) *Request {
|
||||||
if r.err != nil {
|
if r.err != nil {
|
||||||
return r
|
return r
|
||||||
|
@ -119,7 +119,7 @@ func (r *Request) AbsPath(path string) *Request {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the given string as a resource label selector. Optional.
|
// ParseSelector parses the given string as a resource label selector. Optional.
|
||||||
func (r *Request) ParseSelector(item string) *Request {
|
func (r *Request) ParseSelector(item string) *Request {
|
||||||
if r.err != nil {
|
if r.err != nil {
|
||||||
return r
|
return r
|
||||||
|
@ -128,7 +128,7 @@ func (r *Request) ParseSelector(item string) *Request {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the given selector.
|
// Selector makes the request use the given selector.
|
||||||
func (r *Request) Selector(s labels.Selector) *Request {
|
func (r *Request) Selector(s labels.Selector) *Request {
|
||||||
if r.err != nil {
|
if r.err != nil {
|
||||||
return r
|
return r
|
||||||
|
@ -137,7 +137,7 @@ func (r *Request) Selector(s labels.Selector) *Request {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the given duration as a timeout. Optional.
|
// Timeout makes the request use the given duration as a timeout. Optional.
|
||||||
func (r *Request) Timeout(d time.Duration) *Request {
|
func (r *Request) Timeout(d time.Duration) *Request {
|
||||||
if r.err != nil {
|
if r.err != nil {
|
||||||
return r
|
return r
|
||||||
|
@ -146,7 +146,7 @@ func (r *Request) Timeout(d time.Duration) *Request {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use obj as the body of the request. Optional.
|
// Body makes the request use obj as the body. Optional.
|
||||||
// If obj is a string, try to read a file of that name.
|
// If obj is a string, try to read a file of that name.
|
||||||
// If obj is a []byte, send it directly.
|
// If obj is a []byte, send it directly.
|
||||||
// Otherwise, assume obj is an api type and marshall it correctly.
|
// Otherwise, assume obj is an api type and marshall it correctly.
|
||||||
|
@ -190,13 +190,13 @@ func (r *Request) PollPeriod(d time.Duration) *Request {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format and execute the request. Returns the API object received, or an error.
|
// Do formats and executes the request. Returns the API object received, or an error.
|
||||||
func (r *Request) Do() Result {
|
func (r *Request) Do() Result {
|
||||||
for {
|
for {
|
||||||
if r.err != nil {
|
if r.err != nil {
|
||||||
return Result{err: r.err}
|
return Result{err: r.err}
|
||||||
}
|
}
|
||||||
finalUrl := r.c.host + r.path
|
finalURL := r.c.host + r.path
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
if r.selector != nil {
|
if r.selector != nil {
|
||||||
query.Add("labels", r.selector.String())
|
query.Add("labels", r.selector.String())
|
||||||
|
@ -207,8 +207,8 @@ func (r *Request) Do() Result {
|
||||||
query.Add("timeout", r.timeout.String())
|
query.Add("timeout", r.timeout.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finalUrl += "?" + query.Encode()
|
finalURL += "?" + query.Encode()
|
||||||
req, err := http.NewRequest(r.verb, finalUrl, r.body)
|
req, err := http.NewRequest(r.verb, finalURL, r.body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Result{err: err}
|
return Result{err: err}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue