Code Monkey home page Code Monkey logo

etcd3's Introduction

etcd3 Run Tests

etcd3 is a high-quality, production-ready client for the Protocol Buffer-based etcd v3 API. It includes:

and is type-safe for TypeScript consumers.

Quickstart

Install via:

npm install --save etcd3

Start building!

const { Etcd3 } = require('etcd3');
const client = new Etcd3();

(async () => {
  await client.put('foo').value('bar');

  const fooValue = await client.get('foo').string();
  console.log('foo was:', fooValue);

  const allFValues = await client.getAll().prefix('f').keys();
  console.log('all our keys starting with "f":', allFValues);

  await client.delete().all();
})();

API Documentation

Our TypeDoc docs are available here.

Our test cases are also readable.

Running tests

$ npm install
$ cd src/test/containers/3.2 && docker-compose up # in a separate shell
$ npm test
$ docker-compose down

Contributing

Running tests for this module requires running an etcd3 server locally. The tests try to use the default port initially, and you can configure this by setting the ETCD_ADDR environment variable, like export ETCD_ADDR=localhost:12345.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

etcd3's People

Contributors

connor4312 avatar dependabot[bot] avatar doridian avatar gespispace avatar godu avatar hexta avatar keonhee avatar meredian avatar microsoft-github-policy-service[bot] avatar mlerner avatar monkbroc avatar moonrailgun avatar nlsun avatar rezochiang avatar shakefu avatar srz09 avatar tlhunter avatar xadillax avatar yehiyam avatar yujuiting avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

etcd3's Issues

cant set ttl when using lock

var lock = client.lock('foo');
lock.ttl(3); //this will throw an exception "Cannot set a lock TTL after acquiring the lock"
lock.then(...)

solution:
src/lock.ts function ttl(
if (!this.lease) => if(this.lease)

running get and watch on directories

Hello!
It seems like the .get and .watch commands only work for a specific key and not the directory although etcd does have this functionality. Am I missing something in the docs or is this a feature that hasn't been implemented yet? I'd be open to implement it if so!

watcher can't reconnect after disconnection

etcd version: 3.3.5
etcd3: 0.2.11

Server log: etcdserver/api/v3rpc: failed to receive watch request from gRPC stream ("rpc error: code = Canceled desc = context canceled")

How can I fix that bug?

I want to reconnect correctly to etcd cluster, but can't reconnect.

And watcher can't get any event from cluster.

How can a let a lease to expire automatically?

When I use the client.lease(ttl) api, it automatically keeps it alive before the TTL ends using an setTimeout. But what if I do want the leasing to end and automatically revoke all the keys attached to it? I can't find an options to make it happens.

Leases sometimes get stuck in a loop after the lease expires

I've seen this happen twice in in the past several months:

Uncaught error: EtcdError: etcdserver: requested lease not found
    at /Users/copeet/Github/chat/node_modules/grpc/src/node/src/client.js:554:15
Uncaught error: EtcdError: etcdserver: requested lease not found
    at /Users/copeet/Github/chat/node_modules/grpc/src/node/src/client.js:554:15
Uncaught error: EtcdError: etcdserver: requested lease not found
    at /Users/copeet/Github/chat/node_modules/grpc/src/node/src/client.js:554:15

...forever

Getting error when tried with tls

Getting below error when tried with tls.

E1108 12:08:41.067409000 140736133522368 ssl_transport_security.c:177] ssl_info_callback: error occured.

E1108 12:08:41.087651000 140736133522368 ssl_transport_security.c:921] Handshake failed with fatal error SSL_ERROR_SSL: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure.
(node:17954) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Connect Failed
(node:17954) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

and in etcdserver i'm getting this error for same request

etcdmain: rejected connection from "127.0.0.1:60846" (tls: no cipher suite supported by both client and server) 

Same certs/keys worked fine when I tried with golang library https://github.com/coreos/etcd/tree/master/clientv3

Any help would be appreciated
thanks in advance

Q: Is it the right way to create and update lease?

I want to create lease and then update its value every 3-4 minutes..

// create the lease
async createLease(options) {
        if (this._lease && !this._lease.revoked()) {
            throw new Error('cannot register twice');
        }
        this._lease = this._client.lease(options.ttl);
        this._lease.on('lost', err => {
            this.createLease(options);
        })
        await this.updateLease({ path: options.path, value: options.value });
        await this._lease.keepaliveOnce();
        }


     // I want to call this method when I need to change the value of the lease
     async updateLease(options) {
        return this._lease.put(options.path).value(JSON.stringify(options.value));
    }

