Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🎉 release: v1.13.0 #71

Merged
merged 3 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions rapyuta_io/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
BuildOptions
from .clients.buildoperation import BuildOperation, BuildOperationInfo
from .clients.project import Project
from .clients.secret import Secret, SecretConfigSourceSSHAuth, SecretConfigDocker, \
SecretConfigSourceBasicAuth
from .clients.secret import Secret, SecretConfigDocker
from .clients.rosbag import UploadOptions
from .clients.user_group import UserGroup

Expand Down
75 changes: 1 addition & 74 deletions rapyuta_io/clients/secret.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Secret(ObjBase):
:param name: Name of the Secret
:type name: str
:param secret_config: Secret Configuration
:type secret_config: Union[:py:class:`~rapyuta_io.clients.secret.SecretConfigSourceSSHAuth`, :py:class:`~rapyuta_io.clients.secret.SecretConfigSourceBasicAuth`, :py:class:`~rapyuta_io.clients.secret.SecretConfigDocker`]
:type secret_config: Union[:py:class:`~rapyuta_io.clients.secret.SecretConfigDocker`]
"""
SECRET_PATH = '/api/secret'

Expand Down Expand Up @@ -111,8 +111,6 @@ def __str__(self):
return str(self.value)

DOCKER = 'kubernetes.io/dockercfg'
SOURCE_BASIC_AUTH = 'kubernetes.io/basic-auth'
SOURCE_SSH_AUTH = 'kubernetes.io/ssh-auth'


class _SecretConfigBase(six.with_metaclass(ABCMeta, ObjBase)):
Expand All @@ -132,77 +130,6 @@ def get_serialize_map(self):
pass


class SecretConfigSourceSSHAuth(_SecretConfigBase):
"""
SecretConfigSSHAuth represents Source Secret with SSH Authentication. This type of secrets can be used to access
private Git repositories using SSH, for building the Docker images from Source Code.

:param ssh_key: Private SSH key for authenticating with the Git repository hosting
:type ssh_key: str
"""

def __init__(self, ssh_key):
self.validate(ssh_key)
self.ssh_key = ssh_key

@staticmethod
def validate(ssh_key):
if not (isinstance(ssh_key, str) or isinstance(ssh_key, six.string_types)) or ssh_key == '':
raise InvalidParameterException('ssh_key cannot be empty')

@classmethod
def get_type(cls):
return SecretType.SOURCE_SSH_AUTH

def serialize(self):
return {
'ssh-privatekey': base64.b64encode(self.ssh_key.encode()).decode()
}


class SecretConfigSourceBasicAuth(_SecretConfigBase):
"""
SecretConfigSourceBasicAuth represents Source Secret with Basic Authentication. This type of secrets can be used to
access private Git repositories exposing HTTP interface, for building the Docker images from Source Code.

:param username: Username for the Git repository hosting
:type username: str
:param password: Password for the Git repository hosting
:type password: str
:param ca_cert: If the Git repository is using self-signed certificates, a CA Root Certificate can optionally be provided.
:type ca_cert: str
"""

def __init__(self, username, password, ca_cert=None):
self.validate(username, password, ca_cert)
self.username = username
self.password = password
self.ca_cert = ca_cert

@staticmethod
def validate(username, password, ca_cert):
if not isinstance(username, six.string_types) or username == '':
raise InvalidParameterException('username cannot be empty')
if not isinstance(password, six.string_types) or password == '':
raise InvalidParameterException('password cannot be empty')
if ca_cert is not None and (not isinstance(ca_cert, six.string_types) or ca_cert == ''):
raise InvalidParameterException('ca_cert cannot be empty')

@classmethod
def get_type(cls):
return SecretType.SOURCE_BASIC_AUTH

def serialize(self):
ret = {
'username': base64.b64encode(self.username.encode()).decode(),
'password': base64.b64encode(self.password.encode()).decode(),
}
if self.ca_cert is not None:
ret['ca.crt'] = base64.b64encode(self.ca_cert.encode()).decode()

return ret


class SecretConfigDocker(_SecretConfigBase):
"""
SecretConfigDocker represents Docker Secret for Docker registries. This type of secrets can be used to access
Expand Down
9 changes: 7 additions & 2 deletions rapyuta_io/rio_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,20 +485,22 @@ def delete_device(self, device_id):
raise InvalidParameterException('device_id needs to be a non empty string')
return self._dmClient.delete_device(device_id)

