Skip to content
Permalink
Browse files

Merge pull request #891 from ipfs/feat/metadata

Metadata can be set and shown from `ctl`
  • Loading branch information...
hsanjuan committed Sep 6, 2019
2 parents c1ff065 + 2d38942 commit 9eb0deee4e0ac7f79ba9eced378d2d8bb0c0fc5c
Showing with 78 additions and 3 deletions.
  1. +25 −0 api/add.go
  2. +8 −1 cmd/ipfs-cluster-ctl/formatters.go
  3. +25 −2 cmd/ipfs-cluster-ctl/main.go
  4. +10 −0 sharness/t0030-ctl-pin.sh
  5. +10 −0 sharness/t0031-ctl-add.sh
@@ -61,6 +61,7 @@ func DefaultAddParams() *AddParams {
ReplicationFactorMax: 0,
Name: "",
ShardSize: DefaultShardSize,
Metadata: make(map[string]string),
},
}
}
@@ -152,6 +153,17 @@ func AddParamsFromQuery(query url.Values) (*AddParams, error) {
return nil, err
}

for k := range query {
if !strings.HasPrefix(k, pinOptionsMetaPrefix) {
continue
}
metaKey := strings.TrimPrefix(k, pinOptionsMetaPrefix)
if metaKey == "" {
continue
}
params.Metadata[metaKey] = query.Get(k)
}

