IGNITE-13903: Add tox, docker-compose and travis integration
This closes #1
diff --git a/.asf.yaml b/.asf.yaml
new file mode 100644
index 0000000..2fca9c0
--- /dev/null
+++ b/.asf.yaml
@@ -0,0 +1,34 @@
+# 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.
+
+github:
+ description: "Apache Ignite Python Thin Client"
+ homepage: https://ignite.apache.org/
+ labels:
+ - ignite
+ - python
+ features:
+ wiki: false
+ issues: false
+ projects: false
+ enabled_merge_buttons:
+ squash: true
+ merge: false
+ rebase: false
+notifications:
+ commits: commits@ignite.apache.org
+ issues: notifications@ignite.apache.org
+ pullrequests: notifications@ignite.apache.org
+ jira_options: link label worklog
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d9268c3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+.eggs
+.pytest_cache
+.tox
+pyignite.egg-info
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..230a9f1
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,34 @@
+# 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.
+
+sudo: required
+services:
+ - docker
+
+env:
+ COMPOSE_VERSION: 1.27.4
+
+before_install:
+ - curl -L https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
+ - chmod +x docker-compose
+ - sudo mv docker-compose /usr/local/bin
+
+language: python
+python:
+ - "3.6"
+ - "3.7"
+ - "3.8"
+install: pip install tox-travis
+script: tox
\ No newline at end of file
diff --git a/README.md b/README.md
index 22732ce..26b9a6a 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
## Prerequisites
-- Python 3.4 or above (3.6 is tested),
+- Python 3.4 or above (3.6, 3.7 and 3.8 are tested),
- Access to Apache Ignite node, local or remote. The current thin client
version was tested on Apache Ignite 2.7.0 (binary client protocol 1.2.0).
@@ -19,8 +19,7 @@
If you want to run tests, examples or build documentation, clone
the whole repository:
```
-$ git clone git@github.com:apache/ignite.git
-$ cd ignite/modules/platforms/python
+$ git clone git@github.com:apache/ignite-python-thin-client.git
$ pip install -e .
```
@@ -64,12 +63,32 @@
installed, and Apache Ignite node is running on localhost:10800.
## Testing
-Run
+*NB!* All tests require Apache Ignite node running on localhost:10800. For the convenience, `docker-compose.yml` is present.
+So installing `docker` and `docker-compose` is recommended. Also, it is recommended installing `pyignite` in development
+mode. You can do that using following command:
```
-$ cd ignite/modules/platforms/python
-$ python setup.py pytest
+$ pip install -e .
+```
+### Run without ssl
+```
+$ docker-compose down && docker-compose up -d ignite
+$ pytest
+```
+### Run with examples
+```
+$ docker-compose down && docker-compose up -d ignite
+$ pytest --examples
+```
+### Run with ssl and not encrypted key
+```
+$ docker-compose down && docker-compose up -d ignite
+$ pytest --use-ssl=True --ssl-certfile=./tests/config/ssl/client_full.pem
+```
+### Run with ssl and password-protected key
+```
+$ docker-compose down && docker-compose up -d ignite
+$ pytest --use-ssl=True --ssl-certfile=./tests/config/ssl/client_with_pass_full.pem --ssl-keyfile-password=654321
```
-*NB!* All tests require Apache Ignite node running on localhost:10800.
If you need to change the connection parameters, see the documentation on
[testing](https://apache-ignite-binary-protocol-client.readthedocs.io/en/latest/readme.html#testing).
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..2517d25
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,34 @@
+# 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.
+
+services:
+ ignite:
+ image: apacheignite/ignite:latest
+ ports:
+ - 10800:10800
+ restart: always
+ network_mode: host
+
+ ignite-ssl:
+ image: apacheignite/ignite:latest
+ ports:
+ - 10800:10800
+ restart: always
+ network_mode: host
+ volumes:
+ - ./tests/config:/config
+ environment:
+ CONFIG_URI: /config/ssl.xml
+ PYTHON_TEST_CONFIG_PATH: /config
diff --git a/tests/config/ssl.xml b/tests/config/ssl.xml
index d9d406f..8d74cbb 100644
--- a/tests/config/ssl.xml
+++ b/tests/config/ssl.xml
@@ -32,12 +32,10 @@
</bean>
<bean id="test.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
- <property name="localHost" value="127.0.0.1"/>
<property name="connectorConfiguration"><null/></property>
<property name="clientConnectorConfiguration">
<bean class="org.apache.ignite.configuration.ClientConnectorConfiguration">
- <property name="host" value="127.0.0.1"/>
<property name="portRange" value="10"/>
<property name="sslEnabled" value="true"/>
<property name="useIgniteSslContextFactory" value="false"/>
diff --git a/tests/config/ssl/README.txt b/tests/config/ssl/README.txt
index eca07ea..da169fa 100644
--- a/tests/config/ssl/README.txt
+++ b/tests/config/ssl/README.txt
@@ -1,3 +1,3 @@
These files generated using script
-`$IGNITE_SRC/modules/platforms/cpp/thin-client-test/config/ssl/generate_certificates.sh`
+`./tests/config/ssl/generate_certificates.sh`
To update them just run script and move files to this folder.
\ No newline at end of file
diff --git a/tests/config/ssl/generate_certificates.sh b/tests/config/ssl/generate_certificates.sh
new file mode 100755
index 0000000..e4f41e2
--- /dev/null
+++ b/tests/config/ssl/generate_certificates.sh
@@ -0,0 +1,127 @@
+#!/bin/bash
+#
+# 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.
+#
+
+OSSL=$(command -v openssl11)
+
+if [ -z "$OSSL" ]
+then
+ OSSL=$(command -v openssl)
+fi
+
+echo "Using following openssl: $OSSL"
+
+function generate_ca {
+ CA_KEY="$1.key"
+ CA_CRT="$1.crt"
+ OU="$2"
+
+ # Generating CA private key and self-signed certificate
+ $OSSL req \
+ -newkey rsa:2048 -nodes -sha256 -keyout $CA_KEY \
+ -subj "/C=US/ST=Massachusetts/L=Wakefield/CN=ignite.apache.org/O=The Apache Software Foundation/OU=$OU/emailAddress=dev@ignite.apache.org" \
+ -x509 -days 3650 -out $CA_CRT
+}
+
+function generate_client_key_and_crt {
+ CA_KEY="$1.key"
+ CA_CRT="$1.crt"
+ CA_SRL="$1.srl"
+ CLIENT_KEY="$2.key"
+ CLIENT_CSR="$2.scr"
+ CLIENT_CRT="$2.crt"
+ OU="$3"
+
+ # Generating client private key and certificate signature request to be used for certificate signing
+ $OSSL req \
+ -newkey rsa:2048 -nodes -sha256 -keyout $CLIENT_KEY \
+ -subj "/C=US/ST=Massachusetts/L=Wakefield/CN=ignite.apache.org/O=The Apache Software Foundation/OU=$OU/emailAddress=dev@ignite.apache.org" \
+ -out $CLIENT_CSR
+
+ # Signing client cerificate
+ $OSSL x509 -req \
+ -in $CLIENT_CSR -CA $CA_CRT -CAkey $CA_KEY -CAcreateserial \
+ -days 3650 -sha256 -out $CLIENT_CRT
+
+ # Cleaning up.
+ rm -f $CLIENT_CSR
+
+ # Protecting key with the password if required
+ if [ "$4" == "1" ]; then
+ openssl rsa -aes256 -in $CLIENT_KEY -passout pass:654321 -out $CLIENT_KEY
+ fi
+}
+
+function generate_jks {
+ CA_CRT="$1.crt"
+ CA_JKS="$1.jks"
+ SERVER_KEY="$2.key"
+ SERVER_CRT="$2.crt"
+ SERVER_PEM="$2.pem"
+ SERVER_P12="$2.pkcs12"
+ SERVER_JKS="$2.jks"
+
+ rm -f $CA_JKS $SERVER_JKS
+
+ cat $SERVER_KEY $SERVER_CRT > $SERVER_PEM
+
+ $OSSL pkcs12 -export -passout pass:123456 -out $SERVER_P12 -in $SERVER_PEM
+
+ keytool -import -v -trustcacerts \
+ -file $CA_CRT -alias certificateauthority -noprompt \
+ -keystore $CA_JKS -deststorepass 123456
+
+ keytool -v -importkeystore \
+ -srckeystore $SERVER_P12 -srcstoretype PKCS12 -srcstorepass 123456 \
+ -destkeystore $SERVER_JKS -deststoretype JKS -deststorepass 123456
+
+ rm -f $SERVER_P12 $SERVER_PEM
+}
+
+CA='ca'
+CLIENT='client'
+CLIENT_WITH_PASS='client_with_pass'
+SERVER='server'
+CA_UNKNOWN='ca_unknown'
+CLIENT_UNKNOWN='client_unknown'
+
+generate_ca $CA 'Apache Ignite CA'
+generate_client_key_and_crt $CA $CLIENT 'Apache Ignite Client Test'
+generate_client_key_and_crt $CA $CLIENT_WITH_PASS 'Apache Ignite Client Test' 1
+generate_client_key_and_crt $CA $SERVER 'Apache Ignite Server Test'
+
+# We won't sign up any other certs so we do not need CA key or srl
+rm -f "$CA.key" "$CA.srl"
+
+generate_jks $CA $SERVER
+
+generate_ca $CA_UNKNOWN 'Unknown CA'
+generate_client_key_and_crt $CA_UNKNOWN $CLIENT_UNKNOWN 'Unknown Client'
+
+# We do not need this CA anymore
+rm -f $CA_UNKNOWN*
+
+# Re-naming everything as needed
+cat $CLIENT.key $CLIENT.crt > "$CLIENT"_full.pem
+cat $CLIENT_WITH_PASS.key $CLIENT_WITH_PASS.crt > "$CLIENT_WITH_PASS"_full.pem
+cat $CLIENT_UNKNOWN.key $CLIENT_UNKNOWN.crt > $CLIENT_UNKNOWN.pem
+mv $CA.jks trust.jks
+mv $CA.crt ca.pem
+
+rm -f $CLIENT.crt $CLIENT.key $CLIENT_WITH_PASS.key $CLIENT_WITH_PASS.crt $CLIENT_UNKNOWN.key $CLIENT_UNKNOWN.crt $SERVER_KEY $SERVER_CRT
+
+
diff --git a/tests/conftest.py b/tests/conftest.py
index f7e2e1f..8ebd5b8 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -98,6 +98,18 @@
cache_destroy(client, cache_name)
+@pytest.fixture
+def examples(request):
+ return request.config.getoption("--examples")
+
+
+@pytest.fixture(autouse=True)
+def run_examples(request, examples):
+ if request.node.get_closest_marker('examples'):
+ if not examples:
+ pytest.skip('skipped examples: --examples is not passed')
+
+
def pytest_addoption(parser):
parser.addoption(
'--ignite-host',
@@ -225,3 +237,9 @@
if type(param) is not list:
param = [param]
metafunc.parametrize(param_name, param, scope='session')
+
+
+def pytest_configure(config):
+ config.addinivalue_line(
+ "markers", "examples: mark test to run only if --examples are set"
+ )
diff --git a/tests/test_examples.py b/tests/test_examples.py
index 4665d8c..046eb6d 100644
--- a/tests/test_examples.py
+++ b/tests/test_examples.py
@@ -39,13 +39,7 @@
]).returncode
-@pytest.mark.skipif(
- condition=not pytest.config.option.examples,
- reason=(
- 'If you wish to test examples, invoke pytest with '
- '`--examples` option.'
- ),
-)
+@pytest.mark.examples
def test_examples():
for script in glob.glob1('../examples', '*.py'):
if script not in SKIP_LIST:
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..6e70234
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,85 @@
+# 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.
+
+[tox]
+skipsdist = True
+envlist = py{36,37,38}-{no-ssl,ssl,ssl-password}-docker
+
+[travis]
+python =
+ 3.6: py36-{no-ssl,ssl,ssl-password}-docker
+ 3.7: py37-{no-ssl,ssl,ssl-password}-docker
+ 3.8: py38-{no-ssl,ssl,ssl-password}-docker
+
+[testenv]
+passenv = TEAMCITY_VERSION
+envdir = {homedir}/.virtualenvs/pyignite-{envname}
+deps =
+ -r ./requirements/install.txt
+ -r ./requirements/tests.txt
+recreate = True
+usedevelop = True
+allowlist_externals = docker-compose
+commands =
+ pytest {env:PYTESTARGS:} {posargs}
+
+[no-ssl]
+setenv:
+ PYTEST_ADDOPTS = --examples
+
+[ssl]
+setenv:
+ PYTEST_ADDOPTS = --examples --use-ssl=True --ssl-certfile={toxinidir}/tests/config/ssl/client_full.pem
+
+[ssl-password]
+setenv:
+ PYTEST_ADDOPTS = --examples --use-ssl=True --ssl-certfile={toxinidir}/tests/config/ssl/client_with_pass_full.pem --ssl-keyfile-password=654321
+
+[docker]
+commands_pre =
+ docker-compose down
+ docker-compose up -d ignite
+commands_post =
+ docker-compose down
+
+[docker-ssl]
+commands_pre =
+ docker-compose down
+ docker-compose up -d ignite-ssl
+commands_post = {[docker]commands_post}
+
+[testenv:py{36,37,38}-no-ssl]
+setenv: {[no-ssl]setenv}
+
+[testenv:py{36,37,38}-no-ssl-docker]
+commands_pre = {[docker]commands_pre}
+setenv: {[no-ssl]setenv}
+commands_post = {[docker]commands_post}
+
+[testenv:py{36,37,38}-ssl]
+setenv: {[ssl]setenv}
+
+[testenv:py{36,37,38}-ssl-docker]
+commands_pre = {[docker-ssl]commands_pre}
+setenv: {[ssl]setenv}
+commands_post = {[docker]commands_post}
+
+[testenv:py{36,37,38}-ssl-password]
+setenv: {[ssl-password]setenv}
+
+[testenv:py{36,37,38}-ssl-password-docker]
+commands_pre = {[docker-ssl]commands_pre}
+setenv: {[ssl-password]setenv}
+commands_post = {[docker]commands_post}