Skip to content

Commit

Permalink
Merge pull request kubernetes#164 from lavalamp/master
Browse files Browse the repository at this point in the history
Standardize terminology on "selector"
  • Loading branch information
brendandburns committed Jun 19, 2014
2 parents 936ce13 + 5a1a793 commit e031c19
Show file tree
Hide file tree
Showing 40 changed files with 179 additions and 138 deletions.
2 changes: 1 addition & 1 deletion api/doc/controller-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"required": false,
"description": "Number of pods desired in the set"
},
"replicasInSet": {
"replicaSelector": {
"type": "object",
"required": false,
"description": "Required labels used to identify pods in the set"
Expand Down
4 changes: 4 additions & 0 deletions api/doc/service-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,9 @@
"type": "object",
"required": false
}
"selector": {
"type": "object",
"required": false
}
}
}
2 changes: 1 addition & 1 deletion api/examples/controller-list.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"id": "testRun",
"desiredState": {
"replicas": 2,
"replicasInSet": {
"replicaSelector": {
"name": "testRun"
},
"podTemplate": {
Expand Down
2 changes: 1 addition & 1 deletion api/examples/controller.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"id": "nginxController",
"desiredState": {
"replicas": 2,
"replicasInSet": {"name": "nginx"},
"replicaSelector": {"name": "nginx"},
"podTemplate": {
"desiredState": {
"manifest": {
Expand Down
3 changes: 3 additions & 0 deletions api/examples/external-service.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@
"labels": {
"name": "nginx"
},
"selector": {
"name": "nginx"
},
"createExternalLoadBalancer": true
}
7 changes: 7 additions & 0 deletions api/examples/service-list.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
"labels": {
"name": "nginx"
}
"selector": {
"name": "nginx"
}
},
{
"id": "example2",
Expand All @@ -14,6 +17,10 @@
"env": "prod",
"name": "jetty"
}
"selector": {
"env": "prod",
"name": "jetty"
}
}
]
}
3 changes: 3 additions & 0 deletions api/examples/service.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@
"labels": {
"name": "nginx"
}
"selector": {
"name": "nginx"
}
}
12 changes: 6 additions & 6 deletions api/kubernetes.html
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,7 @@ <h3>Body</h3>
"<span class="hljs-attribute">id</span>": <span class="hljs-value"><span class="hljs-string">"testRun"</span></span>,
"<span class="hljs-attribute">desiredState</span>": <span class="hljs-value">{
"<span class="hljs-attribute">replicas</span>": <span class="hljs-value"><span class="hljs-number">2</span></span>,
"<span class="hljs-attribute">replicasInSet</span>": <span class="hljs-value">{
"<span class="hljs-attribute">replicaSelector</span>": <span class="hljs-value">{
"<span class="hljs-attribute">name</span>": <span class="hljs-value"><span class="hljs-string">"testRun"</span>
</span>}</span>,
"<span class="hljs-attribute">podTemplate</span>": <span class="hljs-value">{
Expand Down Expand Up @@ -1074,7 +1074,7 @@ <h3>Body</h3>
"<span class="hljs-attribute">required</span>": <span class="hljs-value"><span class="hljs-literal">false</span></span>,
"<span class="hljs-attribute">description</span>": <span class="hljs-value"><span class="hljs-string">"Number of pods desired in the set"</span>
</span>}</span>,
"<span class="hljs-attribute">replicasInSet</span>": <span class="hljs-value">{
"<span class="hljs-attribute">replicaSelector</span>": <span class="hljs-value">{
"<span class="hljs-attribute">type</span>": <span class="hljs-value"><span class="hljs-string">"object"</span></span>,
"<span class="hljs-attribute">required</span>": <span class="hljs-value"><span class="hljs-literal">false</span></span>,
"<span class="hljs-attribute">description</span>": <span class="hljs-value"><span class="hljs-string">"Required labels used to identify pods in the set"</span>
Expand All @@ -1100,7 +1100,7 @@ <h3>Body</h3>
"<span class="hljs-attribute">id</span>": <span class="hljs-value"><span class="hljs-string">"nginxController"</span></span>,
"<span class="hljs-attribute">desiredState</span>": <span class="hljs-value">{
"<span class="hljs-attribute">replicas</span>": <span class="hljs-value"><span class="hljs-number">2</span></span>,
"<span class="hljs-attribute">replicasInSet</span>": <span class="hljs-value">{"<span class="hljs-attribute">name</span>": <span class="hljs-value"><span class="hljs-string">"nginx"</span></span>}</span>,
"<span class="hljs-attribute">replicaSelector</span>": <span class="hljs-value">{"<span class="hljs-attribute">name</span>": <span class="hljs-value"><span class="hljs-string">"nginx"</span></span>}</span>,
"<span class="hljs-attribute">podTemplate</span>": <span class="hljs-value">{
"<span class="hljs-attribute">desiredState</span>": <span class="hljs-value">{
"<span class="hljs-attribute">manifest</span>": <span class="hljs-value">{
Expand Down Expand Up @@ -1231,7 +1231,7 @@ <h3>Body</h3>
"<span class="hljs-attribute">id</span>": <span class="hljs-value"><span class="hljs-string">"nginxController"</span></span>,
"<span class="hljs-attribute">desiredState</span>": <span class="hljs-value">{
"<span class="hljs-attribute">replicas</span>": <span class="hljs-value"><span class="hljs-number">2</span></span>,
"<span class="hljs-attribute">replicasInSet</span>": <span class="hljs-value">{"<span class="hljs-attribute">name</span>": <span class="hljs-value"><span class="hljs-string">"nginx"</span></span>}</span>,
"<span class="hljs-attribute">replicaSelector</span>": <span class="hljs-value">{"<span class="hljs-attribute">name</span>": <span class="hljs-value"><span class="hljs-string">"nginx"</span></span>}</span>,
"<span class="hljs-attribute">podTemplate</span>": <span class="hljs-value">{
"<span class="hljs-attribute">desiredState</span>": <span class="hljs-value">{
"<span class="hljs-attribute">manifest</span>": <span class="hljs-value">{
Expand Down Expand Up @@ -1333,7 +1333,7 @@ <h3>Body</h3>
"<span class="hljs-attribute">required</span>": <span class="hljs-value"><span class="hljs-literal">false</span></span>,
"<span class="hljs-attribute">description</span>": <span class="hljs-value"><span class="hljs-string">"Number of pods desired in the set"</span>
</span>}</span>,
"<span class="hljs-attribute">replicasInSet</span>": <span class="hljs-value">{
"<span class="hljs-attribute">replicaSelector</span>": <span class="hljs-value">{
"<span class="hljs-attribute">type</span>": <span class="hljs-value"><span class="hljs-string">"object"</span></span>,
"<span class="hljs-attribute">required</span>": <span class="hljs-value"><span class="hljs-literal">false</span></span>,
"<span class="hljs-attribute">description</span>": <span class="hljs-value"><span class="hljs-string">"Required labels used to identify pods in the set"</span>
Expand All @@ -1359,7 +1359,7 @@ <h3>Body</h3>
"<span class="hljs-attribute">id</span>": <span class="hljs-value"><span class="hljs-string">"nginxController"</span></span>,
"<span class="hljs-attribute">desiredState</span>": <span class="hljs-value">{
"<span class="hljs-attribute">replicas</span>": <span class="hljs-value"><span class="hljs-number">2</span></span>,
"<span class="hljs-attribute">replicasInSet</span>": <span class="hljs-value">{"<span class="hljs-attribute">name</span>": <span class="hljs-value"><span class="hljs-string">"nginx"</span></span>}</span>,
"<span class="hljs-attribute">replicaSelector</span>": <span class="hljs-value">{"<span class="hljs-attribute">name</span>": <span class="hljs-value"><span class="hljs-string">"nginx"</span></span>}</span>,
"<span class="hljs-attribute">podTemplate</span>": <span class="hljs-value">{
"<span class="hljs-attribute">desiredState</span>": <span class="hljs-value">{
"<span class="hljs-attribute">manifest</span>": <span class="hljs-value">{
Expand Down
6 changes: 3 additions & 3 deletions cmd/cloudcfg/cloudcfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ var (
versionFlag = flag.Bool("v", false, "Print the version number.")
httpServer = flag.String("h", "", "The host to connect to.")
config = flag.String("c", "", "Path to the config file.")
labelQuery = flag.String("l", "", "Label query to use for listing")
selector = flag.String("l", "", "Selector (label query) to use for listing")
updatePeriod = flag.Duration("u", 60*time.Second, "Update interarrival period")
portSpec = flag.String("p", "", "The port spec, comma-separated list of <external>:<internal>,...")
servicePort = flag.Int("s", -1, "If positive, create and run a corresponding service on this port, only used with 'run'")
Expand Down Expand Up @@ -143,8 +143,8 @@ func executeAPIRequest(method string, auth *kube_client.AuthInfo) bool {
switch method {
case "get", "list":
url := readUrl(parseStorage())
if len(*labelQuery) > 0 && method == "list" {
url = url + "?labels=" + *labelQuery
if len(*selector) > 0 && method == "list" {
url = url + "?labels=" + *selector
}
request, err = http.NewRequest("GET", url, nil)
case "delete":
Expand Down
2 changes: 1 addition & 1 deletion examples/guestbook/frontend-controller.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"id": "frontendController",
"desiredState": {
"replicas": 1,
"replicasInSet": {"name": "frontend"},
"replicaSelector": {"name": "frontend"},
"podTemplate": {
"desiredState": {
"manifest": {
Expand Down
19 changes: 12 additions & 7 deletions examples/guestbook/guestbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,20 @@ CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
### Step Two: Turn up the master service.
A Kubernetes 'service' is a named load balancer that proxies traffic to one or more containers. The services in a Kubernetes cluster are discoverable inside other containers via environment variables. Services find the containers to load balance based on pod labels.

The pod that you created in Step One has the label `name=redis-master`, so the corresponding service is defined by that label. Create a file named `redis-master-service.json` that contains:
The pod that you created in Step One has the label `name=redis-master`. The selector field of the service determines which pods will receive the traffic sent to the service. Create a file named `redis-master-service.json` that contains:

```js
{
"id": "redismaster",
"port": 10000,
"labels": {
"selector": {
"name": "redis-master"
}
}
```

This will cause all pods to see the redis master apparently running on localhost:10000.

Once you have that service description, you can create the service with the `cloudcfg` cli:

```shell
Expand All @@ -106,7 +108,7 @@ Create a file named `redis-slave-controller.json` that contains:
"id": "redisSlaveController",
"desiredState": {
"replicas": 2,
"replicasInSet": {"name": "redis-slave"},
"replicaSelector": {"name": "redis-slave"},
"podTemplate": {
"desiredState": {
"manifest": {
Expand All @@ -126,7 +128,7 @@ Then you can create the service by running:

```shell
$ cluster/cloudcfg.sh -c examples/guestbook/redis-slave-controller.json create /replicationControllers
Name Image(s) Label Query Replicas
Name Image(s) Selector Replicas
---------- ---------- ---------- ----------
redisSlaveController brendanburns/redis-slave name=redisslave 2
```
Expand Down Expand Up @@ -160,11 +162,14 @@ Just like the master, we want to have a service to proxy connections to the read
"port": 10001,
"labels": {
"name": "redis-slave"
},
"selector": {
"name": "redis-slave"
}
}
```

This time the label query for the service is `name=redis-slave`.
This time the selector for the service is `name=redis-slave`, because that identifies the pods running redis slaves. It may also be helpful to set labels on your service itself--as we've done here--to make it easy to locate them with the `cloudcfg -l "label=value" list sevices` command.

Now that you have created the service specification, create it in your cluster with the `cloudcfg` CLI:

Expand All @@ -186,7 +191,7 @@ Create a file named `frontend-controller.json`:
"id": "frontendController",
"desiredState": {
"replicas": 3,
"replicasInSet": {"name": "frontend"},
"replicaSelector": {"name": "frontend"},
"podTemplate": {
"desiredState": {
"manifest": {
Expand All @@ -206,7 +211,7 @@ With this file, you can turn up your frontend with:

```shell
$ cluster/cloudcfg.sh -c examples/guestbook/frontend-controller.json create /replicationControllers
Name Image(s) Label Query Replicas
Name Image(s) Selector Replicas
---------- ---------- ---------- ----------
frontendController brendanburns/php-redis name=frontend 3
```
Expand Down
2 changes: 1 addition & 1 deletion examples/guestbook/redis-master-service.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "redismaster",
"port": 10000,
"labels": {
"selector": {
"name": "redis-master"
}
}
2 changes: 1 addition & 1 deletion examples/guestbook/redis-slave-controller.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"id": "redisSlaveController",
"desiredState": {
"replicas": 2,
"replicasInSet": {"name": "redisslave"},
"replicaSelector": {"name": "redisslave"},
"podTemplate": {
"desiredState": {
"manifest": {
Expand Down
3 changes: 3 additions & 0 deletions examples/guestbook/redis-slave-service.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@
"labels": {
"name": "redisslave"
}
"selector": {
"name": "redisslave"
}
}
20 changes: 13 additions & 7 deletions pkg/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ type Pod struct {

// ReplicationControllerState is the state of a replication controller, either input (create, update) or as output (list, get)
type ReplicationControllerState struct {
Replicas int `json:"replicas" yaml:"replicas"`
ReplicasInSet map[string]string `json:"replicasInSet,omitempty" yaml:"replicasInSet,omitempty"`
PodTemplate PodTemplate `json:"podTemplate,omitempty" yaml:"podTemplate,omitempty"`
Replicas int `json:"replicas" yaml:"replicas"`
ReplicaSelector map[string]string `json:"replicaSelector,omitempty" yaml:"replicaSelector,omitempty"`
PodTemplate PodTemplate `json:"podTemplate,omitempty" yaml:"podTemplate,omitempty"`
}

type ReplicationControllerList struct {
Expand Down Expand Up @@ -138,11 +138,17 @@ type ServiceList struct {
}

// Defines a service abstraction by a name (for example, mysql) consisting of local port
// (for example 3306) that the proxy listens on, and the labels that define the service.
// (for example 3306) that the proxy listens on, and the selector that determines which pods
// will answer requests sent through the proxy.
type Service struct {
JSONBase `json:",inline" yaml:",inline"`
Port int `json:"port,omitempty" yaml:"port,omitempty"`
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
JSONBase `json:",inline" yaml:",inline"`
Port int `json:"port,omitempty" yaml:"port,omitempty"`

// This service's labels.
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`

// This service will route traffic to pods having labels matching this selector.
Selector map[string]string `json:"selector,omitempty" yaml:"selector,omitempty"`
CreateExternalLoadBalancer bool `json:"createExternalLoadBalancer,omitempty" yaml:"createExternalLoadBalancer,omitempty"`
}

Expand Down
6 changes: 3 additions & 3 deletions pkg/apiserver/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (

// RESTStorage is a generic interface for RESTful storage services
type RESTStorage interface {
List(labels.Query) (interface{}, error)
List(labels.Selector) (interface{}, error)
Get(id string) (interface{}, error)
Delete(id string) error
Extract(body string) (interface{}, error)
Expand Down Expand Up @@ -149,12 +149,12 @@ func (server *ApiServer) handleREST(parts []string, requestUrl *url.URL, req *ht
case "GET":
switch len(parts) {
case 1:
query, err := labels.ParseQuery(requestUrl.Query().Get("labels"))
selector, err := labels.ParseSelector(requestUrl.Query().Get("labels"))
if err != nil {
server.error(err, w)
return
}
controllers, err := storage.List(query)
controllers, err := storage.List(selector)
if err != nil {
server.error(err, w)
return
Expand Down
2 changes: 1 addition & 1 deletion pkg/apiserver/apiserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ type SimpleRESTStorage struct {
updated Simple
}

func (storage *SimpleRESTStorage) List(labels.Query) (interface{}, error) {
func (storage *SimpleRESTStorage) List(labels.Selector) (interface{}, error) {
result := SimpleList{
Items: storage.list,
}
Expand Down
32 changes: 16 additions & 16 deletions pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (

// ClientInterface holds the methods for clients of Kubenetes, an interface to allow mock testing
type ClientInterface interface {
ListPods(labelQuery map[string]string) (api.PodList, error)
ListPods(selector map[string]string) (api.PodList, error)
GetPod(name string) (api.Pod, error)
DeletePod(name string) error
CreatePod(api.Pod) (api.Pod, error)
Expand Down Expand Up @@ -112,40 +112,40 @@ func (client Client) makeURL(path string) string {
return client.Host + "/api/v1beta1/" + path
}

// EncodeLabelQuery transforms a label query expressed as a key/value map, into a
// EncodeSelector transforms a selector expressed as a key/value map, into a
// comma separated, key=value encoding.
func EncodeLabelQuery(labelQuery map[string]string) string {
query := make([]string, 0, len(labelQuery))
for key, value := range labelQuery {
query = append(query, key+"="+value)
func EncodeSelector(selector map[string]string) string {
parts := make([]string, 0, len(selector))
for key, value := range selector {
parts = append(parts, key+"="+value)
}
return url.QueryEscape(strings.Join(query, ","))
return url.QueryEscape(strings.Join(parts, ","))
}

// DecodeLabelQuery transforms a label query from a comma separated, key=value format into
// DecodeSelector transforms a selector from a comma separated, key=value format into
// a key/value map.
func DecodeLabelQuery(labelQuery string) map[string]string {
func DecodeSelector(selector string) map[string]string {
result := map[string]string{}
if len(labelQuery) == 0 {
if len(selector) == 0 {
return result
}
parts := strings.Split(labelQuery, ",")
parts := strings.Split(selector, ",")
for _, part := range parts {
pieces := strings.Split(part, "=")
if len(pieces) == 2 {
result[pieces[0]] = pieces[1]
} else {
log.Printf("Invalid label query: %s", labelQuery)
log.Printf("Invalid selector: %s", selector)
}
}
return result
}

// ListPods takes a label query, and returns the list of pods that match that query
func (client Client) ListPods(labelQuery map[string]string) (api.PodList, error) {
// ListPods takes a selector, and returns the list of pods that match that selector
func (client Client) ListPods(selector map[string]string) (api.PodList, error) {
path := "pods"
if labelQuery != nil && len(labelQuery) > 0 {
path += "?labels=" + EncodeLabelQuery(labelQuery)
if selector != nil && len(selector) > 0 {
path += "?labels=" + EncodeSelector(selector)
}
var result api.PodList
_, err := client.rawRequest("GET", path, nil, &result)
Expand Down
Loading

0 comments on commit e031c19

Please sign in to comment.