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

Return error for non supported development platform urls #454

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ kustomize: ## Download kustomize locally if necessary.

ENVTEST = $(shell pwd)/bin/setup-envtest
envtest: ## Download envtest-setup locally if necessary.
$(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest)
$(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@395cfc7486e652d19fe1b544a436f9852ba26e4f)

DLV = $(shell pwd)/bin/dlv
dlv:
Expand Down
14 changes: 14 additions & 0 deletions cdq-analysis/pkg/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,17 @@
}
return rawGitURL, nil
}

// ValidateGithubURL checks if the given url includes github in hostname
// In case of invalid url (not able to parse / not github) returns an error.
func ValidateGithubURL(URL string) error {
parsedURL, err := url.Parse(URL)
if err != nil {
return err
}

Check warning on line 289 in cdq-analysis/pkg/util.go

View check run for this annotation

Codecov / codecov/patch

cdq-analysis/pkg/util.go#L288-L289

Added lines #L288 - L289 were not covered by tests

if strings.Contains(parsedURL.Host, "github") {
return nil
}
return fmt.Errorf("source git url %v is not from github", URL)
}
38 changes: 38 additions & 0 deletions cdq-analysis/pkg/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,11 @@ func TestConvertGitHubURL(t *testing.T) {
url: "https://github.com/devfile/api/tree/2.1.x",
wantUrl: "https://raw.githubusercontent.com/devfile/api/2.1.x",
},
{
name: "A non github url",
url: "https://gitlab.com/",
wantUrl: "https://gitlab.com",
},
{
name: "A non url",
url: "\000x",
Expand Down Expand Up @@ -635,3 +640,36 @@ func TestUpdateGitLink(t *testing.T) {
})
}
}

