Skip to content
Open
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ This repo is designed to produce git hook commands that take care of metadata ad

```
git clone repo
forge init -- exactly same as git-dirs init, just a wrapper around it
forge init -- exactly same as git-drs init, just a wrapper around it
git add files
git commit -m "test" -- same as git-drs
git push origin main -- same as git-dirs
git push origin main -- same as git-drs
forge publish [github personal access token]
```

Expand Down
53 changes: 30 additions & 23 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package client

import (
"bytes"
"context"
"fmt"
"io"
"net/http"
Expand All @@ -10,63 +11,63 @@ import (
"time"

token "github.com/bmeg/grip-graphql/middleware"
"github.com/calypr/git-drs/config"
drsConfig "github.com/calypr/git-drs/config"

"github.com/calypr/data-client/client/commonUtils"
"github.com/calypr/data-client/client/jwt"
"github.com/calypr/data-client/client/conf"
"github.com/calypr/data-client/client/logs"
index_client "github.com/calypr/git-drs/client/indexd"
)

type Gen3Client struct {
Base *url.URL
Cred jwt.Credential
Cred *conf.Credential
ProjectId string
BucketName string
}

// load repo-level config and return a new IndexDClient
func NewGen3Client() (*Gen3Client, error) {
var conf jwt.Configure
func NewGen3Client(remote config.Remote) (*Gen3Client, func(), error) {

cfg, err := drsConfig.LoadConfig()
if err != nil {
return nil, err
return nil, nil, err
}

profile := cfg.Servers.Gen3.Auth.Profile
if profile == "" {
return nil, fmt.Errorf("No gen3 profile specified. Please provide a gen3Profile key in your .drsconfig")
gfc, ok := cfg.Remotes[remote]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does gfc stand for

if !ok {
return nil, nil, fmt.Errorf("remote %s not found in config: %v", remote, cfg.Remotes)
}

cred, err := conf.ParseConfig(profile)
logger, closer := logs.New(string(remote))

cred, err := conf.NewConfigure(logger).Load(string(remote))
if err != nil {
return nil, err
return nil, closer, err
}

baseUrl, err := url.Parse(cred.APIEndpoint)
if err != nil {
return nil, fmt.Errorf("error parsing base URL from profile %s: %v", profile, err)
return nil, closer, fmt.Errorf("error parsing base URL from profile %s: %v", remote, err)
}

// get the gen3Project and gen3Bucket from the config
projectId := cfg.Servers.Gen3.Auth.ProjectID
projectId := gfc.Gen3.ProjectID
if projectId == "" {
return nil, fmt.Errorf("No gen3 project specified. Please provide a gen3Project key in your .drsconfig")
return nil, closer, fmt.Errorf("No gen3 project specified. Please provide a gen3Project key in your .drsconfig")
}

bucketName := cfg.Servers.Gen3.Auth.Bucket
bucketName := gfc.Gen3.Bucket
if bucketName == "" {
return nil, fmt.Errorf("No gen3 bucket specified. Please provide a gen3Bucket key in your .drsconfig")
return nil, closer, fmt.Errorf("No gen3 bucket specified. Please provide a gen3Bucket key in your .drsconfig")
}

return &Gen3Client{Base: baseUrl, Cred: cred, ProjectId: projectId, BucketName: bucketName}, err
return &Gen3Client{Base: baseUrl, Cred: cred, ProjectId: projectId, BucketName: bucketName}, closer, err
}

type Resp struct {
Body []byte
Err error
}

func (cl *Gen3Client) MakeReq(method string, path string, body []byte) *Resp {
func (cl *Gen3Client) MakeReq(method string, path string, body []byte, params map[string]string) *Resp {
a := *cl.Base
a.Path = filepath.Join(a.Path, path)

Expand All @@ -79,14 +80,20 @@ func (cl *Gen3Client) MakeReq(method string, path string, body []byte) *Resp {
if err != nil {
return &Resp{nil, err}
}

q := req.URL.Query()
for key, val := range params {
q.Add(key, val)
}
req.URL.RawQuery = q.Encode()

expiration, err := token.GetExpiration(cl.Cred.AccessToken)
if err != nil {
return &Resp{nil, err}
}
// Update AccessToken if token is old
if expiration.Before(time.Now()) {
r := jwt.Request{}
err := r.RequestNewAccessToken(cl.Base.String()+commonUtils.FenceAccessTokenEndpoint, &cl.Cred)
err := index_client.RefreshToken(context.Background(), cl.Cred)
if err != nil {
return &Resp{nil, err}
}
Expand Down
15 changes: 8 additions & 7 deletions client/fence/fence.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import (
"encoding/json"
"net/http"

"github.com/calypr/data-client/client/commonUtils"
"github.com/calypr/data-client/client/common"
"github.com/calypr/forge/client"
"github.com/calypr/git-drs/config"
)

// FenceBucketEndpoint is is the endpoint postfix for FENCE bucket list
Expand All @@ -31,20 +32,20 @@ func UserPing(f Fence) (*PingResp, error) {
return f.UserPing()
}

func NewFenceClient() (*FenceClient, error) {
gen3Client, err := client.NewGen3Client()
func NewFenceClient(remote config.Remote) (*FenceClient, func(), error) {
gen3Client, closer, err := client.NewGen3Client(remote)
if err != nil {
return nil, err
return nil, closer, err
}
return &FenceClient{Gen3Client: gen3Client}, nil
return &FenceClient{Gen3Client: gen3Client}, closer, nil
}

type FenceClient struct {
*client.Gen3Client
}

func (fc *FenceClient) UserPing() (*PingResp, error) {
reqResp := fc.MakeReq(http.MethodGet, commonUtils.FenceUserEndpoint, nil)
reqResp := fc.MakeReq(http.MethodGet, common.FenceUserEndpoint, nil, nil)
if reqResp.Body == nil || reqResp.Err != nil {
return nil, reqResp.Err
}
Expand All @@ -54,7 +55,7 @@ func (fc *FenceClient) UserPing() (*PingResp, error) {
return nil, err
}

bucketResp := fc.MakeReq(http.MethodGet, FenceBucketEndpoint, nil)
bucketResp := fc.MakeReq(http.MethodGet, FenceBucketEndpoint, nil, nil)
if reqResp.Body == nil || reqResp.Err != nil {
return nil, bucketResp.Err
}
Expand Down
9 changes: 8 additions & 1 deletion client/sower/resp.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
package sower

type DispatchResp struct {
type StatusResp struct {
Uid string `json:"uid"`
Name string `json:"name"`
Status string `json:"status"`
}

type OutputResp struct {
Output string `json:"output"`
}
77 changes: 65 additions & 12 deletions client/sower/sower.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,34 @@ package sower

import (
"encoding/json"
"fmt"
"net/http"

"github.com/calypr/forge/client"
"github.com/calypr/git-drs/config"
)

const sowerDispatch = "/job/dispatch"
const sowerStatus = "/job/status"
const sowerList = "/job/list"
const sowerJobOutput = "/job/output"

type Sower interface {
DispatchJob(name string, args *DispatchArgs) (*DispatchResp, error)
DispatchJob(name string, args *DispatchArgs) (*StatusResp, error)
Status(uid string) (*StatusResp, error)
List() (*[]StatusResp, error)
Output(uid string) (*OutputResp, error)
}

func DispatchJob(s Sower, name string, args *DispatchArgs) (*DispatchResp, error) {
func DispatchJob(s Sower, name string, args *DispatchArgs) (*StatusResp, error) {
return s.DispatchJob(name, args)
}

func NewSowerClient() (*SowerClient, error) {
gen3Client, err := client.NewGen3Client()
func NewSowerClient(remote config.Remote) (*SowerClient, func(), error) {
gen3Client, closer, err := client.NewGen3Client(remote)
if err != nil {
return nil, err
return nil, closer, err
}
return &SowerClient{Gen3Client: gen3Client}, nil
return &SowerClient{Gen3Client: gen3Client}, closer, nil
}

type SowerClient struct {
Expand All @@ -40,7 +46,7 @@ type DispatchArgs struct {
ProjectId string `json:"projectId"`
Profile string `json:"profile"`
BucketName string `json:"bucketName"`
APIEndpoint string `json:"APIEndpoint`
APIEndpoint string `json:"APIEndpoint"`
GHCommitHash string `json:"ghCommitHash"`
GHPAccessToken string `json:"ghToken"`
GHUserName string `json:"ghUserName"`
Expand All @@ -52,7 +58,7 @@ type JobArgs struct {
Action string `json:"action"`
}

func (sc *SowerClient) DispatchJob(name string, args *DispatchArgs) (*DispatchResp, error) {
func (sc *SowerClient) DispatchJob(name string, args *DispatchArgs) (*StatusResp, error) {
body := JobArgs{
Action: name,
Input: *args,
Expand All @@ -62,11 +68,58 @@ func (sc *SowerClient) DispatchJob(name string, args *DispatchArgs) (*DispatchRe
return nil, err
}

resp := sc.MakeReq(http.MethodPost, sowerDispatch, bodyBytes)
resp := sc.MakeReq(http.MethodPost, sowerDispatch, bodyBytes, nil)
if resp.Err != nil {
return nil, resp.Err
}

StatusResp := &StatusResp{}
err = json.Unmarshal(resp.Body, StatusResp)
if err != nil {
return nil, err
}
return StatusResp, nil
}

func (sc *SowerClient) Status(uid string) (*StatusResp, error) {
resp := sc.MakeReq(http.MethodGet, sowerStatus, nil, map[string]string{"UID": uid})
if resp.Err != nil {
return nil, resp.Err
}
fmt.Println("RESP: ", string(resp.Body))

return nil, nil
StatusResp := &StatusResp{}
err := json.Unmarshal(resp.Body, StatusResp)
if err != nil {
return nil, err
}
return StatusResp, nil
}

func (sc *SowerClient) Output(uid string) (*OutputResp, error) {
params := map[string]string{"UID": uid}
resp := sc.MakeReq(http.MethodGet, sowerJobOutput, nil, params)
if resp.Err != nil {
return nil, resp.Err
}

var outputResp OutputResp
err := json.Unmarshal(resp.Body, &outputResp)
if err != nil {
return nil, err
}
return &outputResp, nil
}

func (sc *SowerClient) List() ([]StatusResp, error) {
resp := sc.MakeReq(http.MethodGet, sowerList, nil, nil)
if resp.Err != nil {
return nil, resp.Err
}

ListResp := []StatusResp{{}}
err := json.Unmarshal(resp.Body, &ListResp)
if err != nil {
return nil, err
}
return ListResp, nil
}
23 changes: 17 additions & 6 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package cmd

import (
"github.com/calypr/forge/cmd/initialize"
"github.com/calypr/forge/cmd/config"
"github.com/calypr/forge/cmd/empty"
"github.com/calypr/forge/cmd/meta"
"github.com/calypr/forge/cmd/ping"
"github.com/calypr/forge/cmd/publish"
Expand All @@ -14,16 +15,26 @@ var RootCmd = &cobra.Command{
Short: "A powerful command-line tool for project management.",
Long: `Forge is a versatile CLI application designed to streamline various
development and project management tasks.`,
CompletionOptions: cobra.CompletionOptions{
DisableDefaultCmd: true,
},
}

func init() {
RootCmd.AddCommand(initialize.InitCmd)
RootCmd.AddCommand(ping.PingCmd)
RootCmd.AddCommand(meta.MetaCmd)
RootCmd.AddCommand(validate.ValidateCmd)
RootCmd.AddCommand(validate.CheckEdgeCmd)
RootCmd.AddCommand(publish.PublishCmd)
RootCmd.AddCommand(empty.EmptyCmd)
RootCmd.AddCommand(config.ConfigCmd)
RootCmd.AddCommand(publish.ListCmd)
RootCmd.AddCommand(publish.StatusCmd)
RootCmd.AddCommand(publish.OutputCmd)

// Don't show the help menu for that command every time there is an error
RootCmd.SilenceUsage = true
validate.ValidateParentCmd.AddCommand(validate.ValidateConfigCmd)
validate.ValidateParentCmd.AddCommand(validate.ValidateDataCmd)
validate.ValidateParentCmd.AddCommand(validate.ValidateEdgeCmd)

RootCmd.AddCommand(validate.ValidateParentCmd)

RootCmd.SilenceUsage = true // Hide usage on error
}
38 changes: 38 additions & 0 deletions cmd/config/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package config

import (
"fmt"

"github.com/calypr/forge/config"
"github.com/calypr/forge/utils/remoteutil"
"github.com/spf13/cobra"
)

var (
configRemote string
)

var ConfigCmd = &cobra.Command{
Use: "config",
Short: "Build skeleton template for CALYPR explorer page config.",
Long: `Used for creating a template CALYPR explorer config to build and customize your own config`,
Example: "forge config --remote local",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
remote, err := remoteutil.LoadRemoteOrDefault(configRemote)
if err != nil {
return fmt.Errorf("could not locate remote: %w", err)
}
fmt.Printf("Using remote: %s\n", string(*remote))

err = config.RunConfigInit(*remote)
if err != nil {
return err
}
return nil
},
}

func init() {
ConfigCmd.Flags().StringVarP(&configRemote, "remote", "r", "", "target DRS server (default: default_remote)")
}
Loading