Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add iconUrl check upon index component validation #167

Merged
merged 16 commits into from
Mar 22, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions index/generator/library/library.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"path"
"path/filepath"
"strings"

devfileParser "github.com/devfile/library/v2/pkg/devfile"
"github.com/devfile/library/v2/pkg/devfile/parser"
Expand All @@ -35,6 +37,7 @@ const (
extraDevfileEntries = "extraDevfileEntries.yaml"
stackYaml = "stack.yaml"
ownersFile = "OWNERS"
imageHeaderKeyword = "image/"
)

// MissingArchError is an error if the architecture list is empty
Expand Down Expand Up @@ -64,6 +67,14 @@ func (e *MissingSupportUrlError) Error() string {
return fmt.Sprintf("the %s devfile has no supportUrl mentioned\n", e.devfile)
}

type IconUrlBrokenError struct {
devfile string
}

func (e *IconUrlBrokenError) Error() string {
return fmt.Sprintf("Devfile %s has broken or not existing icon\n", e.devfile)
}

// GenerateIndexStruct parses registry then generates index struct according to the schema
func GenerateIndexStruct(registryDirPath string, force bool) ([]schema.Schema, error) {
// Parse devfile registry then populate index struct
Expand Down Expand Up @@ -170,6 +181,9 @@ func validateIndexComponent(indexComponent schema.Schema, componentType schema.D
}

// Fields to be validated for both stacks and samples
if !iconExists(indexComponent.Icon) {
return &IconUrlBrokenError{devfile: indexComponent.Name}
}
if indexComponent.Provider == "" {
return &MissingProviderError{devfile: indexComponent.Name}
}
Expand Down Expand Up @@ -202,6 +216,28 @@ func dirExists(dirpath string) error {
return nil
}

func iconExists(iconUrl string) bool {
/* #nosec G107 -- iconUrl is taken from the index file. Stacks / Samples with URLs to a devfile icon should be vetted beforehand */
resp, err := http.Get(iconUrl)
github-advanced-security[bot] marked this conversation as resolved.
Fixed
Show resolved Hide resolved
if err != nil {
return false
}

if resp.StatusCode != 200 {
return false
}

// Ensure that the content of response is image related
headers := resp.Header["Content-Type"]
for _, header := range headers {
if strings.Contains(header, imageHeaderKeyword) {
return true
}
}

return false
}

func parseDevfileRegistry(registryDirPath string, force bool) ([]schema.Schema, error) {

var index []schema.Schema
Expand Down
51 changes: 51 additions & 0 deletions index/generator/library/library_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func TestValidateIndexComponent(t *testing.T) {
noVersionErr := ".*no version specified.*"
schemaVersionEmptyErr := ".*schema version is empty.*"
multipleVersionErr := ".*has multiple default versions.*"
iconUrlBrokenErr := ".*has broken or not existing icon.*"

tests := []struct {
name string
Expand Down Expand Up @@ -112,6 +113,7 @@ func TestValidateIndexComponent(t *testing.T) {
"Case 5: test happy path for for stack component",
schema.Schema{
Name: "nodejs",
Icon: "https://raw.githubusercontent.com/devfile-samples/devfile-stack-icons/main/java-maven.jpg",
Architectures: []string{
"amd64",
},
Expand Down Expand Up @@ -148,6 +150,7 @@ func TestValidateIndexComponent(t *testing.T) {
"Case 6: test happy path for for sample component with old struct",
schema.Schema{
Name: "nodejs",
Icon: "https://raw.githubusercontent.com/devfile-samples/devfile-stack-icons/main/java-maven.jpg",
Git: &schema.Git{
Remotes: map[string]string{
"origin": "https://github.com/redhat-developer/devfile-sample",
Expand Down Expand Up @@ -176,10 +179,12 @@ func TestValidateIndexComponent(t *testing.T) {
schema.SampleDevfileType,
&multipleRemotesErr,
},

{
"Case 8: check for missing arch",
schema.Schema{
Name: "nodejs",
Icon: "https://nodejs.org/static/images/logos/nodejs-new-pantone-black.svg",
Git: &schema.Git{
Remotes: map[string]string{
"origin": "https://github.com/redhat-developer/devfile-sample",
Expand All @@ -195,6 +200,7 @@ func TestValidateIndexComponent(t *testing.T) {
"Case 9: check for missing provider",
schema.Schema{
Name: "nodejs",
Icon: "https://nodejs.org/static/images/logos/nodejs-new-pantone-black.svg",
Versions: []schema.Version{
{
Version: "1.0.0",
Expand All @@ -220,6 +226,7 @@ func TestValidateIndexComponent(t *testing.T) {
"Case 10: check for missing supportUrl",
schema.Schema{
Name: "nodejs",
Icon: "https://nodejs.org/static/images/logos/nodejs-new-pantone-black.svg",
Versions: []schema.Version{
{
Version: "1.0.0",
Expand Down Expand Up @@ -354,6 +361,7 @@ func TestValidateIndexComponent(t *testing.T) {
"Case 16: test happy path for for sample component with new struct",
schema.Schema{
Name: "nodejs",
Icon: "https://nodejs.org/static/images/logos/nodejs-new-pantone-black.svg",
Versions: []schema.Version{
{
Version: "1.0.0",
Expand Down Expand Up @@ -479,6 +487,49 @@ func TestValidateIndexComponent(t *testing.T) {
schema.SampleDevfileType,
&multipleVersionErr,
},
{
"Case 21: test stack component missing iconUrl",
schema.Schema{
Name: "nodejs",
Versions: []schema.Version{
{
Version: "1.0.0",
SchemaVersion: "2.0.0",
Default: true,
Links: map[string]string{
"self": "devfile-catalog/java-maven:latest",
},
Resources: []string{
"devfile.yaml",
},
},
},
},
schema.StackDevfileType,
&iconUrlBrokenErr,
},
{
"Case 22: test stack component has wrong iconUrl",
schema.Schema{
Name: "nodejs",
Icon: "https://github.com/",
Versions: []schema.Version{
{
Version: "1.0.0",
SchemaVersion: "2.0.0",
Default: true,
Links: map[string]string{
"self": "devfile-catalog/java-maven:latest",
},
Resources: []string{
"devfile.yaml",
},
},
},
},
schema.StackDevfileType,
&iconUrlBrokenErr,
},
}

for _, tt := range tests {
Expand Down
2 changes: 1 addition & 1 deletion index/generator/tests/registry/extraDevfileEntries.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ samples:
- name: nodejs-basic
displayName: Basic NodeJS
description: A simple Hello World application
icon: nodejsIcon.svg
icon: https://nodejs.org/static/images/logos/nodejs-new-pantone-black.svg
tags: ["NodeJS", "Express"]
projectType: nodejs
language: nodejs
Expand Down
2 changes: 1 addition & 1 deletion index/generator/tests/registry/index_extra.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"NodeJS",
"Express"
],
"icon": "nodejsIcon.svg",
"icon": "https://nodejs.org/static/images/logos/nodejs-new-pantone-black.svg",
"projectType": "nodejs",
"language": "nodejs",
"versions": [
Expand Down
26 changes: 22 additions & 4 deletions index/generator/tests/registry/index_main.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"version": "1.2.0",
"schemaVersion": "2.1.0",
"description": "Stack with the latest Go version with devfile v2.1.0 schema version",
"tags": ["testtag"],
"icon": "https://raw.githubusercontent.com/devfile-samples/devfile-stack-icons/main/golang.svg",
"tags": ["testtag"],
"links": {
"self": "devfile-catalog/go:1.2.0"
},
Expand All @@ -34,8 +34,8 @@
"schemaVersion": "2.0.0",
"default": true,
"description": "Stack with the latest Go version with devfile v2.0.0 schema version",
"tags": ["Go"],
"icon": "https://raw.githubusercontent.com/devfile-samples/devfile-stack-icons/main/golang.svg",
"tags": ["Go"],
"links": {
"self": "devfile-catalog/go:1.1.0"
},
Expand All @@ -53,6 +53,7 @@
},
{
"name": "java-maven",
"icon": "https://raw.githubusercontent.com/devfile-samples/devfile-stack-icons/main/java-maven.jpg",
"displayName": "Maven Java",
"description": "Upstream Maven and OpenJDK 11",
"type": "stack",
Expand All @@ -66,6 +67,7 @@
"schemaVersion": "2.2.0",
"default": true,
"description": "Upstream Maven and OpenJDK 11",
"icon": "https://raw.githubusercontent.com/devfile-samples/devfile-stack-icons/main/java-maven.jpg",
"tags": ["Java", "Maven"],
"links": {
"self": "devfile-catalog/java-maven:1.1.0"
Expand All @@ -84,6 +86,7 @@
},
{
"name": "java-openliberty",
"icon": "https://raw.githubusercontent.com/OpenLiberty/logos/7fbb132949b9b2589e18c8d5665c1b107028a21d/logomark/svg/OL_logomark.svg",
"displayName": "Open Liberty",
"description": "Java application stack using Open Liberty runtime",
"type": "stack",
Expand All @@ -96,6 +99,7 @@
"schemaVersion": "2.2.0",
"default": true,
"description": "Java application stack using Open Liberty runtime",
"icon": "https://raw.githubusercontent.com/OpenLiberty/logos/7fbb132949b9b2589e18c8d5665c1b107028a21d/logomark/svg/OL_logomark.svg",
"links": {
"self": "devfile-catalog/java-openliberty:0.5.0"
},
Expand All @@ -113,6 +117,7 @@
},
{
"name": "java-quarkus",
"icon": "https://design.jboss.org/quarkus/logo/final/SVG/quarkus_icon_rgb_default.svg",
"displayName": "Quarkus Java",
"description": "Upstream Quarkus with Java+GraalVM",
"type": "stack",
Expand All @@ -126,6 +131,7 @@
"schemaVersion": "2.2.0",
"default": true,
"description": "Upstream Quarkus with Java+GraalVM",
"icon": "https://design.jboss.org/quarkus/logo/final/SVG/quarkus_icon_rgb_default.svg",
"tags": ["Java", "Quarkus"],
"links": {
"self": "devfile-catalog/java-quarkus:1.1.0"
Expand Down Expand Up @@ -157,8 +163,8 @@
"schemaVersion": "2.2.0",
"default": true,
"description": "Spring Boot® using Java",
"tags": ["Java", "Spring"],
"icon": "https://www.eclipse.org/che/images/logo-eclipseche.svg",
"tags": ["Java", "Spring"],
"links": {
"self": "devfile-catalog/java-springboot:1.1.0"
},
Expand All @@ -178,6 +184,7 @@
"name": "java-vertx",
"displayName": "Vert.x Java",
"description": "Upstream Vert.x using Java",
"icon": "https://raw.githubusercontent.com/vertx-web-site/vertx-logo/master/vertx-logo.svg",
"type": "stack",
"tags": ["Java", "Vert.x"],
"projectType": "vertx",
Expand All @@ -188,6 +195,7 @@
"schemaVersion": "2.2.0",
"default": true,
"description": "Upstream Vert.x using Java",
"icon": "https://raw.githubusercontent.com/vertx-web-site/vertx-logo/master/vertx-logo.svg",
"tags": ["Java", "Vert.x"],
"links": {
"self": "devfile-catalog/java-vertx:1.1.0"
Expand Down Expand Up @@ -226,6 +234,7 @@
},
{
"name": "java-wildfly",
"icon": "https://design.jboss.org/wildfly/logo/final/wildfly_logomark.svg",
"displayName": "WildFly Java",
"description": "Upstream WildFly",
"type": "stack",
Expand All @@ -238,6 +247,7 @@
"schemaVersion": "2.2.0",
"default": true,
"description": "Upstream WildFly",
"icon": "https://design.jboss.org/wildfly/logo/final/wildfly_logomark.svg",
"tags": ["Java", "WildFly"],
"links": {
"self": "devfile-catalog/java-wildfly:1.0.0"
Expand Down Expand Up @@ -265,6 +275,7 @@
},
{
"name": "java-wildfly-bootable-jar",
"icon": "https://design.jboss.org/wildfly/logo/final/wildfly_logomark.svg",
"displayName": "WildFly Bootable Jar",
"description": "Java stack with WildFly in bootable Jar mode, OpenJDK 11 and Maven 3.5",
"type": "stack",
Expand All @@ -277,6 +288,7 @@
"schemaVersion": "2.2.0",
"default": true,
"description": "Java stack with WildFly in bootable Jar mode, OpenJDK 11 and Maven 3.5",
"icon": "https://design.jboss.org/wildfly/logo/final/wildfly_logomark.svg",
"tags": [
"RHEL8",
"Java",
Expand Down Expand Up @@ -312,6 +324,7 @@
},
{
"name": "nodejs",
"icon": "https://nodejs.org/static/images/logos/nodejs-new-pantone-black.svg",
"displayName": "NodeJS Runtime",
"description": "Stack with NodeJS 12",
"type": "stack",
Expand All @@ -324,6 +337,7 @@
"schemaVersion": "2.2.0",
"default": true,
"description": "Stack with NodeJS 12",
"icon": "https://nodejs.org/static/images/logos/nodejs-new-pantone-black.svg",
"tags": ["NodeJS", "Express", "ubi8"],
"links": {
"self": "devfile-catalog/nodejs:1.0.0"
Expand All @@ -342,6 +356,7 @@
},
{
"name": "python",
"icon": "https://raw.githubusercontent.com/devfile-samples/devfile-stack-icons/main/python.svg",
"displayName": "Python",
"description": "Python Stack with Python 3.7",
"type": "stack",
Expand All @@ -354,6 +369,7 @@
"schemaVersion": "2.2.0",
"default": true,
"description": "Python Stack with Python 3.7",
"icon": "https://raw.githubusercontent.com/devfile-samples/devfile-stack-icons/main/python.svg",
"tags": ["Python", "pip"],
"links": {
"self": "devfile-catalog/python:1.0.0"
Expand All @@ -373,6 +389,7 @@
{
"name": "python-django",
"displayName": "Django",
"icon": "https://static.djangoproject.com/img/logos/django-logo-positive.svg",
"description": "Python3.7 with Django",
"type": "stack",
"tags": ["Python", "pip", "Django"],
Expand All @@ -384,6 +401,7 @@
"schemaVersion": "2.2.0",
"default": true,
"description": "Python3.7 with Django",
"icon": "https://static.djangoproject.com/img/logos/django-logo-positive.svg",
"tags": ["Python", "pip", "Django"],
"links": {
"self": "devfile-catalog/python-django:1.0.0"
Expand All @@ -406,7 +424,7 @@
"description": "A simple Hello World application",
"type": "sample",
"tags": ["NodeJS", "Express"],
"icon": "nodejsIcon.svg",
"icon": "https://nodejs.org/static/images/logos/nodejs-new-pantone-black.svg",
"projectType": "nodejs",
"language": "nodejs",
"versions": [
Expand Down
Loading