You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by ct...@apache.org on 2020/01/10 04:32:58 UTC
[accumulo-proxy] branch master updated: Documentation and code
updates (#17)
This is an automated email from the ASF dual-hosted git repository.
ctubbsii pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/accumulo-proxy.git
The following commit(s) were added to refs/heads/master by this push:
new db3a4b2 Documentation and code updates (#17)
db3a4b2 is described below
commit db3a4b2958d36e738dcdee00ca9e9441a31695b0
Author: Mike Walch <mw...@apache.org>
AuthorDate: Thu Jan 9 23:32:52 2020 -0500
Documentation and code updates (#17)
* Moved namespace code from the Accumulo website to namespace_client.py
* Renamed existing python client to basic_client.py
* Moved Java client code/docs from website to docs/java_client.md
* Updated README.md
---
README.md | 14 +-
docs/java_client.md | 80 +++++++++++
src/main/python/{example.py => basic_client.py} | 0
src/main/python/namespace_client.py | 171 ++++++++++++++++++++++++
4 files changed, 261 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 943ed5b..a2a9120 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,7 @@ Thrift language binding).
# Build language specific bindings
-Bindings have been built in `src/main/` for Java, python, and ruby.
+Bindings have been built in `src/main/` for Java, Python, and Ruby.
Bindings for other languages can be built using the Thrift compiler. Follow the [Thrift tutorial]
to install a Thrift compiler and use the following command to generate language bindings.
@@ -62,10 +62,10 @@ cd accumulo-client/
pipenv --python 2.7
pipenv install thrift
pipenv install -e /path/to/accumulo-proxy/src/main/python
-cp /path/to/accumulo-proxy/src/main/python/example.py .
+cp /path/to/accumulo-proxy/src/main/python/basic_client.py .
# Edit credentials if needed
-vim example.py
-pipenv run python2 example.py
+vim basic_client.py
+pipenv run python2 basic_client.py
```
# Create an Accumulo client using Ruby
@@ -83,6 +83,12 @@ bundle install
bundle exec client.rb
```
+# Java clients to Proxy
+
+[Java clients] to the Proxy can be written to limit access to the cluster. The proxy can be placed
+on a server in the cluster and clients can communicate with proxy from outside of the cluster.
+
+[Java clients]: docs/java_client.md
[accumulo]: https://accumulo.apache.org
[Thrift]: https://thrift.apache.org
[Thrift tutorial]: https://thrift.apache.org/tutorial/
diff --git a/docs/java_client.md b/docs/java_client.md
new file mode 100644
index 0000000..18b2c6c
--- /dev/null
+++ b/docs/java_client.md
@@ -0,0 +1,80 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# Java client
+
+After initiating a connection to the Proxy (see Apache Thrift's documentation for examples
+of connecting to a Thrift service), the methods on the proxy client will be available. The
+first thing to do is log in:
+
+```java
+Map password = new HashMap<String,String>();
+password.put("password", "secret");
+ByteBuffer token = client.login("root", password);
+```
+
+Once logged in, the token returned will be used for most subsequent calls to the client.
+Let's create a table, add some data, scan the table, and delete it.
+
+First, create a table.
+
+```java
+client.createTable(token, "myTable", true, TimeType.MILLIS);
+```
+
+Next, add some data:
+
+```java
+// first, create a writer on the server
+String writer = client.createWriter(token, "myTable", new WriterOptions());
+
+//rowid
+ByteBuffer rowid = ByteBuffer.wrap("UUID".getBytes());
+
+//mutation like class
+ColumnUpdate cu = new ColumnUpdate();
+cu.setColFamily("MyFamily".getBytes());
+cu.setColQualifier("MyQualifier".getBytes());
+cu.setColVisibility("VisLabel".getBytes());
+cu.setValue("Some Value.".getBytes());
+
+List<ColumnUpdate> updates = new ArrayList<ColumnUpdate>();
+updates.add(cu);
+
+// build column updates
+Map<ByteBuffer, List<ColumnUpdate>> cellsToUpdate = new HashMap<ByteBuffer, List<ColumnUpdate>>();
+cellsToUpdate.put(rowid, updates);
+
+// send updates to the server
+client.updateAndFlush(writer, "myTable", cellsToUpdate);
+
+client.closeWriter(writer);
+```
+
+Scan for the data and batch the return of the results on the server:
+
+```java
+String scanner = client.createScanner(token, "myTable", new ScanOptions());
+ScanResult results = client.nextK(scanner, 100);
+
+for(KeyValue keyValue : results.getResultsIterator()) {
+ // do something with results
+}
+
+client.closeScanner(scanner);
+```
+
diff --git a/src/main/python/example.py b/src/main/python/basic_client.py
similarity index 100%
rename from src/main/python/example.py
rename to src/main/python/basic_client.py
diff --git a/src/main/python/namespace_client.py b/src/main/python/namespace_client.py
new file mode 100644
index 0000000..1e7e230
--- /dev/null
+++ b/src/main/python/namespace_client.py
@@ -0,0 +1,171 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#! /usr/bin/env python
+
+from thrift.protocol import TCompactProtocol
+from thrift.transport import TSocket, TTransport
+
+from accumulo import AccumuloProxy
+from accumulo.ttypes import NamespacePermission, IteratorSetting, IteratorScope, AccumuloException
+
+def main():
+ transport = TSocket.TSocket('localhost', 42424)
+ transport = TTransport.TFramedTransport(transport)
+ protocol = TCompactProtocol.TCompactProtocol(transport)
+ client = AccumuloProxy.Client(protocol)
+ transport.open()
+ login = client.login('root', {'password': 'secret'})
+
+ client.createLocalUser(login, 'user1', 'password1')
+
+ print client.listNamespaces(login)
+
+ # create a namespace and give the user1 all permissions
+ print 'creating namespace testing'
+ client.createNamespace(login, 'testing')
+ assert client.namespaceExists(login, 'testing')
+ print client.listNamespaces(login)
+
+ print 'testing namespace renaming'
+ client.renameNamespace(login, 'testing', 'testing2')
+ assert not client.namespaceExists(login, 'testing')
+ assert client.namespaceExists(login, 'testing2')
+ client.renameNamespace(login, 'testing2', 'testing')
+ assert not client.namespaceExists(login, 'testing2')
+ assert client.namespaceExists(login, 'testing')
+
+ print 'granting all namespace permissions to user1'
+ for k, v in NamespacePermission._VALUES_TO_NAMES.iteritems():
+ client.grantNamespacePermission(login, 'user1', 'testing', k)
+
+ # make sure the last operation worked
+ for k, v in NamespacePermission._VALUES_TO_NAMES.iteritems():
+ assert client.hasNamespacePermission(login, 'user1', 'testing', k), \
+ 'user1 does\'nt have namespace permission %s' % v
+
+ print 'default namespace: ' + client.defaultNamespace()
+ print 'system namespace: ' + client.systemNamespace()
+
+ # grab the namespace properties
+ print 'retrieving namespace properties'
+ props = client.getNamespaceProperties(login, 'testing')
+ assert props and props['table.compaction.major.ratio'] == '3'
+
+ # update a property and verify it is good
+ print 'setting namespace property table.compaction.major.ratio = 4'
+ client.setNamespaceProperty(login, 'testing', 'table.compaction.major.ratio', '4')
+ props = client.getNamespaceProperties(login, 'testing')
+ assert props and props['table.compaction.major.ratio'] == '4'
+
+ print 'retrieving namespace ID map'
+ nsids = client.namespaceIdMap(login)
+ assert nsids and 'accumulo' in nsids
+
+ print 'attaching debug iterator to namespace testing'
+ setting = IteratorSetting(priority=40, name='DebugTheThings',
+ iteratorClass='org.apache.accumulo.core.iterators.DebugIterator', properties={})
+ client.attachNamespaceIterator(login, 'testing', setting, [IteratorScope.SCAN])
+ setting = client.getNamespaceIteratorSetting(login, 'testing', 'DebugTheThings', IteratorScope.SCAN)
+ assert setting and setting.name == 'DebugTheThings'
+
+ # make sure the iterator is in the list
+ iters = client.listNamespaceIterators(login, 'testing')
+ found = False
+ for name, scopes in iters.iteritems():
+ if name == 'DebugTheThings':
+ found = True
+ break
+ assert found
+
+ print 'checking for iterator conflicts'
+
+ # this next statment should be fine since we are on a different scope
+ client.checkNamespaceIteratorConflicts(login, 'testing', setting, [IteratorScope.MINC])
+
+ # this time it should throw an exception since we have already added the iterator with this scope
+ try:
+ client.checkNamespaceIteratorConflicts(login, 'testing', setting, [IteratorScope.SCAN, IteratorScope.MINC])
+ except AccumuloException:
+ pass
+ else:
+ assert False, 'There should have been a namespace iterator conflict!'
+
+ print 'removing debug iterator from namespace testing'
+ client.removeNamespaceIterator(login, 'testing', 'DebugTheThings', [IteratorScope.SCAN])
+
+ # make sure the iterator is NOT in the list anymore
+ iters = client.listNamespaceIterators(login, 'testing')
+ found = False
+ for name, scopes in iters.iteritems():
+ if name == 'DebugTheThings':
+ found = True
+ break
+ assert not found
+
+ print 'adding max mutation size namespace constraint'
+ constraintid = client.addNamespaceConstraint(login, 'testing',
+ 'org.apache.accumulo.test.constraints.MaxMutationSize')
+
+ print 'make sure constraint was added'
+ constraints = client.listNamespaceConstraints(login, 'testing')
+ found = False
+ for name, cid in constraints.iteritems():
+ if cid == constraintid and name == 'org.apache.accumulo.test.constraints.MaxMutationSize':
+ found = True
+ break
+ assert found
+
+ print 'remove max mutation size namespace constraint'
+ client.removeNamespaceConstraint(login, 'testing', constraintid)
+
+ print 'make sure constraint was removed'
+ constraints = client.listNamespaceConstraints(login, 'testing')
+ found = False
+ for name, cid in constraints.iteritems():
+ if cid == constraintid and name == 'org.apache.accumulo.test.constraints.MaxMutationSize':
+ found = True
+ break
+ assert not found
+
+ print 'test a namespace class load of the VersioningIterator'
+ res = client.testNamespaceClassLoad(login, 'testing', 'org.apache.accumulo.core.iterators.user.VersioningIterator',
+ 'org.apache.accumulo.core.iterators.SortedKeyValueIterator')
+ assert res
+
+ print 'test a bad namespace class load of the VersioningIterator'
+ res = client.testNamespaceClassLoad(login, 'testing', 'org.apache.accumulo.core.iterators.user.VersioningIterator',
+ 'dummy')
+ assert not res
+
+ # revoke the permissions
+ print 'revoking namespace permissions for user1'
+ for k, v in NamespacePermission._VALUES_TO_NAMES.iteritems():
+ client.revokeNamespacePermission(login, 'user1', 'testing', k)
+
+ # make sure the last operation worked
+ for k, v in NamespacePermission._VALUES_TO_NAMES.iteritems():
+ assert not client.hasNamespacePermission(login, 'user1', 'testing', k), \
+ 'user1 does\'nt have namespace permission %s' % v
+
+ print 'deleting namespace testing'
+ client.deleteNamespace(login, 'testing')
+ assert not client.namespaceExists(login, 'testing')
+
+ print 'deleting user1'
+ client.dropLocalUser(login, 'user1')
+
+if __name__ == "__main__":
+ main()