def toggle_features(self, device_id, features):
def toggle_features(self, device_id, features, config=None):
"""
Patch a device on rapyuta.io platform.
:param device_id: Device ID
:type device_id: str
:param features: A tuple of featues and their states
:type features: list<tuple>
:param config: A dict of additional feature configuration
:type config: dict
Following example demonstrates how to toggle features a device.
>>> from rapyuta_io import Client
>>> client = Client(auth_token='auth_token', project='project_guid')
>>> client.toggle_features('device-id', [('vpn', True), ('tracing', False)])
>>> client.toggle_features('device-id', [('vpn', True), ('tracing', False)], config={'vpn': {'advertise_routes': True}})
"""
if not device_id or not isinstance(device_id, six.string_types):
raise InvalidParameterException('device_id needs to be a non empty string')
Expand All @@ -510,6 +512,9 @@ def toggle_features(self, device_id, features):
feature, state = entry
data[feature] = state

if config is not None:
data['config'] = config

return self._dmClient.patch_daemons(device_id, data)

def create_package_from_manifest(self, manifest_filepath, retry_limit=0):
Expand Down
6 changes: 2 additions & 4 deletions sdk_test/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import six
from six.moves import filter

from rapyuta_io import Client, SecretConfigSourceSSHAuth, SecretConfigDocker, \
from rapyuta_io import Client, SecretConfigDocker, \
DeviceArch, Secret, Project
from rapyuta_io.utils.error import InvalidParameterException
from rapyuta_io.utils.utils import create_auth_header, \
Expand Down Expand Up @@ -154,12 +154,10 @@ def set_devices(self, devices):
self._devices = list(filter(filter_devices_by_name(), devices))

def create_secrets(self):
ssh_key = self._config['git']['ssh-key']
git_secret = self.client.create_secret(Secret('git-secret', SecretConfigSourceSSHAuth(ssh_key)))
docker = self._config['docker']
docker_secret = self.client.create_secret(Secret('docker-secret', SecretConfigDocker(
docker['username'], docker['password'], docker['email'])))
self._secrets = {'git': git_secret, 'docker': docker_secret}
self._secrets = {'docker': docker_secret}

def delete_secrets(self):
for secret in self._secrets.values():
Expand Down
5 changes: 3 additions & 2 deletions sdk_test/coreapi/project_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import unittest

from rapyuta_io import Client, Project, Secret, SecretConfigSourceSSHAuth
from rapyuta_io import Client, Project, Secret, SecretConfigDocker
from rapyuta_io.utils import BadRequestError
from rapyuta_io.utils.utils import generate_random_value
from sdk_test.config import Configuration
Expand Down Expand Up @@ -46,6 +46,7 @@ def test_client_without_project(self):
self.assertRaises(
BadRequestError,
lambda: client.create_secret(
Secret('test-secret', SecretConfigSourceSSHAuth('test'))
Secret('test-secret', SecretConfigDocker(username='username', password='password', email='[email protected]',
registry='quay.io'))
)
)
18 changes: 5 additions & 13 deletions sdk_test/coreapi/secret_test.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from __future__ import absolute_import
import unittest

from rapyuta_io import Secret, SecretConfigSourceSSHAuth, SecretConfigSourceBasicAuth, \
SecretConfigDocker
from rapyuta_io import Secret, SecretConfigDocker
from sdk_test.config import Configuration
from sdk_test.util import get_logger

Expand All @@ -23,26 +22,19 @@ def assertSecret(self, secret):
self.assertIsNotNone(secret.created_at)
self.assertIsNotNone(secret.secret_type)

def test_create_secret_source_ssh_auth(self):
self.secret = self.config.client.create_secret(Secret('ssh-auth-test', SecretConfigSourceSSHAuth('test-ssh-key')))
self.assertSecret(self.secret)

def test_create_secret_source_http_auth(self):
self.secret = self.config.client.create_secret(Secret('basic-auth-test', SecretConfigSourceBasicAuth('user', 'pass')))
self.assertSecret(self.secret)

def test_create_secret_docker(self):
self.secret = self.config.client.create_secret(Secret('docker-test', SecretConfigDocker('user','pass', 'email')))
self.assertSecret(self.secret)

def test_list_secret_docker(self):
self.secret = self.config.client.create_secret(Secret('ssh-auth-test', SecretConfigSourceSSHAuth('test-ssh-key')))
self.secret = self.config.client.create_secret(Secret('docker-test', SecretConfigDocker('user','pass', 'email')))
secret_list = self.config.client.list_secrets()
secret_list = [s for s in secret_list if s.guid == self.secret.guid]
self.assertEqual(len(secret_list), 1)

def test_update_secret_source_basic_auth(self):
self.secret = self.config.client.create_secret(Secret('basic-auth-test', SecretConfigSourceBasicAuth('user', 'pass')))
self.secret = self.config.client.update_secret(self.secret.guid, Secret('basic-auth-test', SecretConfigSourceBasicAuth('user', 'newpass')))
def test_update_secret_source_docker(self):
self.secret = self.config.client.create_secret(Secret('docker-test', SecretConfigDocker('user','pass', 'email')))
self.secret = self.config.client.update_secret(self.secret.guid, Secret('docker-test', SecretConfigDocker('user1','pass1', 'email1')))
self.assertSecret(self.secret)

Loading
Loading