Skip to content

Commit 504f3ca

Browse files
chmouelpipelines-as-code[bot]
authored andcommitted
fix(cli): Skip dashboard URL prompt if not needed
The bootstrap command was always prompting for a Tekton Dashboard URL, even when it wasn't strictly required. This commit modifies the `getDashboardURL` function to: - Allow skipping the dashboard URL prompt by entering an empty string. - Detect Tekton Dashboard URL from ingress resources and prompt the user if they want to use that URL. - Prompt the user to provide a dashboard URL manually if no ingress resources are found. - Added a lot of tests to cover these scenarios. Fixes #1975 Signed-off-by: Chmouel Boudjnah <chmouel@redhat.com>
1 parent 275bf8c commit 504f3ca

File tree

2 files changed

+188
-0
lines changed

2 files changed

+188
-0
lines changed

pkg/cmd/tknpac/bootstrap/bootstrap_test.go

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,19 @@ package bootstrap
33
import (
44
"bytes"
55
"io"
6+
"strings"
67
"testing"
78

89
"github.com/openshift-pipelines/pipelines-as-code/pkg/cli"
10+
"github.com/openshift-pipelines/pipelines-as-code/pkg/cli/prompt"
911
"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
1012
"github.com/openshift-pipelines/pipelines-as-code/pkg/params/clients"
1113
"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
1214
testclient "github.com/openshift-pipelines/pipelines-as-code/pkg/test/clients"
1315
"github.com/openshift-pipelines/pipelines-as-code/pkg/test/logger"
1416
"gotest.tools/v3/assert"
1517
corev1 "k8s.io/api/core/v1"
18+
networkingv1 "k8s.io/api/networking/v1"
1619
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1720
rtesting "knative.dev/pkg/reconciler/testing"
1821
)
@@ -143,3 +146,185 @@ func getConfigMapData(namespace, version string) *corev1.ConfigMap {
143146
},
144147
}
145148
}
149+
150+
func TestGetDashboardURL(t *testing.T) {
151+
testParams := []struct {
152+
name string
153+
ingresses []networkingv1.Ingress
154+
askYNResponse bool
155+
surveyResponse string
156+
wantURL string
157+
wantError bool
158+
errorMsg string
159+
askStubs func(*prompt.AskStubber)
160+
}{
161+
{
162+
name: "detect dashboard in ingress with http",
163+
askStubs: func(as *prompt.AskStubber) {
164+
as.StubOne(true)
165+
},
166+
ingresses: []networkingv1.Ingress{
167+
{
168+
Spec: networkingv1.IngressSpec{
169+
Rules: []networkingv1.IngressRule{
170+
{
171+
Host: "tekton.example.com",
172+
IngressRuleValue: networkingv1.IngressRuleValue{
173+
HTTP: &networkingv1.HTTPIngressRuleValue{
174+
Paths: []networkingv1.HTTPIngressPath{
175+
{
176+
Backend: networkingv1.IngressBackend{
177+
Service: &networkingv1.IngressServiceBackend{
178+
Name: tektonDashboardServiceName,
179+
},
180+
},
181+
},
182+
},
183+
},
184+
},
185+
},
186+
},
187+
},
188+
},
189+
},
190+
askYNResponse: true,
191+
wantURL: "http://tekton.example.com",
192+
},
193+
{
194+
name: "detect dashboard in ingress with https",
195+
askStubs: func(as *prompt.AskStubber) {
196+
as.StubOne(true)
197+
},
198+
ingresses: []networkingv1.Ingress{
199+
{
200+
Spec: networkingv1.IngressSpec{
201+
TLS: []networkingv1.IngressTLS{{
202+
Hosts: []string{"tekton.example.com"},
203+
}},
204+
Rules: []networkingv1.IngressRule{
205+
{
206+
Host: "tekton.example.com",
207+
IngressRuleValue: networkingv1.IngressRuleValue{
208+
HTTP: &networkingv1.HTTPIngressRuleValue{
209+
Paths: []networkingv1.HTTPIngressPath{
210+
{
211+
Backend: networkingv1.IngressBackend{
212+
Service: &networkingv1.IngressServiceBackend{
213+
Name: tektonDashboardServiceName,
214+
},
215+
},
216+
},
217+
},
218+
},
219+
},
220+
},
221+
},
222+
},
223+
},
224+
},
225+
askYNResponse: true,
226+
wantURL: "https://tekton.example.com",
227+
},
228+
{
229+
name: "detect dashboard but user rejects it",
230+
askStubs: func(as *prompt.AskStubber) {
231+
as.StubOne(false)
232+
as.StubOne("https://blah.com")
233+
},
234+
ingresses: []networkingv1.Ingress{
235+
{
236+
Spec: networkingv1.IngressSpec{
237+
Rules: []networkingv1.IngressRule{
238+
{
239+
Host: "tekton.example.com",
240+
IngressRuleValue: networkingv1.IngressRuleValue{
241+
HTTP: &networkingv1.HTTPIngressRuleValue{
242+
Paths: []networkingv1.HTTPIngressPath{
243+
{
244+
Backend: networkingv1.IngressBackend{
245+
Service: &networkingv1.IngressServiceBackend{
246+
Name: tektonDashboardServiceName,
247+
},
248+
},
249+
},
250+
},
251+
},
252+
},
253+
},
254+
},
255+
},
256+
},
257+
},
258+
askYNResponse: false,
259+
wantURL: "https://blah.com",
260+
},
261+
{
262+
name: "no dashboard detected, user provides url",
263+
askStubs: func(as *prompt.AskStubber) {
264+
as.StubOne("https://my-dashboard.example.org")
265+
},
266+
ingresses: []networkingv1.Ingress{},
267+
wantURL: "https://my-dashboard.example.org",
268+
},
269+
{
270+
name: "no dashboard detected, user provides empty url",
271+
ingresses: []networkingv1.Ingress{},
272+
askStubs: func(as *prompt.AskStubber) {
273+
as.StubOne("")
274+
},
275+
wantURL: "",
276+
},
277+
{
278+
name: "no dashboard detected, user provides invalid url",
279+
ingresses: []networkingv1.Ingress{},
280+
askStubs: func(as *prompt.AskStubber) {
281+
as.StubOne("invalid url")
282+
},
283+
wantError: true,
284+
errorMsg: "invalid url:",
285+
},
286+
}
287+
288+
for _, tt := range testParams {
289+
t.Run(tt.name, func(t *testing.T) {
290+
ctx, _ := rtesting.SetupFakeContext(t)
291+
cs, _ := testclient.SeedTestData(t, ctx, testclient.Data{})
292+
logger, _ := logger.GetLogger()
293+
294+
run := &params.Run{
295+
Clients: clients.Clients{
296+
PipelineAsCode: cs.PipelineAsCode,
297+
Log: logger,
298+
Kube: cs.Kube,
299+
},
300+
Info: info.Info{},
301+
}
302+
303+
// Create test ingresses
304+
for _, ing := range tt.ingresses {
305+
if _, err := run.Clients.Kube.NetworkingV1().Ingresses("").Create(ctx, &ing, metav1.CreateOptions{}); err != nil {
306+
t.Errorf("failed to create ingress: %v", err)
307+
}
308+
}
309+
310+
as, teardown := prompt.InitAskStubber()
311+
defer teardown()
312+
313+
if tt.askStubs != nil {
314+
tt.askStubs(as)
315+
}
316+
317+
io, _ := newIOStream()
318+
opts := &bootstrapOpts{ioStreams: io}
319+
320+
err := getDashboardURL(ctx, opts, run)
321+
if tt.wantError {
322+
assert.Assert(t, err != nil)
323+
assert.Assert(t, strings.Contains(err.Error(), tt.errorMsg))
324+
} else {
325+
assert.NilError(t, err)
326+
assert.Equal(t, tt.wantURL, opts.dashboardURL)
327+
}
328+
})
329+
}
330+
}

pkg/cmd/tknpac/bootstrap/install.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ func getDashboardURL(ctx context.Context, opts *bootstrapOpts, run *params.Run)
101101
if err := prompt.SurveyAskOne(qs, &answer); err != nil {
102102
return err
103103
}
104+
if answer == "" {
105+
return nil
106+
}
104107
if _, err := url.ParseRequestURI(answer); err != nil {
105108
return fmt.Errorf("invalid url: %w", err)
106109
}

0 commit comments

Comments
 (0)