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 ability to clone private git repos #376

Merged
merged 3 commits into from
Feb 28, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Add /readme and /yaml Endpoints
- With providing support for reading private catalogs there is a need to
  serve the readme and yaml as the client of Hub API will not be able to
  access the Readme and Yaml from the git provider directly
- Clients of Hub APIs will get the copy of Readme and YAML which was
  there at the time catalog refresh was done. This will ensure that the
  same copy is made available
- The endpoints will return the string content after reading the file
  from the repo which was cloned in the target directory

Signed-off-by: vinamra28 <vinjain@redhat.com>
  • Loading branch information
vinamra28 committed Feb 25, 2022
commit 34934afc3a6fef8770ee08f712c6b676c5beb9bb
33 changes: 33 additions & 0 deletions api/design/types/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,23 @@ var Catalog = ResultType("application/vnd.hub.catalog", "Catalog", func() {
Required("id", "name", "type", "url", "provider")
})

var ResourceContent = ResultType("application/vnd.hub.resourcecontent", "ResourceContent", func() {
Attribute("readme", String, "Readme", func() {
Example("readme", "#Readme\n Sample readme content")
})
Attribute("yaml", String, "Yaml", func() {
Example("yaml", "#YAML\n Sample yaml content")
})

View("readme", func() {
Attribute("readme")
})

View("yaml", func() {
Attribute("yaml")
})
})