allocs := query.Get("user-allocations")
if allocs != "" {
params.UserAllocations = StringsToPeers(strings.Split(allocs, ","))
@@ -189,6 +201,12 @@ func (p *AddParams) ToQueryString() string {
query.Set("replication-min", fmt.Sprintf("%d", p.ReplicationFactorMin))
query.Set("replication-max", fmt.Sprintf("%d", p.ReplicationFactorMax))
query.Set("name", p.Name)
for k, v := range p.Metadata {
if k == "" {
continue
}
query.Set(fmt.Sprintf("%s%s", pinOptionsMetaPrefix, k), v)
}
query.Set("user-allocations", strings.Join(PeersToStrings(p.UserAllocations), ","))
query.Set("shard", fmt.Sprintf("%t", p.Shard))
query.Set("shard-size", fmt.Sprintf("%d", p.ShardSize))
@@ -208,6 +226,13 @@ func (p *AddParams) ToQueryString() string {

// Equals checks if p equals p2.
func (p *AddParams) Equals(p2 *AddParams) bool {
for k, v := range p.Metadata {
v2 := p2.Metadata[k]
if k != "" && v != v2 {
return false
}
}

return p.ReplicationFactorMin == p2.ReplicationFactorMin &&
p.ReplicationFactorMax == p2.ReplicationFactorMax &&
p.Name == p2.Name &&
@@ -188,7 +188,14 @@ func textFormatPrintPin(obj *api.Pin) {
recStr = fmt.Sprintf("Recursive-%d", obj.MaxDepth)
}

fmt.Printf(" | %s\n", recStr)
fmt.Printf(" | %s", recStr)

fmt.Printf(" | Metadata:")
if len(obj.Metadata) == 0 {
fmt.Printf(" no\n")
} else {
fmt.Printf(" yes\n")
}
}

func textFormatPrintAddedOutput(obj *api.AddedOutput) {
@@ -309,7 +309,7 @@ cluster "pin add".
},
cli.BoolFlag{
Name: "wrap-with-directory, w",
Usage: "Wrap a with a directory object.",
Usage: "Wrap a with a directory object",
},
cli.BoolFlag{
Name: "hidden, H",
@@ -331,7 +331,7 @@ cluster "pin add".
},
cli.StringFlag{
Name: "hash",
Usage: "Hash function to use. Implies cid-version=1.",
Usage: "Hash function to use. Implies cid-version=1",
Value: defaultAddParams.HashFun,
},
cli.StringFlag{
@@ -349,6 +349,10 @@ cluster "pin add".
Value: defaultAddParams.ReplicationFactorMax,
Usage: "Sets the maximum replication factor for pinning this file",
},
cli.StringSliceFlag{
Name: "metadata",
Usage: "Pin metadata: key=value. Can be added multiple times",
},
cli.StringFlag{
Name: "allocations, allocs",
Usage: "Optional comma-separated list of peer IDs",
@@ -400,6 +404,7 @@ cluster "pin add".
p := api.DefaultAddParams()
p.ReplicationFactorMin = c.Int("replication-min")
p.ReplicationFactorMax = c.Int("replication-max")
p.Metadata = parseMetadata(c.StringSlice("metadata"))
p.Name = name
if c.String("allocations") != "" {
p.UserAllocations = api.StringsToPeers(strings.Split(c.String("allocations"), ","))
@@ -524,6 +529,10 @@ would stil be respected.
Value: "",
Usage: "Sets a name for this pin",
},
cli.StringSliceFlag{
Name: "metadata",
Usage: "Pin metadata: key=value. Can be added multiple times",
},
cli.BoolFlag{
Name: "no-status, ns",
Usage: "Prevents fetching pin status after pinning (faster, quieter)",
@@ -565,6 +574,7 @@ would stil be respected.
ReplicationFactorMax: rplMax,
Name: c.String("name"),
UserAllocations: userAllocs,
Metadata: parseMetadata(c.StringSlice("metadata")),
}

pin, cerr := globalClient.PinPath(ctx, arg, opts)
@@ -1075,6 +1085,19 @@ func waitFor(
return client.WaitFor(ctx, globalClient, fp)
}

func parseMetadata(metadata []string) map[string]string {
metadataMap := make(map[string]string)
for _, str := range metadata {
parts := strings.SplitN(str, "=", 2)
if len(parts) != 2 {
checkErr("parsing metadata", errors.New("metadata were not in the format key=value"))
}
metadataMap[parts[0]] = parts[1]
}

return metadataMap
}

// func setupTracing(config tracingConfig) {
// if !config.Enable {
// return
@@ -96,6 +96,16 @@ test_expect_success IPFS,CLUSTER "pin update a pin" '
ipfs-cluster-ctl pin ls $cid2
'

test_expect_success IPFS,CLUSTER "pin with metadata" '
cid3=`docker exec ipfs sh -c "echo test3 | ipfs add -q"`
ipfs-cluster-ctl pin add --metadata kind=text "$cid3"
cid4=`docker exec ipfs sh -c "echo test4 | ipfs add -q"`
ipfs-cluster-ctl pin add "$cid4"
ipfs-cluster-ctl pin ls "$cid3" | grep -q "Metadata: yes" &&
ipfs-cluster-ctl --enc=json pin ls "$cid3" | jq .metadata | grep -q "\"kind\": \"text\"" &&
ipfs-cluster-ctl pin ls "$cid4" | grep -q "Metadata: no"
'

test_clean_ipfs
test_clean_cluster

@@ -79,6 +79,16 @@ test_expect_success IPFS,CLUSTER "check pin after locally added" '
ipfs-cluster-ctl pin ls | grep -q -i "$cid"
'

test_expect_success IPFS,CLUSTER "add with metadata" '
echo "test1" > test1.txt
cid1=`ipfs-cluster-ctl add --quieter --metadata kind=text test1.txt`
echo "test2" > test2.txt
cid2=`ipfs-cluster-ctl add --quieter test2.txt`
ipfs-cluster-ctl pin ls "$cid1" | grep -q "Metadata: yes" &&
ipfs-cluster-ctl --enc=json pin ls "$cid1" | jq .metadata | grep -q "\"kind\": \"text\"" &&
ipfs-cluster-ctl pin ls "$cid2" | grep -q "Metadata: no"
'

test_clean_ipfs
test_clean_cluster

0 comments on commit 9eb0dee

Please sign in to comment.
You can’t perform that action at this time.