@@ -34,12 +34,12 @@ import (
3434 "encoding/pem"
3535 "fmt"
3636 "io/ioutil"
37+ "net"
3738 "os/exec"
3839 "path/filepath"
3940 "testing"
4041 "time"
4142
42- "cloud.google.com/go/compute/metadata"
4343 "github.com/sigstore/cosign/pkg/cosign"
4444 "github.com/tektoncd/pipeline/pkg/names"
4545
@@ -58,7 +58,10 @@ type clients struct {
5858 KubeClient kubernetes.Interface
5959 PipelineClient pipelineclientset.Interface
6060 secret secret
61- registry string
61+ // these represent the same registry; internal is accessible from within the cluster
62+ // external is accessible from outside the cluster via port-forwarding
63+ internalRegistry string
64+ externalRegistry string
6265}
6366
6467// newClients instantiates and returns several clientsets required for making requests to the
@@ -85,15 +88,24 @@ func newClients(t *testing.T, configPath, clusterName string) *clients {
8588 return c
8689}
8790
88- func setup (ctx context.Context , t * testing.T , so ... secretOpts ) (* clients , string , func ()) {
91+ type setupOpts struct {
92+ useCosignSigner bool
93+ registry bool
94+ }
95+
96+ func setup (ctx context.Context , t * testing.T , opts setupOpts ) (* clients , string , func ()) {
8997 t .Helper ()
9098 namespace := names .SimpleNameGenerator .RestrictLengthWithRandomSuffix ("earth" )
9199
92100 c := newClients (t , knativetest .Flags .Kubeconfig , knativetest .Flags .Cluster )
93101 createNamespace (ctx , t , namespace , c .KubeClient )
94102
95- c .secret = setupSecret (ctx , t , c .KubeClient , so ... )
96- c .registry = createRegistry (ctx , t , c .KubeClient )
103+ c .secret = setupSecret (ctx , t , c .KubeClient , opts )
104+ if opts .registry {
105+ internalRegistry , svc := createRegistry (ctx , t , namespace , c .KubeClient )
106+ externalRegistry := portForward (ctx , t , svc )
107+ c .internalRegistry , c .externalRegistry = internalRegistry , externalRegistry
108+ }
97109
98110 var cleanup = func () {
99111 t .Logf ("Deleting namespace %s" , namespace )
@@ -121,13 +133,8 @@ type secret struct {
121133 cosignPriv * ecdsa.PrivateKey
122134}
123135
124- func createRegistry (ctx context.Context , t * testing.T , kubeClient kubernetes.Interface ) string {
136+ func createRegistry (ctx context.Context , t * testing.T , namespace string , kubeClient kubernetes.Interface ) ( string , * corev1. Service ) {
125137 t .Helper ()
126- if metadata .OnGCE () {
127- t .Log ("LoadBalancer not supported on GCE, skipping creating registry" )
128- return ""
129- }
130- namespace := "tekton-chains"
131138 replicas := int32 (1 )
132139 label := map [string ]string {"app" : "registry" }
133140 meta := metav1.ObjectMeta {
@@ -161,19 +168,13 @@ func createRegistry(ctx context.Context, t *testing.T, kubeClient kubernetes.Int
161168 service := & corev1.Service {
162169 ObjectMeta : meta ,
163170 Spec : corev1.ServiceSpec {
164- Selector : label ,
165- ExternalTrafficPolicy : corev1 .ServiceExternalTrafficPolicyTypeCluster ,
166- Type : corev1 .ServiceTypeLoadBalancer ,
167- Ports : []corev1.ServicePort {{Port : int32 (5000 ), Protocol : corev1 .ProtocolTCP , TargetPort : intstr.IntOrString {IntVal : int32 (5000 )}}},
171+ Selector : label ,
172+ Ports : []corev1.ServicePort {{Port : int32 (5000 ), Protocol : corev1 .ProtocolTCP , TargetPort : intstr.IntOrString {IntVal : int32 (5000 )}}},
168173 },
169174 }
170175 // first, check if the svc already exists
171176 if svc , err := kubeClient .CoreV1 ().Services (namespace ).Get (ctx , service .Name , metav1.GetOptions {}); err == nil {
172- if ingress := svc .Status .LoadBalancer .Ingress ; ingress != nil {
173- if ingress [0 ].IP != "" {
174- return fmt .Sprintf ("%s:5000" , ingress [0 ].IP )
175- }
176- }
177+ return fmt .Sprintf ("%s.%s.svc.cluster.local:5000" , svc .Name , svc .Namespace ), svc
177178 }
178179 t .Logf ("Creating insecure registry to deploy in ns %s" , namespace )
179180 if _ , err := kubeClient .AppsV1 ().Deployments (namespace ).Create (ctx , deployment , metav1.CreateOptions {}); err != nil {
@@ -186,50 +187,45 @@ func createRegistry(ctx context.Context, t *testing.T, kubeClient kubernetes.Int
186187 t .Fatalf ("Failed to create service for tests: %s" , err )
187188 }
188189
189- t .Logf ("Waiting for external service IP to be exposed..." )
190- return waitForExternalIP (ctx , t , service , 2 * time .Minute , kubeClient )
190+ return fmt .Sprintf ("%s.%s.svc.cluster.local:5000" , service .Name , service .Namespace ), service
191191}
192192
193- func waitForExternalIP (ctx context.Context , t * testing.T , service * corev1.Service , timeout time.Duration , c kubernetes.Interface ) string {
194- t .Helper ()
195- w , err := c .CoreV1 ().Services (service .Namespace ).Watch (ctx , metav1 .SingleObject (metav1.ObjectMeta {
196- Name : service .Name ,
197- Namespace : service .Namespace ,
198- }))
199- if err != nil {
200- t .Errorf ("error watching taskrun: %s" , err )
201- }
202- // Setup a timeout channel
203- timeoutChan := make (chan struct {})
193+ func portForward (ctx context.Context , t * testing.T , svc * corev1.Service ) string {
194+ freePort := getFreePort (t )
204195 go func () {
205- time .Sleep (timeout )
206- timeoutChan <- struct {}{}
207- }()
208-
209- // Wait for the condition to be true or a timeout
210- for {
211- select {
212- case ev := <- w .ResultChan ():
213- tr := ev .Object .(* corev1.Service )
214- if ingress := tr .Status .LoadBalancer .Ingress ; ingress != nil {
215- if ingress [0 ].IP != "" {
216- return fmt .Sprintf ("%s:5000" , ingress [0 ].IP )
196+ // port forwarding has a bad habit of dying randomly, so keep restarting it
197+ for {
198+ t .Logf ("Starting port forwarding on port %d..." , freePort )
199+ ctx , cancel := context .WithCancel (ctx )
200+ cmd := exec .CommandContext (ctx , "kubectl" , "port-forward" , fmt .Sprintf ("svc/%s" , svc .Name ), fmt .Sprintf ("%d:5000" , freePort ), "-n" , svc .Namespace )
201+ select {
202+ case <- ctx .Done ():
203+ cancel ()
204+ return // returning not to leak the goroutine
205+ default :
206+ if err := cmd .Run (); err != nil {
207+ t .Logf ("port forwarding died: %v\n " , err )
208+ } else {
209+ cancel ()
210+ return
217211 }
212+ cancel ()
218213 }
219- case <- timeoutChan :
220- output , err := exec .Command ("kubectl" , "get" , "svc" , "-A" ).CombinedOutput ()
221- t .Fatalf ("Error creating registry, time out:%v\n %s" , err , string (output ))
222214 }
223- }
215+ }()
216+ return fmt .Sprintf ("localhost:%d" , freePort )
224217}
225218
226- type secretOpts func (map [string ]string )
227-
228- func useCosign (data map [string ]string ) {
229- delete (data , "x509.pem" )
219+ func getFreePort (t * testing.T ) int {
220+ l , err := net .Listen ("tcp" , fmt .Sprintf ("%s:0" , "localhost" ))
221+ if err != nil {
222+ t .Error (err )
223+ return 5000 // just return something
224+ }
225+ return l .Addr ().(* net.TCPAddr ).Port
230226}
231227
232- func setupSecret (ctx context.Context , t * testing.T , c kubernetes.Interface , so ... secretOpts ) secret {
228+ func setupSecret (ctx context.Context , t * testing.T , c kubernetes.Interface , opts setupOpts ) secret {
233229 // Only overwrite the secret data if it isn't set.
234230 namespace := "tekton-chains"
235231 s := corev1.Secret {
@@ -267,10 +263,9 @@ func setupSecret(ctx context.Context, t *testing.T, c kubernetes.Interface, so .
267263 t .Error (err )
268264 }
269265
270- for _ , opt := range so {
271- opt (s .StringData )
266+ if opts . useCosignSigner {
267+ delete (s .StringData , "x509.pem" )
272268 }
273-
274269 if _ , err := c .CoreV1 ().Secrets (namespace ).Update (ctx , & s , metav1.UpdateOptions {}); err != nil {
275270 t .Error (err )
276271 }
0 commit comments