From 2d1430478be6abc1812c3232035eea90f5e39db7 Mon Sep 17 00:00:00 2001 From: jakobmoellerdev Date: Tue, 3 Dec 2024 10:45:05 +0100 Subject: [PATCH] fix: setup jfrog plugin --- .github/workflows/components.yaml | 2 +- .../handlers/generic/http/blobhandler.go | 105 --------------- .../generic/http/identity/identity.go | 74 ---------- .../handlers/generic/http/registration.go | 84 ------------ api/ocm/plugin/ppi/cmds/upload/put/cmd.go | 10 ++ cmds/jfrogplugin/uploaders/helm.go | 90 +++++++++---- components/jfrogplugin/Makefile | 127 ++++++++++++++++++ components/jfrogplugin/bindings.yaml | 4 + .../jfrogplugin/component-constructor.yaml | 23 ++++ components/jfrogplugin/sources.yaml | 7 + 10 files changed, 237 insertions(+), 289 deletions(-) delete mode 100644 api/ocm/extensions/blobhandler/handlers/generic/http/blobhandler.go delete mode 100644 api/ocm/extensions/blobhandler/handlers/generic/http/identity/identity.go delete mode 100644 api/ocm/extensions/blobhandler/handlers/generic/http/registration.go create mode 100644 components/jfrogplugin/Makefile create mode 100644 components/jfrogplugin/bindings.yaml create mode 100644 components/jfrogplugin/component-constructor.yaml create mode 100644 components/jfrogplugin/sources.yaml diff --git a/.github/workflows/components.yaml b/.github/workflows/components.yaml index c519473c20..16c18e956e 100644 --- a/.github/workflows/components.yaml +++ b/.github/workflows/components.yaml @@ -30,7 +30,7 @@ permissions: env: REF: ${{ inputs.ref == '' && github.ref || inputs.ref }} CTF_TYPE: directory - components: '["ocmcli", "helminstaller", "helmdemo", "subchartsdemo", "ecrplugin"]' + components: '["ocmcli", "helminstaller", "helmdemo", "subchartsdemo", "ecrplugin", "jfrogplugin"]' IMAGE_PLATFORMS: 'linux/amd64 linux/arm64' PLATFORMS: 'windows/amd64 darwin/arm64 darwin/amd64 linux/amd64 linux/arm64' diff --git a/api/ocm/extensions/blobhandler/handlers/generic/http/blobhandler.go b/api/ocm/extensions/blobhandler/handlers/generic/http/blobhandler.go deleted file mode 100644 index 046eb65ead..0000000000 --- a/api/ocm/extensions/blobhandler/handlers/generic/http/blobhandler.go +++ /dev/null @@ -1,105 +0,0 @@ -package maven - -import ( - "bytes" - "context" - "errors" - "fmt" - "net/http" - "net/url" - "text/template" - - "github.com/google/go-containerregistry/pkg/v1/remote" - mlog "github.com/mandelsoft/logging" - - "ocm.software/ocm/api/ocm/cpi" - "ocm.software/ocm/api/ocm/extensions/accessmethods/helm" - resourcetypes "ocm.software/ocm/api/ocm/extensions/artifacttypes" - "ocm.software/ocm/api/ocm/extensions/blobhandler/handlers/generic/http/identity" - "ocm.software/ocm/api/utils" - "ocm.software/ocm/api/utils/logging" -) - -const REALM = "http" - -const BlobHandlerName = "ocm/" + "http" - -type artifactHandler struct { - spec *Config -} - -func NewArtifactHandler(repospec *Config) cpi.BlobHandler { - return &artifactHandler{spec: repospec} -} - -// blob => http.Request => http.Response => cpi.AccessSpec (HelmAccess, WgetAccess, etc.) -func (b *artifactHandler) StoreBlob(blob cpi.BlobAccess, resourceType string, hint string, _ cpi.AccessSpec, ctx cpi.StorageContext) (_ cpi.AccessSpec, rerr error) { - remote, err := b.URL(ctx, blob) - if err != nil { - return nil, fmt.Errorf("failed to get remote for blob: %w", err) - } - data, err := blob.Reader() - if err != nil { - return nil, fmt.Errorf("failed to read blob: %w", err) - } - defer func() { - rerr = errors.Join(rerr, data.Close()) - }() - - rawURL := remote.String() - - req, err := http.NewRequestWithContext(context.TODO(), b.spec.Method, rawURL, data) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - creds := identity.GetCredentials(ctx.GetContext(), rawURL) - user, pass := creds[identity.ATTR_USERNAME], creds[identity.ATTR_PASSWORD] - if user != "" && pass != "" { - req.SetBasicAuth(creds["username"], creds["password"]) - } - - client := Client(b.spec) - client.Transport = logging.NewRoundTripper(client.Transport, logging.DynamicLogger(ctx, REALM, - mlog.NewAttribute(logging.ATTR_HOST, remote.Host), - mlog.NewAttribute(logging.ATTR_PATH, remote.Path), - mlog.NewAttribute(logging.ATTR_USER, user), - )) - - response, err := client.Do(req) - if err != nil { - return nil, fmt.Errorf("failed to store blob via request: %w", err) - } - - //TODO: replace with registry based mapping so we dont have to bind the api here - switch resourceType { - case resourcetypes.HELM_CHART: - return helm.New("demoapp", "https://int.repositories.cloud.sap/artifactory/api/helm/ocm-helm-test"), nil - } - - return nil, errors.New("not implemented") -} - -func (h *artifactHandler) URL(ctx cpi.StorageContext, blob cpi.BlobAccess) (*url.URL, error) { - tpl, err := template.New("").Parse(h.spec.RepositoryURL) - if err != nil { - return nil, fmt.Errorf("failed to parse url template: %w", err) - } - var buf bytes.Buffer - err = tpl.Execute(&buf, map[string]string{ - "mimeType": blob.MimeType(), - "size": fmt.Sprintf("%d", blob.Size()), - "digest": string(blob.Digest()), - "component": ctx.TargetComponentName(), - }) - if err != nil { - return nil, fmt.Errorf("failed to execute url template: %w", err) - } - return utils.ParseURL(buf.String()) -} - -func Client(_ *Config) *http.Client { - return &http.Client{ - Transport: remote.DefaultTransport, - } -} diff --git a/api/ocm/extensions/blobhandler/handlers/generic/http/identity/identity.go b/api/ocm/extensions/blobhandler/handlers/generic/http/identity/identity.go deleted file mode 100644 index 9504a1009b..0000000000 --- a/api/ocm/extensions/blobhandler/handlers/generic/http/identity/identity.go +++ /dev/null @@ -1,74 +0,0 @@ -package identity - -import ( - "ocm.software/ocm/api/credentials/cpi" - "ocm.software/ocm/api/credentials/identity/hostpath" - "ocm.software/ocm/api/utils/listformat" - common "ocm.software/ocm/api/utils/misc" -) - -// CONSUMER_TYPE is the Helm chart repository type. -const CONSUMER_TYPE = "HTTPUploader" - -// ID_TYPE is the type field of a consumer identity. -const ID_TYPE = cpi.ID_TYPE - -// ID_SCHEME is the scheme of the repository. -const ID_SCHEME = hostpath.ID_SCHEME - -// ID_HOSTNAME is the hostname of a repository. -const ID_HOSTNAME = hostpath.ID_HOSTNAME - -// ID_PORT is the port number of a repository. -const ID_PORT = hostpath.ID_PORT - -// ID_PATHPREFIX is the path of a repository. -const ID_PATHPREFIX = hostpath.ID_PATHPREFIX - -func init() { - attrs := listformat.FormatListElements("", listformat.StringElementDescriptionList{ - ATTR_USERNAME, "the basic auth user name", - ATTR_PASSWORD, "the basic auth password", - ATTR_CERTIFICATE, "TLS client certificate", - ATTR_PRIVATE_KEY, "TLS private key", - ATTR_CERTIFICATE_AUTHORITY, "TLS certificate authority", - }) - - cpi.RegisterStandardIdentity(CONSUMER_TYPE, IdentityMatcher, `HTTPUploader - -It matches the `+CONSUMER_TYPE+` consumer type and additionally acts like -the `+hostpath.IDENTITY_TYPE+` type.`, - attrs) -} - -var identityMatcher = hostpath.IdentityMatcher("") - -func IdentityMatcher(pattern, cur, id cpi.ConsumerIdentity) bool { - return identityMatcher(pattern, cur, id) -} - -// used credential attributes - -const ( - ATTR_USERNAME = cpi.ATTR_USERNAME - ATTR_PASSWORD = cpi.ATTR_PASSWORD - ATTR_CERTIFICATE_AUTHORITY = cpi.ATTR_CERTIFICATE_AUTHORITY - ATTR_CERTIFICATE = cpi.ATTR_CERTIFICATE - ATTR_PRIVATE_KEY = cpi.ATTR_PRIVATE_KEY - ATTR_TOKEN = cpi.ATTR_TOKEN -) - -func GetCredentials(ctx cpi.ContextProvider, consumerType string, url string) common.Properties { - if consumerType == "" { - consumerType = CONSUMER_TYPE - } - id := hostpath.GetConsumerIdentity(consumerType, url) - if id == nil { - return nil - } - creds, err := cpi.CredentialsForConsumer(ctx.CredentialsContext(), id) - if creds == nil || err != nil { - return nil - } - return creds.Properties() -} diff --git a/api/ocm/extensions/blobhandler/handlers/generic/http/registration.go b/api/ocm/extensions/blobhandler/handlers/generic/http/registration.go deleted file mode 100644 index ec69d82554..0000000000 --- a/api/ocm/extensions/blobhandler/handlers/generic/http/registration.go +++ /dev/null @@ -1,84 +0,0 @@ -package maven - -import ( - "encoding/json" - "fmt" - - "github.com/mandelsoft/goutils/errors" - - "ocm.software/ocm/api/ocm/cpi" - resourcetypes "ocm.software/ocm/api/ocm/extensions/artifacttypes" - "ocm.software/ocm/api/utils/mime" - "ocm.software/ocm/api/utils/registrations" -) - -func init() { - cpi.RegisterBlobHandlerRegistrationHandler(BlobHandlerName, &RegistrationHandler{}) -} - -type Config struct { - RepositoryURL string `json:"url"` - Path string `json:"path"` - Method string `json:"method"` - Credentials CredentialsConfig `json:"credentials"` -} - -type CredentialsConfig struct { - Method string `json:"method"` -} - -type rawConfig Config - -func (c *Config) UnmarshalJSON(data []byte) error { - err := json.Unmarshal(data, &c.RepositoryURL) - if err == nil { - return nil - } - var raw rawConfig - err = json.Unmarshal(data, &raw) - if err != nil { - return err - } - *c = Config(raw) - - return nil -} - -type RegistrationHandler struct{} - -var _ cpi.BlobHandlerRegistrationHandler = (*RegistrationHandler)(nil) - -func (r *RegistrationHandler) RegisterByName(handler string, ctx cpi.Context, config cpi.BlobHandlerConfig, olist ...cpi.BlobHandlerOption) (bool, error) { - if handler != "" { - return true, fmt.Errorf("invalid %s handler %q", resourcetypes.HELM_CHART, handler) - } - if config == nil { - return true, fmt.Errorf("http repository specification required") - } - cfg, err := registrations.DecodeConfig[Config](config) - if err != nil { - return true, errors.Wrapf(err, "blob handler configuration") - } - - ctx.BlobHandlers().Register(NewArtifactHandler(cfg), - cpi.ForArtifactType(resourcetypes.HELM_CHART), - cpi.ForArtifactType(resourcetypes.BLOB), - cpi.ForMimeType(mime.MIME_TGZ), - cpi.ForMimeType(mime.MIME_TGZ_ALT), - cpi.NewBlobHandlerOptions(olist...), - ) - - return true, nil -} - -func (r *RegistrationHandler) GetHandlers(_ cpi.Context) registrations.HandlerInfos { - return registrations.NewLeafHandlerInfo("uploading http charts to http repositories", ` -The `+BlobHandlerName+` uploader is able to upload artifacts to an arbitrary http path. -If registered the default mime type is: `+mime.MIME_TGZ+` and `+mime.MIME_TGZ_ALT+`. - -It accepts a plain string for the URL and a config with the following field: -'url': the URL of the http server to request. -'method': the HTTP Method to use for the request for an individual artifact. -'' -`) -} diff --git a/api/ocm/plugin/ppi/cmds/upload/put/cmd.go b/api/ocm/plugin/ppi/cmds/upload/put/cmd.go index b679d7a797..4d5489b9a1 100644 --- a/api/ocm/plugin/ppi/cmds/upload/put/cmd.go +++ b/api/ocm/plugin/ppi/cmds/upload/put/cmd.go @@ -87,7 +87,17 @@ func Command(p ppi.Plugin, cmd *cobra.Command, opts *Options) error { if u == nil { return errors.ErrNotFound(descriptor.KIND_UPLOADER, fmt.Sprintf("%s:%s", opts.ArtifactType, opts.MediaType)) } + + fi, err := os.Stdin.Stat() + if err != nil { + fmt.Println("failed to stat stdin", err) + } + if size := fi.Size(); size == 0 { + return fmt.Errorf("stdin is empty, and nothing can be uploaded") + } + h, err := u.Upload(p, opts.ArtifactType, opts.MediaType, opts.Hint, spec, opts.Credentials, os.Stdin) + if err != nil { return fmt.Errorf("upload failed: %w", err) } diff --git a/cmds/jfrogplugin/uploaders/helm.go b/cmds/jfrogplugin/uploaders/helm.go index 03b7df4ae9..2698987d3d 100644 --- a/cmds/jfrogplugin/uploaders/helm.go +++ b/cmds/jfrogplugin/uploaders/helm.go @@ -1,6 +1,7 @@ package uploaders import ( + "context" "encoding/json" "fmt" "io" @@ -8,8 +9,9 @@ import ( "net/url" "path" "strings" + "time" - "github.com/mandelsoft/goutils/errors" + "github.com/containerd/containerd/reference" "ocm.software/ocm/api/credentials" "ocm.software/ocm/api/credentials/cpi" @@ -21,7 +23,7 @@ import ( ) const ( - NAME = "JFrog" + NAME = "JFrogHelm" VERSION = "v1" ID_HOSTNAME = hostpath.ID_HOSTNAME @@ -35,9 +37,8 @@ type Config struct { func GetConfig(raw json.RawMessage) (interface{}, error) { var cfg Config - err := json.Unmarshal(raw, &cfg) - if err != nil { - return nil, err + if err := json.Unmarshal(raw, &cfg); err != nil { + return nil, fmt.Errorf("could not get config: %w", err) } return &cfg, nil } @@ -47,7 +48,6 @@ type HelmTargetSpec struct { // URL is the hostname of the JFrog instance URL string `json:"url"` - url *url.URL // Repository is the repository to upload to Repository string `json:"repository"` @@ -83,49 +83,66 @@ func (a *Uploader) Decoders() ppi.UploadFormats { return types } -func (a *Uploader) ValidateSpecification(_ ppi.Plugin, spec ppi.UploadTargetSpec) (*ppi.UploadTargetSpecInfo, error) { +func (a *Uploader) ValidateSpecification(p ppi.Plugin, spec ppi.UploadTargetSpec) (*ppi.UploadTargetSpecInfo, error) { var info ppi.UploadTargetSpecInfo my, ok := spec.(*HelmTargetSpec) if !ok { return nil, fmt.Errorf("invalid spec type %T", spec) } - var err error - if my.url, err = url.Parse(my.URL); err != nil { - return nil, fmt.Errorf("invalid URL: %w", err) + purl, err := ParseURL(my.URL) + if err != nil { + return nil, fmt.Errorf("failed to parse URL: %w", err) } info.ConsumerId = credentials.ConsumerIdentity{ cpi.ID_TYPE: NAME, - ID_HOSTNAME: my.url.Hostname(), - ID_PORT: my.url.Port(), + ID_HOSTNAME: purl.Hostname(), ID_REPOSITORY: my.Repository, } + if purl.Port() != "" { + info.ConsumerId.SetNonEmptyValue(ID_PORT, purl.Port()) + } + return &info, nil } -func (a *Uploader) Upload(p ppi.Plugin, artifactType, mediatype, _ string, repo ppi.UploadTargetSpec, creds credentials.Credentials, reader io.Reader) (ppi.AccessSpecProvider, error) { - cfg, err := p.GetConfig() - if err != nil { - return nil, errors.Wrapf(err, "can't get config for access method %s", mediatype) - } - +func (a *Uploader) Upload(_ ppi.Plugin, artifactType, _, hint string, repo ppi.UploadTargetSpec, creds credentials.Credentials, reader io.Reader) (ppi.AccessSpecProvider, error) { if artifactType != artifacttypes.HELM_CHART { return nil, fmt.Errorf("unsupported artifact type %s", artifactType) } - if cfg != nil { - _, ok := cfg.(Config) - if !ok { - return nil, fmt.Errorf("invalid config type %T", cfg) + my := repo.(*HelmTargetSpec) + + if refFromHint, err := reference.Parse(hint); err == nil { + if refFromHint.Digest() != "" && refFromHint.Object == "" { + return nil, fmt.Errorf("the hint contained a valid reference but it was a digest, so it cannot be used to deduce a version of the helm chart: %s", refFromHint) } + my.ChartVersion = refFromHint.Object + my.ChartName = path.Base(refFromHint.Locator) } - my := repo.(*HelmTargetSpec) + if my.ChartName == "" { + return nil, fmt.Errorf("the chart name could not be deduced from the hint (%s) or the config (%s)", hint, my) + } + if my.ChartVersion == "" { + return nil, fmt.Errorf("the chart version could not be deduced from the hint (%s) or the config (%s)", hint, my) + } + + requestURL := path.Join(my.URL, "artifactory", my.Repository, fmt.Sprintf("%s-%s.tgz", my.ChartName, my.ChartVersion)) - requestURL := path.Join(my.url.String(), "artifactory", my.Repository, fmt.Sprintf("%s-%s.tgz", my.ChartName, my.ChartVersion)) + requestURLParsed, err := ParseURL(requestURL) + if err != nil { + return nil, fmt.Errorf("failed to parse full request URL: %w", err) + } + if requestURLParsed.Scheme == "" { + requestURLParsed.Scheme = "https" + } + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() - req, err := http.NewRequest(http.MethodPost, requestURL, reader) + req, err := http.NewRequestWithContext(ctx, http.MethodPut, requestURLParsed.String(), reader) if err != nil { return nil, err } @@ -151,6 +168,14 @@ func (a *Uploader) Upload(p ppi.Plugin, artifactType, mediatype, _ string, repo } defer response.Body.Close() + if 200 > response.StatusCode || response.StatusCode >= 300 { + var body string + if d, err := io.ReadAll(response.Body); err == nil && len(d) > 0 { + body = fmt.Sprintf(": %s", string(d)) + } + return nil, fmt.Errorf("invalid response (status %v)%s", response.StatusCode, body) + } + uploadResponse := &ArtifactoryUploadResponse{} if err := json.NewDecoder(response.Body).Decode(uploadResponse); err != nil { return nil, fmt.Errorf("failed to decode response: %w", err) @@ -207,3 +232,18 @@ func (r *ArtifactoryUploadResponse) ToHelmAccessSpec() (ppi.AccessSpec, error) { return helm.New(chart, repo), nil } + +func ParseURL(urlToParse string) (*url.URL, error) { + const dummyScheme = "dummy" + if !strings.Contains(urlToParse, "://") { + urlToParse = dummyScheme + "://" + urlToParse + } + parsedURL, err := url.Parse(urlToParse) + if err != nil { + return nil, err + } + if parsedURL.Scheme == dummyScheme { + parsedURL.Scheme = "" + } + return parsedURL, nil +} diff --git a/components/jfrogplugin/Makefile b/components/jfrogplugin/Makefile new file mode 100644 index 0000000000..ef51b171e2 --- /dev/null +++ b/components/jfrogplugin/Makefile @@ -0,0 +1,127 @@ +NAME = jfrogplugin +PROVIDER ?= ocm.software +GITHUBORG ?= open-component-model +COMPONENT = $(PROVIDER)/plugins/$(NAME) +OCMREPO ?= ghcr.io/$(GITHUBORG)/ocm +PLATFORMS ?= linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 +CTF_TYPE ?= directory + + +REPO_ROOT := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))/../.. +ifeq ($(VERSION),) +VERSION := $(shell go run ../../api/version/generate/release_generate.go print-rc-version $(CANDIDATE)) +endif +COMMIT = $(shell git rev-parse --verify HEAD) +# if EFFECTIVE_VERSION is not set, set it to VERSION+COMMIT +# this is not the same as '?=' because it will also set the value if EFFECTIVE_VERSION is set to an empty string +ifeq ($(EFFECTIVE_VERSION),) +EFFECTIVE_VERSION := $(VERSION)+$(COMMIT) +endif +GIT_TREE_STATE := $(shell [ -z "$$(git status --porcelain 2>/dev/null)" ] && echo clean || echo dirty) + +CMDSRCS=$(shell find $(REPO_ROOT)/cmds/$(NAME) -type f) +OCMSRCS=$(shell find $(REPO_ROOT)/api -type f) $(REPO_ROOT)/go.* + +CREDS ?= +# Define the path to the binary +OCM_BIN = $(REPO_ROOT)/bin/ocm + +# Rule to build the binary if it doesn't exist or if the source code has changed +$(OCM_BIN): $(REPO_ROOT)/cmds/ocm/main.go + mkdir -p $(REPO_ROOT)/bin + go build -ldflags $(BUILD_FLAGS) -o $(OCM_BIN) $(REPO_ROOT)/cmds/ocm + +# Use the binary for the OCM command +OCM = $(OCM_BIN) $(CREDS) + +GEN = $(REPO_ROOT)/gen/$(NAME) + + $(GEN): + @mkdir -p $(GEN) + +NOW := $(shell date -u +%FT%T%z) +BUILD_FLAGS := "-s -w \ + -X ocm.software/ocm/api/version.gitVersion=$(EFFECTIVE_VERSION) \ + -X ocm.software/ocm/api/version.gitTreeState=$(GIT_TREE_STATE) \ + -X ocm.software/ocm/api/version.gitCommit=$(COMMIT) \ + -X ocm.software/ocm/api/version.buildDate=$(NOW)" + +.PHONY: build +build: $(GEN)/build + +$(GEN)/build: $(GEN) $(CMDSRCS) $(OCMSRCS) + @for i in $(PLATFORMS); do \ + tag=$$(echo $$i | sed -e s:/:-:g); \ + echo GOARCH=$$(basename $$i) GOOS=$$(dirname $$i) CGO_ENABLED=0 go build -ldflags $(BUILD_FLAGS) -o $(GEN)/$(NAME).$$tag ../../cmds/$(NAME); \ + GOARCH=$$(basename $$i) GOOS=$$(dirname $$i) CGO_ENABLED=0 go build -ldflags $(BUILD_FLAGS) -o $(GEN)/$(NAME).$$tag ../../cmds/$(NAME) & \ + done; \ + wait + @touch $(GEN)/build + + +.PHONY: ctf +ctf: $(GEN)/ctf + +$(GEN)/ctf: $(OCM_BIN) $(GEN)/.exists $(GEN)/build component-constructor.yaml $(CHARTSRCS) + @rm -rf "$(GEN)/ctf" + $(OCM) add componentversions \ + --create \ + --file $(GEN)/ctf \ + --type $(CTF_TYPE) \ + --templater=spiff \ + COMPONENT="$(COMPONENT)" \ + NAME="$(NAME)" \ + VERSION="$(VERSION)" \ + PROVIDER="$(PROVIDER)" \ + COMMIT="$(COMMIT)" \ + GEN="$(GEN)" \ + PLATFORMS="$(PLATFORMS)" \ + component-constructor.yaml + touch "$(GEN)/ctf" + +.PHONY: version +version: + @echo $(VERSION) + +.PHONY: push +push: $(GEN)/ctf $(GEN)/push.$(NAME) + +$(GEN)/push.$(NAME): $(GEN)/ctf $(OCM_BIN) + $(OCM) transfer ctf -f $(GEN)/ctf $(OCMREPO) + @touch $(GEN)/push.$(NAME) + +.PHONY: plain-push +plain-push: $(GEN) $(OCM_BIN) + $(OCM) transfer ctf -f $(GEN)/ctf $(OCMREPO) + @touch $(GEN)/push.$(NAME) + +.PHONY: transport +transport: $(OCM_BIN) +ifneq ($(TARGETREPO),) + $(OCM) transfer component -Vc $(OCMREPO)//$(COMPONENT):$(VERSION) $(TARGETREPO) +endif + +$(GEN)/.exists: + @mkdir -p $(GEN) + @touch $@ + +.PHONY: info +info: + @echo "ROOT: $(REPO_ROOT)" + @echo "VERSION: $(VERSION)" + @echo "COMMIT; $(COMMIT)" + +.PHONY: describe +describe: $(GEN)/ctf $(OCM_BIN) + $(OCM) get resources --lookup $(OCMREPO) -r -o treewide $(GEN)/ctf + +.PHONY: descriptor +descriptor: $(GEN)/ctf $(OCM_BIN) + $(OCM) get component -S v3alpha1 -o yaml $(GEN)/ctf + +.PHONY: clean +clean: + rm -rf $(GEN) + +install: $(GEN)/ctf $(OCM_BIN) + $(OCM) install plugin -f $(GEN)/ctf \ No newline at end of file diff --git a/components/jfrogplugin/bindings.yaml b/components/jfrogplugin/bindings.yaml new file mode 100644 index 0000000000..ae8fb3bd18 --- /dev/null +++ b/components/jfrogplugin/bindings.yaml @@ -0,0 +1,4 @@ +values: + GEN: ../../gen/jfrogplugin + PLATFORMS: linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 + VERSION: "1.0" diff --git a/components/jfrogplugin/component-constructor.yaml b/components/jfrogplugin/component-constructor.yaml new file mode 100644 index 0000000000..b5b7d3f51b --- /dev/null +++ b/components/jfrogplugin/component-constructor.yaml @@ -0,0 +1,23 @@ +--- +helper: + <<<: (( &temporary )) + executable: + <<<: (( &template )) + name: jfrog + type: ocmPlugin + version: (( values.VERSION )) + extraIdentity: + os: ((dirname(p) )) + architecture: (( basename(p) )) + input: + type: file + # Generate the path to the plugin binary by looking into the base path and encoding the platform + path: (( values.GEN "/" values.NAME "." replace(p,"/","-") )) + +components: + - name: (( values.COMPONENT)) + version: (( values.VERSION)) + provider: + name: (( values.PROVIDER)) + # use all platforms and create a resource for each + resources: (( map[split(" ", values.PLATFORMS)|p|-> *helper.executable] )) \ No newline at end of file diff --git a/components/jfrogplugin/sources.yaml b/components/jfrogplugin/sources.yaml new file mode 100644 index 0000000000..dcc9c5f896 --- /dev/null +++ b/components/jfrogplugin/sources.yaml @@ -0,0 +1,7 @@ +name: source +type: filesytem +access: + type: github + repoUrl: github.com/open-component-model/ocm + commit: ${COMMIT} +version: ${VERSION}