var ResourceVersionData = ResultType("application/vnd.hub.resource.version.data", "ResourceVersionData", func() {
Description("The Version result type describes resource's version information.")

Expand Down Expand Up @@ -426,6 +443,22 @@ var Resource = ResultType("application/vnd.hub.resource", "Resource", func() {
Required("data")
})

var ResourceVersionReadme = ResultType("application/vnd.hub.resource.version.readme", "ResourceVersionReadme", func() {
Description("README of a particular version of a Resource")
Attribute("data", ResourceContent, func() {
View("readme")
})
Required("data")
})

var ResourceVersionYaml = ResultType("application/vnd.hub.resource.version.yaml", "ResourceVersionYaml", func() {
Description("YAML of a particular version of a Resource")
Attribute("data", ResourceContent, func() {
View("yaml")
})
Required("data")
})

var CatalogErrors = Type("CatalogErrors", func() {
Description("CatalogErrors define the errors that occurred during catalog refresh")
Attribute("type", String, "Catalog Errror type", func() {
Expand Down
16 changes: 13 additions & 3 deletions api/pkg/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,22 @@ func (ab *APIBase) Service(name string) Service {
SugaredLogger: ab.logger.With(zap.String("service", name)),
}
return &BaseService{
logger: l,
db: ab.DB(),
env: ab,
logger: l,
db: ab.DB(),
env: ab,
basePath: CatalogClonePath(),
}
}

// Returns the base path where catalog is to be cloned and stored
func CatalogClonePath() string {
catalogCloneBasePath := os.Getenv("CLONE_BASE_PATH")
if catalogCloneBasePath != "" {
return catalogCloneBasePath
}
return "/tmp/catalog"
}

// Data returns Data object which consist app data from config file
func (ab *APIBase) Data() *Data {
return &ab.data
Expand Down
13 changes: 10 additions & 3 deletions api/pkg/app/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Service interface {
Logger(ctx context.Context) *log.Logger
LoggerWith(ctx context.Context, args ...interface{}) *log.Logger
DB(ctx context.Context) *gorm.DB
CatalogClonePath() string
}

type environmenter interface {
Expand All @@ -36,9 +37,10 @@ type environmenter interface {
// BaseService defines configuraition for creating logger and
// db object with http request id
type BaseService struct {
env environmenter
logger *log.Logger
db *gorm.DB
env environmenter
logger *log.Logger
db *gorm.DB
basePath string
}

// Logger looks for http request id in passed context and append it to
Expand All @@ -57,6 +59,11 @@ func (s *BaseService) LoggerWith(ctx context.Context, args ...interface{}) *log.
return &log.Logger{SugaredLogger: s.Logger(ctx).With(args...)}
}

// Returns the base path where catalog is to be cloned and stored
func (s *BaseService) CatalogClonePath() string {
return s.basePath
}

// DB gets logger initialized with http request id and creates a gorm db
// session replacing writer for gorm logger with log.Logger so that gorm log
// will have http request id.
Expand Down
18 changes: 9 additions & 9 deletions api/pkg/git/fetch_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,30 @@
package git

import (
"net/url"
"path/filepath"
"strings"
)

// FetchSpec describes how to initialize and fetch from a Git repository.
type FetchSpec struct {
URL string
SSHUrl string
Revision string
Path string
Depth uint
SSLVerify bool
URL string
SSHUrl string
Revision string
Path string
Depth uint
SSLVerify bool
CatalogName string
}

func (f *FetchSpec) sanitize() {
f.URL = strings.TrimSpace(f.URL)
f.SSHUrl = strings.TrimSpace(f.SSHUrl)
f.Path = strings.TrimSpace(f.Path)
f.Revision = strings.TrimSpace(f.Revision)
f.CatalogName = strings.TrimSpace(f.CatalogName)
}

func (f *FetchSpec) clonePath() string {
f.sanitize()
u, _ := url.Parse(f.URL)
return filepath.Join(f.Path, u.Host, u.Path+"@"+f.Revision)
return filepath.Join(f.Path, f.CatalogName)
}
2 changes: 1 addition & 1 deletion api/pkg/service/catalog/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var errorTypes = []string{
// New returns the catalog service implementation.
func New(api app.Config) catalog.Service {
svc := validator.NewService(api, "catalog")
wq := newSyncer(api)
wq := newSyncer(api, svc.CatalogClonePath())

// start running after some delay to allow for all services to mount
time.AfterFunc(3*time.Second, wq.Run)
Expand Down
2 changes: 1 addition & 1 deletion api/pkg/service/catalog/catalog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
// NewServiceTest returns the catalog service implementation for test.
func NewServiceTest(api app.Config) catalog.Service {
svc := validator.NewService(api, "catalog")
wq := newSyncer(api)
wq := newSyncer(api, "")

s := &service{
svc,
Expand Down
32 changes: 17 additions & 15 deletions api/pkg/service/catalog/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,30 +27,30 @@ import (
"gorm.io/gorm"
)

var clonePath = "/tmp/catalog"

type syncer struct {
db *gorm.DB
logger *zap.SugaredLogger
running bool
limit chan bool
stop chan bool
git git.Client
db *gorm.DB
logger *zap.SugaredLogger
running bool
limit chan bool
stop chan bool
git git.Client
clonePath string
}

var (
queued = &model.SyncJob{Status: model.JobQueued.String()}
running = &model.SyncJob{Status: model.JobRunning.String()}
)

func newSyncer(api app.BaseConfig) *syncer {
func newSyncer(api app.BaseConfig, clonePath string) *syncer {
logger := api.Logger("syncer")
return &syncer{
db: app.DBWithLogger(api.Environment(), api.DB(), logger),
logger: logger.SugaredLogger,
limit: make(chan bool, 1),
stop: make(chan bool),
git: git.New(api.Logger("git").SugaredLogger),
db: app.DBWithLogger(api.Environment(), api.DB(), logger),
logger: logger.SugaredLogger,
limit: make(chan bool, 1),
stop: make(chan bool),
git: git.New(api.Logger("git").SugaredLogger),
clonePath: clonePath,
}
}

Expand Down Expand Up @@ -170,7 +170,9 @@ func (s *syncer) Process() error {
return err
}

fetchSpec := git.FetchSpec{URL: catalog.URL, Revision: catalog.Revision, Path: clonePath, SSHUrl: catalog.SSHURL}
fmt.Println("dddd", s.clonePath)

fetchSpec := git.FetchSpec{URL: catalog.URL, Revision: catalog.Revision, Path: s.clonePath, SSHUrl: catalog.SSHURL, CatalogName: catalog.Name}
repo, err := s.git.Fetch(fetchSpec)
if err != nil {
log.Error(err, "clone failed")
Expand Down
5 changes: 5 additions & 0 deletions api/pkg/service/status/status_http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"fmt"
"io/ioutil"
"net/http"
"os"
"testing"

"github.com/ikawaha/goahttpcheck"
Expand Down Expand Up @@ -74,6 +75,10 @@ func (fs *fakeService) DB(ctx context.Context) *gorm.DB {
return fs.db
}

func (fs *fakeService) CatalogClonePath() string {
return os.Getenv("CLONE_BASE_PATH")
}

func TestOk_http(t *testing.T) {
tc := testutils.Setup(t)
testutils.LoadFixtures(t, tc.FixturePath())
Expand Down
58 changes: 58 additions & 0 deletions api/v1/design/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,64 @@ var _ = Service("resource", func() {
})
})

Method("ByCatalogKindNameVersionReadme", func() {
Description("Find resource README using name of catalog & name, kind and version of resource")
Payload(func() {
Attribute("catalog", String, "name of catalog", func() {
Example("catalog", "tektoncd")
})
Attribute("kind", String, "kind of resource", func() {
Enum("task", "pipeline")
})
Attribute("name", String, "name of resource", func() {
Example("name", "buildah")
})
Attribute("version", String, "version of resource", func() {
Example("version", "0.1")
})

Required("catalog", "kind", "name", "version")
})
Result(types.ResourceVersionReadme)
vinamra28 marked this conversation as resolved.
Show resolved Hide resolved

HTTP(func() {
GET("/resource/{catalog}/{kind}/{name}/{version}/readme")

Response(StatusOK)
Response("internal-error", StatusInternalServerError)
Response("not-found", StatusNotFound)
})
})

Method("ByCatalogKindNameVersionYaml", func() {
Description("Find resource YAML using name of catalog & name, kind and version of resource")
Payload(func() {
Attribute("catalog", String, "name of catalog", func() {
Example("catalog", "tektoncd")
})
Attribute("kind", String, "kind of resource", func() {
Enum("task", "pipeline")
})
Attribute("name", String, "name of resource", func() {
Example("name", "buildah")
})
Attribute("version", String, "version of resource", func() {
Example("version", "0.1")
})

Required("catalog", "kind", "name", "version")
})
Result(types.ResourceVersionYaml)

HTTP(func() {
GET("/resource/{catalog}/{kind}/{name}/{version}/yaml")

Response(StatusOK)
Response("internal-error", StatusInternalServerError)
Response("not-found", StatusNotFound)
})
})

Method("ByVersionId", func() {
Description("Find a resource using its version's id")
Payload(func() {
Expand Down
Loading