Skip to content

Commit

Permalink
Documentation and code updates (#17)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
mikewalch authored and ctubbsii committed Jan 10, 2020
1 parent 32e2c09 commit db3a4b2
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 4 deletions.
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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/
Expand Down
80 changes: 80 additions & 0 deletions docs/java_client.md
Original file line number Diff line number Diff line change
@@ -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);
```

File renamed without changes.
171 changes: 171 additions & 0 deletions src/main/python/namespace_client.py
Original file line number Diff line number Diff line change
@@ -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()

0 comments on commit db3a4b2

Please sign in to comment.