Commit Graph

19322 Commits

Author SHA1 Message Date
Piotr Sarna
176b7dfd17 alternator-test: add batch writing test case
Message-Id: <a950799dd6d31db429353d9220b63aa96676a7a7.1557914382.git.sarna@scylladb.com>
2019-08-19 15:48:17 +03:00
Piotr Sarna
30d4b4e689 alternator: add basic BatchWriteItem
The initial implementation only supports PutRequest requests,
without serving DeleteRequest properly.
Message-Id: <451bcbed61f7eb2307ff5722de33c2e883563643.1557914382.git.sarna@scylladb.com>
2019-08-19 15:48:17 +03:00
Nadav Har'El
3b73c49ac8 alternator: improve where DescribeEndpoints gets its information
Instead of blindly returning "localhost:8000" in response to
DescribeEndpoints and for sure causing us problems in the future,
the right thing to do is to return the same domain name which the
user originally used to get to us, be it "localhost:8000" or
"some.domain.name:1234". But how can we know what this domain name
was? Easy - this is why HTTP 1.1 added a mandatory "Host:" header,
and the DynamoDB driver I tested (boto3) adds it as expected,
indeed with the expected value of "localhost:8000" on my local setup.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:17 +03:00
Nadav Har'El
b556356a7d alternator-test: test for sort order of items in a single partition
Although different partitions are returned by a Scan in (seemingly)
random order, items in a single partition need to be returned sorted
by their sort key. This adds a test to verify this.

This patch adds to the filled_test_table fixture, which until now
had just one item in each partition, another partition (with the key
"long") with 164 additional items. The test_scan_sort_order_string
test then scans this table, and verifies that the items are really
returned in sorted order.

The sort order is, of course, string order. So we have the first
item with sort key "1", then "10", then "100", then "101", "102",
etc. When we implement numeric keys we'll need to add a version
of this test which uses a numeric clustering key and verifies the
sort order is numeric.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:17 +03:00
Nadav Har'El
90c12b4ea3 alternator: fix clustering key setup
Because of a typo, we incorrectly set the table's sort key as a second
partition key column instead of a clustering key column. This has bad
but subtle consequences - such as that the items are *not* sorted
according to the sort key. So in this patch we fix the typo.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:17 +03:00
Nadav Har'El
287a986715 alternator: add initial implementation of DescribeEndpoints
DescribeEndpoints is not a very important API (and by default, clients
don't use it) but I wanted to understand how DynamoDB responds to it,
and what better way than to write a test :-)

And then, if we already have a test, let's implement this request in
Scylla as well. This is a silly implementation, which always returns
"localhost:8000". In the future, this will need to be configurable -
we're not supposed here to return *this* server's IP address, but rather
a domain name which can be used to get to all servers.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:17 +03:00
Nadav Har'El
9b46c6ac2d alternator: unify and improve TableName field handling
Most of the request types need to a TableName parameter, specifying the
name of the table they operate on. There's a lot of boilerplate code
required to get this table name and verify that it is valid (the parameter
exists, is a string, passes DynamoDB's naming rules, and the table
actually exists), which resulted in a lot of code duplication - and
in some cases missing checks.

So this patch introduces two utility functions, get_table_name()
and get_table(), to fetch a table name or the schema of an existing
table, from the request, with all necessary validation. If validation
fails, the appropriate api_error() is thrown so the user gets the
right error message.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:17 +03:00
Nadav Har'El
f0436aeecc alternator-test: clean up conftest.py
Remove unused random-string code from conftest.py, and also add a
TODO comment how we should speed up filled_test_table fixture by
using a batch write - when that becomes available in Alternator.
(right now this fixture takes almost 4 seconds to prepare on a local
Alternator, and a whopping 3 minutes (!) to prepare on DynamoDB).

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:17 +03:00
Piotr Sarna
e3ba65003d alternator-test: add initial scan test
Message-Id: <c28ff1d38930527b299fe34e9295ecd25607398c.1557757402.git.sarna@scylladb.com>
2019-08-19 15:48:17 +03:00
Piotr Sarna
d25a07a6c0 alternator-test: add filled test table fixture
The fixture creates a test table and fills it with random data,
which can be later used for testing reads.
Message-Id: <649a8b8928e1899c5cbd82d65d745a464c1163c8.1557757402.git.sarna@scylladb.com>
2019-08-19 15:48:17 +03:00
Piotr Sarna
426f53bc89 alternator: implement basic scan
The most basic version of Scan request is implemented.
It still contains a list of TODOs, among which the support for Segments
parameter for scan parallelism.
Message-Id: <5d1bfc086dbbe64b3674b0053e58a0439e64909b.1557757402.git.sarna@scylladb.com>
2019-08-19 15:48:17 +03:00
Piotr Sarna
1d85558d47 alternator: lower debug messages verbosity in the HTTP server
The HTTP server still uses WARN log level to log debug messages,
which is way higher than necessary. These messages are degraded
to TRACE level.
Message-Id: <59559277f2548d4046001bebff45ab2d3b7063b5.1557744617.git.sarna@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
1c7b1ac165 alternator-test: simplify test_put_and_get_attribute_types
The test test_put_and_get_attribute_types needlessly named all the
different attributes and their variables, causing a lot of repetition
and chance for mistakes when adding additional attributes to the test.

