Skip to content

Commit

Permalink
Add a better status message
Browse files Browse the repository at this point in the history
We are adding a better status message that will include the Namespace
and the PipelineRun.

We link the Namespace to the Namespace view in the consoles.

Introducing a new setting for that `custom-console-url-namespace` that
would need to be setup when using a custom console.

Signed-off-by: Chmouel Boudjnah <[email protected]>
  • Loading branch information
chmouel committed Nov 3, 2023
1 parent 6978c28 commit 81b006c
Show file tree
Hide file tree
Showing 13 changed files with 118 additions and 30 deletions.
10 changes: 10 additions & 0 deletions docs/content/docs/install/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,16 @@ A few settings are available to configure this feature:

Set this to the root URL of your custom console. example: `https://mycorp.com`

* `custom-console-url-namespace`

Set this to the URL where to view the details of the `Namespace`.

The URL supports all the standard variables as exposed on the Pipelinerun (refer to
the documentation on [Authoring PipelineRuns](../authoringprs)) with the added
variable:

* `{{ namespace }}`: The target namespace where the pipelinerun is executed

* `custom-console-url-pr-details`

Set this to the URL where to view the details of the `PipelineRun`. This is
Expand Down
14 changes: 14 additions & 0 deletions pkg/consoleui/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,20 @@ func (o *CustomConsole) DetailURL(pr *tektonv1.PipelineRun) string {
return o.generateURL(o.Info.Pac.CustomConsolePRdetail, nm)
}

func (o *CustomConsole) NameSpaceURL(pr *tektonv1.PipelineRun) string {
if o.Info.Pac.CustomConsoleNamespaceURL == "" {
return fmt.Sprintf("https://detailurl.setting.%s.is.not.configured", settings.CustomConsoleNamespaceURLKey)
}
nm := o.params
// make sure the map is not nil before setting this up
// there is a case where SetParams is not called before DetailURL and this would crash the container
if nm == nil {
nm = make(map[string]string)
}
nm["namespace"] = pr.GetNamespace()
return o.generateURL(o.Info.Pac.CustomConsoleNamespaceURL, nm)
}

