Skip to content

Commit

Permalink
About page gets Openshift pipelines version and displays if the envir…
Browse files Browse the repository at this point in the history
…oment is openshift
  • Loading branch information
CarolynMabbott authored and tekton-robot committed Feb 12, 2020
1 parent 882e5d7 commit efcdad3
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 25 deletions.
9 changes: 6 additions & 3 deletions pkg/endpoints/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Properties struct {
InstallNamespace string
DashboardVersion string
PipelineVersion string
IsOpenshift bool
}

const (
Expand Down Expand Up @@ -161,10 +162,12 @@ func (r Resource) GetEndpoints(request *restful.Request, response *restful.Respo

// GetProperties is used to get the installed namespace, version of tekton dashboard and version of tekton pipelines
func (r Resource) GetProperties(request *restful.Request, response *restful.Response) {
dashboardVersion := GetDashboardVersion(r)
pipelineVersion := GetPipelineVersion(r)
installedNamespace := os.Getenv("INSTALLED_NAMESPACE")
dashboardVersion := GetDashboardVersion(r, installedNamespace)
isOpenshift := IsOpenshift(r, installedNamespace)
pipelineVersion := GetPipelineVersion(r, isOpenshift)

properties := Properties{InstallNamespace: os.Getenv("INSTALLED_NAMESPACE"), DashboardVersion: dashboardVersion, PipelineVersion: pipelineVersion}
properties := Properties{InstallNamespace: installedNamespace, DashboardVersion: dashboardVersion, PipelineVersion: pipelineVersion, IsOpenshift: isOpenshift}

response.WriteEntity(properties)
}
112 changes: 100 additions & 12 deletions pkg/endpoints/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,22 @@ limitations under the License.
package endpoints

import (
"os"
"strings"

"github.com/tektoncd/dashboard/pkg/logging"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Get dashboard version
func GetDashboardVersion(r Resource) string {
properties := Properties{InstallNamespace: os.Getenv("INSTALLED_NAMESPACE")}
func GetDashboardVersion(r Resource, installedNamespace string) string {
version := ""

listOptions := metav1.ListOptions{
LabelSelector: "app=tekton-dashboard",
}

deployments, err := r.K8sClient.AppsV1().Deployments(properties.InstallNamespace).List(listOptions)
deployments, err := r.K8sClient.AppsV1().Deployments(installedNamespace).List(listOptions)
if err != nil {
logging.Log.Errorf("Error getting dashboard deployment: %s", err.Error())
return ""
Expand All @@ -55,24 +54,117 @@ func GetDashboardVersion(r Resource) string {
}

// Get pipelines version
func GetPipelineVersion(r Resource) string {
func GetPipelineVersion(r Resource, isOpenshift bool) string {
version := ""
namespacesToCheck := []string{"tekton-pipelines"}

if isOpenshift {
namespacesToCheck = append(namespacesToCheck, "openshift-pipelines")
}

// Go through possible namespaces Tekton Pipelines is installed in
// For each namespace if the version is empty then it goes through to get the deployments within that namespace to try and locate the Tekton Pipelines deployment to get the version
for _, versionAttempt := range namespacesToCheck {
if version == "" {
version = getPipelineDeployments(r, versionAttempt)
}
}

if version == "" {
logging.Log.Error("Error getting the Tekton Pipelines deployment version. Version is unknown")
return ""
}
return version
}

// Get whether running on openshift or not
func IsOpenshift(r Resource, installedNamespace string) bool {
namespaces, err := r.K8sClient.CoreV1().Namespaces().List(v1.ListOptions{})
if err != nil {
logging.Log.Errorf("Error getting the list of namespaces: %s", err.Error())
return false
}

openshiftPipelineFound := false
tektonPipelinesFound := false
routeFound := false
for _, namespace := range namespaces.Items {
namespaceName := namespace.GetName()

if namespaceName == "openshift-pipelines" {
openshiftPipelineFound = SearchForPipelineDeployments(r, "openshift-pipelines")
}
if namespaceName == "tekton-pipelines" {
tektonPipelinesFound = SearchForPipelineDeployments(r, "tekton-pipelines")
}
}

routes, err := r.RouteClient.Route().Routes(installedNamespace).List(v1.ListOptions{})
if err != nil {
logging.Log.Errorf("Error getting the list of routes: %s", err.Error())
}

for _, route := range routes.Items {
routeA := route.GetName()
if routeA == "tekton-dashboard" {
routeFound = true
}
}

if (openshiftPipelineFound == true || tektonPipelinesFound == true) && routeFound == true {
return true
}
return false
}

// Get Deployments in namespace and search for tekton-pipelines-controller
func SearchForPipelineDeployments(r Resource, namespace string) bool {
deployments, err := r.K8sClient.AppsV1().Deployments(namespace).List(v1.ListOptions{})
if err != nil {
logging.Log.Errorf("Error getting the %s deployment: %s", namespace, err.Error())
return false
}

for _, deployment := range deployments.Items {
deploymentName := deployment.ObjectMeta.GetName()
if deploymentName == "tekton-pipelines-controller" {
return true
}
}
return false
}

// Go through pipeline deployments and find what version it is
func getPipelineDeployments(r Resource, namespace string) string {
version := ""

listOptions := metav1.ListOptions{
LabelSelector: "app.kubernetes.io/component=controller,app.kubernetes.io/name=tekton-pipelines",
}

deployments, err := r.K8sClient.AppsV1().Deployments("tekton-pipelines").List(listOptions)
deployments, err := r.K8sClient.AppsV1().Deployments(namespace).List(listOptions)
if err != nil {
logging.Log.Errorf("Error getting the tekton pipelines deployment: %s", err.Error())
logging.Log.Errorf("Error getting the Tekton Pipelines deployment: %s", err.Error())
return ""
}

for _, deployment := range deployments.Items {
deploymentAnnotations := deployment.Spec.Template.GetAnnotations()

if namespace == "openshift-pipelines" {
deploymentImage := deployment.Spec.Template.Spec.Containers[0].Image
if strings.Contains(deploymentImage, "openshift-pipeline/tektoncd-pipeline-controller") && strings.Contains(deploymentImage, ":") {
s := strings.SplitAfter(deploymentImage, ":")
if s[1] != "" {
version = s[1]
}
}
}

// For master of Tekton Pipelines
version = deploymentAnnotations["pipeline.tekton.dev/release"]
if version == "" {
version = deploymentAnnotations["pipeline.tekton.dev/release"]
}

// For Tekton Pipelines 0.10.0 + 0.10.1
if version == "" {
Expand All @@ -92,9 +184,5 @@ func GetPipelineVersion(r Resource) string {
}
}

if version == "" {
logging.Log.Error("Error getting the tekton pipelines deployment version. Version is unknown")
return ""
}
return version
}
13 changes: 10 additions & 3 deletions src/containers/About/About.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,14 @@ export /* istanbul ignore next */ class About extends Component {

makeLines(property) {
let data = '';
const value = this.state.dashboardInfo[property];
let value = this.state.dashboardInfo[property];
if (this.state.dashboardInfo[property] !== undefined) {
if (value === false) {
value = 'False';
}
if (value === true) {
value = 'True';
}
data = {
id: property,
property,
Expand Down Expand Up @@ -98,7 +104,8 @@ export /* istanbul ignore next */ class About extends Component {
const propertiesToCheck = [
'InstallNamespace',
'DashboardVersion',
'PipelineVersion'
'PipelineVersion',
'IsOpenshift'
];
propertiesToCheck.forEach(element => {
const line = this.makeLines(element);
Expand All @@ -120,7 +127,7 @@ export /* istanbul ignore next */ class About extends Component {
kind="error"
title={intl.formatMessage({
id: 'dashboard.displayVersion.error',
defaultMessage: 'Error getting version'
defaultMessage: 'Error getting data'
})}
subtitle={this.state.error}
lowContrast
Expand Down
19 changes: 14 additions & 5 deletions src/containers/About/About.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ it('About renders errors when undefined field', async () => {
jest.spyOn(API, 'getInstallProperties').mockImplementation(() => ({
InstallNamespace: 'tekton-pipelines',
DashboardVersion: '',
PipelineVersion: 'v0.10.0'
PipelineVersion: 'v0.10.0',
IsOpenshift: 'True'
}));

const store = mockStore({
Expand All @@ -55,17 +56,20 @@ it('About renders errors when undefined field', async () => {
expect(getByText('Value')).toBeTruthy();
expect(getByText('InstallNamespace')).toBeTruthy();
expect(getByText('PipelineVersion')).toBeTruthy();
expect(getByText('IsOpenshift')).toBeTruthy();
expect(getByText('tekton-pipelines')).toBeTruthy();
expect(getByText('v0.10.0')).toBeTruthy();
expect(getByText('Error getting version')).toBeTruthy();
expect(getByText('True')).toBeTruthy();
expect(getByText('Error getting data')).toBeTruthy();
expect(getByText('DashboardVersion cannot be found')).toBeTruthy();
});

it('About renders correctly', async () => {
jest.spyOn(API, 'getInstallProperties').mockImplementation(() => ({
InstallNamespace: 'tekton-pipelines',
DashboardVersion: 'v0.100.0',
PipelineVersion: 'v0.10.0'
PipelineVersion: 'v0.10.0',
IsOpenshift: 'False'
}));

const store = mockStore({
Expand All @@ -86,9 +90,11 @@ it('About renders correctly', async () => {
expect(getByText('InstallNamespace')).toBeTruthy();
expect(getByText('DashboardVersion')).toBeTruthy();
expect(getByText('PipelineVersion')).toBeTruthy();
expect(getByText('IsOpenshift')).toBeTruthy();
expect(getByText('tekton-pipelines')).toBeTruthy();
expect(getByText('v0.100.0')).toBeTruthy();
expect(getByText('v0.10.0')).toBeTruthy();
expect(getByText('False')).toBeTruthy();
});

it('About renders correctly when not loaded', async () => {
Expand Down Expand Up @@ -117,7 +123,8 @@ it('About renders errors when there are multiple undefined fields', async () =>
jest.spyOn(API, 'getInstallProperties').mockImplementation(() => ({
InstallNamespace: 'tekton-pipelines',
DashboardVersion: '',
PipelineVersion: ''
PipelineVersion: '',
IsOpenshift: 'True'
}));

const store = mockStore({
Expand All @@ -137,7 +144,9 @@ it('About renders errors when there are multiple undefined fields', async () =>
expect(getByText('Value')).toBeTruthy();
expect(getByText('InstallNamespace')).toBeTruthy();
expect(getByText('tekton-pipelines')).toBeTruthy();
expect(getByText('Error getting version')).toBeTruthy();
expect(getByText('IsOpenshift')).toBeTruthy();
expect(getByText('True')).toBeTruthy();
expect(getByText('Error getting data')).toBeTruthy();
expect(
getByText('DashboardVersionPipelineVersion cannot be found')
).toBeTruthy();
Expand Down
4 changes: 2 additions & 2 deletions src/nls/messages_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"dashboard.deletePipelineRun.heading": "Delete PipelineRun",
"dashboard.deleteTaskRun.body": "Are you sure you would like to delete TaskRun {name}?",
"dashboard.deleteTaskRun.heading": "Delete TaskRun",
"dashboard.displayVersion.error": "Error getting version",
"dashboard.displayVersion.error": "Error getting data",
"dashboard.emptyState.allNamespaces": "No {kind} under any namespace.",
"dashboard.emptyState.clusterTasks": "No {kind}",
"dashboard.emptyState.selectedNamespace": "No {kind} under namespace {selectedNamespace}",
Expand Down Expand Up @@ -142,8 +142,8 @@
"dashboard.serviceAccount.noSecrets": "No Secrets found for this ServiceAccount.",
"dashboard.serviceAccount.secretsTableTitle": "Secrets",
"dashboard.serviceAccount.unavailable": "ServiceAccount not available",
"dashboard.sideNav.importResources": "Import Tekton resources",
"dashboard.sideNav.about": "About",
"dashboard.sideNav.importResources": "Import Tekton resources",
"dashboard.sideNav.tektonResources": "Tekton resources",
"dashboard.step.containerStatus": "Container status",
"dashboard.step.definitionNotAvailable": "description: step definition not available",
Expand Down

0 comments on commit efcdad3

Please sign in to comment.