2017-02-09 15:29:17 +00:00
|
|
|
package test
|
2016-12-16 16:22:37 +00:00
|
|
|
|
|
|
|
import (
|
2018-06-27 04:03:15 +00:00
|
|
|
"context"
|
2016-12-16 16:22:37 +00:00
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
2018-02-14 04:44:43 +00:00
|
|
|
"io/ioutil"
|
2016-12-16 16:22:37 +00:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
2016-12-16 18:14:45 +00:00
|
|
|
"net/url"
|
|
|
|
"strconv"
|
2016-12-16 16:22:37 +00:00
|
|
|
"strings"
|
2019-08-09 14:45:54 +00:00
|
|
|
"sync"
|
2019-02-20 14:24:25 +00:00
|
|
|
"testing"
|
2019-01-11 10:36:44 +00:00
|
|
|
"time"
|
|
|
|
|
2017-02-13 15:46:53 +00:00
|
|
|
"github.com/ipfs/ipfs-cluster/api"
|
2019-02-20 14:24:25 +00:00
|
|
|
"github.com/ipfs/ipfs-cluster/datastore/inmem"
|
2019-02-19 17:59:46 +00:00
|
|
|
"github.com/ipfs/ipfs-cluster/state"
|
2019-02-20 14:24:25 +00:00
|
|
|
"github.com/ipfs/ipfs-cluster/state/dsstate"
|
2017-02-09 15:29:17 +00:00
|
|
|
|
2016-12-16 16:22:37 +00:00
|
|
|
cid "github.com/ipfs/go-cid"
|
2018-02-14 04:44:43 +00:00
|
|
|
u "github.com/ipfs/go-ipfs-util"
|
2019-02-19 17:59:46 +00:00
|
|
|
cors "github.com/rs/cors"
|
2016-12-16 16:22:37 +00:00
|
|
|
)
|
|
|
|
|
2019-01-11 10:47:56 +00:00
|
|
|
// Some values used by the ipfs mock
|
|
|
|
const (
|
2019-01-10 19:03:59 +00:00
|
|
|
IpfsCustomHeaderName = "X-Custom-Header"
|
2019-01-11 10:36:44 +00:00
|
|
|
IpfsTimeHeaderName = "X-Time-Now"
|
2019-01-10 19:03:59 +00:00
|
|
|
IpfsCustomHeaderValue = "42"
|
|
|
|
IpfsACAOrigin = "myorigin"
|
2019-08-09 14:45:54 +00:00
|
|
|
IpfsErrFromNotPinned = "'from' cid was not recursively pinned already"
|
2019-01-10 19:03:59 +00:00
|
|
|
)
|
|
|
|
|
2017-02-09 15:29:17 +00:00
|
|
|
// IpfsMock is an ipfs daemon mock which should sustain the functionality used by ipfscluster.
|
|
|
|
type IpfsMock struct {
|
2018-04-24 00:39:07 +00:00
|
|
|
server *httptest.Server
|
|
|
|
Addr string
|
|
|
|
Port int
|
2019-02-19 17:59:46 +00:00
|
|
|
pinMap state.State
|
2018-04-24 00:39:07 +00:00
|
|
|
BlockStore map[string][]byte
|
2019-08-09 14:45:54 +00:00
|
|
|
reqCounts map[string]int
|
|
|
|
reqCounter chan string
|
|
|
|
|
|
|
|
closeMux sync.Mutex
|
|
|
|
closed bool
|
2016-12-16 16:22:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type mockPinResp struct {
|
2019-06-20 17:49:07 +00:00
|
|
|
Pins []string
|
|
|
|
Progress int `json:",omitempty"`
|
2016-12-16 16:22:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type mockPinType struct {
|
|
|
|
Type string
|
|
|
|
}
|
|
|
|
|
|
|
|
type mockPinLsResp struct {
|
|
|
|
Keys map[string]mockPinType
|
|
|
|
}
|
|
|
|
|
|
|
|
type ipfsErr struct {
|
|
|
|
Code int
|
|
|
|
Message string
|
|
|
|
}
|
|
|
|
|
2017-04-06 02:27:02 +00:00
|
|
|
type mockIDResp struct {
|
2017-02-09 15:29:17 +00:00
|
|
|
ID string
|
|
|
|
Addresses []string
|
|
|
|
}
|
|
|
|
|
2017-03-29 20:52:13 +00:00
|
|
|
type mockRepoStatResp struct {
|
2017-10-26 13:06:00 +00:00
|
|
|
RepoSize uint64
|
|
|
|
NumObjects uint64
|
|
|
|
StorageMax uint64
|
2017-03-27 13:07:12 +00:00
|
|
|
}
|
|
|
|
|
2017-03-29 20:52:13 +00:00
|
|
|
type mockConfigResp struct {
|
2017-03-27 13:07:12 +00:00
|
|
|
Datastore struct {
|
|
|
|
StorageMax string
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-29 20:52:13 +00:00
|
|
|
type mockAddResp struct {
|
2017-11-13 12:52:33 +00:00
|
|
|
Name string
|
|
|
|
Hash string
|
|
|
|
Bytes uint64
|
2017-03-29 20:52:13 +00:00
|
|
|
}
|
|
|
|
|
2018-03-07 13:51:37 +00:00
|
|
|
type mockRefsResp struct {
|
|
|
|
Ref string
|
|
|
|
Err string
|
|
|
|
}
|
|
|
|
|
2018-01-18 02:49:35 +00:00
|
|
|
type mockSwarmPeersResp struct {
|
|
|
|
Peers []mockIpfsPeer
|
|
|
|
}
|
|
|
|
|
|
|
|
type mockIpfsPeer struct {
|
|
|
|
Peer string
|
|
|
|
}
|
|
|
|
|
2018-02-14 04:44:43 +00:00
|
|
|
type mockBlockPutResp struct {
|
|
|
|
Key string
|
|
|
|
}
|
|
|
|
|
2019-10-22 05:40:32 +00:00
|
|
|
type mockRepoGCResp struct {
|
|
|
|
Key cid.Cid `json:",omitempty"`
|
|
|
|
Error string `json:",omitempty"`
|
|
|
|
}
|
|
|
|
|
2017-02-09 15:29:17 +00:00
|
|
|
// NewIpfsMock returns a new mock.
|
2019-02-20 14:24:25 +00:00
|
|
|
func NewIpfsMock(t *testing.T) *IpfsMock {
|
|
|
|
store := inmem.New()
|
|
|
|
st, err := dsstate.New(store, "", dsstate.DefaultHandle())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2019-08-09 14:45:54 +00:00
|
|
|
|
2017-02-09 15:29:17 +00:00
|
|
|
m := &IpfsMock{
|
2018-04-24 00:39:07 +00:00
|
|
|
pinMap: st,
|
2019-08-09 14:45:54 +00:00
|
|
|
BlockStore: make(map[string][]byte),
|
|
|
|
reqCounts: make(map[string]int),
|
|
|
|
reqCounter: make(chan string, 100),
|
2016-12-16 16:22:37 +00:00
|
|
|
}
|
2019-01-10 19:03:59 +00:00
|
|
|
|
2019-08-09 14:45:54 +00:00
|
|
|
go m.countRequests()
|
|
|
|
|
2019-01-10 19:03:59 +00:00
|
|
|
mux := http.NewServeMux()
|
|
|
|
mux.HandleFunc("/", m.handler)
|
|
|
|
|
|
|
|
c := cors.New(cors.Options{
|
|
|
|
AllowedOrigins: []string{IpfsACAOrigin},
|
|
|
|
AllowedMethods: []string{"POST"},
|
|
|
|
ExposedHeaders: []string{"X-Stream-Output", "X-Chunked-Output", "X-Content-Length"},
|
|
|
|
AllowCredentials: true, // because IPFS does it, even if for no reason.
|
|
|
|
})
|
|
|
|
corsHandler := c.Handler(mux)
|
|
|
|
|
|
|
|
ts := httptest.NewServer(corsHandler)
|
2016-12-16 16:22:37 +00:00
|
|
|
m.server = ts
|
2016-12-16 18:14:45 +00:00
|
|
|
|
2016-12-16 21:00:08 +00:00
|
|
|
url, _ := url.Parse(ts.URL)
|
2016-12-16 18:14:45 +00:00
|
|
|
h := strings.Split(url.Host, ":")
|
|
|
|
i, _ := strconv.Atoi(h[1])
|
|
|
|
|
2017-02-09 15:29:17 +00:00
|
|
|
m.Port = i
|
|
|
|
m.Addr = h[0]
|
2016-12-16 16:22:37 +00:00
|
|
|
return m
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-08-09 14:45:54 +00:00
|
|
|
func (m *IpfsMock) countRequests() {
|
|
|
|
for str := range m.reqCounter {
|
|
|
|
m.reqCounts[str]++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetCount allows to get the number of times and endpoint was called.
|
|
|
|
// Do not use concurrently to requests happening.
|
|
|
|
func (m *IpfsMock) GetCount(path string) int {
|
|
|
|
return m.reqCounts[path]
|
|
|
|
}
|
|
|
|
|
2016-12-16 16:22:37 +00:00
|
|
|
// FIXME: what if IPFS API changes?
|
2017-02-09 15:29:17 +00:00
|
|
|
func (m *IpfsMock) handler(w http.ResponseWriter, r *http.Request) {
|
2018-06-27 04:03:15 +00:00
|
|
|
ctx := context.Background()
|
2016-12-16 16:22:37 +00:00
|
|
|
p := r.URL.Path
|
2019-01-10 19:03:59 +00:00
|
|
|
w.Header().Set(IpfsCustomHeaderName, IpfsCustomHeaderValue)
|
2018-12-18 14:44:11 +00:00
|
|
|
w.Header().Set("Server", "ipfs-mock")
|
2019-01-11 10:36:44 +00:00
|
|
|
w.Header().Set(IpfsTimeHeaderName, fmt.Sprintf("%d", time.Now().Unix()))
|
2016-12-16 16:22:37 +00:00
|
|
|
endp := strings.TrimPrefix(p, "/api/v0/")
|
2019-08-09 14:45:54 +00:00
|
|
|
|
|
|
|
m.reqCounter <- endp
|
|
|
|
|
2016-12-16 16:22:37 +00:00
|
|
|
switch endp {
|
2017-01-26 18:59:31 +00:00
|
|
|
case "id":
|
2017-04-06 02:27:02 +00:00
|
|
|
resp := mockIDResp{
|
2019-02-27 20:19:10 +00:00
|
|
|
ID: PeerID1.Pretty(),
|
2017-01-26 18:59:31 +00:00
|
|
|
Addresses: []string{
|
|
|
|
"/ip4/0.0.0.0/tcp/1234",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
j, _ := json.Marshal(resp)
|
|
|
|
w.Write(j)
|
2016-12-16 16:22:37 +00:00
|
|
|
case "pin/add":
|
2018-04-20 04:09:07 +00:00
|
|
|
arg, ok := extractCid(r.URL)
|
|
|
|
if !ok {
|
2016-12-16 16:22:37 +00:00
|
|
|
goto ERROR
|
|
|
|
}
|
2019-02-27 20:09:31 +00:00
|
|
|
if arg == ErrorCid.String() {
|
2016-12-16 16:22:37 +00:00
|
|
|
goto ERROR
|
|
|
|
}
|
2018-04-20 04:09:07 +00:00
|
|
|
c, err := cid.Decode(arg)
|
2016-12-16 16:22:37 +00:00
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
2018-06-27 04:03:15 +00:00
|
|
|
m.pinMap.Add(ctx, api.PinCid(c))
|
2016-12-16 16:22:37 +00:00
|
|
|
resp := mockPinResp{
|
2018-04-20 04:09:07 +00:00
|
|
|
Pins: []string{arg},
|
2016-12-16 16:22:37 +00:00
|
|
|
}
|
2019-06-20 17:49:07 +00:00
|
|
|
|
2019-05-28 08:35:04 +00:00
|
|
|
if c.Equals(SlowCid1) {
|
|
|
|
for i := 0; i <= 10; i++ {
|
|
|
|
time.Sleep(1 * time.Second)
|
2019-06-20 17:49:07 +00:00
|
|
|
resp.Progress = i
|
|
|
|
j, _ := json.Marshal(resp)
|
2019-05-28 08:35:04 +00:00
|
|
|
w.Write(j)
|
|
|
|
}
|
|
|
|
} else {
|
2019-06-20 17:49:07 +00:00
|
|
|
j, _ := json.Marshal(resp)
|
2019-05-28 08:35:04 +00:00
|
|
|
w.Write(j)
|
|
|
|
}
|
2016-12-16 16:22:37 +00:00
|
|
|
case "pin/rm":
|
2018-04-20 04:09:07 +00:00
|
|
|
arg, ok := extractCid(r.URL)
|
|
|
|
if !ok {
|
2016-12-16 16:22:37 +00:00
|
|
|
goto ERROR
|
|
|
|
}
|
2018-04-20 04:09:07 +00:00
|
|
|
c, err := cid.Decode(arg)
|
2016-12-16 16:22:37 +00:00
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
2018-06-27 04:03:15 +00:00
|
|
|
m.pinMap.Rm(ctx, c)
|
2016-12-16 16:22:37 +00:00
|
|
|
resp := mockPinResp{
|
2018-04-20 04:09:07 +00:00
|
|
|
Pins: []string{arg},
|
2016-12-16 16:22:37 +00:00
|
|
|
}
|
2019-07-12 14:40:29 +00:00
|
|
|
j, _ := json.Marshal(resp)
|
|
|
|
w.Write(j)
|
|
|
|
case "pin/update":
|
|
|
|
args := r.URL.Query()["arg"]
|
|
|
|
if len(args) != 2 {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
fromStr := args[0]
|
|
|
|
toStr := args[1]
|
|
|
|
from, err := cid.Decode(fromStr)
|
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
to, err := cid.Decode(toStr)
|
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
|
|
|
|
pin, err := m.pinMap.Get(ctx, from)
|
|
|
|
if err != nil {
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2019-08-09 14:45:54 +00:00
|
|
|
resp := ipfsErr{0, IpfsErrFromNotPinned}
|
2019-07-12 14:40:29 +00:00
|
|
|
j, _ := json.Marshal(resp)
|
|
|
|
w.Write(j)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
pin.Cid = to
|
|
|
|
err = m.pinMap.Add(ctx, pin)
|
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
|
|
|
|
resp := mockPinResp{
|
|
|
|
Pins: []string{from.String(), to.String()},
|
|
|
|
}
|
|
|
|
|
2016-12-16 16:22:37 +00:00
|
|
|
j, _ := json.Marshal(resp)
|
|
|
|
w.Write(j)
|
|
|
|
case "pin/ls":
|
2018-04-20 04:09:07 +00:00
|
|
|
arg, ok := extractCid(r.URL)
|
2016-12-16 16:22:37 +00:00
|
|
|
if !ok {
|
|
|
|
rMap := make(map[string]mockPinType)
|
2019-02-20 14:24:25 +00:00
|
|
|
pins, err := m.pinMap.List(ctx)
|
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
2016-12-16 16:22:37 +00:00
|
|
|
for _, p := range pins {
|
2017-02-13 15:46:53 +00:00
|
|
|
rMap[p.Cid.String()] = mockPinType{"recursive"}
|
2016-12-16 16:22:37 +00:00
|
|
|
}
|
|
|
|
j, _ := json.Marshal(mockPinLsResp{rMap})
|
|
|
|
w.Write(j)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2018-04-20 04:09:07 +00:00
|
|
|
cidStr := arg
|
2016-12-16 16:22:37 +00:00
|
|
|
c, err := cid.Decode(cidStr)
|
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
2019-06-07 17:02:27 +00:00
|
|
|
|
2019-02-20 14:24:25 +00:00
|
|
|
ok, err = m.pinMap.Has(ctx, c)
|
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
2016-12-16 16:22:37 +00:00
|
|
|
if ok {
|
2019-06-07 17:02:27 +00:00
|
|
|
if c.Equals(Cid4) { // this a v1 cid. Do not return default-base32
|
|
|
|
w.Write([]byte(`{ "Keys": { "zb2rhiKhUepkTMw7oFfBUnChAN7ABAvg2hXUwmTBtZ6yxuc57": { "Type": "recursive" }}}`))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2016-12-16 16:22:37 +00:00
|
|
|
rMap := make(map[string]mockPinType)
|
|
|
|
rMap[cidStr] = mockPinType{"recursive"}
|
|
|
|
j, _ := json.Marshal(mockPinLsResp{rMap})
|
|
|
|
w.Write(j)
|
|
|
|
} else {
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
resp := ipfsErr{0, fmt.Sprintf("Path '%s' is not pinned", cidStr)}
|
|
|
|
j, _ := json.Marshal(resp)
|
|
|
|
w.Write(j)
|
|
|
|
}
|
2017-03-23 18:34:33 +00:00
|
|
|
case "swarm/connect":
|
2018-04-20 04:09:07 +00:00
|
|
|
arg, ok := extractCid(r.URL)
|
2017-03-23 18:34:33 +00:00
|
|
|
if !ok {
|
|
|
|
goto ERROR
|
|
|
|
}
|
2018-04-20 04:09:07 +00:00
|
|
|
addr := arg
|
2017-03-23 18:34:33 +00:00
|
|
|
splits := strings.Split(addr, "/")
|
|
|
|
pid := splits[len(splits)-1]
|
|
|
|
resp := struct {
|
|
|
|
Strings []string
|
|
|
|
}{
|
|
|
|
Strings: []string{fmt.Sprintf("connect %s success", pid)},
|
|
|
|
}
|
|
|
|
j, _ := json.Marshal(resp)
|
|
|
|
w.Write(j)
|
2018-01-18 02:49:35 +00:00
|
|
|
case "swarm/peers":
|
|
|
|
peer1 := mockIpfsPeer{
|
2019-02-27 20:19:10 +00:00
|
|
|
Peer: PeerID4.Pretty(),
|
2018-01-18 02:49:35 +00:00
|
|
|
}
|
|
|
|
peer2 := mockIpfsPeer{
|
2019-02-27 20:19:10 +00:00
|
|
|
Peer: PeerID5.Pretty(),
|
2018-01-18 02:49:35 +00:00
|
|
|
}
|
|
|
|
resp := mockSwarmPeersResp{
|
|
|
|
Peers: []mockIpfsPeer{peer1, peer2},
|
|
|
|
}
|
|
|
|
j, _ := json.Marshal(resp)
|
|
|
|
w.Write(j)
|
2018-02-14 04:44:43 +00:00
|
|
|
case "block/put":
|
|
|
|
// Get the data and retun the hash
|
|
|
|
mpr, err := r.MultipartReader()
|
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
part, err := mpr.NextPart()
|
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
data, err := ioutil.ReadAll(part)
|
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
2018-04-24 00:39:07 +00:00
|
|
|
// Parse cid from data and format and add to mock block-store
|
|
|
|
query := r.URL.Query()
|
|
|
|
format, ok := query["f"]
|
|
|
|
if !ok || len(format) != 1 {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
var c string
|
|
|
|
hash := u.Hash(data)
|
|
|
|
codec, ok := cid.Codecs[format[0]]
|
|
|
|
if !ok {
|
2018-02-14 04:44:43 +00:00
|
|
|
goto ERROR
|
|
|
|
}
|
2018-04-24 00:39:07 +00:00
|
|
|
if format[0] == "v0" {
|
|
|
|
c = cid.NewCidV0(hash).String()
|
|
|
|
} else {
|
|
|
|
c = cid.NewCidV1(codec, hash).String()
|
|
|
|
}
|
|
|
|
m.BlockStore[c] = data
|
|
|
|
|
2018-02-14 04:44:43 +00:00
|
|
|
resp := mockBlockPutResp{
|
|
|
|
Key: c,
|
|
|
|
}
|
|
|
|
j, _ := json.Marshal(resp)
|
|
|
|
w.Write(j)
|
2018-03-18 19:29:02 +00:00
|
|
|
case "block/get":
|
|
|
|
query := r.URL.Query()
|
|
|
|
arg, ok := query["arg"]
|
|
|
|
if !ok {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
if len(arg) != 1 {
|
|
|
|
goto ERROR
|
|
|
|
}
|
2018-04-24 00:39:07 +00:00
|
|
|
data, ok := m.BlockStore[arg[0]]
|
|
|
|
if !ok {
|
2018-03-18 19:29:02 +00:00
|
|
|
goto ERROR
|
|
|
|
}
|
2018-04-24 00:39:07 +00:00
|
|
|
w.Write(data)
|
2019-10-22 05:40:32 +00:00
|
|
|
case "repo/gc":
|
|
|
|
// It assumes `/repo/gc` with parameter `stream-errors=true`
|
|
|
|
enc := json.NewEncoder(w)
|
|
|
|
resp := []mockRepoGCResp{
|
|
|
|
{
|
|
|
|
Key: Cid1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: Cid2,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: Cid3,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Key: Cid4,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Error: "no link by that name",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, r := range resp {
|
|
|
|
if err := enc.Encode(&r); err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-27 13:07:12 +00:00
|
|
|
case "repo/stat":
|
2018-08-17 14:53:40 +00:00
|
|
|
sizeOnly := r.URL.Query().Get("size-only")
|
2019-02-20 14:24:25 +00:00
|
|
|
list, err := m.pinMap.List(ctx)
|
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
len := len(list)
|
2018-08-17 14:53:40 +00:00
|
|
|
numObjs := uint64(len)
|
|
|
|
if sizeOnly == "true" {
|
|
|
|
numObjs = 0
|
|
|
|
}
|
2017-03-29 20:52:13 +00:00
|
|
|
resp := mockRepoStatResp{
|
2017-10-26 13:06:00 +00:00
|
|
|
RepoSize: uint64(len) * 1000,
|
2018-08-17 14:53:40 +00:00
|
|
|
NumObjects: numObjs,
|
2017-10-26 13:06:00 +00:00
|
|
|
StorageMax: 10000000000, //10 GB
|
2017-03-27 13:07:12 +00:00
|
|
|
}
|
|
|
|
j, _ := json.Marshal(resp)
|
|
|
|
w.Write(j)
|
Add PinPath/UnpinPath support.
Squashed commit of the following:
commit 38cf569c6aed77c46ee4e0f8baa4d1a9daf8f03e
Merge: d125f69 aaada42
Author: Hector Sanjuan <hsanjuan@users.noreply.github.com>
Date: Wed Feb 20 11:02:00 2019 +0000
Merge pull request #634 from ipfs/issue_450
Support PinPath, UnpinPath (resolve before pinning)
commit aaada42054e1f1c7b2abb1270859d0de41a0e5d8
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Tue Feb 19 22:16:25 2019 +0530
formatResponse accepts api.Pin and not api.PinSerial
commit b5da4bea045865814cc422da71827b44ddd44b90
Merge: ba59036 cc8dd7e
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Tue Feb 19 21:36:46 2019 +0530
Merge branch 'master' into issue_450
commit ba5903649c1df1dba20f4d6f7e3573d6fe24921f
Merge: f002914 d59880c
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Mon Feb 18 08:41:11 2019 +0530
Merge branch 'issue_450' of github.com:ipfs/ipfs-cluster into issue_450
commit f00291494c0c02621c2296cbb7ac71e4c23aa9ec
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Mon Feb 18 08:31:39 2019 +0530
PinPath: more improvements
Added tracing for new methods
commit d59880c338eaa8214fe06b4f930a540793d78407
Merge: 0ca4c7c b4f0eb3
Author: Hector Sanjuan <hsanjuan@users.noreply.github.com>
Date: Wed Feb 13 15:22:49 2019 +0000
Merge branch 'master' into issue_450
commit 0ca4c7c3b0670ed9c8279f8274d36e3485c10030
Merge: d35017a ecef9ea
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Tue Feb 12 13:10:13 2019 +0530
Merge branch 'master' into issue_450
commit d35017a8de91ca9fc9a9a047c48c75134cee9f98
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Tue Feb 12 13:07:25 2019 +0530
PinPath: more improvements
- Worth having `PinOptions` as a separate field in the struct and
constructing the query in the test with ToQuery()
- sharness: "intialization" line can be placed outside the tests at
the top
commit 68e3b90417ffbad89d41a70ac81d85f9037f8848
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Sun Feb 10 21:43:50 2019 +0530
Using if-continue pattern instead of if-else
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit 3c29799f3b85be328b27508332ab92049d8b82f3
Merge: 956790b 4324889
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Thu Feb 7 10:25:52 2019 +0530
Merge branch 'master' into issue_450
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit 956790b381db9858e4194f983e898b07dc51ba66
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Wed Feb 6 21:11:20 2019 +0530
Removing resolved path
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit 7191cc46cedfbec116a9746937e28881b50ca044
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Wed Feb 6 16:45:07 2019 +0530
Fix go vet
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit f8b3d5b63b1b7569e2a3e0d82894fd4491c246c4
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Wed Feb 6 16:07:03 2019 +0530
Fixed linting error
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit 23c57eb467755a1f21387a1615a7f34e97348053
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Wed Feb 6 09:20:41 2019 +0530
Fixed tests
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit 0caedd94aefeb3b6649dedc214cb4b849ace2ea4
Merge: 17e555e 5a7ee1d
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Wed Feb 6 00:07:10 2019 +0530
Merge branch 'master' into issue_450
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit 17e555e4a7c574413df90aac70c5cc29cab98f54
Author: Hector Sanjuan <code@hector.link>
Date: Tue Feb 5 16:58:50 2019 +0000
PinPath: address some feedback + improvements
* Changed client's Pin() API and PinPath to be consistent
* Added helper methods to turn PinPath to query and back
* Make code and tests build
* Use TestCidResolved everywhere
* Fix cluster.PinPath arguments
* Fix formatting of responses with --no-status
* Make tests readable and call Fatal when needed
* Use a pathTestCases variable
commit f0e7369c47c5ddadc8ed45df5fd2d4d9b2d42b38
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Tue Feb 5 18:34:26 2019 +0530
Support PinPath, UnpinPath(resolve before pinning)
Addressed review comments as in
https://github.com/ipfs/ipfs-cluster/pull/634#pullrequestreview-198751932
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit a8b4f181d2d7afed32ee41331dfaab19fd66a173
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Tue Jan 29 22:41:27 2019 +0530
Fixing tests
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit e39b95ca19e4d75506f4f492678245ef13936a44
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Tue Jan 29 14:52:53 2019 +0530
Support PinPath, UnpinPath(resolve before pinning)
- PinPath and UnpinPath should return api.Pin
- PinPath should accept pin options
- Removing duplicate logic for Resolve from cluster
- And many other review comments https://github.com/ipfs/ipfs-cluster/pull/634#pullrequestreview-195509504
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit d146075126320896665ba58d337a13789f68ea86
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Wed Jan 23 17:08:41 2019 +0530
Support PinPath, UnpinPath(resolve before pinning)
PinPath(in both rest and rpc) should return a serializable struct in the
form `{"\":"Q...cid..string..."}` (as used in "github.com/ipfs/go-cid"
to marshal and unmarshal)
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit 1f4869568a8adb450275257154ea3a26d03a30f3
Merge: 7acfd28 a244af9
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Wed Jan 23 07:18:56 2019 +0530
Merge branch 'master' into issue_450
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit 7acfd282732ddf2282a67d4f9d0170a494eb3ed4
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Tue Jan 22 18:14:32 2019 +0530
Support PinPath, UnpinPath(resolve before pinning)
- RPC must always use serializable structs
- In command, just use pin with path as cid is also a valid path
- Addressing many other small review comments as in
https://github.com/ipfs/ipfs-cluster/pull/634#pullrequestreview-192122534
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit 36905041e1e3f0b204942030aab3ab7b5b9e4d62
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Wed Jan 16 09:36:42 2019 +0530
Support PinPath, UnpinPath(resolve before pinning)
Extra logic for path checking should go into resolve so that it can be
properly reused
Added sharness tests
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit 9116bda3534e77bb391d873051bb520a1b01a326
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Wed Jan 16 08:08:07 2019 +0530
Support PinPath, UnpinPath(resolve before pinning)
error strings should not be capitalized
Fixes #450
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit ca7e61861374f456300a85ddc0374e594f74f963
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Tue Jan 15 23:40:25 2019 +0530
Support PinPath, UnpinPath(resolve before pinning)
Tests
Fixes #450
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit 522fbcd899f01c01680375561a32a87464157c0a
Merge: f1a56ab f7bc468
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Tue Jan 15 10:40:54 2019 +0530
Merge branch 'master' into issue_450
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit f1a56ab925fb74c0c44273a4524afa4843cf757f
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Mon Jan 14 20:58:17 2019 +0530
Support PinPath, UnpinPath(resolve before pinning)
- IPFS Connector should act as a pure IPFS client, any extra logic
should go to cluster.go
- Use cid.Undef, instead of cid.Cid{}
Fixes #450
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit c83b91054f6774f1f9d4930cfc3f1fa28236f57c
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Thu Jan 10 08:57:17 2019 +0530
Support PinPath, UnpinPath(resolve before pinning)
- Separate handlers, methods and rpc apis for PinPath and UnpinPath from
Pin and Unpin
- Support ipld paths as well
Fixes #450
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit 719dff88129366ce3ccb5e04cb6f8082a0915c5c
Merge: 91ceb47 21170c4
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Wed Jan 9 19:38:35 2019 +0530
Merge branch 'issue_450_old' into HEAD
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit 91ceb4796259ca7ef2974ec43e6a278a12796b13
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Wed Jan 9 19:36:41 2019 +0530
Revert "WIP: Figure out why test does not impleme"
This reverts commit 28a3a3f25dce6f296c8cbef86221644c099a7e75.
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
commit 28a3a3f25dce6f296c8cbef86221644c099a7e75
Author: cd10012 <ced361@nyu.edu>
Date: Tue Jul 24 23:23:10 2018 -0400
WIP: Figure out why test does not implement IPFSConnector interface...
License: MIT
Signed-off-by: cd10012 <ced361@nyu.edu>
commit 21170c48e77e69583db64544b08120a9baf40d8d
Author: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Date: Tue Jan 8 10:37:59 2019 +0530
Support PinPath, UnpinPath (resolve before pinning)
This commit adds API support for pinning using path
`POST /pins/<ipfs or ipns path>` and `DELETE /pins/<ipfs or ipns path>`
will resolve the path into a cid and perform perform pinning or
unpinning
Fixes #450
License: MIT
Signed-off-by: Kishan Mohanbhai Sagathiya <kishansagathiya@gmail.com>
Co-authored-by: Hector Sanjuan <hector@protocol.ai>
License: MIT
Signed-off-by: Hector Sanjuan <hector@protocol.ai>
2019-02-20 11:07:50 +00:00
|
|
|
case "resolve":
|
2019-02-27 20:19:10 +00:00
|
|
|
w.Write([]byte("{\"Path\":\"" + "/ipfs/" + CidResolved.String() + "\"}"))
|
2017-03-27 13:07:12 +00:00
|
|
|
case "config/show":
|
2017-03-29 20:52:13 +00:00
|
|
|
resp := mockConfigResp{
|
2017-03-27 13:07:12 +00:00
|
|
|
Datastore: struct {
|
|
|
|
StorageMax string
|
|
|
|
}{
|
|
|
|
StorageMax: "10G",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
j, _ := json.Marshal(resp)
|
|
|
|
w.Write(j)
|
2018-03-07 13:51:37 +00:00
|
|
|
case "refs":
|
2018-04-20 04:09:07 +00:00
|
|
|
arg, ok := extractCid(r.URL)
|
2018-03-07 13:51:37 +00:00
|
|
|
if !ok {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
resp := mockRefsResp{
|
2018-04-20 04:09:07 +00:00
|
|
|
Ref: arg,
|
2018-03-07 13:51:37 +00:00
|
|
|
}
|
|
|
|
j, _ := json.Marshal(resp)
|
2019-05-28 08:35:04 +00:00
|
|
|
if arg == SlowCid1.String() {
|
|
|
|
for i := 0; i <= 5; i++ {
|
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
w.Write(j)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
w.Write(j)
|
|
|
|
}
|
2017-01-26 21:49:53 +00:00
|
|
|
case "version":
|
|
|
|
w.Write([]byte("{\"Version\":\"m.o.c.k\"}"))
|
2016-12-16 16:22:37 +00:00
|
|
|
default:
|
|
|
|
w.WriteHeader(http.StatusNotFound)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
ERROR:
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
}
|
|
|
|
|
2017-02-15 14:16:16 +00:00
|
|
|
// Close closes the mock server. It's important to call after each test or
|
|
|
|
// the listeners are left hanging around.
|
2017-02-09 15:29:17 +00:00
|
|
|
func (m *IpfsMock) Close() {
|
2019-08-09 14:45:54 +00:00
|
|
|
m.closeMux.Lock()
|
|
|
|
defer m.closeMux.Unlock()
|
|
|
|
if !m.closed {
|
|
|
|
m.closed = true
|
|
|
|
m.server.Close()
|
2019-10-31 20:51:13 +00:00
|
|
|
close(m.reqCounter)
|
2019-08-09 14:45:54 +00:00
|
|
|
}
|
2016-12-16 16:22:37 +00:00
|
|
|
}
|
2018-04-20 04:09:07 +00:00
|
|
|
|
|
|
|
// extractCid extracts the cid argument from a url.URL, either via
|
|
|
|
// the query string parameters or from the url path itself.
|
|
|
|
func extractCid(u *url.URL) (string, bool) {
|
|
|
|
arg := u.Query().Get("arg")
|
|
|
|
if arg != "" {
|
|
|
|
return arg, true
|
|
|
|
}
|
|
|
|
|
|
|
|
p := strings.TrimPrefix(u.Path, "/api/v0/")
|
|
|
|
segs := strings.Split(p, "/")
|
|
|
|
|
|
|
|
if len(segs) > 2 {
|
|
|
|
return segs[len(segs)-1], true
|
|
|
|
}
|
|
|
|
return "", false
|
|
|
|
}
|