func (o *CustomConsole) TaskLogURL(pr *tektonv1.PipelineRun, taskRunStatus *tektonv1.PipelineRunTaskRunStatus) string {
if o.Info.Pac.CustomConsolePRTaskLog == "" {
return fmt.Sprintf("https://tasklogurl.setting.%s.is.not.configured", settings.CustomConsolePRTaskLogKey)
Expand Down
11 changes: 7 additions & 4 deletions pkg/consoleui/custom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,18 @@ func TestCustomGood(t *testing.T) {
Info: &info.Info{
Pac: &info.PacOpts{
Settings: &settings.Settings{
CustomConsoleName: consoleName,
CustomConsoleURL: consoleURL,
CustomConsolePRdetail: "{{ notthere}}",
CustomConsolePRTaskLog: "{{ notthere}}",
CustomConsoleName: consoleName,
CustomConsoleURL: consoleURL,
CustomConsolePRdetail: "{{ notthere}}",
CustomConsolePRTaskLog: "{{ notthere}}",
CustomConsoleNamespaceURL: "https://mycorp.console/{{ namespace }}",
},
},
},
}
assert.Assert(t, strings.Contains(o.DetailURL(pr), consoleURL))
assert.Assert(t, strings.Contains(o.TaskLogURL(pr, trStatus), consoleURL))
assert.Assert(t, strings.Contains(o.NameSpaceURL(pr), "https://mycorp.console/ns"))
}

func TestCustomBad(t *testing.T) {
Expand All @@ -122,4 +124,5 @@ func TestCustomBad(t *testing.T) {
assert.Assert(t, strings.Contains(c.URL(), "is.not.configured"))
assert.Assert(t, strings.Contains(c.DetailURL(pr), "is.not.configured"))
assert.Assert(t, strings.Contains(c.TaskLogURL(pr, nil), "is.not.configured"))
assert.Assert(t, strings.Contains(c.NameSpaceURL(pr), "is.not.configured"), c.NameSpaceURL(pr))
}
5 changes: 5 additions & 0 deletions pkg/consoleui/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const consoleIsnotConfiguredURL = "https://dashboard.is.not.configured"
type Interface interface {
DetailURL(pr *tektonv1.PipelineRun) string
TaskLogURL(pr *tektonv1.PipelineRun, taskRunStatusstatus *tektonv1.PipelineRunTaskRunStatus) string
NameSpaceURL(pr *tektonv1.PipelineRun) string
UI(ctx context.Context, kdyn dynamic.Interface) error
URL() string
GetName() string
Expand All @@ -33,6 +34,10 @@ func (f FallBackConsole) TaskLogURL(_ *tektonv1.PipelineRun, _ *tektonv1.Pipelin
return consoleIsnotConfiguredURL
}

func (f FallBackConsole) NameSpaceURL(_ *tektonv1.PipelineRun) string {
return consoleIsnotConfiguredURL
}

func (f FallBackConsole) UI(_ context.Context, _ dynamic.Interface) error {
return nil
}
Expand Down
21 changes: 13 additions & 8 deletions pkg/consoleui/openshift.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import (
)

const (
openShiftConsoleNS = "openshift-console"
openShiftConsoleRouteName = "console"
openShiftPipelineDetailViewURL = "https://%s/k8s/ns/%s/tekton.dev~v1beta1~PipelineRun/%s"
openShiftPipelineTaskLogURL = "%s/logs/%s"
openShiftRouteGroup = "route.openshift.io"
openShiftRouteVersion = "v1"
openShiftRouteResource = "routes"
openshiftConsoleName = "OpenShift Console"
openShiftConsoleNS = "openshift-console"
openShiftConsoleRouteName = "console"
openShiftPipelineNamespaceViewURL = "https://%s/pipelines/ns/%s/pipeline-runs"
openShiftPipelineDetailViewURL = "https://%s/k8s/ns/%s/tekton.dev~v1beta1~PipelineRun/%s"
openShiftPipelineTaskLogURL = "%s/logs/%s"
openShiftRouteGroup = "route.openshift.io"
openShiftRouteVersion = "v1"
openShiftRouteResource = "routes"
openshiftConsoleName = "OpenShift Console"
)

type OpenshiftConsole struct {
Expand All @@ -44,6 +45,10 @@ func (o *OpenshiftConsole) TaskLogURL(pr *tektonv1.PipelineRun, taskRunStatus *t
return fmt.Sprintf(openShiftPipelineTaskLogURL, o.DetailURL(pr), taskRunStatus.PipelineTaskName)
}

func (o *OpenshiftConsole) NameSpaceURL(pr *tektonv1.PipelineRun) string {
return fmt.Sprintf(openShiftPipelineNamespaceViewURL, o.host, pr.GetNamespace())
}

// UI use dynamic client to get the route of the openshift
// console where we can point to.
func (o *OpenshiftConsole) UI(ctx context.Context, kdyn dynamic.Interface) error {
Expand Down
11 changes: 6 additions & 5 deletions pkg/consoleui/openshift_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,16 @@ func TestOpenshiftConsoleUI(t *testing.T) {
func TestOpenshiftConsoleURLs(t *testing.T) {
pr := &tektonv1.PipelineRun{
ObjectMeta: metav1.ObjectMeta{
Namespace: "ns",
Namespace: "theNS",
Name: "pr",
},
}
trStatus := &tektonv1.PipelineRunTaskRunStatus{
PipelineTaskName: "task",
}
o := OpenshiftConsole{host: "http://fakeconsole"}
assert.Assert(t, o.URL() != "")
assert.Assert(t, o.DetailURL(pr) != "")
assert.Assert(t, o.TaskLogURL(pr, trStatus) != "")
o := OpenshiftConsole{host: "fakeconsole"}
assert.Equal(t, o.URL(), "https://fakeconsole")
assert.Equal(t, o.DetailURL(pr), "https://fakeconsole/k8s/ns/theNS/tekton.dev~v1beta1~PipelineRun/pr")
assert.Equal(t, o.TaskLogURL(pr, trStatus), "https://fakeconsole/k8s/ns/theNS/tekton.dev~v1beta1~PipelineRun/pr/logs/task")
assert.Equal(t, o.NameSpaceURL(pr), "https://fakeconsole/pipelines/ns/theNS/pipeline-runs")
}
4 changes: 4 additions & 0 deletions pkg/consoleui/tektondashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ func (t *TektonDashboard) DetailURL(pr *tektonv1.PipelineRun) string {
return fmt.Sprintf("%s/#/namespaces/%s/pipelineruns/%s", t.BaseURL, pr.GetNamespace(), pr.GetName())
}

func (t *TektonDashboard) NameSpaceURL(pr *tektonv1.PipelineRun) string {
return fmt.Sprintf("%s/#/namespaces/%s/pipelineruns", t.BaseURL, pr.GetNamespace())
}

func (t *TektonDashboard) TaskLogURL(pr *tektonv1.PipelineRun, taskRunStatus *tektonv1.PipelineRunTaskRunStatus) string {
return fmt.Sprintf("%s?pipelineTask=%s", t.DetailURL(pr), taskRunStatus.PipelineTaskName)
}
Expand Down
10 changes: 8 additions & 2 deletions pkg/formatting/starting.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,24 @@ var StartingPipelineRunText string
//go:embed templates/queuing.go.tmpl
var QueuingPipelineRunText string

//go:embed templates/failures.tmpl
var FailurePipelineRunText string

type MessageTemplate struct {
PipelineRunName string
Namespace string
NamespaceURL string
ConsoleName string
ConsoleURL string
TknBinary string
TknBinaryURL string
TaskStatus string
FailureSnippet string
}

func (mt MessageTemplate) MakeTemplate(msg string) (string, error) {
func (mt MessageTemplate) MakeTemplate(tmpl string) (string, error) {
outputBuffer := bytes.Buffer{}
t := template.Must(template.New("Message").Parse(msg))
t := template.Must(template.New("Message").Parse(tmpl))
data := struct{ Mt MessageTemplate }{Mt: mt}
if err := t.Execute(&outputBuffer, data); err != nil {
return "", err
Expand Down
7 changes: 7 additions & 0 deletions pkg/formatting/starting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func TestMessageTemplate_MakeTemplate(t *testing.T) {
ConsoleURL: "https://test-console-url.com",
TknBinary: "test-tkn",
TknBinaryURL: "https://test-tkn-url.com",
FailureSnippet: "such a failure",
}

tests := []struct {
Expand All @@ -33,6 +34,12 @@ func TestMessageTemplate_MakeTemplate(t *testing.T) {
msg: "Starting Pipelinerun {{.Mt.PipelineRunName}} in namespace {{.FOOOBAR }}",
wantErr: true,
},
{
name: "Failure template",
mt: mt,
msg: "I am {{ .Mt.FailureSnippet }}",
want: "I am such a failure",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
10 changes: 10 additions & 0 deletions pkg/formatting/templates/failures.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<ul>
<li><b>Namespace</b>: <a href="{{ .Mt.NamespaceURL }}">{{ .Mt.Namespace }}</a></li>
<li><b>PipelineRun:</b> <a href="{{ .Mt.ConsoleURL }}">{{ .Mt.PipelineRunName }}</a></li>
</ul>
<hr>
<h4>Task Statuses:</h4>
{{ .Mt.TaskStatus }}
<hr>
<h4>Failure snippet:</h4>
{{ .Mt.FailureSnippet }}
2 changes: 1 addition & 1 deletion pkg/formatting/templates/starting.go.tmpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Starting Pipelinerun <b>{{ .Mt.PipelineRunName }}</b> in namespace<b> {{ .Mt.Namespace }}</b><br>
You can monitor the execution using the [{{ .Mt.ConsoleName }}]({{ .Mt.ConsoleURL }}) PipelineRun viewer or through the command line by
using the [{{ .Mt.TknBinary }}]({{ .Mt.TknBinaryURL }}) CLI with the following command:
<br>

<code>{{ .Mt.TknBinary }} pr logs -n {{ .Mt.Namespace }} {{ .Mt.PipelineRunName }} -f</code>
23 changes: 15 additions & 8 deletions pkg/params/settings/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ const (
AutoConfigureNewGitHubRepoKey = "auto-configure-new-github-repo"
AutoConfigureRepoNamespaceTemplateKey = "auto-configure-repo-namespace-template"

CustomConsoleNameKey = "custom-console-name"
CustomConsoleURLKey = "custom-console-url"
CustomConsolePRDetailKey = "custom-console-url-pr-details"
CustomConsolePRTaskLogKey = "custom-console-url-pr-tasklog"
CustomConsoleNameKey = "custom-console-name"
CustomConsoleURLKey = "custom-console-url"
CustomConsolePRDetailKey = "custom-console-url-pr-details"
CustomConsolePRTaskLogKey = "custom-console-url-pr-tasklog"
CustomConsoleNamespaceURLKey = "custom-console-url-namespace"

SecretAutoCreateKey = "secret-auto-create"
secretAutoCreateDefaultValue = "true"
Expand Down Expand Up @@ -94,10 +95,11 @@ type Settings struct {
ErrorDetectionNumberOfLines int
ErrorDetectionSimpleRegexp string

CustomConsoleName string
CustomConsoleURL string
CustomConsolePRdetail string
CustomConsolePRTaskLog string
CustomConsoleName string
CustomConsoleURL string
CustomConsolePRdetail string
CustomConsolePRTaskLog string
CustomConsoleNamespaceURL string

RememberOKToTest bool
}
Expand Down Expand Up @@ -227,6 +229,11 @@ func ConfigToSettings(logger *zap.SugaredLogger, setting *Settings, config map[s
setting.CustomConsolePRdetail = config[CustomConsolePRDetailKey]
}

if setting.CustomConsoleNamespaceURL != config[CustomConsoleNamespaceURLKey] {
logger.Infof("CONFIG: setting custom console namespace URL to %v", config[CustomConsoleNamespaceURLKey])
setting.CustomConsoleNamespaceURL = config[CustomConsoleNamespaceURLKey]
}

if setting.CustomConsolePRTaskLog != config[CustomConsolePRTaskLogKey] {
logger.Infof("CONFIG: setting custom console pr task log URL to %v", config[CustomConsolePRTaskLogKey])
setting.CustomConsolePRTaskLog = config[CustomConsolePRTaskLogKey]
Expand Down
20 changes: 18 additions & 2 deletions pkg/reconciler/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/openshift-pipelines/pipelines-as-code/pkg/kubeinteraction"
kstatus "github.com/openshift-pipelines/pipelines-as-code/pkg/kubeinteraction/status"
"github.com/openshift-pipelines/pipelines-as-code/pkg/params/info"
"github.com/openshift-pipelines/pipelines-as-code/pkg/params/settings"
"github.com/openshift-pipelines/pipelines-as-code/pkg/provider"
"github.com/openshift-pipelines/pipelines-as-code/pkg/secrets"
"github.com/openshift-pipelines/pipelines-as-code/pkg/sort"
Expand All @@ -26,7 +27,6 @@ import (
const (
maxPipelineRunStatusRun = 5
logSnippetNumLines = 3
failureReasonText = "%s<br><h4>Failure reason</h4><br>%s"
)

var backoffSchedule = []time.Duration{
Expand Down Expand Up @@ -127,7 +127,23 @@ func (r *Reconciler) postFinalStatus(ctx context.Context, logger *zap.SugaredLog
if failures != "" {
secretValues := secrets.GetSecretsAttachedToPipelineRun(ctx, r.kinteract, pr)
failures = secrets.ReplaceSecretsInText(failures, secretValues)
taskStatusText = fmt.Sprintf(failureReasonText, taskStatusText, failures)

consoleURL := r.run.Clients.ConsoleUI.DetailURL(pr)
namespaceURL := r.run.Clients.ConsoleUI.NameSpaceURL(pr)
mt := formatting.MessageTemplate{
PipelineRunName: pr.GetName(),
Namespace: pr.GetNamespace(),
NamespaceURL: namespaceURL,
ConsoleName: r.run.Clients.ConsoleUI.GetName(),
ConsoleURL: consoleURL,
TknBinary: settings.TknBinaryName,
TknBinaryURL: settings.TknBinaryURL,
TaskStatus: taskStatusText,
FailureSnippet: failures,
}
if taskStatusText, err = mt.MakeTemplate(formatting.FailurePipelineRunText); err != nil {
return nil, fmt.Errorf("cannot create message template: %w", err)
}
}
}

Expand Down

0 comments on commit 81b006c

Please sign in to comment.