2015-02-20 17:35:42 +00:00
/ *
2015-05-01 16:19:44 +00:00
Copyright 2015 The Kubernetes Authors All rights reserved .
2015-02-20 17:35:42 +00:00
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
package e2e
import (
2015-09-10 21:32:57 +00:00
"bytes"
2015-02-20 17:35:42 +00:00
"encoding/json"
2015-03-26 20:34:18 +00:00
"errors"
2015-03-26 19:22:04 +00:00
"fmt"
2015-08-31 17:23:47 +00:00
"io"
2015-06-30 16:43:37 +00:00
"io/ioutil"
2016-05-17 21:56:27 +00:00
"log"
2015-09-17 20:11:27 +00:00
"mime/multipart"
2015-07-07 10:39:38 +00:00
"net"
2015-06-30 16:43:37 +00:00
"net/http"
2016-05-17 21:56:27 +00:00
"net/http/httptest"
2015-07-07 10:39:38 +00:00
"os"
2015-07-07 05:09:22 +00:00
"os/exec"
2015-09-29 15:20:49 +00:00
"path"
2015-02-20 17:35:42 +00:00
"path/filepath"
2015-06-30 16:43:37 +00:00
"regexp"
2016-03-29 17:01:54 +00:00
"sort"
2015-07-07 05:09:22 +00:00
"strconv"
2015-02-20 17:35:42 +00:00
"strings"
"time"
2016-05-17 21:56:27 +00:00
"github.com/elazarl/goproxy"
2015-09-10 21:32:57 +00:00
"github.com/ghodss/yaml"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/api"
2016-05-05 00:37:03 +00:00
"k8s.io/kubernetes/pkg/api/annotations"
2015-09-10 01:28:53 +00:00
apierrs "k8s.io/kubernetes/pkg/api/errors"
2015-10-09 01:32:15 +00:00
"k8s.io/kubernetes/pkg/api/unversioned"
2015-08-13 19:01:50 +00:00
client "k8s.io/kubernetes/pkg/client/unversioned"
2016-03-29 17:01:54 +00:00
"k8s.io/kubernetes/pkg/controller"
2015-11-13 01:07:21 +00:00
"k8s.io/kubernetes/pkg/kubectl/cmd/util"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/labels"
2016-05-26 20:01:49 +00:00
"k8s.io/kubernetes/pkg/registry/generic/registry"
2016-03-31 03:42:57 +00:00
pkgutil "k8s.io/kubernetes/pkg/util"
2016-03-15 19:29:08 +00:00
utilnet "k8s.io/kubernetes/pkg/util/net"
2015-09-10 01:28:53 +00:00
"k8s.io/kubernetes/pkg/util/wait"
2016-01-13 19:27:40 +00:00
"k8s.io/kubernetes/pkg/version"
2016-04-07 17:21:31 +00:00
"k8s.io/kubernetes/test/e2e/framework"
2015-03-05 04:35:51 +00:00
2015-02-20 17:35:42 +00:00
. "github.com/onsi/ginkgo"
2015-04-30 02:53:09 +00:00
. "github.com/onsi/gomega"
2015-02-20 17:35:42 +00:00
)
const (
2015-03-31 17:25:20 +00:00
nautilusImage = "gcr.io/google_containers/update-demo:nautilus"
kittenImage = "gcr.io/google_containers/update-demo:kitten"
2015-03-13 16:26:41 +00:00
updateDemoSelector = "name=update-demo"
updateDemoContainer = "update-demo"
2015-09-23 09:37:47 +00:00
frontendSelector = "app=guestbook,tier=frontend"
redisMasterSelector = "app=redis,role=master"
redisSlaveSelector = "app=redis,role=slave"
2015-09-17 20:11:27 +00:00
goproxyContainer = "goproxy"
goproxyPodSelector = "name=goproxy"
netexecContainer = "netexec"
netexecPodSelector = "name=netexec"
2015-03-13 16:26:41 +00:00
kubectlProxyPort = 8011
2015-03-18 14:16:26 +00:00
guestbookStartupTimeout = 10 * time . Minute
2015-03-24 12:59:45 +00:00
guestbookResponseTimeout = 3 * time . Minute
2015-06-30 16:43:37 +00:00
simplePodSelector = "name=nginx"
simplePodName = "nginx"
nginxDefaultOutput = "Welcome to nginx!"
simplePodPort = 80
2016-05-26 00:25:02 +00:00
pausePodSelector = "name=pause"
pausePodName = "pause"
2016-01-08 16:14:55 +00:00
runJobTimeout = 5 * time . Minute
2016-03-19 23:02:29 +00:00
busyboxImage = "gcr.io/google_containers/busybox:1.24"
2016-02-25 00:54:40 +00:00
nginxImage = "gcr.io/google_containers/nginx:1.7.9"
2016-04-27 04:43:19 +00:00
kubeCtlManifestPath = "test/e2e/testing-manifests/kubectl"
2016-05-18 01:13:14 +00:00
redisControllerFilename = "redis-master-controller.json"
redisServiceFilename = "redis-master-service.json"
2015-06-30 16:43:37 +00:00
)
2016-01-13 19:27:40 +00:00
var (
proxyRegexp = regexp . MustCompile ( "Starting to serve on 127.0.0.1:([0-9]+)" )
// Extended pod logging options were introduced in #13780 (v1.1.0) so we don't expect tests
// that rely on extended pod logging options to work on clusters before that.
//
// TODO(ihmccreery): remove once we don't care about v1.0 anymore, (tentatively in v1.3).
extendedPodLogFilterVersion = version . MustParse ( "v1.1.0" )
// NodePorts were made optional in #12831 (v1.1.0) so we don't expect tests that used to
// require NodePorts but no longer include them to work on clusters before that.
//
// TODO(ihmccreery): remove once we don't care about v1.0 anymore, (tentatively in v1.3).
nodePortsOptionalVersion = version . MustParse ( "v1.1.0" )
// Jobs were introduced in v1.1, so we don't expect tests that rely on jobs to work on
// clusters before that.
//
// TODO(ihmccreery): remove once we don't care about v1.0 anymore, (tentatively in v1.3).
jobsVersion = version . MustParse ( "v1.1.0" )
2016-02-17 21:36:24 +00:00
// Deployments were introduced by default in v1.2, so we don't expect tests that rely on
// deployments to work on clusters before that.
//
// TODO(ihmccreery): remove once we don't care about v1.1 anymore, (tentatively in v1.4).
deploymentsVersion = version . MustParse ( "v1.2.0-alpha.7.726" )
2016-03-15 02:58:44 +00:00
// Pod probe parameters were introduced in #15967 (v1.2) so we dont expect tests that use
// these probe parameters to work on clusters before that.
//
// TODO(ihmccreery): remove once we don't care about v1.1 anymore, (tentatively in v1.4).
podProbeParametersVersion = version . MustParse ( "v1.2.0-alpha.4" )
2016-01-13 19:27:40 +00:00
)
2015-02-20 17:35:42 +00:00
2016-04-26 16:22:18 +00:00
// Stops everything from filePath from namespace ns and checks if everything matching selectors from the given namespace is correctly stopped.
// Aware of the kubectl example files map.
func cleanupKubectlInputs ( fileContents string , ns string , selectors ... string ) {
By ( "using delete to clean up resources" )
var nsArg string
if ns != "" {
nsArg = fmt . Sprintf ( "--namespace=%s" , ns )
}
// support backward compatibility : file paths or raw json - since we are removing file path
// dependencies from this test.
framework . RunKubectlOrDieInput ( fileContents , "delete" , "--grace-period=0" , "-f" , "-" , nsArg )
framework . AssertCleanup ( ns , selectors ... )
}
2016-05-18 01:13:14 +00:00
func readTestFileOrDie ( file string ) [ ] byte {
return framework . ReadOrDie ( path . Join ( kubeCtlManifestPath , file ) )
}
2016-05-26 20:01:49 +00:00
func runKubectlRetryOrDie ( args ... string ) string {
var err error
var output string
for i := 0 ; i < 3 ; i ++ {
output , err = framework . RunKubectl ( args ... )
if err == nil || ! strings . Contains ( err . Error ( ) , registry . OptimisticLockErrorMsg ) {
break
}
time . Sleep ( time . Second )
}
// Expect no errors to be present after retries are finished
// Copied from framework #ExecOrDie
framework . Logf ( "stdout: %q" , output )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
return output
}
2016-04-07 17:21:31 +00:00
var _ = framework . KubeDescribe ( "Kubectl client" , func ( ) {
2015-05-19 16:13:08 +00:00
defer GinkgoRecover ( )
2016-04-07 17:21:31 +00:00
f := framework . NewDefaultFramework ( "kubectl" )
2016-03-31 18:45:08 +00:00
// Reustable cluster state function. This won't be adversly affected by lazy initialization of framework.
clusterState := func ( ) * framework . ClusterVerification {
return f . NewClusterVerification (
framework . PodStateVerification {
Selectors : map [ string ] string { "app" : "redis" } ,
ValidPhases : [ ] api . PodPhase { api . PodRunning /*api.PodPending*/ } ,
} )
}
2016-05-18 01:13:14 +00:00
2016-03-31 18:45:08 +00:00
forEachPod := func ( podFunc func ( p api . Pod ) ) {
clusterState ( ) . ForEach ( podFunc )
}
2015-03-05 04:35:51 +00:00
var c * client . Client
2015-04-30 02:53:09 +00:00
var ns string
2015-03-02 18:15:34 +00:00
BeforeEach ( func ( ) {
2016-04-07 17:21:31 +00:00
c = f . Client
ns = f . Namespace . Name
2015-03-02 18:15:34 +00:00
} )
2015-02-20 17:35:42 +00:00
2016-05-18 01:13:14 +00:00
// Customized Wait / ForEach wrapper for this test. These demonstrate the
// idiomatic way to wrap the ClusterVerification structs for syntactic sugar in large
// test files.
// Print debug info if atLeast Pods are not found before the timeout
waitForOrFailWithDebug := func ( atLeast int ) {
2016-05-24 11:10:56 +00:00
pods , err := clusterState ( ) . WaitFor ( atLeast , framework . PodStartTimeout )
2016-05-18 01:13:14 +00:00
if err != nil || len ( pods ) < atLeast {
// TODO: Generalize integrating debug info into these tests so we always get debug info when we need it
framework . DumpAllNamespaceInfo ( c , ns )
framework . Failf ( "Verified %v of %v pods , error : %v" , len ( pods ) , atLeast , err )
}
}
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Update Demo" , func ( ) {
2016-04-26 16:22:18 +00:00
var nautilus , kitten [ ] byte
2015-05-19 16:13:08 +00:00
BeforeEach ( func ( ) {
2016-04-26 16:22:18 +00:00
updateDemoRoot := "docs/user-guide/update-demo"
nautilus = framework . ReadOrDie ( filepath . Join ( updateDemoRoot , "nautilus-rc.yaml" ) )
kitten = framework . ReadOrDie ( filepath . Join ( updateDemoRoot , "kitten-rc.yaml" ) )
2015-05-19 16:13:08 +00:00
} )
2015-10-07 14:09:24 +00:00
It ( "should create and stop a replication controller [Conformance]" , func ( ) {
2016-04-26 16:22:18 +00:00
defer cleanupKubectlInputs ( string ( nautilus ) , ns , updateDemoSelector )
2015-03-13 16:26:41 +00:00
By ( "creating a replication controller" )
2016-04-26 16:22:18 +00:00
framework . RunKubectlOrDieInput ( string ( nautilus [ : ] ) , "create" , "-f" , "-" , fmt . Sprintf ( "--namespace=%v" , ns ) )
2016-04-07 17:21:31 +00:00
framework . ValidateController ( c , nautilusImage , 2 , "update-demo" , updateDemoSelector , getUDData ( "nautilus.jpg" , ns ) , ns )
2015-03-13 16:26:41 +00:00
} )
2015-10-07 14:09:24 +00:00
It ( "should scale a replication controller [Conformance]" , func ( ) {
2016-04-26 16:22:18 +00:00
defer cleanupKubectlInputs ( string ( nautilus [ : ] ) , ns , updateDemoSelector )
2015-03-13 16:26:41 +00:00
By ( "creating a replication controller" )
2016-04-26 16:22:18 +00:00
framework . RunKubectlOrDieInput ( string ( nautilus [ : ] ) , "create" , "-f" , "-" , fmt . Sprintf ( "--namespace=%v" , ns ) )
2016-04-07 17:21:31 +00:00
framework . ValidateController ( c , nautilusImage , 2 , "update-demo" , updateDemoSelector , getUDData ( "nautilus.jpg" , ns ) , ns )
2015-03-13 16:26:41 +00:00
By ( "scaling down the replication controller" )
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "scale" , "rc" , "update-demo-nautilus" , "--replicas=1" , "--timeout=5m" , fmt . Sprintf ( "--namespace=%v" , ns ) )
framework . ValidateController ( c , nautilusImage , 1 , "update-demo" , updateDemoSelector , getUDData ( "nautilus.jpg" , ns ) , ns )
2015-03-13 16:26:41 +00:00
By ( "scaling up the replication controller" )
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "scale" , "rc" , "update-demo-nautilus" , "--replicas=2" , "--timeout=5m" , fmt . Sprintf ( "--namespace=%v" , ns ) )
framework . ValidateController ( c , nautilusImage , 2 , "update-demo" , updateDemoSelector , getUDData ( "nautilus.jpg" , ns ) , ns )
2015-03-13 16:26:41 +00:00
} )
2015-10-07 14:09:24 +00:00
It ( "should do a rolling update of a replication controller [Conformance]" , func ( ) {
2015-03-13 16:26:41 +00:00
By ( "creating the initial replication controller" )
2016-04-26 16:22:18 +00:00
framework . RunKubectlOrDieInput ( string ( nautilus [ : ] ) , "create" , "-f" , "-" , fmt . Sprintf ( "--namespace=%v" , ns ) )
2016-04-07 17:21:31 +00:00
framework . ValidateController ( c , nautilusImage , 2 , "update-demo" , updateDemoSelector , getUDData ( "nautilus.jpg" , ns ) , ns )
2015-03-27 23:24:59 +00:00
By ( "rolling-update to new replication controller" )
2016-04-26 16:22:18 +00:00
framework . RunKubectlOrDieInput ( string ( kitten [ : ] ) , "rolling-update" , "update-demo-nautilus" , "--update-period=1s" , "-f" , "-" , fmt . Sprintf ( "--namespace=%v" , ns ) )
2016-04-07 17:21:31 +00:00
framework . ValidateController ( c , kittenImage , 2 , "update-demo" , updateDemoSelector , getUDData ( "kitten.jpg" , ns ) , ns )
2015-05-15 03:10:32 +00:00
// Everything will hopefully be cleaned up when the namespace is deleted.
2015-03-13 16:26:41 +00:00
} )
2015-02-20 17:35:42 +00:00
} )
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Guestbook application" , func ( ) {
2016-04-26 16:22:18 +00:00
forEachGBFile := func ( run func ( s string ) ) {
for _ , gbAppFile := range [ ] string {
"examples/guestbook/frontend-deployment.yaml" ,
"examples/guestbook/frontend-service.yaml" ,
"examples/guestbook/redis-master-deployment.yaml" ,
"examples/guestbook/redis-master-service.yaml" ,
"examples/guestbook/redis-slave-deployment.yaml" ,
"examples/guestbook/redis-slave-service.yaml" ,
} {
contents := framework . ReadOrDie ( gbAppFile )
run ( string ( contents ) )
}
}
2015-03-13 16:26:41 +00:00
2015-10-07 14:09:24 +00:00
It ( "should create and stop a working application [Conformance]" , func ( ) {
2016-04-15 17:48:47 +00:00
framework . SkipUnlessServerVersionGTE ( deploymentsVersion , c )
2016-01-13 19:27:40 +00:00
2016-04-26 16:22:18 +00:00
defer forEachGBFile ( func ( contents string ) {
cleanupKubectlInputs ( contents , ns )
} )
2015-03-13 16:26:41 +00:00
By ( "creating all guestbook components" )
2016-04-26 16:22:18 +00:00
forEachGBFile ( func ( contents string ) {
framework . Logf ( contents )
framework . RunKubectlOrDieInput ( contents , "create" , "-f" , "-" , fmt . Sprintf ( "--namespace=%v" , ns ) )
} )
2015-02-20 17:35:42 +00:00
2015-03-13 16:26:41 +00:00
By ( "validating guestbook app" )
2015-04-30 02:53:09 +00:00
validateGuestbookApp ( c , ns )
2015-03-13 16:26:41 +00:00
} )
2015-02-20 17:35:42 +00:00
} )
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Simple pod" , func ( ) {
2016-04-26 16:22:18 +00:00
var podPath [ ] byte
2015-06-30 16:43:37 +00:00
BeforeEach ( func ( ) {
2016-05-18 01:13:14 +00:00
podPath = framework . ReadOrDie ( path . Join ( kubeCtlManifestPath , "pod-with-readiness-probe.yaml" ) )
2016-04-26 16:22:18 +00:00
By ( fmt . Sprintf ( "creating the pod from %v" , string ( podPath ) ) )
framework . RunKubectlOrDieInput ( string ( podPath [ : ] ) , "create" , "-f" , "-" , fmt . Sprintf ( "--namespace=%v" , ns ) )
2016-05-19 21:34:41 +00:00
Expect ( framework . CheckPodsRunningReady ( c , ns , [ ] string { simplePodName } , framework . PodStartTimeout ) ) . To ( BeTrue ( ) )
2015-06-30 16:43:37 +00:00
} )
AfterEach ( func ( ) {
2016-04-26 16:22:18 +00:00
cleanupKubectlInputs ( string ( podPath [ : ] ) , ns , simplePodSelector )
2015-06-30 16:43:37 +00:00
} )
It ( "should support exec" , func ( ) {
By ( "executing a command in the container" )
2016-04-07 17:21:31 +00:00
execOutput := framework . RunKubectlOrDie ( "exec" , fmt . Sprintf ( "--namespace=%v" , ns ) , simplePodName , "echo" , "running" , "in" , "container" )
2016-05-12 01:40:58 +00:00
if e , a := "running in container" , strings . TrimSpace ( execOutput ) ; e != a {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Unexpected kubectl exec output. Wanted %q, got %q" , e , a )
2015-08-31 17:23:47 +00:00
}
By ( "executing a command in the container with noninteractive stdin" )
2016-04-07 17:21:31 +00:00
execOutput = framework . NewKubectlCommand ( "exec" , fmt . Sprintf ( "--namespace=%v" , ns ) , "-i" , simplePodName , "cat" ) .
WithStdinData ( "abcd1234" ) .
ExecOrDie ( )
2015-08-31 17:23:47 +00:00
if e , a := "abcd1234" , execOutput ; e != a {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Unexpected kubectl exec output. Wanted %q, got %q" , e , a )
2015-08-31 17:23:47 +00:00
}
// pretend that we're a user in an interactive shell
2015-09-17 20:11:27 +00:00
r , closer , err := newBlockingReader ( "echo hi\nexit\n" )
2015-08-31 17:23:47 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Error creating blocking reader: %v" , err )
2015-08-31 17:23:47 +00:00
}
// NOTE this is solely for test cleanup!
2015-09-17 20:11:27 +00:00
defer closer . Close ( )
2015-08-31 17:23:47 +00:00
By ( "executing a command in the container with pseudo-interactive stdin" )
2016-04-07 17:21:31 +00:00
execOutput = framework . NewKubectlCommand ( "exec" , fmt . Sprintf ( "--namespace=%v" , ns ) , "-i" , simplePodName , "bash" ) .
WithStdinReader ( r ) .
ExecOrDie ( )
2016-05-12 01:40:58 +00:00
if e , a := "hi" , strings . TrimSpace ( execOutput ) ; e != a {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Unexpected kubectl exec output. Wanted %q, got %q" , e , a )
2015-06-30 16:43:37 +00:00
}
} )
2015-08-31 17:23:47 +00:00
2015-10-19 18:17:02 +00:00
It ( "should support exec through an HTTP proxy" , func ( ) {
2015-09-17 20:11:27 +00:00
// Note: We are skipping local since we want to verify an apiserver with HTTPS.
// At this time local only supports plain HTTP.
2016-04-07 17:21:31 +00:00
framework . SkipIfProviderIs ( "local" )
2015-09-17 20:11:27 +00:00
// Fail if the variable isn't set
2016-04-07 17:21:31 +00:00
if framework . TestContext . Host == "" {
framework . Failf ( "--host variable must be set to the full URI to the api server on e2e run." )
2015-09-17 20:11:27 +00:00
}
2015-10-19 18:17:02 +00:00
2016-05-17 21:56:27 +00:00
By ( "Starting goproxy" )
testSrv , proxyLogs := startLocalProxy ( )
defer testSrv . Close ( )
proxyAddr := testSrv . URL
2015-09-17 20:11:27 +00:00
2016-04-20 00:46:26 +00:00
for _ , proxyVar := range [ ] string { "https_proxy" , "HTTPS_PROXY" } {
2016-05-17 21:56:27 +00:00
proxyLogs . Reset ( )
By ( "Running kubectl via an HTTP proxy using " + proxyVar )
output := framework . NewKubectlCommand ( fmt . Sprintf ( "--namespace=%s" , ns ) , "exec" , "nginx" , "echo" , "running" , "in" , "container" ) .
WithEnv ( append ( os . Environ ( ) , fmt . Sprintf ( "%s=%s" , proxyVar , proxyAddr ) ) ) .
ExecOrDie ( )
2016-01-21 23:58:37 +00:00
2015-09-17 20:11:27 +00:00
// Verify we got the normal output captured by the exec server
expectedExecOutput := "running in container\n"
2016-05-17 21:56:27 +00:00
if output != expectedExecOutput {
framework . Failf ( "Unexpected kubectl exec output. Wanted %q, got %q" , expectedExecOutput , output )
2015-09-17 20:11:27 +00:00
}
// Verify the proxy server logs saw the connection
2016-04-07 17:21:31 +00:00
expectedProxyLog := fmt . Sprintf ( "Accepting CONNECT to %s" , strings . TrimRight ( strings . TrimLeft ( framework . TestContext . Host , "https://" ) , "/api" ) )
2015-09-17 20:11:27 +00:00
2016-05-17 21:56:27 +00:00
proxyLog := proxyLogs . String ( )
2015-09-17 20:11:27 +00:00
if ! strings . Contains ( proxyLog , expectedProxyLog ) {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Missing expected log result on proxy server for %s. Expected: %q, got %q" , proxyVar , expectedProxyLog , proxyLog )
2015-09-17 20:11:27 +00:00
}
}
} )
2015-09-01 23:42:16 +00:00
It ( "should support inline execution and attach" , func ( ) {
2016-04-07 17:21:31 +00:00
framework . SkipUnlessServerVersionGTE ( jobsVersion , c )
2016-01-13 19:27:40 +00:00
2015-10-06 15:31:48 +00:00
nsFlag := fmt . Sprintf ( "--namespace=%v" , ns )
By ( "executing a command with run and attach with stdin" )
2016-04-07 17:21:31 +00:00
runOutput := framework . NewKubectlCommand ( nsFlag , "run" , "run-test" , "--image=" + busyboxImage , "--restart=Never" , "--attach=true" , "--stdin" , "--" , "sh" , "-c" , "cat && echo 'stdin closed'" ) .
WithStdinData ( "abcd1234" ) .
ExecOrDie ( )
2015-10-06 15:31:48 +00:00
Expect ( runOutput ) . To ( ContainSubstring ( "abcd1234" ) )
Expect ( runOutput ) . To ( ContainSubstring ( "stdin closed" ) )
2016-02-23 21:56:59 +00:00
Expect ( c . Extensions ( ) . Jobs ( ns ) . Delete ( "run-test" , nil ) ) . To ( BeNil ( ) )
2015-10-06 15:31:48 +00:00
By ( "executing a command with run and attach without stdin" )
2016-04-07 17:21:31 +00:00
runOutput = framework . NewKubectlCommand ( fmt . Sprintf ( "--namespace=%v" , ns ) , "run" , "run-test-2" , "--image=" + busyboxImage , "--restart=Never" , "--attach=true" , "--leave-stdin-open=true" , "--" , "sh" , "-c" , "cat && echo 'stdin closed'" ) .
WithStdinData ( "abcd1234" ) .
ExecOrDie ( )
2015-10-06 15:31:48 +00:00
Expect ( runOutput ) . ToNot ( ContainSubstring ( "abcd1234" ) )
Expect ( runOutput ) . To ( ContainSubstring ( "stdin closed" ) )
2016-02-23 21:56:59 +00:00
Expect ( c . Extensions ( ) . Jobs ( ns ) . Delete ( "run-test-2" , nil ) ) . To ( BeNil ( ) )
2015-10-06 15:31:48 +00:00
By ( "executing a command with run and attach with stdin with open stdin should remain running" )
2016-04-07 17:21:31 +00:00
runOutput = framework . NewKubectlCommand ( nsFlag , "run" , "run-test-3" , "--image=" + busyboxImage , "--restart=Never" , "--attach=true" , "--leave-stdin-open=true" , "--stdin" , "--" , "sh" , "-c" , "cat && echo 'stdin closed'" ) .
WithStdinData ( "abcd1234\n" ) .
ExecOrDie ( )
2015-10-06 15:31:48 +00:00
Expect ( runOutput ) . ToNot ( ContainSubstring ( "stdin closed" ) )
2016-03-29 17:01:54 +00:00
f := func ( pods [ ] * api . Pod ) sort . Interface { return sort . Reverse ( controller . ActivePods ( pods ) ) }
runTestPod , _ , err := util . GetFirstPod ( c , ns , labels . SelectorFromSet ( map [ string ] string { "run" : "run-test-3" } ) , 1 * time . Minute , f )
2015-11-13 01:07:21 +00:00
if err != nil {
os . Exit ( 1 )
}
2016-04-07 17:21:31 +00:00
if ! framework . CheckPodsRunningReady ( c , ns , [ ] string { runTestPod . Name } , time . Minute ) {
framework . Failf ( "Pod %q of Job %q should still be running" , runTestPod . Name , "run-test-3" )
2015-10-06 15:31:48 +00:00
}
// NOTE: we cannot guarantee our output showed up in the container logs before stdin was closed, so we have
// to loop test.
2015-11-13 01:07:21 +00:00
err = wait . PollImmediate ( time . Second , time . Minute , func ( ) ( bool , error ) {
2016-04-07 17:21:31 +00:00
if ! framework . CheckPodsRunningReady ( c , ns , [ ] string { runTestPod . Name } , 1 * time . Second ) {
framework . Failf ( "Pod %q of Job %q should still be running" , runTestPod . Name , "run-test-3" )
2015-10-06 15:31:48 +00:00
}
2016-04-07 17:21:31 +00:00
logOutput := framework . RunKubectlOrDie ( nsFlag , "logs" , runTestPod . Name )
2015-10-06 15:31:48 +00:00
Expect ( logOutput ) . ToNot ( ContainSubstring ( "stdin closed" ) )
return strings . Contains ( logOutput , "abcd1234" ) , nil
} )
if err != nil {
os . Exit ( 1 )
}
Expect ( err ) . To ( BeNil ( ) )
2016-02-23 21:56:59 +00:00
Expect ( c . Extensions ( ) . Jobs ( ns ) . Delete ( "run-test-3" , nil ) ) . To ( BeNil ( ) )
2015-09-01 23:42:16 +00:00
} )
2015-06-30 16:43:37 +00:00
It ( "should support port-forward" , func ( ) {
By ( "forwarding the container port to a local port" )
2016-03-24 18:56:27 +00:00
cmd := runPortForward ( ns , simplePodName , simplePodPort )
defer cmd . Stop ( )
2015-09-22 20:29:51 +00:00
2015-06-30 16:43:37 +00:00
By ( "curling local port output" )
2016-03-24 18:56:27 +00:00
localAddr := fmt . Sprintf ( "http://localhost:%d" , cmd . port )
2015-06-30 16:43:37 +00:00
body , err := curl ( localAddr )
2016-04-07 17:21:31 +00:00
framework . Logf ( "got: %s" , body )
2015-06-30 16:43:37 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed http.Get of forwarded port (%s): %v" , localAddr , err )
2015-06-30 16:43:37 +00:00
}
if ! strings . Contains ( body , nginxDefaultOutput ) {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Container port output missing expected value. Wanted:'%s', got: %s" , nginxDefaultOutput , body )
2015-06-30 16:43:37 +00:00
}
} )
} )
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Kubectl api-versions" , func ( ) {
2015-10-07 14:09:24 +00:00
It ( "should check if v1 is in available api versions [Conformance]" , func ( ) {
2015-07-24 08:20:35 +00:00
By ( "validating api verions" )
2016-04-07 17:21:31 +00:00
output := framework . RunKubectlOrDie ( "api-versions" )
2015-07-24 08:20:35 +00:00
if ! strings . Contains ( output , "v1" ) {
2016-04-07 17:21:31 +00:00
framework . Failf ( "No v1 in kubectl api-versions" )
2015-07-24 08:20:35 +00:00
}
2015-07-09 00:14:28 +00:00
} )
2015-07-24 08:20:35 +00:00
} )
2015-07-09 00:14:28 +00:00
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Kubectl apply" , func ( ) {
2015-09-10 21:32:57 +00:00
It ( "should apply a new configuration to an existing RC" , func ( ) {
2016-05-18 01:13:14 +00:00
controllerJson := readTestFileOrDie ( redisControllerFilename )
2015-09-10 21:32:57 +00:00
nsFlag := fmt . Sprintf ( "--namespace=%v" , ns )
By ( "creating Redis RC" )
2016-04-26 16:22:18 +00:00
framework . RunKubectlOrDieInput ( string ( controllerJson ) , "create" , "-f" , "-" , nsFlag )
2015-09-10 21:32:57 +00:00
By ( "applying a modified configuration" )
2016-04-26 16:22:18 +00:00
stdin := modifyReplicationControllerConfiguration ( string ( controllerJson ) )
2016-04-07 17:21:31 +00:00
framework . NewKubectlCommand ( "apply" , "-f" , "-" , nsFlag ) .
WithStdinReader ( stdin ) .
ExecOrDie ( )
2015-09-10 21:32:57 +00:00
By ( "checking the result" )
forEachReplicationController ( c , ns , "app" , "redis" , validateReplicationControllerConfiguration )
} )
2016-04-20 06:30:03 +00:00
It ( "should reuse nodePort when apply to an existing SVC" , func ( ) {
2016-05-18 01:13:14 +00:00
serviceJson := readTestFileOrDie ( redisServiceFilename )
2016-04-20 06:30:03 +00:00
nsFlag := fmt . Sprintf ( "--namespace=%v" , ns )
2016-04-26 16:22:18 +00:00
2016-04-20 06:30:03 +00:00
By ( "creating Redis SVC" )
2016-04-26 16:22:18 +00:00
framework . RunKubectlOrDieInput ( string ( serviceJson [ : ] ) , "create" , "-f" , "-" , nsFlag )
2016-04-20 06:30:03 +00:00
By ( "getting the original nodePort" )
originalNodePort := framework . RunKubectlOrDie ( "get" , "service" , "redis-master" , nsFlag , "-o" , "jsonpath={.spec.ports[0].nodePort}" )
2016-04-26 16:22:18 +00:00
2016-04-20 06:30:03 +00:00
By ( "applying the same configuration" )
2016-04-26 16:22:18 +00:00
framework . RunKubectlOrDieInput ( string ( serviceJson [ : ] ) , "apply" , "-f" , "-" , nsFlag )
2016-04-20 06:30:03 +00:00
By ( "getting the nodePort after applying configuration" )
currentNodePort := framework . RunKubectlOrDie ( "get" , "service" , "redis-master" , nsFlag , "-o" , "jsonpath={.spec.ports[0].nodePort}" )
2016-04-26 16:22:18 +00:00
2016-04-20 06:30:03 +00:00
By ( "checking the result" )
if originalNodePort != currentNodePort {
framework . Failf ( "nodePort should keep the same" )
}
} )
2015-09-10 21:32:57 +00:00
} )
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Kubectl cluster-info" , func ( ) {
2015-10-07 14:09:24 +00:00
It ( "should check if Kubernetes master services is included in cluster-info [Conformance]" , func ( ) {
2015-07-24 08:20:35 +00:00
By ( "validating cluster-info" )
2016-04-07 17:21:31 +00:00
output := framework . RunKubectlOrDie ( "cluster-info" )
2015-08-08 21:29:57 +00:00
// Can't check exact strings due to terminal control commands (colors)
2015-07-24 08:20:35 +00:00
requiredItems := [ ] string { "Kubernetes master" , "is running at" }
2016-04-07 17:21:31 +00:00
if framework . ProviderIs ( "gce" , "gke" ) {
2015-07-24 08:20:35 +00:00
requiredItems = append ( requiredItems , "KubeDNS" , "Heapster" )
}
for _ , item := range requiredItems {
if ! strings . Contains ( output , item ) {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Missing %s in kubectl cluster-info" , item )
2015-07-24 08:20:35 +00:00
}
2015-07-09 00:14:28 +00:00
}
2015-07-24 08:20:35 +00:00
} )
} )
2015-07-09 00:14:28 +00:00
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Kubectl describe" , func ( ) {
2016-05-04 17:19:05 +00:00
// Flaky issue: #25083
It ( "should check if kubectl describe prints relevant information for rc and pods [Conformance] [Flaky]" , func ( ) {
2016-04-07 17:21:31 +00:00
framework . SkipUnlessServerVersionGTE ( nodePortsOptionalVersion , c )
2016-05-18 01:13:14 +00:00
controllerJson := readTestFileOrDie ( redisControllerFilename )
serviceJson := readTestFileOrDie ( redisServiceFilename )
2015-07-24 08:20:35 +00:00
nsFlag := fmt . Sprintf ( "--namespace=%v" , ns )
2016-04-26 16:22:18 +00:00
framework . RunKubectlOrDieInput ( string ( controllerJson [ : ] ) , "create" , "-f" , "-" , nsFlag )
framework . RunKubectlOrDieInput ( string ( serviceJson [ : ] ) , "create" , "-f" , "-" , nsFlag )
2015-07-24 08:20:35 +00:00
2016-05-12 17:02:36 +00:00
By ( "Waiting for Redis master to start." )
2016-05-18 01:13:14 +00:00
waitForOrFailWithDebug ( 1 )
2015-07-24 08:20:35 +00:00
// Pod
2016-03-31 18:45:08 +00:00
forEachPod ( func ( pod api . Pod ) {
2016-04-07 17:21:31 +00:00
output := framework . RunKubectlOrDie ( "describe" , "pod" , pod . Name , nsFlag )
2015-07-24 08:20:35 +00:00
requiredStrings := [ ] [ ] string {
{ "Name:" , "redis-master-" } ,
{ "Namespace:" , ns } ,
{ "Node:" } ,
2016-04-07 18:21:58 +00:00
{ "Labels:" , "app=redis" } ,
{ "role=master" } ,
2015-07-24 08:20:35 +00:00
{ "Status:" , "Running" } ,
{ "IP:" } ,
2016-02-16 23:43:59 +00:00
{ "Controllers:" , "ReplicationController/redis-master" } ,
2016-04-27 04:43:19 +00:00
{ "Image:" , redisImage } ,
2016-02-16 23:43:59 +00:00
{ "cpu:" , "BestEffort" } ,
{ "State:" , "Running" } ,
}
2015-07-24 08:20:35 +00:00
checkOutput ( output , requiredStrings )
} )
// Rc
2016-04-07 17:21:31 +00:00
output := framework . RunKubectlOrDie ( "describe" , "rc" , "redis-master" , nsFlag )
2015-07-24 08:20:35 +00:00
requiredStrings := [ ] [ ] string {
{ "Name:" , "redis-master" } ,
{ "Namespace:" , ns } ,
2016-04-27 04:43:19 +00:00
{ "Image(s):" , redisImage } ,
2015-07-24 08:20:35 +00:00
{ "Selector:" , "app=redis,role=master" } ,
2016-04-07 18:21:58 +00:00
{ "Labels:" , "app=redis" } ,
{ "role=master" } ,
2015-07-24 08:20:35 +00:00
{ "Replicas:" , "1 current" , "1 desired" } ,
{ "Pods Status:" , "1 Running" , "0 Waiting" , "0 Succeeded" , "0 Failed" } ,
2016-01-22 18:56:14 +00:00
// {"Events:"} would ordinarily go in the list
// here, but in some rare circumstances the
// events are delayed, and instead kubectl
// prints "No events." This string will match
// either way.
{ "vents" } }
2015-07-24 08:20:35 +00:00
checkOutput ( output , requiredStrings )
// Service
2016-04-07 17:21:31 +00:00
output = framework . RunKubectlOrDie ( "describe" , "service" , "redis-master" , nsFlag )
2015-07-24 08:20:35 +00:00
requiredStrings = [ ] [ ] string {
{ "Name:" , "redis-master" } ,
{ "Namespace:" , ns } ,
2016-04-07 18:21:58 +00:00
{ "Labels:" , "app=redis" } ,
{ "role=master" } ,
2015-07-24 08:20:35 +00:00
{ "Selector:" , "app=redis" , "role=master" } ,
{ "Type:" , "ClusterIP" } ,
{ "IP:" } ,
2016-03-01 15:16:51 +00:00
{ "Port:" , "<unset>" , "6379/TCP" } ,
2015-07-24 08:20:35 +00:00
{ "Endpoints:" } ,
{ "Session Affinity:" , "None" } }
checkOutput ( output , requiredStrings )
// Node
2015-12-10 14:35:58 +00:00
// It should be OK to list unschedulable Nodes here.
2015-12-10 09:39:03 +00:00
nodes , err := c . Nodes ( ) . List ( api . ListOptions { } )
2015-07-24 08:20:35 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-09-10 08:40:22 +00:00
node := nodes . Items [ 0 ]
2016-04-07 17:21:31 +00:00
output = framework . RunKubectlOrDie ( "describe" , "node" , node . Name )
2015-07-24 08:20:35 +00:00
requiredStrings = [ ] [ ] string {
{ "Name:" , node . Name } ,
{ "Labels:" } ,
{ "CreationTimestamp:" } ,
{ "Conditions:" } ,
{ "Type" , "Status" , "LastHeartbeatTime" , "LastTransitionTime" , "Reason" , "Message" } ,
{ "Addresses:" } ,
{ "Capacity:" } ,
{ "Version:" } ,
{ "Kernel Version:" } ,
{ "OS Image:" } ,
{ "Container Runtime Version:" } ,
{ "Kubelet Version:" } ,
{ "Kube-Proxy Version:" } ,
{ "Pods:" } }
checkOutput ( output , requiredStrings )
// Namespace
2016-04-07 17:21:31 +00:00
output = framework . RunKubectlOrDie ( "describe" , "namespace" , ns )
2015-07-24 08:20:35 +00:00
requiredStrings = [ ] [ ] string {
{ "Name:" , ns } ,
{ "Labels:" } ,
{ "Status:" , "Active" } }
checkOutput ( output , requiredStrings )
// Quota and limitrange are skipped for now.
2015-07-09 00:14:28 +00:00
} )
} )
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Kubectl expose" , func ( ) {
2015-10-07 14:09:24 +00:00
It ( "should create services for rc [Conformance]" , func ( ) {
2016-05-18 01:13:14 +00:00
controllerJson := readTestFileOrDie ( redisControllerFilename )
2015-07-14 09:37:30 +00:00
nsFlag := fmt . Sprintf ( "--namespace=%v" , ns )
redisPort := 6379
By ( "creating Redis RC" )
2016-03-31 18:45:08 +00:00
framework . Logf ( "namespace %v" , ns )
2016-04-26 16:22:18 +00:00
framework . RunKubectlOrDieInput ( string ( controllerJson [ : ] ) , "create" , "-f" , "-" , nsFlag )
2016-04-23 04:43:59 +00:00
// It may take a while for the pods to get registered in some cases, wait to be sure.
By ( "Waiting for Redis master to start." )
2016-05-18 01:13:14 +00:00
waitForOrFailWithDebug ( 1 )
2016-03-31 18:45:08 +00:00
forEachPod ( func ( pod api . Pod ) {
2016-04-23 04:43:59 +00:00
framework . Logf ( "wait on redis-master startup in %v " , ns )
2016-04-07 17:21:31 +00:00
framework . LookForStringInLog ( ns , pod . Name , "redis-master" , "The server is now ready to accept connections" , framework . PodStartTimeout )
2015-07-14 09:37:30 +00:00
} )
validateService := func ( name string , servicePort int , timeout time . Duration ) {
2016-04-07 17:21:31 +00:00
err := wait . Poll ( framework . Poll , timeout , func ( ) ( bool , error ) {
2015-07-14 09:37:30 +00:00
endpoints , err := c . Endpoints ( ns ) . Get ( name )
2015-09-16 23:20:40 +00:00
if err != nil {
2015-09-10 01:28:53 +00:00
if apierrs . IsNotFound ( err ) {
err = nil
}
2016-04-07 17:21:31 +00:00
framework . Logf ( "Get endpoints failed (interval %v): %v" , framework . Poll , err )
2015-09-10 01:28:53 +00:00
return false , err
2015-09-16 23:20:40 +00:00
}
2015-07-14 09:37:30 +00:00
2015-08-04 13:24:37 +00:00
uidToPort := getContainerPortsByPodUID ( endpoints )
2015-06-26 08:08:48 +00:00
if len ( uidToPort ) == 0 {
2016-04-07 17:21:31 +00:00
framework . Logf ( "No endpoint found, retrying" )
2015-09-10 01:28:53 +00:00
return false , nil
2015-07-14 09:37:30 +00:00
}
2015-06-26 08:08:48 +00:00
if len ( uidToPort ) > 1 {
2015-09-16 23:20:40 +00:00
Fail ( "Too many endpoints found" )
2015-06-26 08:08:48 +00:00
}
for _ , port := range uidToPort {
2015-07-14 09:37:30 +00:00
if port [ 0 ] != redisPort {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Wrong endpoint port: %d" , port [ 0 ] )
2015-07-14 09:37:30 +00:00
}
}
2015-09-10 01:28:53 +00:00
return true , nil
} )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-07-14 09:37:30 +00:00
service , err := c . Services ( ns ) . Get ( name )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
if len ( service . Spec . Ports ) != 1 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "1 port is expected" )
2015-07-14 09:37:30 +00:00
}
port := service . Spec . Ports [ 0 ]
2016-04-27 04:35:14 +00:00
if port . Port != int32 ( servicePort ) {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Wrong service port: %d" , port . Port )
2015-07-14 09:37:30 +00:00
}
2015-11-18 18:15:16 +00:00
if port . TargetPort . IntValue ( ) != redisPort {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Wrong target port: %d" )
2015-07-14 09:37:30 +00:00
}
}
By ( "exposing RC" )
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "expose" , "rc" , "redis-master" , "--name=rm2" , "--port=1234" , fmt . Sprintf ( "--target-port=%d" , redisPort ) , nsFlag )
framework . WaitForService ( c , ns , "rm2" , true , framework . Poll , framework . ServiceStartTimeout )
validateService ( "rm2" , 1234 , framework . ServiceStartTimeout )
2015-07-14 09:37:30 +00:00
By ( "exposing service" )
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "expose" , "service" , "rm2" , "--name=rm3" , "--port=2345" , fmt . Sprintf ( "--target-port=%d" , redisPort ) , nsFlag )
framework . WaitForService ( c , ns , "rm3" , true , framework . Poll , framework . ServiceStartTimeout )
validateService ( "rm3" , 2345 , framework . ServiceStartTimeout )
2015-07-14 09:37:30 +00:00
} )
} )
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Kubectl label" , func ( ) {
2016-04-26 16:22:18 +00:00
var pod [ ] byte
2015-07-24 08:20:35 +00:00
var nsFlag string
BeforeEach ( func ( ) {
2016-05-26 00:25:02 +00:00
pod = readTestFileOrDie ( "pause-pod.yaml" )
2015-07-24 08:20:35 +00:00
By ( "creating the pod" )
nsFlag = fmt . Sprintf ( "--namespace=%v" , ns )
2016-04-26 16:22:18 +00:00
framework . RunKubectlOrDieInput ( string ( pod ) , "create" , "-f" , "-" , nsFlag )
2016-05-26 00:25:02 +00:00
Expect ( framework . CheckPodsRunningReady ( c , ns , [ ] string { pausePodName } , framework . PodStartTimeout ) ) . To ( BeTrue ( ) )
2015-07-24 08:20:35 +00:00
} )
AfterEach ( func ( ) {
2016-05-26 00:25:02 +00:00
cleanupKubectlInputs ( string ( pod [ : ] ) , ns , pausePodSelector )
2015-07-24 08:20:35 +00:00
} )
2015-10-07 14:09:24 +00:00
It ( "should update the label on a resource [Conformance]" , func ( ) {
2015-07-24 08:20:35 +00:00
labelName := "testing-label"
labelValue := "testing-label-value"
By ( "adding the label " + labelName + " with value " + labelValue + " to a pod" )
2016-05-26 00:25:02 +00:00
framework . RunKubectlOrDie ( "label" , "pods" , pausePodName , labelName + "=" + labelValue , nsFlag )
2015-07-24 08:20:35 +00:00
By ( "verifying the pod has the label " + labelName + " with the value " + labelValue )
2016-05-26 00:25:02 +00:00
output := framework . RunKubectlOrDie ( "get" , "pod" , pausePodName , "-L" , labelName , nsFlag )
2015-07-24 08:20:35 +00:00
if ! strings . Contains ( output , labelValue ) {
2016-05-26 00:25:02 +00:00
framework . Failf ( "Failed updating label " + labelName + " to the pod " + pausePodName )
2015-07-24 08:20:35 +00:00
}
By ( "removing the label " + labelName + " of a pod" )
2016-05-26 00:25:02 +00:00
framework . RunKubectlOrDie ( "label" , "pods" , pausePodName , labelName + "-" , nsFlag )
2015-07-24 08:20:35 +00:00
By ( "verifying the pod doesn't have the label " + labelName )
2016-05-26 00:25:02 +00:00
output = framework . RunKubectlOrDie ( "get" , "pod" , pausePodName , "-L" , labelName , nsFlag )
2015-07-24 08:20:35 +00:00
if strings . Contains ( output , labelValue ) {
2016-05-26 00:25:02 +00:00
framework . Failf ( "Failed removing label " + labelName + " of the pod " + pausePodName )
2015-07-24 08:20:35 +00:00
}
} )
} )
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Kubectl logs" , func ( ) {
2016-04-26 16:22:18 +00:00
var rc [ ] byte
2015-09-10 03:46:11 +00:00
var nsFlag string
containerName := "redis-master"
BeforeEach ( func ( ) {
2016-05-18 01:13:14 +00:00
rc = readTestFileOrDie ( redisControllerFilename )
2015-09-10 03:46:11 +00:00
By ( "creating an rc" )
nsFlag = fmt . Sprintf ( "--namespace=%v" , ns )
2016-04-26 16:22:18 +00:00
framework . RunKubectlOrDieInput ( string ( rc [ : ] ) , "create" , "-f" , "-" , nsFlag )
2015-09-10 03:46:11 +00:00
} )
AfterEach ( func ( ) {
2016-04-26 16:22:18 +00:00
cleanupKubectlInputs ( string ( rc [ : ] ) , ns , simplePodSelector )
2015-09-10 03:46:11 +00:00
} )
2015-10-07 14:09:24 +00:00
It ( "should be able to retrieve and filter logs [Conformance]" , func ( ) {
2016-04-07 17:21:31 +00:00
framework . SkipUnlessServerVersionGTE ( extendedPodLogFilterVersion , c )
2016-01-13 19:27:40 +00:00
2016-05-12 17:02:36 +00:00
// Split("something\n", "\n") returns ["something", ""], so
// strip trailing newline first
lines := func ( out string ) [ ] string {
return strings . Split ( strings . TrimRight ( out , "\n" ) , "\n" )
}
By ( "Waiting for Redis master to start." )
2016-05-18 01:13:14 +00:00
waitForOrFailWithDebug ( 1 )
2016-03-31 18:45:08 +00:00
forEachPod ( func ( pod api . Pod ) {
2015-09-10 03:46:11 +00:00
By ( "checking for a matching strings" )
2016-04-07 17:21:31 +00:00
_ , err := framework . LookForStringInLog ( ns , pod . Name , containerName , "The server is now ready to accept connections" , framework . PodStartTimeout )
2015-07-13 12:06:00 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
2015-09-10 03:46:11 +00:00
By ( "limiting log lines" )
2016-04-07 17:21:31 +00:00
out := framework . RunKubectlOrDie ( "log" , pod . Name , containerName , nsFlag , "--tail=1" )
2015-09-10 03:46:11 +00:00
Expect ( len ( out ) ) . NotTo ( BeZero ( ) )
2016-05-12 17:02:36 +00:00
Expect ( len ( lines ( out ) ) ) . To ( Equal ( 1 ) )
2015-09-10 03:46:11 +00:00
By ( "limiting log bytes" )
2016-04-07 17:21:31 +00:00
out = framework . RunKubectlOrDie ( "log" , pod . Name , containerName , nsFlag , "--limit-bytes=1" )
2016-05-12 17:02:36 +00:00
Expect ( len ( lines ( out ) ) ) . To ( Equal ( 1 ) )
2015-09-10 03:46:11 +00:00
Expect ( len ( out ) ) . To ( Equal ( 1 ) )
By ( "exposing timestamps" )
2016-04-07 17:21:31 +00:00
out = framework . RunKubectlOrDie ( "log" , pod . Name , containerName , nsFlag , "--tail=1" , "--timestamps" )
2016-05-12 17:02:36 +00:00
l := lines ( out )
Expect ( len ( l ) ) . To ( Equal ( 1 ) )
words := strings . Split ( l [ 0 ] , " " )
2015-09-10 03:46:11 +00:00
Expect ( len ( words ) ) . To ( BeNumerically ( ">" , 1 ) )
if _ , err := time . Parse ( time . RFC3339Nano , words [ 0 ] ) ; err != nil {
if _ , err := time . Parse ( time . RFC3339 , words [ 0 ] ) ; err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "expected %q to be RFC3339 or RFC3339Nano" , words [ 0 ] )
2015-09-10 03:46:11 +00:00
}
}
By ( "restricting to a time range" )
2016-01-28 23:35:49 +00:00
// Note: we must wait at least two seconds,
// because the granularity is only 1 second and
// it could end up rounding the wrong way.
time . Sleep ( 2500 * time . Millisecond ) // ensure that startup logs on the node are seen as older than 1s
2016-04-07 17:21:31 +00:00
recent_out := framework . RunKubectlOrDie ( "log" , pod . Name , containerName , nsFlag , "--since=1s" )
2016-01-28 21:18:36 +00:00
recent := len ( strings . Split ( recent_out , "\n" ) )
2016-04-07 17:21:31 +00:00
older_out := framework . RunKubectlOrDie ( "log" , pod . Name , containerName , nsFlag , "--since=24h" )
2016-01-28 21:18:36 +00:00
older := len ( strings . Split ( older_out , "\n" ) )
Expect ( recent ) . To ( BeNumerically ( "<" , older ) , "expected recent(%v) to be less than older(%v)\nrecent lines:\n%v\nolder lines:\n%v\n" , recent , older , recent_out , older_out )
2015-07-13 12:06:00 +00:00
} )
} )
} )
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Kubectl patch" , func ( ) {
2015-10-07 14:09:24 +00:00
It ( "should add annotations for pods in rc [Conformance]" , func ( ) {
2016-05-18 01:13:14 +00:00
controllerJson := readTestFileOrDie ( redisControllerFilename )
2015-07-13 12:06:00 +00:00
nsFlag := fmt . Sprintf ( "--namespace=%v" , ns )
By ( "creating Redis RC" )
2016-04-26 16:22:18 +00:00
framework . RunKubectlOrDieInput ( string ( controllerJson [ : ] ) , "create" , "-f" , "-" , nsFlag )
2016-05-12 17:02:36 +00:00
By ( "Waiting for Redis master to start." )
2016-05-18 01:13:14 +00:00
waitForOrFailWithDebug ( 1 )
2015-07-13 12:06:00 +00:00
By ( "patching all pods" )
2016-03-31 18:45:08 +00:00
forEachPod ( func ( pod api . Pod ) {
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "patch" , "pod" , pod . Name , nsFlag , "-p" , "{\"metadata\":{\"annotations\":{\"x\":\"y\"}}}" )
2015-07-13 12:06:00 +00:00
} )
By ( "checking annotations" )
2016-03-31 18:45:08 +00:00
forEachPod ( func ( pod api . Pod ) {
2015-07-13 12:06:00 +00:00
found := false
for key , val := range pod . Annotations {
if key == "x" && val == "y" {
found = true
}
}
if ! found {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Added annotation not found" )
2015-07-13 12:06:00 +00:00
}
} )
} )
} )
2015-07-23 12:15:15 +00:00
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Kubectl version" , func ( ) {
2015-10-07 14:09:24 +00:00
It ( "should check is all data is printed [Conformance]" , func ( ) {
2016-04-07 17:21:31 +00:00
version := framework . RunKubectlOrDie ( "version" )
2015-07-23 12:15:15 +00:00
requiredItems := [ ] string { "Client Version:" , "Server Version:" , "Major:" , "Minor:" , "GitCommit:" }
for _ , item := range requiredItems {
if ! strings . Contains ( version , item ) {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Required item %s not found in %s" , item , version )
2015-07-23 12:15:15 +00:00
}
}
} )
} )
2015-07-09 18:26:48 +00:00
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Kubectl run default" , func ( ) {
2016-03-14 22:09:32 +00:00
var nsFlag string
var name string
var cleanUp func ( )
BeforeEach ( func ( ) {
nsFlag = fmt . Sprintf ( "--namespace=%v" , ns )
2016-04-07 17:21:31 +00:00
gte , err := framework . ServerVersionGTE ( deploymentsVersion , c )
2016-03-14 22:09:32 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed to get server version: %v" , err )
2016-03-14 22:09:32 +00:00
}
if gte {
name = "e2e-test-nginx-deployment"
2016-04-07 17:21:31 +00:00
cleanUp = func ( ) { framework . RunKubectlOrDie ( "delete" , "deployment" , name , nsFlag ) }
2016-03-14 22:09:32 +00:00
} else {
name = "e2e-test-nginx-rc"
2016-04-07 17:21:31 +00:00
cleanUp = func ( ) { framework . RunKubectlOrDie ( "delete" , "rc" , name , nsFlag ) }
2016-03-14 22:09:32 +00:00
}
} )
AfterEach ( func ( ) {
cleanUp ( )
} )
It ( "should create an rc or deployment from an image [Conformance]" , func ( ) {
By ( "running the image " + nginxImage )
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "run" , name , "--image=" + nginxImage , nsFlag )
2016-03-14 22:09:32 +00:00
By ( "verifying the pod controlled by " + name + " gets created" )
label := labels . SelectorFromSet ( labels . Set ( map [ string ] string { "run" : name } ) )
2016-04-07 17:21:31 +00:00
podlist , err := framework . WaitForPodsWithLabel ( c , ns , label )
2016-03-14 22:09:32 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed getting pod controlled by %s: %v" , name , err )
2016-03-14 22:09:32 +00:00
}
pods := podlist . Items
if pods == nil || len ( pods ) != 1 || len ( pods [ 0 ] . Spec . Containers ) != 1 || pods [ 0 ] . Spec . Containers [ 0 ] . Image != nginxImage {
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "get" , "pods" , "-L" , "run" , nsFlag )
framework . Failf ( "Failed creating 1 pod with expected image %s. Number of pods = %v" , nginxImage , len ( pods ) )
2016-03-14 22:09:32 +00:00
}
} )
} )
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Kubectl run rc" , func ( ) {
2015-07-09 18:26:48 +00:00
var nsFlag string
var rcName string
BeforeEach ( func ( ) {
nsFlag = fmt . Sprintf ( "--namespace=%v" , ns )
rcName = "e2e-test-nginx-rc"
} )
AfterEach ( func ( ) {
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "delete" , "rc" , rcName , nsFlag )
2015-07-09 18:26:48 +00:00
} )
2015-10-07 14:09:24 +00:00
It ( "should create an rc from an image [Conformance]" , func ( ) {
2016-02-25 00:54:40 +00:00
By ( "running the image " + nginxImage )
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "run" , rcName , "--image=" + nginxImage , "--generator=run/v1" , nsFlag )
2015-07-09 18:26:48 +00:00
By ( "verifying the rc " + rcName + " was created" )
rc , err := c . ReplicationControllers ( ns ) . Get ( rcName )
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed getting rc %s: %v" , rcName , err )
2015-07-09 18:26:48 +00:00
}
containers := rc . Spec . Template . Spec . Containers
2016-02-25 00:54:40 +00:00
if containers == nil || len ( containers ) != 1 || containers [ 0 ] . Image != nginxImage {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed creating rc %s for 1 pod with expected image %s" , rcName , nginxImage )
2015-07-09 18:26:48 +00:00
}
By ( "verifying the pod controlled by rc " + rcName + " was created" )
label := labels . SelectorFromSet ( labels . Set ( map [ string ] string { "run" : rcName } ) )
2016-04-07 17:21:31 +00:00
podlist , err := framework . WaitForPodsWithLabel ( c , ns , label )
2015-07-09 18:26:48 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed getting pod controlled by rc %s: %v" , rcName , err )
2015-07-09 18:26:48 +00:00
}
pods := podlist . Items
2016-02-25 00:54:40 +00:00
if pods == nil || len ( pods ) != 1 || len ( pods [ 0 ] . Spec . Containers ) != 1 || pods [ 0 ] . Spec . Containers [ 0 ] . Image != nginxImage {
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "get" , "pods" , "-L" , "run" , nsFlag )
framework . Failf ( "Failed creating 1 pod with expected image %s. Number of pods = %v" , nginxImage , len ( pods ) )
2015-07-09 18:26:48 +00:00
}
2016-02-16 20:21:35 +00:00
By ( "confirm that you can get logs from an rc" )
2016-03-07 14:30:08 +00:00
podNames := [ ] string { }
for _ , pod := range pods {
podNames = append ( podNames , pod . Name )
}
2016-04-07 17:21:31 +00:00
if ! framework . CheckPodsRunningReady ( c , ns , podNames , framework . PodStartTimeout ) {
framework . Failf ( "Pods for rc %s were not ready" , rcName )
2016-03-07 14:30:08 +00:00
}
2016-04-07 17:21:31 +00:00
_ , err = framework . RunKubectl ( "logs" , "rc/" + rcName , nsFlag )
2016-02-16 20:21:35 +00:00
// a non-nil error is fine as long as we actually found a pod.
if err != nil && ! strings . Contains ( err . Error ( ) , " in pod " ) {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed getting logs by rc %s: %v" , rcName , err )
2016-02-16 20:21:35 +00:00
}
2015-07-09 18:26:48 +00:00
} )
2015-07-07 05:09:22 +00:00
} )
2016-04-25 20:38:45 +00:00
framework . KubeDescribe ( "Kubectl rolling-update" , func ( ) {
var nsFlag string
var rcName string
var c * client . Client
BeforeEach ( func ( ) {
c = f . Client
nsFlag = fmt . Sprintf ( "--namespace=%v" , ns )
rcName = "e2e-test-nginx-rc"
} )
AfterEach ( func ( ) {
framework . RunKubectlOrDie ( "delete" , "rc" , rcName , nsFlag )
} )
2016-05-12 21:15:12 +00:00
It ( "should support rolling-update to same image [Conformance]" , func ( ) {
2016-04-25 20:38:45 +00:00
By ( "running the image " + nginxImage )
framework . RunKubectlOrDie ( "run" , rcName , "--image=" + nginxImage , "--generator=run/v1" , nsFlag )
By ( "verifying the rc " + rcName + " was created" )
rc , err := c . ReplicationControllers ( ns ) . Get ( rcName )
if err != nil {
framework . Failf ( "Failed getting rc %s: %v" , rcName , err )
}
containers := rc . Spec . Template . Spec . Containers
if containers == nil || len ( containers ) != 1 || containers [ 0 ] . Image != nginxImage {
framework . Failf ( "Failed creating rc %s for 1 pod with expected image %s" , rcName , nginxImage )
}
2016-05-04 20:47:34 +00:00
framework . WaitForRCToStabilize ( c , ns , rcName , framework . PodStartTimeout )
2016-04-25 20:38:45 +00:00
By ( "rolling-update to same image controller" )
2016-05-26 20:01:49 +00:00
runKubectlRetryOrDie ( "rolling-update" , rcName , "--update-period=1s" , "--image=" + nginxImage , "--image-pull-policy=" + string ( api . PullIfNotPresent ) , nsFlag )
2016-04-25 20:38:45 +00:00
framework . ValidateController ( c , nginxImage , 1 , rcName , "run=" + rcName , noOpValidatorFn , ns )
} )
} )
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Kubectl run deployment" , func ( ) {
2016-02-02 22:51:15 +00:00
var nsFlag string
var dName string
BeforeEach ( func ( ) {
nsFlag = fmt . Sprintf ( "--namespace=%v" , ns )
dName = "e2e-test-nginx-deployment"
} )
AfterEach ( func ( ) {
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "delete" , "deployment" , dName , nsFlag )
2016-02-02 22:51:15 +00:00
} )
It ( "should create a deployment from an image [Conformance]" , func ( ) {
2016-04-07 17:21:31 +00:00
framework . SkipUnlessServerVersionGTE ( deploymentsVersion , c )
2016-02-17 21:36:24 +00:00
2016-02-25 00:54:40 +00:00
By ( "running the image " + nginxImage )
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "run" , dName , "--image=" + nginxImage , "--generator=deployment/v1beta1" , nsFlag )
2016-02-02 22:51:15 +00:00
By ( "verifying the deployment " + dName + " was created" )
d , err := c . Extensions ( ) . Deployments ( ns ) . Get ( dName )
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed getting deployment %s: %v" , dName , err )
2016-02-02 22:51:15 +00:00
}
containers := d . Spec . Template . Spec . Containers
2016-02-25 00:54:40 +00:00
if containers == nil || len ( containers ) != 1 || containers [ 0 ] . Image != nginxImage {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed creating deployment %s for 1 pod with expected image %s" , dName , nginxImage )
2016-02-02 22:51:15 +00:00
}
By ( "verifying the pod controlled by deployment " + dName + " was created" )
label := labels . SelectorFromSet ( labels . Set ( map [ string ] string { "run" : dName } ) )
2016-04-07 17:21:31 +00:00
podlist , err := framework . WaitForPodsWithLabel ( c , ns , label )
2016-02-02 22:51:15 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed getting pod controlled by deployment %s: %v" , dName , err )
2016-02-02 22:51:15 +00:00
}
pods := podlist . Items
2016-02-25 00:54:40 +00:00
if pods == nil || len ( pods ) != 1 || len ( pods [ 0 ] . Spec . Containers ) != 1 || pods [ 0 ] . Spec . Containers [ 0 ] . Image != nginxImage {
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "get" , "pods" , "-L" , "run" , nsFlag )
framework . Failf ( "Failed creating 1 pod with expected image %s. Number of pods = %v" , nginxImage , len ( pods ) )
2016-02-02 22:51:15 +00:00
}
} )
} )
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Kubectl run job" , func ( ) {
2015-08-04 19:54:17 +00:00
var nsFlag string
2015-11-13 01:07:21 +00:00
var jobName string
2015-08-04 19:54:17 +00:00
BeforeEach ( func ( ) {
nsFlag = fmt . Sprintf ( "--namespace=%v" , ns )
2015-11-13 01:07:21 +00:00
jobName = "e2e-test-nginx-job"
2015-08-04 19:54:17 +00:00
} )
AfterEach ( func ( ) {
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "delete" , "jobs" , jobName , nsFlag )
2015-08-04 19:54:17 +00:00
} )
2015-11-13 01:07:21 +00:00
It ( "should create a job from an image when restart is OnFailure [Conformance]" , func ( ) {
2016-04-07 17:21:31 +00:00
framework . SkipUnlessServerVersionGTE ( jobsVersion , c )
2016-01-13 19:27:40 +00:00
2016-02-25 00:54:40 +00:00
By ( "running the image " + nginxImage )
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "run" , jobName , "--restart=OnFailure" , "--image=" + nginxImage , nsFlag )
2015-11-13 01:07:21 +00:00
By ( "verifying the job " + jobName + " was created" )
job , err := c . Extensions ( ) . Jobs ( ns ) . Get ( jobName )
2015-08-04 19:54:17 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed getting job %s: %v" , jobName , err )
2015-08-04 19:54:17 +00:00
}
2015-11-13 01:07:21 +00:00
containers := job . Spec . Template . Spec . Containers
2016-02-25 00:54:40 +00:00
if containers == nil || len ( containers ) != 1 || containers [ 0 ] . Image != nginxImage {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed creating job %s for 1 pod with expected image %s" , jobName , nginxImage )
2015-08-04 19:54:17 +00:00
}
2015-11-13 01:07:21 +00:00
if job . Spec . Template . Spec . RestartPolicy != api . RestartPolicyOnFailure {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed creating a job with correct restart policy for --restart=OnFailure" )
2015-08-04 19:54:17 +00:00
}
} )
2015-11-13 01:07:21 +00:00
It ( "should create a job from an image when restart is Never [Conformance]" , func ( ) {
2016-04-07 17:21:31 +00:00
framework . SkipUnlessServerVersionGTE ( jobsVersion , c )
2016-01-13 19:27:40 +00:00
2016-02-25 00:54:40 +00:00
By ( "running the image " + nginxImage )
2016-04-07 17:21:31 +00:00
framework . RunKubectlOrDie ( "run" , jobName , "--restart=Never" , "--image=" + nginxImage , nsFlag )
2015-11-13 01:07:21 +00:00
By ( "verifying the job " + jobName + " was created" )
job , err := c . Extensions ( ) . Jobs ( ns ) . Get ( jobName )
2015-08-04 19:54:17 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed getting job %s: %v" , jobName , err )
2015-08-04 19:54:17 +00:00
}
2015-11-13 01:07:21 +00:00
containers := job . Spec . Template . Spec . Containers
2016-02-25 00:54:40 +00:00
if containers == nil || len ( containers ) != 1 || containers [ 0 ] . Image != nginxImage {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed creating job %s for 1 pod with expected image %s" , jobName , nginxImage )
2015-08-04 19:54:17 +00:00
}
2015-11-13 01:07:21 +00:00
if job . Spec . Template . Spec . RestartPolicy != api . RestartPolicyNever {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed creating a job with correct restart policy for --restart=OnFailure" )
2015-08-04 19:54:17 +00:00
}
} )
} )
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Kubectl run --rm job" , func ( ) {
2015-12-10 02:36:25 +00:00
nsFlag := fmt . Sprintf ( "--namespace=%v" , ns )
jobName := "e2e-test-rm-busybox-job"
It ( "should create a job from an image, then delete the job [Conformance]" , func ( ) {
2016-04-07 17:21:31 +00:00
framework . SkipUnlessServerVersionGTE ( jobsVersion , c )
2016-01-13 19:27:40 +00:00
2015-12-10 02:36:25 +00:00
By ( "executing a command with run --rm and attach with stdin" )
2016-01-08 16:14:55 +00:00
t := time . NewTimer ( runJobTimeout )
defer t . Stop ( )
2016-04-07 17:21:31 +00:00
runOutput := framework . NewKubectlCommand ( nsFlag , "run" , jobName , "--image=" + busyboxImage , "--rm=true" , "--restart=Never" , "--attach=true" , "--stdin" , "--" , "sh" , "-c" , "cat && echo 'stdin closed'" ) .
WithStdinData ( "abcd1234" ) .
WithTimeout ( t . C ) .
ExecOrDie ( )
2015-12-10 02:36:25 +00:00
Expect ( runOutput ) . To ( ContainSubstring ( "abcd1234" ) )
Expect ( runOutput ) . To ( ContainSubstring ( "stdin closed" ) )
By ( "verifying the job " + jobName + " was deleted" )
_ , err := c . Extensions ( ) . Jobs ( ns ) . Get ( jobName )
Expect ( err ) . To ( HaveOccurred ( ) )
Expect ( apierrs . IsNotFound ( err ) ) . To ( BeTrue ( ) )
} )
} )
2016-04-07 17:21:31 +00:00
framework . KubeDescribe ( "Proxy server" , func ( ) {
2015-07-07 05:09:22 +00:00
// TODO: test proxy options (static, prefix, etc)
2015-10-07 14:09:24 +00:00
It ( "should support proxy with --port 0 [Conformance]" , func ( ) {
2015-07-07 05:09:22 +00:00
By ( "starting the proxy server" )
port , cmd , err := startProxyServer ( )
if cmd != nil {
2016-04-07 17:21:31 +00:00
defer framework . TryKill ( cmd )
2015-07-07 05:09:22 +00:00
}
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed to start proxy server: %v" , err )
2015-07-07 05:09:22 +00:00
}
By ( "curling proxy /api/ output" )
localAddr := fmt . Sprintf ( "http://localhost:%d/api/" , port )
apiVersions , err := getAPIVersions ( localAddr )
2015-10-09 05:18:16 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Expected at least one supported apiversion, got error %v" , err )
2015-10-09 05:18:16 +00:00
}
2015-07-07 05:09:22 +00:00
if len ( apiVersions . Versions ) < 1 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Expected at least one supported apiversion, got %v" , apiVersions )
2015-07-07 05:09:22 +00:00
}
} )
2015-07-09 18:26:48 +00:00
2015-10-07 14:09:24 +00:00
It ( "should support --unix-socket=/path [Conformance]" , func ( ) {
2015-07-07 10:39:38 +00:00
By ( "Starting the proxy" )
tmpdir , err := ioutil . TempDir ( "" , "kubectl-proxy-unix" )
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed to create temporary directory: %v" , err )
2015-07-07 10:39:38 +00:00
}
path := filepath . Join ( tmpdir , "test" )
defer os . Remove ( path )
defer os . Remove ( tmpdir )
2016-04-07 17:21:31 +00:00
cmd := framework . KubectlCmd ( "proxy" , fmt . Sprintf ( "--unix-socket=%s" , path ) )
stdout , stderr , err := framework . StartCmdAndStreamOutput ( cmd )
2015-07-07 10:39:38 +00:00
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed to start kubectl command: %v" , err )
2015-07-07 10:39:38 +00:00
}
defer stdout . Close ( )
defer stderr . Close ( )
2016-04-07 17:21:31 +00:00
defer framework . TryKill ( cmd )
2015-07-07 10:39:38 +00:00
buf := make ( [ ] byte , 128 )
if _ , err = stdout . Read ( buf ) ; err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Expected output from kubectl proxy: %v" , err )
2015-07-07 10:39:38 +00:00
}
By ( "retrieving proxy /api/ output" )
_ , err = curlUnix ( "http://unused/api" , path )
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed get of /api at %s: %v" , path , err )
2015-07-07 10:39:38 +00:00
}
} )
} )
2016-03-31 03:42:57 +00:00
framework . KubeDescribe ( "Kubectl taint" , func ( ) {
It ( "should update the taint on a node" , func ( ) {
taintName := fmt . Sprintf ( "kubernetes.io/e2e-taint-key-%s" , string ( pkgutil . NewUUID ( ) ) )
taintValue := "testing-taint-value"
taintEffect := fmt . Sprintf ( "%s" , api . TaintEffectNoSchedule )
nodes , err := c . Nodes ( ) . List ( api . ListOptions { } )
Expect ( err ) . NotTo ( HaveOccurred ( ) )
node := nodes . Items [ 0 ]
nodeName := node . Name
By ( "adding the taint " + taintName + " with value " + taintValue + " and taint effect " + taintEffect + " to a node" )
framework . RunKubectlOrDie ( "taint" , "nodes" , nodeName , taintName + "=" + taintValue + ":" + taintEffect )
By ( "verifying the node has the taint " + taintName + " with the value " + taintValue )
output := framework . RunKubectlOrDie ( "describe" , "node" , nodeName )
requiredStrings := [ ] [ ] string {
{ "Name:" , nodeName } ,
{ "Taints:" } ,
{ taintName + "=" + taintValue + ":" + taintEffect } ,
}
checkOutput ( output , requiredStrings )
By ( "removing the taint " + taintName + " of a node" )
framework . RunKubectlOrDie ( "taint" , "nodes" , nodeName , taintName + "-" )
By ( "verifying the node doesn't have the taint " + taintName )
output = framework . RunKubectlOrDie ( "describe" , "node" , nodeName )
if strings . Contains ( output , taintName ) {
framework . Failf ( "Failed removing taint " + taintName + " of the node " + nodeName )
}
} )
} )
2015-02-20 17:35:42 +00:00
} )
2015-07-24 08:20:35 +00:00
// Checks whether the output split by line contains the required elements.
func checkOutput ( output string , required [ ] [ ] string ) {
outputLines := strings . Split ( output , "\n" )
currentLine := 0
for _ , requirement := range required {
for currentLine < len ( outputLines ) && ! strings . Contains ( outputLines [ currentLine ] , requirement [ 0 ] ) {
currentLine ++
}
if currentLine == len ( outputLines ) {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed to find %s in %s" , requirement [ 0 ] , output )
2015-07-24 08:20:35 +00:00
}
for _ , item := range requirement [ 1 : ] {
if ! strings . Contains ( outputLines [ currentLine ] , item ) {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Failed to find %s in %s" , item , outputLines [ currentLine ] )
2015-07-24 08:20:35 +00:00
}
}
}
}
2015-10-09 01:30:38 +00:00
func getAPIVersions ( apiEndpoint string ) ( * unversioned . APIVersions , error ) {
2015-07-07 05:09:22 +00:00
body , err := curl ( apiEndpoint )
if err != nil {
return nil , fmt . Errorf ( "Failed http.Get of %s: %v" , apiEndpoint , err )
}
2015-10-09 01:30:38 +00:00
var apiVersions unversioned . APIVersions
2015-07-07 05:09:22 +00:00
if err := json . Unmarshal ( [ ] byte ( body ) , & apiVersions ) ; err != nil {
return nil , fmt . Errorf ( "Failed to parse /api output %s: %v" , body , err )
}
return & apiVersions , nil
}
func startProxyServer ( ) ( int , * exec . Cmd , error ) {
// Specifying port 0 indicates we want the os to pick a random port.
2016-04-07 17:21:31 +00:00
cmd := framework . KubectlCmd ( "proxy" , "-p" , "0" )
stdout , stderr , err := framework . StartCmdAndStreamOutput ( cmd )
2015-07-07 05:09:22 +00:00
if err != nil {
return - 1 , nil , err
}
defer stdout . Close ( )
defer stderr . Close ( )
buf := make ( [ ] byte , 128 )
var n int
if n , err = stdout . Read ( buf ) ; err != nil {
return - 1 , cmd , fmt . Errorf ( "Failed to read from kubectl proxy stdout: %v" , err )
}
output := string ( buf [ : n ] )
match := proxyRegexp . FindStringSubmatch ( output )
if len ( match ) == 2 {
if port , err := strconv . Atoi ( match [ 1 ] ) ; err == nil {
return port , cmd , nil
}
}
return - 1 , cmd , fmt . Errorf ( "Failed to parse port from proxy stdout: %s" , output )
}
2015-07-07 10:39:38 +00:00
func curlUnix ( url string , path string ) ( string , error ) {
dial := func ( proto , addr string ) ( net . Conn , error ) {
return net . Dial ( "unix" , path )
}
2016-03-15 19:29:08 +00:00
transport := utilnet . SetTransportDefaults ( & http . Transport {
2015-07-07 10:39:38 +00:00
Dial : dial ,
2016-03-15 19:29:08 +00:00
} )
2015-07-07 10:39:38 +00:00
return curlTransport ( url , transport )
}
func curlTransport ( url string , transport * http . Transport ) ( string , error ) {
client := & http . Client { Transport : transport }
resp , err := client . Get ( url )
2015-06-30 16:43:37 +00:00
if err != nil {
return "" , err
}
defer resp . Body . Close ( )
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
return "" , err
}
return string ( body [ : ] ) , nil
}
2015-07-07 10:39:38 +00:00
func curl ( url string ) ( string , error ) {
2016-03-15 19:29:08 +00:00
return curlTransport ( url , utilnet . SetTransportDefaults ( & http . Transport { } ) )
2015-07-07 10:39:38 +00:00
}
2015-04-30 02:53:09 +00:00
func validateGuestbookApp ( c * client . Client , ns string ) {
2016-04-07 17:21:31 +00:00
framework . Logf ( "Waiting for frontend to serve content." )
2015-04-30 02:53:09 +00:00
if ! waitForGuestbookResponse ( c , "get" , "" , ` { "data": ""} ` , guestbookStartupTimeout , ns ) {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Frontend service did not start serving content in %v seconds." , guestbookStartupTimeout . Seconds ( ) )
2015-03-13 16:26:41 +00:00
}
2016-04-07 17:21:31 +00:00
framework . Logf ( "Trying to add a new entry to the guestbook." )
2015-04-30 02:53:09 +00:00
if ! waitForGuestbookResponse ( c , "set" , "TestEntry" , ` { "message": "Updated"} ` , guestbookResponseTimeout , ns ) {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Cannot added new entry in %v seconds." , guestbookResponseTimeout . Seconds ( ) )
2015-03-13 16:26:41 +00:00
}
2016-04-07 17:21:31 +00:00
framework . Logf ( "Verifying that added entry can be retrieved." )
2015-04-30 02:53:09 +00:00
if ! waitForGuestbookResponse ( c , "get" , "" , ` { "data": "TestEntry"} ` , guestbookResponseTimeout , ns ) {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Entry to guestbook wasn't correctly added in %v seconds." , guestbookResponseTimeout . Seconds ( ) )
2015-03-13 16:26:41 +00:00
}
2015-03-18 14:16:26 +00:00
}
// Returns whether received expected response from guestbook on time.
2015-04-30 02:53:09 +00:00
func waitForGuestbookResponse ( c * client . Client , cmd , arg , expectedResponse string , timeout time . Duration , ns string ) bool {
2015-05-19 18:17:32 +00:00
for start := time . Now ( ) ; time . Since ( start ) < timeout ; time . Sleep ( 5 * time . Second ) {
2015-04-30 02:53:09 +00:00
res , err := makeRequestToGuestbook ( c , cmd , arg , ns )
2015-03-18 14:16:26 +00:00
if err == nil && res == expectedResponse {
2015-05-19 18:17:32 +00:00
return true
2015-03-18 14:16:26 +00:00
}
2016-04-07 17:21:31 +00:00
framework . Logf ( "Failed to get response from guestbook. err: %v, response: %s" , err , res )
2015-05-19 18:17:32 +00:00
}
return false
2015-03-13 16:26:41 +00:00
}
2015-04-30 02:53:09 +00:00
func makeRequestToGuestbook ( c * client . Client , cmd , value string , ns string ) ( string , error ) {
2016-04-07 17:21:31 +00:00
proxyRequest , errProxy := framework . GetServicesProxyRequest ( c , c . Get ( ) )
2015-11-18 03:42:03 +00:00
if errProxy != nil {
return "" , errProxy
}
result , err := proxyRequest . Namespace ( ns ) .
2015-03-13 16:26:41 +00:00
Name ( "frontend" ) .
2015-08-10 18:00:44 +00:00
Suffix ( "/guestbook.php" ) .
2015-03-13 16:26:41 +00:00
Param ( "cmd" , cmd ) .
Param ( "key" , "messages" ) .
Param ( "value" , value ) .
Do ( ) .
Raw ( )
return string ( result ) , err
}
2015-03-26 20:34:18 +00:00
type updateDemoData struct {
Image string
2015-03-26 19:22:04 +00:00
}
2015-09-10 21:32:57 +00:00
const applyTestLabel = "kubectl.kubernetes.io/apply-test"
func readBytesFromFile ( filename string ) [ ] byte {
file , err := os . Open ( filename )
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( err . Error ( ) )
2015-09-10 21:32:57 +00:00
}
data , err := ioutil . ReadAll ( file )
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( err . Error ( ) )
2015-09-10 21:32:57 +00:00
}
return data
}
2016-04-26 16:22:18 +00:00
func readReplicationControllerFromString ( contents string ) * api . ReplicationController {
2015-09-10 21:32:57 +00:00
rc := api . ReplicationController { }
2016-04-26 16:22:18 +00:00
if err := yaml . Unmarshal ( [ ] byte ( contents ) , & rc ) ; err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( err . Error ( ) )
2015-09-10 21:32:57 +00:00
}
return & rc
}
2016-04-26 16:22:18 +00:00
func modifyReplicationControllerConfiguration ( contents string ) io . Reader {
rc := readReplicationControllerFromString ( contents )
2015-09-10 21:32:57 +00:00
rc . Labels [ applyTestLabel ] = "ADDED"
rc . Spec . Selector [ applyTestLabel ] = "ADDED"
rc . Spec . Template . Labels [ applyTestLabel ] = "ADDED"
data , err := json . Marshal ( rc )
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "json marshal failed: %s\n" , err )
2015-09-10 21:32:57 +00:00
}
return bytes . NewReader ( data )
}
func forEachReplicationController ( c * client . Client , ns , selectorKey , selectorValue string , fn func ( api . ReplicationController ) ) {
var rcs * api . ReplicationControllerList
var err error
2016-04-07 17:21:31 +00:00
for t := time . Now ( ) ; time . Since ( t ) < framework . PodListTimeout ; time . Sleep ( framework . Poll ) {
2015-12-02 11:12:57 +00:00
label := labels . SelectorFromSet ( labels . Set ( map [ string ] string { selectorKey : selectorValue } ) )
2015-12-10 09:39:03 +00:00
options := api . ListOptions { LabelSelector : label }
2015-12-02 11:12:57 +00:00
rcs , err = c . ReplicationControllers ( ns ) . List ( options )
2015-09-10 21:32:57 +00:00
Expect ( err ) . NotTo ( HaveOccurred ( ) )
if len ( rcs . Items ) > 0 {
break
}
}
if rcs == nil || len ( rcs . Items ) == 0 {
2016-04-07 17:21:31 +00:00
framework . Failf ( "No replication controllers found" )
2015-09-10 21:32:57 +00:00
}
for _ , rc := range rcs . Items {
fn ( rc )
}
}
func validateReplicationControllerConfiguration ( rc api . ReplicationController ) {
if rc . Name == "redis-master" {
2016-05-05 00:37:03 +00:00
if _ , ok := rc . Annotations [ annotations . LastAppliedConfigAnnotation ] ; ! ok {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Annotation not found in modified configuration:\n%v\n" , rc )
2015-09-10 21:32:57 +00:00
}
if value , ok := rc . Labels [ applyTestLabel ] ; ! ok || value != "ADDED" {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Added label %s not found in modified configuration:\n%v\n" , applyTestLabel , rc )
2015-09-10 21:32:57 +00:00
}
}
}
2015-03-26 20:34:18 +00:00
// getUDData creates a validator function based on the input string (i.e. kitten.jpg).
2015-10-20 02:41:58 +00:00
// For example, if you send "kitten.jpg", this function verifies that the image jpg = kitten.jpg
2015-03-26 20:34:18 +00:00
// in the container's json field.
2015-04-30 02:53:09 +00:00
func getUDData ( jpgExpected string , ns string ) func ( * client . Client , string ) error {
2015-03-26 20:34:18 +00:00
// getUDData validates data.json in the update-demo (returns nil if data is ok).
return func ( c * client . Client , podID string ) error {
2016-04-07 17:21:31 +00:00
framework . Logf ( "validating pod %s" , podID )
subResourceProxyAvailable , err := framework . ServerVersionGTE ( framework . SubResourcePodProxyVersion , c )
2015-12-16 19:18:47 +00:00
if err != nil {
return err
}
var body [ ] byte
if subResourceProxyAvailable {
body , err = c . Get ( ) .
Namespace ( ns ) .
Resource ( "pods" ) .
SubResource ( "proxy" ) .
Name ( podID ) .
Suffix ( "data.json" ) .
Do ( ) .
Raw ( )
} else {
body , err = c . Get ( ) .
Prefix ( "proxy" ) .
Namespace ( ns ) .
Resource ( "pods" ) .
Name ( podID ) .
Suffix ( "data.json" ) .
Do ( ) .
Raw ( )
}
2015-03-26 20:34:18 +00:00
if err != nil {
return err
2015-03-26 19:22:04 +00:00
}
2016-04-07 17:21:31 +00:00
framework . Logf ( "got data: %s" , body )
2015-03-26 20:34:18 +00:00
var data updateDemoData
if err := json . Unmarshal ( body , & data ) ; err != nil {
return err
2015-03-26 19:22:04 +00:00
}
2016-04-07 17:21:31 +00:00
framework . Logf ( "Unmarshalled json jpg/img => %s , expecting %s ." , data , jpgExpected )
2015-03-26 20:34:18 +00:00
if strings . Contains ( data . Image , jpgExpected ) {
return nil
} else {
2015-08-20 02:09:57 +00:00
return errors . New ( fmt . Sprintf ( "data served up in container is inaccurate, %s didn't contain %s" , data , jpgExpected ) )
2015-03-26 19:22:04 +00:00
}
}
2015-02-20 17:35:42 +00:00
}
2015-08-31 17:23:47 +00:00
2016-04-25 20:38:45 +00:00
func noOpValidatorFn ( c * client . Client , podID string ) error { return nil }
2015-08-31 17:23:47 +00:00
// newBlockingReader returns a reader that allows reading the given string,
// then blocks until Close() is called on the returned closer.
//
// We're explicitly returning the reader and closer separately, because
// the closer needs to be the *os.File we get from os.Pipe(). This is required
// so the exec of kubectl can pass the underlying file descriptor to the exec
// syscall, instead of creating another os.Pipe and blocking on the io.Copy
// between the source (e.g. stdin) and the write half of the pipe.
func newBlockingReader ( s string ) ( io . Reader , io . Closer , error ) {
r , w , err := os . Pipe ( )
if err != nil {
return nil , nil , err
}
w . Write ( [ ] byte ( s ) )
return r , w , nil
}
2015-09-17 20:11:27 +00:00
// newStreamingUpload creates a new http.Request that will stream POST
// a file to a URI.
func newStreamingUpload ( filePath string ) ( * io . PipeReader , * multipart . Writer , error ) {
file , err := os . Open ( filePath )
if err != nil {
return nil , nil , err
}
r , w := io . Pipe ( )
postBodyWriter := multipart . NewWriter ( w )
go streamingUpload ( file , filepath . Base ( filePath ) , postBodyWriter , w )
return r , postBodyWriter , err
}
// streamingUpload streams a file via a pipe through a multipart.Writer.
// Generally one should use newStreamingUpload instead of calling this directly.
func streamingUpload ( file * os . File , fileName string , postBodyWriter * multipart . Writer , w * io . PipeWriter ) {
defer GinkgoRecover ( )
defer file . Close ( )
defer w . Close ( )
// Set up the form file
fileWriter , err := postBodyWriter . CreateFormFile ( "file" , fileName )
if err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Unable to to write file at %s to buffer. Error: %s" , fileName , err )
2015-09-17 20:11:27 +00:00
}
// Copy kubectl binary into the file writer
if _ , err := io . Copy ( fileWriter , file ) ; err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Unable to to copy file at %s into the file writer. Error: %s" , fileName , err )
2015-09-17 20:11:27 +00:00
}
// Nothing more should be written to this instance of the postBodyWriter
if err := postBodyWriter . Close ( ) ; err != nil {
2016-04-07 17:21:31 +00:00
framework . Failf ( "Unable to close the writer for file upload. Error: %s" , err )
2015-09-17 20:11:27 +00:00
}
}
2015-11-02 17:58:50 +00:00
var binPrefixes = [ ] string {
"_output/dockerized/bin" ,
"_output/local/bin" ,
"platforms" ,
}
// findBinary searches through likely paths to find the specified binary. It
// takes the one that has been built most recently. Platform should be
// specified as '<os>/<arch>'. For example: 'linux/amd64'.
func findBinary ( binName string , platform string ) ( string , error ) {
var binTime time . Time
var binPath string
for _ , pre := range binPrefixes {
2016-04-07 17:21:31 +00:00
tryPath := path . Join ( framework . TestContext . RepoRoot , pre , platform , binName )
2015-11-02 17:58:50 +00:00
fi , err := os . Stat ( tryPath )
if err != nil {
continue
}
if fi . ModTime ( ) . After ( binTime ) {
binPath = tryPath
binTime = fi . ModTime ( )
}
}
if len ( binPath ) > 0 {
return binPath , nil
}
return binPath , fmt . Errorf ( "Could not find %v for %v" , binName , platform )
}
2016-05-17 21:56:27 +00:00
func startLocalProxy ( ) ( srv * httptest . Server , logs * bytes . Buffer ) {
logs = & bytes . Buffer { }
p := goproxy . NewProxyHttpServer ( )
p . Verbose = true
p . Logger = log . New ( logs , "" , 0 )
return httptest . NewServer ( p ) , logs
}