add a --expose flag to kubectl run

This commit is contained in:
Brendan Burns
2015-10-20 11:27:26 -07:00
parent b9c7cf43b2
commit 54fd60727e
6 changed files with 314 additions and 56 deletions

View File

@@ -17,12 +17,20 @@ limitations under the License.
package cmd
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"reflect"
"testing"
"github.com/spf13/cobra"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
client "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/fake"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/util"
)
func TestGetRestartPolicy(t *testing.T) {
@@ -97,3 +105,160 @@ func TestGetEnv(t *testing.T) {
t.Errorf("expected: %s, saw: %s", test.expected, envStrings)
}
}
func TestGenerateService(t *testing.T) {
tests := []struct {
port string
args []string
serviceGenerator string
params map[string]interface{}
expectErr bool
name string
service api.Service
expectPOST bool
}{
{
port: "80",
args: []string{"foo"},
serviceGenerator: "service/v2",
params: map[string]interface{}{
"name": "foo",
},
expectErr: false,
name: "basic",
service: api.Service{
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
Spec: api.ServiceSpec{
Ports: []api.ServicePort{
{
Port: 80,
Protocol: "TCP",
TargetPort: util.NewIntOrStringFromInt(80),
},
},
Selector: map[string]string{
"run": "foo",
},
Type: api.ServiceTypeClusterIP,
SessionAffinity: api.ServiceAffinityNone,
},
},
expectPOST: true,
},
{
port: "80",
args: []string{"foo"},
serviceGenerator: "service/v2",
params: map[string]interface{}{
"name": "foo",
"labels": "app=bar",
},
expectErr: false,
name: "custom labels",
service: api.Service{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Labels: map[string]string{"app": "bar"},
},
Spec: api.ServiceSpec{
Ports: []api.ServicePort{
{
Port: 80,
Protocol: "TCP",
TargetPort: util.NewIntOrStringFromInt(80),
},
},
Selector: map[string]string{
"app": "bar",
},
Type: api.ServiceTypeClusterIP,
SessionAffinity: api.ServiceAffinityNone,
},
},
expectPOST: true,
},
{
expectErr: true,
name: "missing port",
expectPOST: false,
},
{
port: "80",
args: []string{"foo"},
serviceGenerator: "service/v2",
params: map[string]interface{}{
"name": "foo",
},
expectErr: false,
name: "dry-run",
expectPOST: false,
},
}
for _, test := range tests {
sawPOST := false
f, tf, codec := NewAPIFactory()
tf.ClientConfig = &client.Config{Version: testapi.Default.Version()}
tf.Client = &fake.RESTClient{
Codec: codec,
Client: fake.HTTPClientFunc(func(req *http.Request) (*http.Response, error) {
switch p, m := req.URL.Path, req.Method; {
case test.expectPOST && m == "POST" && p == "/namespaces/namespace/services":
sawPOST = true
body := objBody(codec, &test.service)
data, err := ioutil.ReadAll(req.Body)
if err != nil {
t.Errorf("unexpected error: %v", err)
t.FailNow()
}
defer req.Body.Close()
svc := &api.Service{}
if err := codec.DecodeInto(data, svc); err != nil {
t.Errorf("unexpected error: %v", err)
t.FailNow()
}
// Copy things that are defaulted by the system
test.service.Annotations = svc.Annotations
if !reflect.DeepEqual(&test.service, svc) {
t.Errorf("expected:\n%v\nsaw:\n%v\n", &test.service, svc)
}
return &http.Response{StatusCode: 200, Body: body}, nil
default:
// Ensures no GET is performed when deleting by name
t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req)
return nil, fmt.Errorf("unexpected request")
}
}),
}
cmd := &cobra.Command{}
cmd.Flags().String("output", "", "")
addRunFlags(cmd)
if !test.expectPOST {
cmd.Flags().Set("dry-run", "true")
}
if len(test.port) > 0 {
cmd.Flags().Set("port", test.port)
test.params["port"] = test.port
}
buff := &bytes.Buffer{}
err := generateService(f, cmd, test.args, test.serviceGenerator, test.params, "namespace", buff)
if test.expectErr {
if err == nil {
t.Error("unexpected non-error")
}
continue
}
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if test.expectPOST != sawPOST {
t.Error("expectPost: %v, sawPost: %v", test.expectPOST, sawPOST)
}
}
}