Watch always returns watch_id=0

For the cancel watch to work, the watch_id field needs to be saved.
From what I can see, the watch_id is always 0 (the default value?). This causes the cancelWatch gRPC method to always have id 0.
It seems that watchResponse message is too short. It only decodes the messageHeader
I'm not familiar with gRPC so I might be missing something.
Could you take a look?
Thanks

watch grpc stream stays open after the last watcher is canceled

Following my conclusion from #61 I saw that when the last watch is canceled, the gRPC stream on the client side is closed, and a new one is created when a new watch is requested.
Looking at the etcd prometheus metric etcd_debugging_mvcc_watch_stream_total, the watch stream in the server is not closed, and the count is increasing until the client process exit.
This leads to resource leak in the server.

grpc version 1.9.0 breaks getAll()

I don't have a good unit test, but the following sequence throws an error:
etcd.getAll().prefix(myPrefix).strings().then() --> Error: Argument mismatch in makeUnaryRequest

I can dig deeper if needed, but my guess is you just need to fix your dependency for now.

Lock API does not allow locking from one process and unlocking from another process

Hi,

What my use-case is that I want to lock a particular resource from one process and unlock it from another process. Currently, one can lock it like this.

const lock = client.lock('mylock2');
lock.ttl(10).acquire()
    .then(lock => {
        console.log(lock);
    })
    .catch(e => console.error("ERROR in aquiring lock, {}", e));

But in order to unlock, one will have use the same lock object, we wont be possible if I want to unlock it from a different process.

Is there a way to achieve it or can you expose the lease ID so that lock object can be created from the lease ID as well and unlock can be called on that?

Give the metadata to both Watch and Lease

I checked your code and you forgot to give the metadata to the Watch client

/* rpc#WatchClient */
watch() {
    return this.client.getConnection('Watch').then(cnx => cnx.client.watch());
}

Should be

/* rpc#WatchClient */
watch() {
    return this.client.getConnection('Watch').then(cnx => cnx.client.watch(cnx.metadata));
}

Same things for LeaseClient#leaseKeepAlive

etcd3 v0.2.1 packaging failure

I try use etcd3 v0.2.1. but etcd3 package cannot be installed.

client.patch.js is missing in package?

$ npm i etcd3

> [email protected] install /home/akihiro/test-etcd3/node_modules/grpc
> node-pre-gyp install --fallback-to-build --library=static_library

[grpc] Success: "/home/akihiro/test-etcd3/node_modules/grpc/src/node/extension_binary/grpc_node.node" is installed via remote

> [email protected] install /path/to/node_modules/etcd3
> node client.patch.js

module.js:471
    throw err;
    ^

Error: Cannot find module '/home/akihiro/test-etcd3/node_modules/etcd3/client.patch.js'
    at Function.Module._resolveFilename (module.js:469:15)
    at Function.Module._load (module.js:417:25)
    at Module.runMain (module.js:604:10)
    at run (bootstrap_node.js:393:7)
    at startup (bootstrap_node.js:150:9)
    at bootstrap_node.js:508:3
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm ERR! Linux 4.9.0-3-amd64
npm ERR! argv "/home/akihiro/.nvm/versions/node/v6.10.1/bin/node" "/home/akihiro/.nvm/versions/node/v6.10.1/bin/npm" "i" "etcd3"
npm ERR! node v6.10.1
npm ERR! npm  v3.10.10
npm ERR! code ELIFECYCLE