In this rewrite, we only have a list of items, and automatically build
attributes with them as values (using sequential names for the attributes)
and check we read back the same item (Python's dict equality operator
checks the equality recursively, as expected).

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
c4c71989bf alternator-test: test all attribute types
Although we planned to initially support only string types, it turns out
for the attributes (*not* the key), we actually support all types already,
including all scalar types (string, number, bool, binary and null) and
more complex types (list, nested document, and sets).

This adds a tests which PutItem's these types and verifies that we can
retrieve them.

Note that this test deals with top-level attributes only. There is no
attempt to modify only a nested attribute (and with the current code,
it wouldn't work).

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
4dad76a6a7 alternator-test: rewrite ListTables test
In our tests, we cannot really assume that ListTables should returns *only*
the tables we created for the test, or even that a page size of 100 will
be enough to list our 3 pages. The issue is that on a shared DynamoDB, or
in hypothetical cases where multiple tests are run in parallel, or previous
tests had catestrophic errors and failed to clean up, we have no idea how
many unrelated tables there are in the system. There may be hundreds of
them.  So every ListTables test will need to use paging.

So in this re-implementation, we begin with a list_tables() utility function
which calls ListTables multiple times to fetch all tables, and return the
resulting list (we assume this list isn't so huge it becomes unreasonable
to hold it in memory). We then use this utility function to fetch the table
list with various page sizes, and check that the test tables we created are
listed in the resulting list.

There's no longer a separate test for "all" tables (really was a page of 100
tables) and smaller pages (1,2,3,4) - we now have just one test that does the
page sizes 1,2,3,4, 50 and 100.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Piotr Sarna
323268e9ab alternator: add tests to ListTables command
Test cases cover both listing appropriate table names
and pagination.
Message-Id: <e7d5f1e5cce10c86c47cdfb4d803149488935ec0.1557402320.git.sarna@scylladb.com>
2019-08-19 15:48:16 +03:00
Piotr Sarna
a441ad9360 alternator-test: add 2 tables fixture
For some tests, more than 1 table is needed, so another fixture
that provided two additional test tables is added.
Message-Id: <75ae9de5cc1bca19594db1f0bc03260f83459380.1557402320.git.sarna@scylladb.com>
2019-08-19 15:48:16 +03:00
Piotr Sarna
d04a5b01c3 alternator: implement ListTables
ListTables is used to extract all table names created so far.
Message-Id: <04f4d804a40ff08a38125f36351e56d7426d2e3d.1557402320.git.sarna@scylladb.com>
2019-08-19 15:48:16 +03:00
Piotr Sarna
4da8171b42 alternator: use trace level for debug messages
In the early development stage, warn level was used for all
debug messages, while it's more appropriate to use 'trace' or 'debug'.
Message-Id: <419ca5a22bc356c6e47fce80b392403cefbee14d.1557402320.git.sarna@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
fbc6f222b8 alternator-test: cleanup in conftest.py
This patch cleans up some comments and reorganizes some functions in
conftest.py, where the test_table fixture was defined. The goal is to
later add additional types of test tables with different schemas (e.g.,
just a partition key, different key types, etc.) without too much
code duplication.

This patch doesn't change anything functional in the tests, and they
still pass ("pytest --local" runs all tests against the local Alternator).

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
31cce0323e alternator: make ck_from_json() easier to use
The ck_from_json() utility function is easier to use if it handles
the no-clustering-key case as the callers need them too, instead of
requiring them to handle the no-clustering-key case separately.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Piotr Sarna
f3d1cefe3e alternator: migrate to std::string
Most JSON libraries, including jsoncpp, are based on std::string,
so sstring becomes a source of unneeded copying. The usage of sstring
is only preserved in code that interacts with Scylla API directly.
Message-Id: <691d64c7d71196e33fb0e0847dd8a13704d3cdb2.1557314233.git.sarna@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
8bf6e963f2 alternator: add support for UpdateItem's DELETE operation
So far we supported UpdateItem only with PUT operations - this patch
adds support for DELETE operations, to delete specific attributes from
an item.

Only the case of a missing value is support. DynamoDB also provides
the ability to pass the old value, and only perform the deletion if
the value and/or its type is still up-to-date - but we don't support
this yet and fail such request if it is attempted.

This patch also includes a test for this case in alternator-test/

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
ac65f91b5d alternator-test: add tests for UpdateItem
Add initial tests for UpdateItem. Only the features currently supported
by our code (only string attributes, only "PUT" action) are tested.

