This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit fc9e085198644fa0491843fd1f066c1d810162f6
Author: lburgazzoli <[email protected]>
AuthorDate: Sat Jun 6 10:25:30 2020 +0200

    CLI - Make kamel run handle github urls that are not raw  #1497
---
 e2e/common/run_test.go | 19 +++++++++-
 go.mod                 |  1 +
 go.sum                 | 15 ++++++++
 pkg/cmd/modeline.go    |  2 +-
 pkg/cmd/run.go         | 51 +++++++++++++--------------
 pkg/cmd/util_getter.go | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 156 insertions(+), 28 deletions(-)

diff --git a/e2e/common/run_test.go b/e2e/common/run_test.go
index 391927d..77ebbbc 100644
--- a/e2e/common/run_test.go
+++ b/e2e/common/run_test.go
@@ -24,7 +24,6 @@ package common
 import (
        "testing"
 
-       . "github.com/apache/camel-k/e2e/support"
        camelv1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        . "github.com/onsi/gomega"
        v1 "k8s.io/api/core/v1"
@@ -44,6 +43,24 @@ func TestRunSimpleExamples(t *testing.T) {
                        Expect(Kamel("delete", "--all", "-n", 
ns).Execute()).Should(BeNil())
                })
 
+               t.Run("run java from GitHub", func(t *testing.T) {
+                       RegisterTestingT(t)
+                       Expect(Kamel("run", "-n", ns, 
"github:apache/camel-k/e2e/common/files/Java.java").Execute()).Should(BeNil())
+                       Eventually(IntegrationPodPhase(ns, "java"), 
TestTimeoutMedium).Should(Equal(v1.PodRunning))
+                       Eventually(IntegrationCondition(ns, "java", 
camelv1.IntegrationConditionReady), 
TestTimeoutShort).Should(Equal(v1.ConditionTrue))
+                       Eventually(IntegrationLogs(ns, "java"), 
TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
+                       Expect(Kamel("delete", "--all", "-n", 
ns).Execute()).Should(BeNil())
+               })
+
+               t.Run("run java from GitHub (RAW)", func(t *testing.T) {
+                       RegisterTestingT(t)
+                       Expect(Kamel("run", "-n", ns, 
"https://raw.githubusercontent.com/apache/camel-k/master/e2e/common/files/Java.java";).Execute()).Should(BeNil())
+                       Eventually(IntegrationPodPhase(ns, "java"), 
TestTimeoutMedium).Should(Equal(v1.PodRunning))
+                       Eventually(IntegrationCondition(ns, "java", 
camelv1.IntegrationConditionReady), 
TestTimeoutShort).Should(Equal(v1.ConditionTrue))
+                       Eventually(IntegrationLogs(ns, "java"), 
TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
+                       Expect(Kamel("delete", "--all", "-n", 
ns).Execute()).Should(BeNil())
+               })
+
                t.Run("run java with properties", func(t *testing.T) {
                        RegisterTestingT(t)
                        Expect(Kamel("run", "-n", ns, "files/Prop.java", 
"--property-file", "files/prop.properties").Execute()).Should(BeNil())
diff --git a/go.mod b/go.mod
index 4261a95..7163200 100644
--- a/go.mod
+++ b/go.mod
@@ -15,6 +15,7 @@ require (
        github.com/gertd/go-pluralize v0.1.1
        github.com/go-logr/logr v0.1.0
        github.com/google/uuid v1.1.1
+       github.com/hashicorp/go-getter v1.4.1
        github.com/jpillora/backoff v1.0.0
        github.com/magiconair/properties v1.8.1
        github.com/mitchellh/go-homedir v1.1.0
diff --git a/go.sum b/go.sum
index 7aa83dc..c5771d7 100644
--- a/go.sum
+++ b/go.sum
@@ -17,6 +17,7 @@ cloud.google.com/go/bigquery v1.3.0/go.mod 
h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNF
 cloud.google.com/go/datastore v1.0.0/go.mod 
h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
 cloud.google.com/go/pubsub v1.0.1/go.mod 
h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
 cloud.google.com/go/storage v1.0.0/go.mod 
h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.3.0 
h1:2Ze/3nQD5F+HfL0xOPM2EeawDWs+NPRtzgcre+17iZU=
 cloud.google.com/go/storage v1.3.0/go.mod 
h1:9IAwXhoyBJ7z9LcAwkj0/7NnPzYaPeZxxVp3zm+5IqA=
 contrib.go.opencensus.io/exporter/ocagent v0.6.0 
h1:Z1n6UAyr0QwM284yUuh5Zd8JlvxUGAhFZcgMJkMPrGM=
 contrib.go.opencensus.io/exporter/ocagent v0.6.0/go.mod 
h1:zmKjrJcdo0aYcVS7bmEeSEBLPA9YJp5bjrofdU3pIXs=
@@ -121,6 +122,7 @@ github.com/asaskevich/govalidator 
v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:l
 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod 
h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod 
h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
 github.com/aws/aws-sdk-go v1.15.11/go.mod 
h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
+github.com/aws/aws-sdk-go v1.15.78/go.mod 
h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
 github.com/aws/aws-sdk-go v1.16.26/go.mod 
h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
 github.com/aws/aws-sdk-go v1.17.7/go.mod 
h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
 github.com/aws/aws-sdk-go v1.23.20 
h1:2CBuL21P0yKdZN5urf2NxKa1ha8fhnY+A3pBCHFeZoA=
@@ -135,6 +137,8 @@ github.com/beorn7/perks v1.0.0 
h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
 github.com/beorn7/perks v1.0.0/go.mod 
h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod 
h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d 
h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
+github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod 
h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
 github.com/bgentry/speakeasy v0.1.0/go.mod 
h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod 
h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
 github.com/bitly/go-simplejson v0.5.0/go.mod 
h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
@@ -163,6 +167,7 @@ github.com/cespare/xxhash/v2 v2.1.0/go.mod 
h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tj
 github.com/cespare/xxhash/v2 v2.1.1 
h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod 
h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod 
h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
+github.com/cheggaaa/pb v1.0.27/go.mod 
h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
 github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod 
h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
 github.com/circonus-labs/circonusllhist v0.1.3/go.mod 
h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
 github.com/client9/misspell v0.3.4/go.mod 
h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -486,7 +491,10 @@ github.com/hashicorp/consul/sdk v0.3.0/go.mod 
h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyN
 github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod 
h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/errwrap v1.0.0/go.mod 
h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/go-cleanhttp v0.5.0/go.mod 
h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-cleanhttp v0.5.1 
h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
 github.com/hashicorp/go-cleanhttp v0.5.1/go.mod 
h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-getter v1.4.1 
h1:3A2Mh8smGFcf5M+gmcv898mZdrxpseik45IpcyISLsA=
+github.com/hashicorp/go-getter v1.4.1/go.mod 
h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY=
 github.com/hashicorp/go-immutable-radix v1.0.0/go.mod 
h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
 github.com/hashicorp/go-immutable-radix v1.1.0/go.mod 
h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
 github.com/hashicorp/go-msgpack v0.5.3/go.mod 
h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
@@ -496,11 +504,14 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod 
h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh
 github.com/hashicorp/go-retryablehttp v0.5.3/go.mod 
h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
 github.com/hashicorp/go-rootcerts v1.0.0/go.mod 
h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
 github.com/hashicorp/go-rootcerts v1.0.1/go.mod 
h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
+github.com/hashicorp/go-safetemp v1.0.0 
h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
+github.com/hashicorp/go-safetemp v1.0.0/go.mod 
h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
 github.com/hashicorp/go-sockaddr v1.0.0/go.mod 
h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
 github.com/hashicorp/go-sockaddr v1.0.2/go.mod 
h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
 github.com/hashicorp/go-syslog v1.0.0/go.mod 
h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
 github.com/hashicorp/go-uuid v1.0.0/go.mod 
h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
 github.com/hashicorp/go-uuid v1.0.1/go.mod 
h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-version v1.1.0 
h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
 github.com/hashicorp/go-version v1.1.0/go.mod 
h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
 github.com/hashicorp/go.net v0.0.1/go.mod 
h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
 github.com/hashicorp/golang-lru v0.5.0/go.mod 
h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@@ -634,6 +645,7 @@ github.com/mitchellh/copystructure v1.0.0/go.mod 
h1:SNtv71yrdKgLRyLFxmLdkAbkKEFW
 github.com/mitchellh/go-homedir v1.0.0/go.mod 
h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-homedir v1.1.0 
h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
 github.com/mitchellh/go-homedir v1.1.0/go.mod 
h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-testing-interface v1.0.0 
h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
 github.com/mitchellh/go-testing-interface v1.0.0/go.mod 
h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
 github.com/mitchellh/go-wordwrap v1.0.0/go.mod 
h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
 github.com/mitchellh/gox v0.4.0/go.mod 
h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
@@ -909,6 +921,8 @@ github.com/uber/jaeger-client-go 
v2.20.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMW
 github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod 
h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
 github.com/ugorji/go v1.1.4/go.mod 
h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod 
h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
+github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
+github.com/ulikunitz/xz v0.5.5/go.mod 
h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
 github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod 
h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 github.com/urfave/cli v1.20.0/go.mod 
h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 github.com/vdemeester/k8s-pkg-credentialprovider v1.17.4/go.mod 
h1:inCTmtUdr5KJbreVojo06krnTgaeAz/Z7lynpPk/Q2c=
@@ -1256,6 +1270,7 @@ gopkg.in/check.v1 
v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 
h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod 
h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
+gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod 
h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod 
h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
diff --git a/pkg/cmd/modeline.go b/pkg/cmd/modeline.go
index 3a4f321..7d6a848 100644
--- a/pkg/cmd/modeline.go
+++ b/pkg/cmd/modeline.go
@@ -116,7 +116,7 @@ func createKamelWithModelineCommand(ctx context.Context, 
args []string, processe
                        return nil, nil, errors.Wrapf(err, "cannot process file 
%s", f)
                }
                for i, o := range ops {
-                       if fileOptions[o.Name] && !isRemoteHTTPFile(f) {
+                       if fileOptions[o.Name] && isLocal(f) {
                                refPath := o.Value
                                if !filepath.IsAbs(refPath) {
                                        full := path.Join(baseDir, refPath)
diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go
index 31869d3..90f545d 100644
--- a/pkg/cmd/run.go
+++ b/pkg/cmd/run.go
@@ -23,13 +23,12 @@ import (
        "fmt"
 
        "io/ioutil"
-       "net/http"
+       "net/url"
        "os"
        "os/signal"
        "path"
        "reflect"
        "regexp"
-       "strconv"
        "strings"
        "syscall"
 
@@ -202,24 +201,17 @@ func (o *runCmdOptions) validateArgs(_ *cobra.Command, 
args []string) error {
                return errors.New("run expects at least 1 argument, received 0")
        }
 
-       for _, fileName := range args {
-               if !isRemoteHTTPFile(fileName) {
-                       if _, err := os.Stat(fileName); err != nil && 
os.IsNotExist(err) {
-                               return errors.Wrap(err, "file "+fileName+" does 
not exist")
+       for _, source := range args {
+               if isLocal(source) {
+                       if _, err := os.Stat(source); err != nil && 
os.IsNotExist(err) {
+                               return errors.Wrapf(err, "file %s does not 
exist", source)
                        } else if err != nil {
-                               return errors.Wrap(err, "error while accessing 
file "+fileName)
+                               return errors.Wrapf(err, "error while accessing 
file %s", source)
                        }
                } else {
-                       // nolint: gosec
-                       resp, err := http.Get(fileName)
-                       if resp != nil && resp.Body != nil {
-                               _ = resp.Body.Close()
-                       }
-
+                       _, err := loadData(source, false)
                        if err != nil {
-                               return errors.Wrap(err, "The URL provided is 
not reachable")
-                       } else if resp.StatusCode != 200 {
-                               return errors.New("The URL provided is not 
reachable " + fileName + " The error code returned is " + 
strconv.Itoa(resp.StatusCode))
+                               return errors.Wrap(err, "The provided source is 
not reachable")
                        }
                }
        }
@@ -401,7 +393,7 @@ func (o *runCmdOptions) syncIntegration(c client.Client, 
sources []string) error
        files = append(files, o.OpenAPIs...)
 
        for _, s := range files {
-               if !isRemoteHTTPFile(s) {
+               if isLocal(s) {
                        changes, err := sync.File(o.Context, s)
                        if err != nil {
                                return err
@@ -638,24 +630,27 @@ func (o *runCmdOptions) GetIntegrationName(sources 
[]string) string {
        return name
 }
 
-func loadData(fileName string, compress bool) (string, error) {
+func loadData(source string, compress bool) (string, error) {
        var content []byte
        var err error
 
-       if !isRemoteHTTPFile(fileName) {
-               content, err = ioutil.ReadFile(fileName)
+       if isLocal(source) {
+               content, err = ioutil.ReadFile(source)
                if err != nil {
                        return "", err
                }
        } else {
-               /* #nosec */
-               resp, err := http.Get(fileName)
+               u, err := url.Parse(source)
                if err != nil {
                        return "", err
                }
-               defer resp.Body.Close()
 
-               content, err = ioutil.ReadAll(resp.Body)
+               g, ok := Getters[u.Scheme]
+               if !ok {
+                       return "", fmt.Errorf("unable to find a getter for URL: 
%s", source)
+               }
+
+               content, err = g.Get(u)
                if err != nil {
                        return "", err
                }
@@ -709,8 +704,12 @@ func (*runCmdOptions) configureTrait(integration 
*v1.Integration, config string)
        return nil
 }
 
-func isRemoteHTTPFile(fileName string) bool {
-       return strings.HasPrefix(fileName, "http://";) || 
strings.HasPrefix(fileName, "https://";)
+func isLocal(fileName string) bool {
+       info, err := os.Stat(fileName)
+       if os.IsNotExist(err) {
+               return false
+       }
+       return !info.IsDir()
 }
 
 func addPropertyFile(fileName string, spec *v1.IntegrationSpec) error {
diff --git a/pkg/cmd/util_getter.go b/pkg/cmd/util_getter.go
new file mode 100644
index 0000000..f472396
--- /dev/null
+++ b/pkg/cmd/util_getter.go
@@ -0,0 +1,96 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package cmd
+
+import (
+       "fmt"
+       "io/ioutil"
+       "net/http"
+       "net/url"
+       "regexp"
+)
+
+var Getters map[string]Getter
+
+func init() {
+       Getters = map[string]Getter{
+               "http":   HttpGetter{},
+               "https":  HttpGetter{},
+               "github": GitHubGetter{},
+       }
+}
+
+type Getter interface {
+       Get(u *url.URL) ([]byte, error)
+}
+
+// A simple getter that retrieves the content of an integration from an
+// http(s) endpoint.
+type HttpGetter struct {
+}
+
+func (g HttpGetter) Get(u *url.URL) ([]byte, error) {
+       return g.doGet(u.String())
+}
+
+func (g HttpGetter) doGet(source string) ([]byte, error) {
+       // nolint: gosec
+       resp, err := http.Get(source)
+       if err != nil {
+               return []byte{}, err
+       }
+       defer func() {
+               _ = resp.Body.Close()
+       }()
+
+       if resp.StatusCode != 200 {
+               return []byte{}, fmt.Errorf("the provided URL %s is not 
reachable, error code is %d", source, resp.StatusCode)
+       }
+
+       content, err := ioutil.ReadAll(resp.Body)
+       if err != nil {
+               return []byte{}, err
+       }
+
+       return content, nil
+}
+
+// A simple getter that retrieves the content of an integration from
+// a GitHub endpoint using a RAW endpoint.
+type GitHubGetter struct {
+       HttpGetter
+}
+
+func (g GitHubGetter) Get(u *url.URL) ([]byte, error) {
+       src := u.Scheme + ":" + u.Opaque
+       re := regexp.MustCompile(`^github:([^/]+)/([^/]+)/(.+)$`)
+
+       items := re.FindStringSubmatch(src)
+       if len(items) != 4 {
+               return []byte{}, fmt.Errorf("malformed github url: %s", src)
+       }
+
+       branch := u.Query().Get("branch")
+       if branch == "" {
+               branch = "master"
+       }
+
+       srcURL := fmt.Sprintf("https://raw.githubusercontent.com/%s/%s/%s/%s";, 
items[1], items[2], branch, items[3])
+
+       return g.HttpGetter.doGet(srcURL)
+}

Reply via email to