Giter VIP home page Giter VIP logo

pkgcloud's Issues

Normalize File access API across all providers and storage APIs

When dealing with files in the cloud, pkgcloud should provide a unified API to consume.

The best remote storage API to build is one that matches Node's core Filesystem API as much as possible.

Here is an example using the new pkgcloud Dropbox API versus node's core File-system:

var dropbox = pkgcloud.storage.createClient(options);
//
// Read a remote file from the drop-box
//
dropbox.readFile('/public/test.txt', function(err, file){
  console.log(err, file.toString())
});

Reading the same file from the local file-system:

var fs = require('fs');
//
// Read a local file
//
fs.readFile('/public/test.txt', function(err, file){
  console.log(err, file.toString())
});

Note: You could also use dropbox.createReadStream or fs.createReadStream if you require a stream.

Storage API using Buffer instead of Stream

Hey guys,

I'm trying to use your storage lib with a buffer instead of a stream. I don't believe this is supported, but I think it can be done if the buffer has a wrapper that makes it look like a stream.

Any thoughts on how I can accomplish this? Here's what I started with:

function BufferStream (buffer) {
    this.data = new Buffer(buffer);
}

BufferStream.prototype.pipe = function(destination) {
      destination.emit('data', this.data);
      this.emit('close');
      this.emit('end');
};

Cheers!

Mock the databases tests

This was missed from the PR about mongolab. I opened this for not forget to add the mocks.

RENAMED

All others providers like mongohq, redistogo and iriscouch need to be mocked too.

uploading stream with multiparty

I'm using version 0.6.12 with node 0.8.22 to attempt to upload files to rackspace through my server without storing them on the server disk first. I'm using https://github.com/superjoe30/node-multiparty to parse the request form data which produces parts as ReadableStreams. My upload handler (coffeescript) code looks like this:

app.post "/images", (req, res, next) ->
  uris = []

  form = new multiparty.Form()
  form.on 'part', (part) ->
    return unless part.filename?
    path = 'somerandompath'
    logger.debug "received part: #{part.filename}, uploading to rackspace at: #{path}"

    rackspace.upload({container: rackspaceImageContainer, remote: path, stream: part}, (err) ->
      return next err if err?
      uri = rackspaceCdnBaseUrl + "/#{path}"
      uris.push uri)

  form.on 'error', (err) ->
    next new Error err

  form.on 'close', ->
    res.send uris

  form.parse req