As usual, this test (like all others) was tested to pass on both DynamoDB
and Alternator.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
c7d7c1e50d alternator: add initial UpdateItem implementation
Add an initial UpdateItem implementation. As PutItem and GetItem we
are still limited to string attributes. This initial implementation
of UpdateItem implements only the "PUT" action (not "DELETE" and
certainly not "ADD") and not any of the more advanced options.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Piotr Sarna
829f5fe359 alternator: add attrs_column() helper function
Message-Id: <d93ae70ccd27fe31d0bc6915a20d83d7a85342cf.1557223199.git.sarna@scylladb.com>
2019-08-19 15:48:16 +03:00
Piotr Sarna
5f9409af68 alternator: make constant names more explicit
KEYSPACE and ATTRS constants refer to their names, not objects,
so they're named more explicitly.
Message-Id: <14b1f00d625e041985efbc4cbde192bd447cbf03.1557223199.git.sarna@scylladb.com>
2019-08-19 15:48:16 +03:00
Piotr Sarna
f28680ec5c alternator: remove inaccessible return statement
Message-Id: <afaef20e7e110fa23271fb8c3dc40cec0716efb6.1557223199.git.sarna@scylladb.com>
2019-08-19 15:48:16 +03:00
Piotr Sarna
a7175ddd44 alternator: inline keywords
It was decided that all alternator-specific keywords can be inlined
in code instead of defining them as constants.
Message-Id: <6dffb9527cfab2a28b8b95ac0ad614c18027f679.1557223199.git.sarna@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
90f56c32b0 alternator: some cleanups in validate_table_name()
Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
2808f7ae3f alternator: clean up api_error() interface
All operation-generated error messages should have the 400 HTTP error
code. It's a real nag to have to type it every time. So make it the
default.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
ac278d67ca alternator-test: test for error on creating an already-existing table
Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
53a9567804 alternator: correct error when trying to CreateTable an existing table
Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
5a751ddcff alternator: fix return object from PutItem
Without special options, PutItem should return nothing (an empty
JSON result). Previously we had trouble doing this, because instead
of return an empty JSON result, we converted an empty string into
JSON :-) So the existing code had an ugly workaround which worked,
sort of, for the Python driver but not for the Java driver.

The correct fix, in this patch, is to invent a new type json_string
which is a string *already* in JSON and doesn't need further conversion,
so we can use it to return the empty result. PutItem now works from
YCSB's Java driver.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
dae70c892f alternator-test: more examples in README.md
Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
4cbb40d5d8 alternator-test: test table name limit of 222 bytes, instead of 255.
Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
ae779ade37 alternator: limit table names to 222 bytes
Although we would like to allow table names up to 222 bytes, this is not
currently possible because Scylla tacks additional 33 bytes to create
a directory name, and directory names are limited to 255 bytes.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
8839b22277 alternator-test: verify appropriate error when invalid key type is used
Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
35bc488f5b alternator: better key type parsing
The supported key types are just S(tring), B(lob), or N(umber).
Other types are valid for attributes, but not for keys, and should
not be accepted. And wrong types used should result in the appropriate
user-visible error.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
c85dcfb71d alternator-test: additional cases of invalid schemas in CreateTable
Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
a37b334e16 alternator: better invalid schema detection for CreateTable
To be correct, CreateTable's input parsing need to work in reverse from
what it did: First, the key columns are listed in KeySchema, and then
each of these (and potetially more, e.g., from indexes) need to appear
AttributeDefinitions.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
d52e7de7be alternator-test: tests for CreateTable with bad schema
Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
dd884b5552 alternator: better error handling for schema errors in CreateTable
Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
6c6c5a37a1 alternator-test: test for PutItem to nonexistant table
We expect to see the right error code, not some "internal error".

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
4ff599b21f alternator: PutItem: appropriate error for a non-existant table
Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
6178694b0e alternator-test: add another column to test_basic_string_put_and_get()
Just to make sure our success isn't limited to just a single non-key
attribute, let's add another one.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
700a3bb7be alternator: GetItem should by default returns all the columns, not none
The test

  pytest --local test_item.py::test_basic_string_put_and_get

Now passes.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
eb13166fb5 alternator: change empty return of PutItem
Without any arguments, PutItem should return no data at all. But somehow,
for reasons I don't understand, the boto3 driver gets confused from an
empty JSON thinking it isn't JSON at all. If we return a structure with
an empty "attributes" fields, boto3 is happy.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
325773d65b alternator: add initial implementation of DeleteTable
Add an initial implementation of Delete table, enough for making the

   pytest --local test_table.py::test_create_and_delete_table

Pass.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00
Nadav Har'El
4e12a4f212 alternator: on unknown operation, return standard API error
When given an unknown operation (we didn't implement yet many of them...)
we should throw the appropriate api_error, not some random exception.

This allows the client to understand the operation is not supported
and stop retrying - instead of retrying thinking this was a weird
internal error.

For example the test
   pytest --local test_table.py::test_create_and_delete_table

Now fails immediately, saying Unsupported operation DeleteTable.

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
2019-08-19 15:48:16 +03:00