func TestValidateGithubURL(t *testing.T) {
tests := []struct {
name string
sourceGitURL string
wantErr bool
}{
{
name: "Valid github url",
sourceGitURL: "https://github.com/devfile-samples",
wantErr: false,
},
{
name: "Invalid url",
sourceGitURL: "afgae devfile",
wantErr: true,
},
{
name: "Not github url",
sourceGitURL: "https://gitlab.com/devfile-samples",
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := ValidateGithubURL(tt.sourceGitURL)
if (err != nil) != tt.wantErr {
t.Errorf("TestValidateGithubURL() unexpected error: %v", err)
}
})
}
}
7 changes: 7 additions & 0 deletions controllers/component_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,13 @@ func (r *ComponentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
var devfileBytes []byte

if source.GitSource != nil && source.GitSource.URL != "" {
if err := cdqanalysis.ValidateGithubURL(source.GitSource.URL); err != nil {
// User error - the git url provided is not from github
log.Error(err, "unable to validate github url")
metrics.IncrementComponentCreationSucceeded("", "")
_ = r.SetCreateConditionAndUpdateCR(ctx, req, &component, err)
return ctrl.Result{}, nil
}
context := source.GitSource.Context
// If a Git secret was passed in, retrieve it for use in our Git operations
// The secret needs to be in the same namespace as the Component
Expand Down
86 changes: 74 additions & 12 deletions controllers/component_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,15 @@ var _ = Describe("Component controller", func() {

// Define utility constants for object names and testing timeouts/durations and intervals.
const (
HASAppName = "test-application"
HASCompName = "test-component"
HASAppNamespace = "default"
DisplayName = "petclinic"
Description = "Simple petclinic app"
ComponentName = "backend"
SampleRepoLink = "https://github.com/devfile-samples/devfile-sample-java-springboot-basic"
gitToken = "" //empty for public repo test
HASAppName = "test-application"
HASCompName = "test-component"
HASAppNamespace = "default"
DisplayName = "petclinic"
Description = "Simple petclinic app"
ComponentName = "backend"
SampleRepoLink = "https://github.com/devfile-samples/devfile-sample-java-springboot-basic"
SampleGitlabRepoLink = "https://gitlab.com/devfile-samples/devfile-sample-java-springboot-basic"
gitToken = "" //empty for public repo test
)

prometheus.MustRegister(metrics.GetComponentCreationTotalReqs(), metrics.GetComponentCreationFailed(), metrics.GetComponentCreationSucceeded())
Expand Down Expand Up @@ -1104,11 +1105,11 @@ var _ = Describe("Component controller", func() {
return len(createdHasComp.Status.Conditions) > 0
}, timeout, interval).Should(BeTrue())

// Make sure the devfile model was properly set in Component
errCondition := createdHasComp.Status.Conditions[len(createdHasComp.Status.Conditions)-1]
Expect(errCondition.Status).Should(Equal(metav1.ConditionFalse))
Expect(errCondition.Message).Should(ContainSubstring("Component create failed: unable to get default branch of Github Repo"))
// Make sure the err was set
Expect(createdHasComp.Status.Conditions[len(createdHasComp.Status.Conditions)-1].Reason).Should(Equal("Error"))
Expect(strings.ToLower(createdHasComp.Status.Conditions[len(createdHasComp.Status.Conditions)-1].Message)).Should(ContainSubstring("component create failed:"))

// Confirm user error hasn't increase the failure metrics
hasAppLookupKey := types.NamespacedName{Name: applicationName, Namespace: HASAppNamespace}

Expect(testutil.ToFloat64(metrics.GetComponentCreationTotalReqs()) > beforeCreateTotalReqs).To(BeTrue())
Expand Down Expand Up @@ -2953,6 +2954,67 @@ var _ = Describe("Component controller", func() {
// Delete the specified HASComp resource
deleteHASCompCR(hasCompLookupKey)

// Delete the specified HASApp resource
deleteHASAppCR(hasAppLookupKey)
})
})
Context("Create component having git source from gitlab", func() {
It("Should not increase the component failure metrics", func() {
beforeCreateTotalReqs := testutil.ToFloat64(metrics.GetComponentCreationTotalReqs())
beforeCreateSucceedReqs := testutil.ToFloat64(metrics.GetComponentCreationSucceeded())
beforeCreateFailedReqs := testutil.ToFloat64(metrics.GetComponentCreationFailed())

ctx := context.Background()

applicationName := HASAppName + "30"
componentName := HASCompName + "30"

createAndFetchSimpleApp(applicationName, HASAppNamespace, DisplayName, Description)

hasComp := &appstudiov1alpha1.Component{
TypeMeta: metav1.TypeMeta{
APIVersion: "appstudio.redhat.com/v1alpha1",
Kind: "Component",
},
ObjectMeta: metav1.ObjectMeta{
Name: componentName,
Namespace: HASAppNamespace,
},
Spec: appstudiov1alpha1.ComponentSpec{
ComponentName: ComponentName,
Application: applicationName,
Source: appstudiov1alpha1.ComponentSource{
ComponentSourceUnion: appstudiov1alpha1.ComponentSourceUnion{
GitSource: &appstudiov1alpha1.GitSource{
URL: SampleGitlabRepoLink,
},
},
},
},
}
Expect(k8sClient.Create(ctx, hasComp)).Should(Succeed())

// Look up the has app resource that was created.
// num(conditions) may still be < 1 on the first try, so retry until at least _some_ condition is set
hasCompLookupKey := types.NamespacedName{Name: componentName, Namespace: HASAppNamespace}
createdHasComp := &appstudiov1alpha1.Component{}
Eventually(func() bool {
k8sClient.Get(ctx, hasCompLookupKey, createdHasComp)
return len(createdHasComp.Status.Conditions) > 0
}, timeout, interval).Should(BeTrue())

// Make sure the err was set
Expect(createdHasComp.Status.Conditions[len(createdHasComp.Status.Conditions)-1].Reason).Should(Equal("Error"))
Expect(strings.ToLower(createdHasComp.Status.Conditions[len(createdHasComp.Status.Conditions)-1].Message)).Should(ContainSubstring("is not from github"))
hasAppLookupKey := types.NamespacedName{Name: applicationName, Namespace: HASAppNamespace}

Expect(testutil.ToFloat64(metrics.GetComponentCreationTotalReqs()) > beforeCreateTotalReqs).To(BeTrue())
Expect(testutil.ToFloat64(metrics.GetComponentCreationSucceeded()) > beforeCreateSucceedReqs).To(BeTrue())
Expect(testutil.ToFloat64(metrics.GetComponentCreationFailed()) == beforeCreateFailedReqs).To(BeTrue())

// Delete the specified HASComp resource
deleteHASCompCR(hasCompLookupKey)

// Delete the specified HASApp resource
deleteHASAppCR(hasAppLookupKey)
})
Expand Down
8 changes: 8 additions & 0 deletions controllers/componentdetectionquery_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ func (r *ComponentDetectionQueryReconciler) Reconcile(ctx context.Context, req c
return ctrl.Result{}, nil
}

// check if the given url is from github
if err := cdqanalysis.ValidateGithubURL(sourceURL); err != nil {
// User error - the git url provided is not from github
log.Error(err, "unable to validate github url")
r.SetCompleteConditionAndUpdateCR(ctx, req, &componentDetectionQuery, copiedCDQ, err)
return ctrl.Result{}, nil
}

cdqInfo := &cdqanalysis.CDQInfo{
DevfileRegistryURL: r.DevfileRegistryURL,
GitURL: cdqanalysis.GitURL{RepoURL: source.URL, Revision: source.Revision, Token: gitToken},
Expand Down
44 changes: 44 additions & 0 deletions controllers/componentdetectionquery_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3337,6 +3337,50 @@ metadata:
})

})
Context("Create Component Detection Query with non Github URL", func() {
It("Should err out", func() {
ctx := context.Background()

queryName := HASCompDetQuery + "21"

hasCompDetectionQuery := &appstudiov1alpha1.ComponentDetectionQuery{
TypeMeta: metav1.TypeMeta{
APIVersion: "appstudio.redhat.com/v1alpha1",
Kind: "ComponentDetectionQuery",
},
ObjectMeta: metav1.ObjectMeta{
Name: queryName,
Namespace: HASNamespace,
Annotations: map[string]string{
"runCDQAnalysisLocal": "true",
},
},
Spec: appstudiov1alpha1.ComponentDetectionQuerySpec{
GitSource: appstudiov1alpha1.GitSource{
URL: "https://gitlab.com/redhat-appstudio-appdata/sample",
Revision: "main",
},
},
}

Expect(k8sClient.Create(ctx, hasCompDetectionQuery)).Should(Succeed())

// Look up the has app resource that was created.
// num(conditions) may still be < 1 on the first try, so retry until at least _some_ condition is set
hasCompDetQueryLookupKey := types.NamespacedName{Name: queryName, Namespace: HASNamespace}
createdHasCompDetectionQuery := &appstudiov1alpha1.ComponentDetectionQuery{}
Eventually(func() bool {
k8sClient.Get(context.Background(), hasCompDetQueryLookupKey, createdHasCompDetectionQuery)
return len(createdHasCompDetectionQuery.Status.Conditions) > 1
}, timeout, interval).Should(BeTrue())

// Make sure the right err is set
Expect(createdHasCompDetectionQuery.Status.Conditions[1].Message).Should(ContainSubstring("is not from github"))

// Delete the specified Detection Query resource
deleteCompDetQueryCR(hasCompDetQueryLookupKey)
})
})

})

Expand Down
Loading