The code hits the debug "received part" output, but the file never gets created on rackspace and the request is eventually aborted from the client side. I have also tried removing setting the stream from the options and piping directly to upload function as shown in the examples:

 part.pipe rackspace.upload({....

To no avail. What am I missing?

first upload takes 60 seconds (streaming)

I'm using node 0.8.22 and pkgcloud 0.6.12.

After my server has been started the first upload to rackspace takes exactly one minute. Subsequent uploads are sub 1 second. I have created a test server and mocha test that demonstrate the issue: https://gist.github.com/2fours/5427194.

Simply start the server, then run the test (bump the mocha timeout up to 100 seconds). You'll need a file named "testImage" in the same folder as the test. You will see that the first time the test is run after the server is started it takes one minute, then subsequent runnings are very fast. This does not seem to be an issue when using the default express multipart middleware which saves the upload to a file, and then passing this file's path as "local" in the options.

Build `node-cloudfiles` from `pkgcloud.rackspace.compute`

The Azure team at Microsoft is willing to make their node.js client for azure storage compliant with the pkgcloud API. There are also a lot of fixes in pkgcloud.rackspace.compute that are not in node-cloudfiles because it was a significant rewrite.

Make tests deterministic

Currently, the tests have a significantly high variability.

I routinely get different results on my local box, and it's even worse when using travis to valid a commit or PR.

I propose we rework the tests to try and address the non-deterministic nature of them.

Errors while destroying Azure servers

{ [Error: azure Error (400): Bad Request]
  stack: 'Error: azure Error (400): Bad Request\n    at Request.handleRequest [as _callback] (/Users/maciej/dev/js/pkgcloud/lib/pkgcloud/core/base/client.js:94:27)\n    at Request.self.callback (/Users/maciej/dev/js/pkgcloud/node_modules/request/main.js:122:22)\n    at Request.EventEmitter.emit (events.js:97:17)\n    at Request.<anonymous> (/Users/maciej/dev/js/pkgcloud/node_modules/request/main.js:661:16)\n    at Request.EventEmitter.emit (events.js:124:20)\n    at IncomingMessage.<anonymous> (/Users/maciej/dev/js/pkgcloud/node_modules/request/main.js:623:14)\n    at IncomingMessage.EventEmitter.emit (events.js:124:20)\n    at _stream_readable.js:806:12\n    at process._tickCallback (node.js:427:13)',
  name: 'Error',
  provider: 'azure',
  failCode: 'Bad Request',
  result: { err: '<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Code>BadRequest</Code><Message>A disk with name azure-east-us-nodejitsu0-azure-east-us-nodejitsu0-0-20130311141848 is currently in use by virtual machine azure-east-us-nodejitsu0 running within hosted service azure-east-us-nodejitsu0, deployment azure-east-us-nodejitsu0.</Message></Error>' } }

We should probably wait before trying to delete the disk/delete the service first.

/cc @stammen

OpenStack KeyPair API Support

(See: http://api.openstack.org/api-ref.html)

Generates, imports, and deletes SSH keys.

GET v2/{tenant_id}/os-keypairs
View a lists of keypairs associated with the account.

POST v2/{tenant_id}/os-keypairs
Generate or import a keypair.

DELETE v2/{tenant_id}/os-keypairs/{keypair_name}
Delete a keypair.

GET v2/{tenant_id}/os-keypairs/{keypair_name}
Show a keypair associated with the account.

We want this for upstream.

Mock server for tests

The nock-based test fixtures for pkgcloud are becoming large enough that it's worthwhile to refactor them into a stand-alone module that accepts HTTP requests.

Bootstrapper should optionally accept keys with `public` and `private` mappings

This will probably be inconsistent and breaking for Azure once #70 is merged due to how they treat .pem files.

We should take the advice from @stammen in this comment and implement it as accepting both an Array and an Object. e.g.:

New Behavior

  var bootstrapper = new Bootstrapper({
    keys: {
      private: '/path/to/key.pem'
      public: '/path/to/key.pub'
    }
  });

Existing Behavior

  var bootstrapper = new Bootstrapper({
    keys: ['/path/to/key.pem', '/path/to/key.pub']
  });

Create server with OpenStack returns inconsistent response

This is actually somewhat expected as OpenStack requires an additional step after server creation (see: http://api.openstack.org/api-ref.html POST v2/{tenant_id}/servers)

Response JSON

{
    "server": {
        "adminPass": "MVk5HPrazHcG",
        "id": "5bbcc3c4-1da2-4437-a48a-66f15b1b13f9",
        "links": [
            {
                "href": "http://openstack.example.com/v2/openstack/servers/5bbcc3c4-1da2-4437-a48a-66f15b1b13f9",
                "rel": "self"
            },
            {
                "href": "http://openstack.example.com/openstack/servers/5bbcc3c4-1da2-4437-a48a-66f15b1b13f9",
                "rel": "bookmark"
            }
        ]
    }
}

Since there is no .addresses pkgcloud. It would be strange to have one provider always respond with addresses and another not. Maybe we should make this change for consistency?

Not best practice: using for-in construct to iterate over array

This is a tricky bug, because I'm using another great library, Docpad, which sets Array.prototype.remove. I originally reported this issue here, docpad/docpad#441

This causes a problem in pkgcloud in at least place:

pkgcloud/lib/pkgcloud/core/base/client.js

  function sendRequest () {
    //
    // Setup any specific request options before 
    // making the request
    //
    if (self.before) {
      var errors = false;
      for (var i in self.before) {
        var fn = self.before[i];
        try {
          options = fn.call(self, options) || options;  // <----- fn ends up being Array::remove, causes exception
        // on errors do error handling, break.
        } catch (exc) { errs.handle(exc, errback); errors = true; break; }
      }
      if (errors) { return; }
    }

...

I think it is best practice to use "for (var i = 0; i != self.before.length; ++i) { ... }" rather than "for (var i in self.before)" for this reason. But I also know that modifying prototypes isn't always too cool (for exactly reasons like this) too... but, the
"remove" prototype that Docpad adds is a handy one.

Invalid URI on Rackspace Storage?

I am attempting the list the available buckets on my Rackspace Account. As per the documentation I am doing something like this:

this._storage = pkgcloud.storage.createClient(settings.rackspace.server);

this._storage.getContainers(function (err, containers) {
    console.log( util.inspect( err ) );
})

My settings are similar to:

exports.rackspace = 
{
    // Server Settings
    server: {
        provider: 'rackspace',
        username: 'someusername',
        apiKey: 'somekey'
    }
}

But I appear to consistently be getting this error:

[Error: Invalid URI "?format=json"]

I have tried this command and also upload. All seem to be failing with the same/similar error. Is it missing the FULL URI?

Regards:

John

Improve testing - check for failures as well ?

I've noticed that most of the tests focus on successes, almost never on failures. Shouldn't it be something we should be checking as well ? That s a huge job I'm pretty sure of it...

Support more than 1000 servers in Joyent

Currently Joyent API limits number of returned servers to 1000. It also informs us if it returned all servers. We should decide on what to do here - waiting for, say, 8 requests to finish might take too long.

[storage] Adding base storage tests

I'm currently using and mostly interested in Rackspace storage tests. I want to add additional tests to fill out the suite. However when I add a test and subsequently add/fix the Rackspace code to pass the tests, this leaves the other storage clients with failing tests. How should I best address/overcome this? I don't want to push code where I made tests fail.

[rackspace] Add the support for pagination

Recently rackspace added support for pagination to all list operations such instances, databases and users. So I need to add pagination mechanism to pkgcloud on rackspace databases.

Rackspace use a limit parameter to limit the result set, if limit is not specify then 20 is the default value. Also if a result set has more of 20 results a next link is provided, otherwise not link is provided

Any suggestion for how you want the interface call?

Multiple Uploads cause Error Message

I am uploading multiple files using the async library, e.g.:

async.series(
    [
        function(callback){
            self._storage.getContainers(function(err, res){
                callback(err);
            });
        },
        function(callback){
            self.uploadFile(mp4hdSource, mp4hdDest, callback);
        },
        function(callback){
            self.uploadFile(mp4sdSource, mp4sdDest, callback);
        },
        function(callback){
            self.uploadFile(webmhdSource, webmhdDest, callback);
        },
        function(callback){
            self.uploadFile(webmsdSource, webmsdDest, callback);
        }
    ],
    // optional callback
    function(err, results){
        if(err)
        {
            self.onUploadError();
        }
        else
        {
            console.log(clc.magenta('Queue') + ' - S3 uploadComplete');
            //self.uploadComplete();
        }

    }
);

Also note the first task in the 'series' ensures that an internet connection is available, for some reason any type of stream related operation crashes my server if there is no internet connection.

and the uploadFile function is here:

Queue.prototype.uploadFile = function (from, to, callback) {
    var self = this;

    this._storage.upload({
        container: 'otomo',
        local: from,
        remote: to
    }, function(err, res){
        callback(err, res);
    });

}

For some reason the file was failing to upload when using the pipe method which is why I am using the 'local' option.

The error I get now is this:

You have already piped to this stream. Pipeing twice is likely to break the request.

[api] Add support for MongoLab as mongo database provider

According to the needs under nodejitsu/nodejitsu#193 I open this ticket.

Is necessary add to pkgcloud support of MongoLab. The Docs suggest the following features:

  • Create database
  • Create database in differents datacenters (not for this milestone, maybe later)
  • List databases
  • View database
  • Update database (for change the password, or plan)
  • Delete database

I started the work under the mongolab branch, check for review or comments.

[rackspace] CDN/Storage discussion

Over the past couple days I have been looking through Rackspace's Storage/CDN API trying to figure out a good way to setup the CDN API in pkgcloud. From what I have found, Rackspace setup their API in an odd manner. Both Storage and CDN use separate URLs, yet create a coupling in some of the functions. To better explain what I am talking about, lets go through a couple examples.

First Example

Here I am emulating the current storage API except using the CDN URL.

var pkgcloud = require('pkgcloud');

client = pkgcloud.cdn.createClient({
  provider: 'rackspace',
  username: 'nodejitsu',
  apiKey: 'xxxxxxxxxxxxxxxxxxxxxxx'
});

client.getContainers(function (err, containers) {
  if(err) {
    console.err(err);
  } else {
    console.log(container);
  }
});

So what happens in this example is as expected. It outputs an array of CDN enabled storage containers with all of the needed metadata. note This outputs only CDN enabled containers.

var pkgcloud = require('pkgcloud');

client = pkgcloud.storage.createClient({
  provider: 'rackspace',
  username: 'nodejitsu',
  apiKey: 'xxxxxxxxxxxxxxxxxxxxxxx'
});

client.getContainers(function (err, containers) {
  if(err) {
    console.err(err);
  } else {
    console.log(container);
  }
});

Now if you take this same example with the storage API it tells a bit of a different story. This example outputs an Array of all containers (both CDN enabled and not) with very little metadata for all.

Second Example

Now lets look at the case for creating a container. This time we will start with the storage API.

var pkgcloud = require('pkgcloud');

client = pkgcloud.storage.createClient({
  provider: 'rackspace',
  username: 'nodejitsu',
  apiKey: 'xxxxxxxxxxxxxxxxxxxxxxx'
});

client.createContainer('foo', function (err, container) {
  if(err) {
    console.err(err);
  } else {
    console.log(container);
  }
});

This function works as expected. It creates a new container named 'foo' and returns it in the callback.

var pkgcloud = require('pkgcloud');

client = pkgcloud.cdn.createClient({
  provider: 'rackspace',
  username: 'nodejitsu',
  apiKey: 'xxxxxxxxxxxxxxxxxxxxxxx'
});

client.createContainer('bar', function (err, container) {
  if(err) {
    console.err(err);
  } else {
    console.log(container);
  }
});

Now if this same API method was created using the CDN URL, it has some interesting behavior. This function would return a container 'bar' with all of the relevant CDN metadata. What it doesn't tell you is that if you look on the Rackspace website, the CDN container does not actually exist. In order for you as the user to create a CDN enabled container, you must first have created a storage container with the storage URL and then run a 'PUT' request with 'x-cdn-enabled' header set to true.

Now when attempting to follow the model of the storage API to implement CDN interaction, I ran into these oddities. Some can be circumvented with multi-request methods and some cannot (like the first example). Before this drove me crazy that Rackspace has it setup in this manner, I decided to start this issue to see what you guys think. I am relatively new to the project so I am sure you guys have already put in some forethought.

note My observations come from the testing with a live cloud files account

Upload file when offline crashes

Hi:

I am trying to upload files to Rackspace, this works fine, but if the internet connection is down my server crashes with the following error:

/Users/digitaljohn/Documents/projects/rehabstudio/OtomoServer/node_modules/pkgcloud/node_modules/request/main.js:519
  self.req = self.httpModule.request(self, function (response) {
                             ^
TypeError: Cannot call method 'request' of undefined
    at Request.start (/Users/digitaljohn/Documents/projects/rehabstudio/OtomoServer/node_modules/pkgcloud/node_modules/request/main.js:519:30)
    at Request.write (/Users/digitaljohn/Documents/projects/rehabstudio/OtomoServer/node_modules/pkgcloud/node_modules/request/main.js:949:28)
    at ondata (stream.js:38:26)
    at EventEmitter.emit (events.js:96:17)
    at Client.request.buffer.emit (/Users/digitaljohn/Documents/projects/rehabstudio/OtomoServer/node_modules/pkgcloud/lib/pkgcloud/core/base/client.js:181:49)
    at BufferedStream.pipe.process.nextTick.self.size (/Users/digitaljohn/Documents/projects/rehabstudio/OtomoServer/node_modules/pkgcloud/node_modules/morestreams/main.js:28:44)
    at Array.forEach (native)
    at BufferedStream.pipe.piped (/Users/digitaljohn/Documents/projects/rehabstudio/OtomoServer/node_modules/pkgcloud/node_modules/morestreams/main.js:28:17)
    at process.startup.processNextTick.process._tickCallback (node.js:244:9)
BeanBook:OtomoServer digitaljohn$ 

I am having issues finding a way to catch this error and abort the upload and try again later. One would expect the callback to be called with an error rather than totally crash.

Regards:

John

[Auth] Fix rackspace client to return err when unauthorized

from: https://github.com/nodejitsu/pkgcloud/blob/master/lib/pkgcloud/rackspace/client.js#L70-L82

We don't actually check that you've had a valid authentication:

  request(authOptions, function (err, res, body) {
    if (err) {
      return callback(err);
    }

    self.authorized = true;
    self.config.serverUrl = res.headers['x-server-management-url'];
    self.config.storageUrl = res.headers['x-storage-url'];
    self.config.cdnUrl = res.headers['x-cdn-management-url'];
    self.config.authToken = res.headers['x-auth-token'];

    callback(null, res);
  });

Finalize Documentation

Make sure we have proper documentation, examples, code snippets, etc.

Docs for install, use, test, and bug fills, and contributing policy

.gitignore test/fixtures/testkey* breaks npm installed pkgcloud

In order to have a cross platform npm test command, we no longer generate ssh keys as part of the npm test script. This removes the dependency on openssh being installed on the user's computer (windows for example). Sample test keys have been checked into test/fixtures/testkey and test/fixtures/testkey.pub. We need to remove test/fixtures/testkey* in .gitignore so npm install will install the test/fixtures/testkey and test/fixtures/testkey.pub files.

To reproduce:

mkdir test
cd test
npm init test
npm install pkgcloud
cd node_modules/pkgcloud
npm install -d
npm test
Some tests will fail due to missing keys.

However if you git clone the pkgcloud repo the tests will pass as the testkey files are included in the repo.

Please delete test/fixtures/testkey* from .gitignore after reviewing this issue.

Support IrisCouch as a Redis Provider

Hi @cronopio !

Please also add IrisCouch as a Redis provider as part of this refactor.

Thank you,
Nuno

Iris Stack provisioning API.

You have a "partner" username, such as "somepartner" with a password. I would
email those to you. You can log in to Futon and change the password if you like.

https://central.iriscouch.net/_utils/

Anyway you would POST with basic auth, Content-Type:application/json,
to https://hosting.iriscouch.com/hosting_public. For example:

{ "_id":"Server/SERVERNAME",
, "partner": "somepartner"
, "creation": { "first_name": "John"
, "last_name": "Doe"
, "email": "[email protected]"
, "subdomain": "SERVERNAME"
}
}

That's it! The server will be up and we have everything we need to
identify partner servers.

If you query for this document again, it will have all of its data blanked out.
That confirms that the provisioning request is received.

Redis

For a Redis server, change the document id to "Redis/SERVERNAME", and include
an initial password in the creation data.

{ "_id":"Redis/SERVERNAME",
, "partner": "somepartner"
, "creation": { "first_name": "John"
, "last_name": "Doe"
, "email": "[email protected]"
, "subdomain": "SERVERNAME"
, "password": "secret"
}
}

Connect to SERVERNAME.redis.irstack.com on the standard port. Authenticate with
the string "SERVERNAME.redis.irstack.com:" + your password.

For example,

$ redis-cli -h example.redis.irstack.com \
            -a example.redis.irstack.com:secret \
            PING
PONG

Faster connection

We support Redis through a reverse-proxy. Many probaly don't notice, but for
the best performance, connect via the internal IP within the data center.

The [iris-redis][ir] project shows the best way to do this.

$ redis-cli -h example.redis.irstack.com \
            -a example.redis.irstack.com:secret
> keys _config:*
1) "_config:ip"
2) "_config:datacenter"
3) "_config:port"
4) "_config:max_memory"
5) "_config:server"

> get _config:datacenter
"dal01.sl"

> get _config:ip
"10.8.55.66"

> get _config:port
"19788"

Thus if you are in this data center (SoftLayer Dallas 1), then you can connect
instead to 10.8.55.66:19788 and circumvent our proxy. Authentication is the
same; it's just faster.

Redis Password

To change your password, you must make another API call, not currently
documented contact me for details. (It goes through the same system as
resetting CouchDB passwords.)

Data center selection

In the creation data, you may also select a data center. Data centers are only
whitelisted for certain situations (partners).

  • "east1.joyent"
  • "dal01.sl"
  • "us-east-1.aws"

I am on Freenode IRC as JasonSmith, usually in the #couchdb and #iriscouch
channels if you need to contact me.

Use ssh2

We should be using ssh2 by @mscdex instead of spawning ssh processes in our Bootstrapper

I'm unsure about the Bootstrapper use of scp, I've opened this issue on ssh2 to clarify. Worst case I suppose we could use sftp instead of scp, but I'm unsure of the implications.

Rackspace CloudFiles Metadata empty

Dont now if this is a issue of Rackspace or pkgcloud.

With getFiles i get i list of files without additional data (null):

    "name": "f5/f53af8f0df3bd48a586d69554c6691.jpg",
    "etag": null,
    "contentType": null,
    "lastModified": null,
    "bytes": null,
    "size": null

Call for a single file with getFile i receive:

  "name": "f5/f53af8f0df3bd48a586d69554c6691.jpg",
  "etag": "5e3cbffb5b99c5cce2a49a293470b26d",
  "contentType": "image/jpeg",
  "lastModified": "2013-04-08T15:46:59.000Z",
  "bytes": 109213,
  "size": 109213

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.