npm ERR! [email protected] install: `node client.patch.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] install script 'node client.patch.js'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the etcd3 package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node client.patch.js
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs etcd3
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls etcd3
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /home/akihiro/test-etcd3/npm-debug.log

Cannot use user/pass auth w/o ssl

Tried to create client like this:

new Etcd3({ hosts: conf.etcdurl, auth: { username: 'readonly', password: 'readonly' } })

Error is like this:

unexpected error:  TypeError: Cannot compose insecure credential
    at Object.exports.combineChannelCredentials (/Users/xxx/node_modules/grpc/src/node/src/credentials.js:151:23)
    at getCredentialsFromHost.then.token (/Users/xxx/node_modules/etcd3/lib/src/connection-pool.js:62:41)
    at <anonymous

Maybe this is related: https://stackoverflow.com/questions/37526077/how-to-add-metadata-to-nodejs-grpc-call

Possible failure to detect etcd lease destruction

I noticed this morning that etcd lost the lease used for service discovery on my local instance of our chat server. Chat's last report of the lease being lost and reestablished yesterday. Etcd was empty and when sending SIGINT (which tears down the lease in a graceful shutdown) it errored that the lease was not found in etcd. Seems like it never detected that yesterday's lease was timed out.

{"name":"chat","hostname":"hera.peet.io","pid":18186,"level":30,"err":{"message":"Lease 7587822556486125056 is expired or revoked","name":"Error","stack":"Error: Lease 7587822556486125056 is expired or revoked\n    at EtcdLeaseInvalidError (/Users/copeet/Github/chat/node_modules/etcd3/lib/src/errors.js:71:9)\n    at ClientDuplexStream.stream.on.res (/Users/copeet/Github/chat/node_modules/etcd3/lib/src/lease.js:158:33)\n    at emitOne (events.js:96:13)\n    at ClientDuplexStream.emit (events.js:188:7)\n    at readableAddChunk (_stream_readable.js:176:18)\n    at ClientDuplexStream.Readable.push (_stream_readable.js:134:10)\n    at readCallback (/Users/copeet/Github/chat/node_modules/etcd3/node_modules/grpc/src/node/src/client.js:245:14)"},"msg":"Etcd3 lease lost, attempting to re-grant","time":"2017-06-08T17:22:58.238Z","v":0}
{"name":"chat","hostname":"hera.peet.io","pid":18186,"level":30,"msg":"Ectd3 lease re-established","time":"2017-06-08T17:22:58.290Z","v":0}
^CUncaught error: EtcdError: etcdserver: requested lease not found
    at /Users/copeet/Github/chat/node_modules/etcd3/node_modules/grpc/src/node/src/client.js:434:17
Uncaught error: EtcdError: etcdserver: requested lease not found
    at /Users/copeet/Github/chat/node_modules/etcd3/node_modules/grpc/src/node/src/client.js:434:17
Failed to handle shutdown: EtcdError: etcdserver: requested lease not found
    at /Users/copeet/Github/chat/node_modules/etcd3/node_modules/grpc/src/node/src/client.js:434:17
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: `tsc && node dist/index`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/copeet/.npm/_logs/2017-06-09T16_09_43_535Z-debug.log

Application level heartbeat

In some cases (code errors, network errors, etc.), the watcher may silently hang. As one of the security tools etcd offers an application level heartbeat based on the progress_notify parameter when creating a watcher.
Perhaps such a functional would be useful in the library.

As far as I know, this approach is used, at least in libraries, to RabbitMQ to detect network problems.
I created a question to clarify how this option works: etcd-io/etcd#8495

Why keepalive fire lost after twice ttl

if (Date.now() - this.lastKeepAlive > 2 * 1000 * this.ttl) {
            this.close();
            this.emit('lost', new errors_1.GRPCConnectFailedError('We lost connection to etcd and our lease has expired.'));
            return;
        }

This code is in lease.js keepalive, and why lost is fired after twice TTL?
Even if thinking about far past the end of our key's TTL, I think 3s is ok.

No way to put multiple keys under folder

The put method just provide the put with the key, values as strings. Is there a way to store multiple keys under the single folder to group create/retrieve them ?

TLS with self signed certificate

I tried reading our CA cert from a pem formated x509 certificate file and providing to the client in the credentials property of the options argument. I receive a handshake error, SSL_ERROR_SSL: error:14094410:SSL. I have the same certificate as a .der encoded file, that yields a different error and hangs, Could not load any root certificate.

Not sure if my cert encoding is off. These same certificate works with other etcd libraries, including the etcd v2 plugin for nconf.

Watcher cannot specify starting revision.

This is keenly important to avoid having to use locking. This is trivial to fix in WatchBuilder class by adding something like this to it:

public fromRevision(revision: string, increment: number) {
    this.request.start_revision = new BigNumber(revision).add(increment).toString();
    return this;
}

The revision I am passing in here is from a previous call to get all of the keys under a prefix. I want to be able to tell it to use that revision plus one (hence the increment). I'm not sure if that is a string or whatnot. I would have done a pull request myself, but I've not dabbled in Typescript, and when I tried to run the tests unmodified they blew up on me.

Maximum call stack size exceeded

Trying to run npm run build:proto and got error

> [email protected] build:proto /Users/sebastien/Documents/github/mixer
> node ./bin/update-proto ./proto && node bin/generate-methods.js ./proto/rpc.proto > src/rpc.ts

RangeError: Maximum call stack size exceeded
    at String.replace (<anonymous>)
    at stripPackageNameFrom (/Users/sebastien/Documents/github/mixer/bin/generate-methods.js:98:17)
    at MessageCollection.find (/Users/sebastien/Documents/github/mixer/bin/generate-methods.js:63:27)
    at _.values.map.f (/Users/sebastien/Documents/github/mixer/bin/generate-methods.js:233:24)
    at arrayMap (/Users/sebastien/Documents/github/mixer/node_modules/lodash/lodash.js:660:23)
    at Function.map (/Users/sebastien/Documents/github/mixer/node_modules/lodash/lodash.js:9571:14)
    at interceptor (/Users/sebastien/Documents/github/mixer/node_modules/lodash/lodash.js:16970:35)
    at Function.thru (/Users/sebastien/Documents/github/mixer/node_modules/lodash/lodash.js:8812:14)
    at /Users/sebastien/Documents/github/mixer/node_modules/lodash/lodash.js:4379:28
    at arrayReduce (/Users/sebastien/Documents/github/mixer/node_modules/lodash/lodash.js:704:21)
    at baseWrapperValue (/Users/sebastien/Documents/github/mixer/node_modules/lodash/lodash.js:4378:14)
    at LodashWrapper.wrapperValue (/Users/sebastien/Documents/github/mixer/node_modules/lodash/lodash.js:9067:14)

I'm trying to do that because I had to change the file bin/template/duplex-stream-method.tmpl to allow add metadata when client function are called.

Notes: Even without my changes I got the error

Lock never unlocks with lease

Hi, we're trying to use distributed locking in a project but we're having some trouble getting them to work. Maybe we don't get how they're supposed to work. We have a little test case here that should reproduce the problem:

package main

import (
	"context"
	"fmt"
	"log"

	"time"

	"github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/clientv3/concurrency"
)

func main() {
	cli, err := clientv3.New(clientv3.Config{Endpoints: []string{"localhost:2379"}})
	if err != nil {
		log.Fatal(err)
	}
	defer cli.Close()

	// get a grant
	ctxc, cancelc := context.WithTimeout(context.Background(), 1*time.Second)
	lresp, err := cli.Grant(ctxc, 2)
	if err != nil {
		log.Fatal(err)
	}
	defer cancelc()
	fmt.Println("lease", lresp.ID)

	// create two separate sessions for lock competition
	s1, err := concurrency.NewSession(cli, concurrency.WithLease(lresp.ID))
	if err != nil {
		log.Fatal(err)
	}
	defer s1.Close()
	m1 := concurrency.NewMutex(s1, "/xxxsx/")

	s2, err := concurrency.NewSession(cli)
	if err != nil {
		log.Fatal(err)
	}
	defer s2.Close()
	m2 := concurrency.NewMutex(s2, "/xxxsx/")

	// acquire lock for s1
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	if err := m1.Lock(ctx); err != nil {
		log.Fatal("timeout", err)
	}
	defer cancel()
	fmt.Println("acquired lock for s1")

	m2Locked := make(chan struct{})
	go func() {
		defer close(m2Locked)
		// wait until s1 is unlocked /xxxsx/
		if err := m2.Lock(context.TODO()); err != nil {
			log.Fatal(err)
		}
	}()

	<-m2Locked
	fmt.Println("acquired lock for s2")
}

As you can see, we get a grant with a TTL of 2 seconds :

lresp, err := cli.Grant(ctxc, 2)

And this lease is used when we create the section:

s1, err := concurrency.NewSession(cli, concurrency.WithLease(lresp.ID))

We manage to acquire the lock correctly the first time, but the second Lock (from a goroutine) never returns.

Shouldn't the lock be unlocked when the lease expires?

Add more examples

Hey. I'm joining forces today and I'm redirecting my etcd-grpc client to this package because I see that you've already added support for all the available etcd v3 services. That's awesome!

What I would propose is that you add more step-by-step examples and in depth explanation on how things work, because the current documentation isn't always clear and you have to read the source code all the time to really understand what's happening.

client.watch() not a function?

Using [email protected] I'm trying the following:

var etcd = require('etcd3');
var client = new etcd.Etcd3();
var watcher = client.watch().key(new Buffer('/')).create();

I get "TypeError: client.watch is not a function". Am I doing something wrong?

Feature request: API for software transactional memory (STM)

The golang client provides an implementation of STM. This API is very useful for applications that update a lot of related keys in parallel.

For example, in my application several administrators can modify the system settings in parallel. However, some settings are related.

Now it has to be implemented manually, because of what the convenience of the API provided by this library is lost (I mean the .json() method and others)

More information about the topic:

https://coreos.com/blog/transactional-memory-with-etcd3.html
https://godoc.org/github.com/coreos/etcd/clientv3/concurrency#STM

How to watch historical changes of keys

I want to synchronous data from etcd to node.js application.
But if I watch the key after getting it, I think the change that occurs during get() and watch() may be lost.
And if I can watch the historical change, the task of synchronizing data will be simply resolved.
And I found the official website of etcd shows an example as follows.
etcdctl watch --rev=2 foo
this command could watch the historical changes.
Or is there any other way can help synchronous data without losing change event.

Q: where can i set ttl value?

I know in node-etcd (v2) lib that i could use etcd.set(key, value, {ttl: 10}) to set ttl value.
But I did't found anywhere to set ttl value here in etcd3 lib.

After reconnect watchers no receive events

My code is:

        const watcher = await etcd.watch().prefix('...').create();

        watcher.on('put', (res) => {
          console.log('put');
        });

        watcher.on('delete', (res) => {
           console.log('delete');
        });
        watcher.on('disconnected', () => console.log('disconnected...'));
        watcher.on('connected', () => console.log('successfully reconnected!'));

In normal case this code work is correct. After stop and start etcd on console i see this lines:

disconnected...
successfully reconnected!

But the events no longer come.

Add available to setup request option

GRPC allows set request options, for example deadline.
lib.service.method(requestData, requestOptions, callback);

Please add method addRequestOptions to your Builders, or create other avaliability for setting request options.

Not all Etcd3 class methods accessible

I noticed that the client.if() method and some other methods are undefined. In the source code looks like it should work but the npm package doesn't provide it.

const etcd = new Etcd3();
console.log(etcd.if) // -> undefined

GRPCConnectFailedError: Connect Failed

This is my constructor code

const etcd = new Etcd3({
	hosts: ['https://example1.com:4758', 'https://example2.com:4758', 'https://example3.com:4758'],
	auth: {username: username, password: pwd},
});

And I got this error

GRPCConnectFailedError: Connect Failed\n    at /media/zyf/data/Programming/project/duobei/duobeiyun-mobile-server/node_modules/etcd3/node_modules/grpc/src/node/src/client.js:569:15

What happened?

Watch after cancel not working

My code:

const { Etcd3 } = require('etcd3');
const uuidv4 = require('uuid/v4');
const path = `path-${uuidv4()}`;
const client = new Etcd3({ hosts: 'http://localhost:4001' });
let watcher;

const watch = async (path) => {
    watcher = await client.watch().prefix(path).create();
}

const unwatch = async () => {
    await watcher.cancel();
}

const test = async () => {
    await watch(path);
    console.log(`success watch`);

    await unwatch();
    console.log(`success unwatch`);

    await watch(path); // this does not resolved
    console.log(`success watch`);
}

test();

This test prints:
success watch
success unwatch

I would expect:
success watch
success unwatch
success watch

What I'm doing wrong?

typescript compling error

node_modules/etcd3/lib/src/connection-pool.d.ts(16,98): error TS2694: Namespace '"grpc"' has no exported member 'ChannelOptions'.
node_modules/etcd3/lib/src/options.d.ts(2,10): error TS2305: Module '"grpc"' has no exported member 'ChannelOptions'.
node_modules/etcd3/lib/src/rpc.d.ts(13,43): error TS2694: Namespace '"grpc"' has no exported member 'StatusMessage'.

etcd3: 0.2.7
typescript: 2.6.2

Auth not working

I'm attempting to read a value from a hosted etcd cluster with a proxy in front (compose.io), but it seems to hang and I'm not really sure what it's doing. I have tested with etcdctl and it works.

Here's the code I'm using to test. Any ideas?

const { Etcd3 } = require('etcd3')                                                                                                                                                                                                                                             const client = new Etcd3({
    hosts: 'https://etcd-proxy.domain.com:1234',
    auth: {
        username: 'user',
        password: 'password'
    }
})

console.log("getting...")
client.get('test/test1').string().then(value => {
    console.log(value)
})

lease default ttl of undefined causes infinite loop

Using v0.2.9, I'm using the same code as in the documentation to acquire a lease:

const lease = client.lease();

https://mixer.github.io/etcd3/classes/lease_.lease.html

But this causes the lease TTL to be undefined which causes an infinite loop for me. Code to reproduce:

const { Etcd3 } = require('etcd3');

const client = new Etcd3({ hosts: 'myhostname:2379' });
const lease = client.lease();
    
lease.on('lost', err => {
  console.log('etcd: lost', err);
});

lease.on('keepaliveFired', () => {
  console.log('etcd: keepaliveFired');
});

lease.on('keepaliveSucceeded', () => {
  console.log('etcd: keepaliveSucceeded');
});

lease.on('keepaliveFailed', () => {
  console.log('etcd: keepaliveFailed');
});

lease.on('keepaliveEstablished', () => {
  console.log('etcd: keepaliveEstablished');
});

It does work correctly if I give it a ttl like client.lease(8) does not cause an issue. But it took me a bit to figure this out, so I wanted to let you know. Maybe clarify documentation?

client.close() dont close gRPC connection

I cannot manage to stop node thread when a etcd3's watcher is running. gRPC connection don't seem to be closed and keep thread alive.

Way to reproduce

const {Etcd3} = require('etcd3');

const client = new Etcd3();

const watcher$ = client
  .watch()
  .prefix('')
  .create();

watcher$.then(async watcher => {
  console.log('watcher.cancel');
  await watcher.cancel();
  console.log('client.close');
  client.close();
});
# lsof -i tcp:2379 -n -P | grep node
node    35687 arthurweber   13u  IPv4 0x181b472d2650f03f      0t0  TCP 127.0.0.1:59146->127.0.0.1:2379 (ESTABLISHED)

Watcher becomes unresponsive but no events

I found that my watchers on prefixes were becoming unresponsive but not emitting "disconnected" or "error" or any event for that matter. It's very hard to reproduce but in my testing, I now have one container updating the value of a key on etcd every twenty minutes. I created six containers that each watch with a prefix of that key. Over the course of a few hours, one or two of those containers' watchers will stop seeing the put events.

Have you seen this behavior happen and/or are there suggestions for how to mitigate this or get better logging on why this might be happening?

etcd3 errors when no servers are running locally

from @SimonSchick

TypeError: Cannot read property 'availableAfter' of undefined
    at util_1.minBy.r (XXX/node_modules/etcd3/lib/src/shared-pool.js:45:61)
    at Object.minBy (XXX/node_modules/etcd3/lib/src/util.js:7:15)
    at SharedPool.pull (XXX/node_modules/etcd3/lib/src/shared-pool.js:45:38)
    at ConnectionPool.getConnection (XXX/node_modules/etcd3/lib/src/connection-pool.js:132:26)
    at ConnectionPool.exec (XXX/node_modules/etcd3/lib/src/connection-pool.js:105:21)
    at LeaseClient.leaseGrant (XXX/node_modules/etcd3/lib/src/rpc.js:76:28)
    at Lease (XXX/node_modules/etcd3/lib/src/lease.js:52:14)
    at Etcd3.lease (XXX/node_modules/etcd3/lib/src/index.js:57:16)
    at Discovery.start (XXX/dist/discovery.js:24:46)
    at Lease.lease.on.err (XXX/dist/discovery.js:28:18)
    at emitOne (events.js:96:13)
    at Lease.emit (events.js:188:7)
    at Lease.leaseID.client.leaseGrant.then.catch.err (XXX/node_modules/etcd3/lib/src/lease.js:60:18)

Enable auth with http

Hi

I try to use your library to connect etcd but it always fail to do something.

We are using http but we have an authentication with username + password to access it.

When I let the library as it is, I get:

Error: grpc does not allow you to use password authentication without connecting over SSL.

But when I comment the related line in the file connection-pool.js:

buildAuthentication() {
        const { credentials } = this.options;
        let protocolCredentials = grpc.credentials.createInsecure();
        if (credentials) {
            protocolCredentials = grpc.credentials.createSsl(credentials.rootCertificate, credentials.privateKey, credentials.certChain);
        }
        else if (this.hasSecureHost()) {
            protocolCredentials = grpc.credentials.createSsl();
        }
        // else if (this.options.auth) {
        //     throw new Error('grpc does not allow you to use password authentication without connecting ' +
        //         'over SSL. See how to set up etcd with ssl here: https://git.io/v7uhX');
        // }
        return this.authenticator.augmentCredentials(protocolCredentials);
    }

It does not throw any error AND I can not perform any action with this snippet of code:

const { Etcd3 } = require('etcd3');
const client = new Etcd3({
    hosts: 'http://my.domain.com:2379',
    auth: {
        username: 'my_username',
        password: 'my_password'
    }
});

client
  .get('foo')
  .string()
  .then(_ => console.log('GOT => ', _))
  .catch(err => console.log('ERR => ', err));

It is always waiting for something that didn't come...

If you have any idea how I can do to get a result, it would be very cool !

Thanks

`.json()` cannot put/get `NaN` correctly.

When using '.json()', NaN is parsed as null.

my wrapper

import { Etcd3 } from 'etcd3'
import { posix as path } from 'path'
export class EtcdClient<T> {
    client: Etcd3
    static QUEUE_PREFIX = 'queue'
    constructor(protected rootPath: string = '/') {
        this.client = new Etcd3({
            hosts: [ '127.0.0.1:2379' ]
        })
        if (!path.isAbsolute(this.rootPath)) {
            throw new Error(`the rootPath must be a absolute posix path. but got ${this.rootPath}`)
        }
    }
    protected finalKey(key: string, postfix: string = '') {
        return path.join(this.rootPath, key, postfix)
    }
    async get(key: string): Promise<object|null> {
        return await this.client
            .get(this.finalKey(key))
            .json()
    }
    async put(key: string, value: T) {
        return await this.client
            .put(this.finalKey(key))
            .value(JSON.stringify(value))
            .exec()
    }
    async destroy() {
        this.client.close()
    }
}

the test code

import { expect } from 'chai'
import { EtcdClient } from './EtcdClient'

describe.only('', () => {
    describe('function', () => {
        const key = '__test_key'
        const body = {
            a: null, 
            b: NaN, 
            c: 1,
            d: true,
            e: 'string', 
            f: [], 
            g: {},
            h: [1, 2, 3],
            i: [null, null],
            j: [undefined, undefined],
            k: [1, 2],
            l: [NaN, NaN],
            m: [999999999999999999999999999999999999999, 999999999999999999999999999999999999999],
            n: [true, false],
            o: ['', ''],
            p: ['stringA', 'stringB'],
            q: [[], [1]],
        }
        let client: EtcdClient<typeof body>
        beforeEach(async () => {
            client = new EtcdClient<typeof body>('/test')
        })
        afterEach(async () => {
            await client.destroy()
        })
        it('get & set', async () => {
            await client.put(key, body)
            const resp = await client.get(key)
            expect(resp).to.eql(body)
        })
    })
})

the output

 1) function get & set:

     AssertionError: expected { Object (a, b, ...) } to deeply equal { Object (a, b, ...) }
     + expected - actual

      {
        "a": [null]
     -  "b": [null]
     +  "b": NaN
        "c": 1
        "d": true
        "e": "string"
        "f": []
          [null]
          [null]
        ]
        "j": [
     -    [null]
     -    [null]
     +    [undefined]
     +    [undefined]
        ]
        "k": [
          1
          2
        ]
        "l": [
     -    [null]
     -    [null]
     +    NaN
     +    NaN
        ]
        "m": [
          1e+39
          1e+39

     at Object.<anonymous> (src\crawler\storage\EtcdClient.test.ts:47:29)
     at Generator.next (<anonymous>)
     at fulfilled (src\crawler\storage\EtcdClient.test.ts:4:58)
     at <anonymous>

Node v10.6.0

After upgrading to Node v10.6.0 - got this message:
(node:32397) DeprecationWarning: grpc.load: Use the @grpc/proto-loader module with grpc.loadPackageDefinition instead.

Everything works fine, but just want let you know
Thanks.

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.