Skip to content

Commit

Permalink
Fix #190: Add objects DockerConfigs and DockerSecrets (#596)
Browse files Browse the repository at this point in the history
  • Loading branch information
akiuni committed Jul 21, 2021
1 parent 5eb26cf commit 5dfa90e
Show file tree
Hide file tree
Showing 10 changed files with 727 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGES/190.feat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support of Docker swarm secrets and configs.
1 change: 1 addition & 0 deletions CONTRIBUTORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Jason Kraus
Joongi Kim
Joshua Chung
Julien Kmec
Julien Simbola
Konstantin Valetov
Martin Koppehel
Nikolay Novik
Expand Down
155 changes: 155 additions & 0 deletions aiodocker/configs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import json
from base64 import b64encode
from typing import Any, List, Mapping

from .utils import clean_filters, clean_map


class DockerConfigs(object):
def __init__(self, docker):
self.docker = docker

async def list(self, *, filters: Mapping = None) -> List[Mapping]:
"""
Return a list of configs
Args:
filters: a dict with a list of filters
Available filters:
id=<config id>
label=<key> or label=<key>=value
name=<config name>
names=<config name>
"""

params = {"filters": clean_filters(filters)}
response = await self.docker._query_json("configs", method="GET", params=params)
return response

async def create(
self,
name: str,
data: str,
*,
b64: bool = False,
labels: List = None,
templating: Mapping = None,
) -> Mapping[str, Any]:
"""
Create a config
Args:
name: name of the config
labels: user-defined key/value metadata
data: config data
b64: True if data is already Base64-url-safe-encoded
templating: Driver represents a driver (network, logging, secrets).
Returns:
a dict with info of the created config
"""

b64_data = None
if data is not None:
b64_data = data if b64 else b64encode(data.encode()).decode()

headers = None
request = {
"Name": name,
"Labels": labels,
"Data": b64_data,
"Templating": templating,
}

request_data = json.dumps(clean_map(request))
response = await self.docker._query_json(
"configs/create", method="POST", data=request_data, headers=headers
)
return response

async def inspect(self, config_id: str) -> Mapping[str, Any]:
"""
Inspect a config
Args:
config_id: ID of the config
Returns:
a dict with info about a config
"""

response = await self.docker._query_json(
"configs/{config_id}".format(config_id=config_id), method="GET"
)
return response

async def delete(self, config_id: str) -> bool:
"""
Remove a config
Args:
config_id: ID or name of the config
Returns:
True if successful
"""

async with self.docker._query(
"configs/{config_id}".format(config_id=config_id), method="DELETE"
):
return True

async def update(
self,
config_id: str,
version: str,
*,
name: str = None,
data: str = None,
b64: bool = False,
labels: List = None,
templating: Mapping = None,
) -> bool:
"""
Update a config.
Args:
config_id: ID of the config.
name: name of the config
labels: user-defined key/value metadata
data: config data
b64: True if data is already Base64-url-safe-encoded
templating: Driver represents a driver (network, logging, secrets).
Returns:
True if successful.
"""

inspect_config = await self.inspect(config_id)
spec = inspect_config["Spec"]

b64_data = None
if data is not None:
b64_data = data if b64 else b64encode(data.encode()).decode()
spec["Data"] = b64_data

if name is not None:
spec["Name"] = name

if labels is not None:
spec["Labels"] = labels

if templating is not None:
spec["Templating"] = templating

params = {"version": version}
request_data = json.dumps(clean_map(spec))

await self.docker._query_json(
"configs/{config_id}/update".format(config_id=config_id),
method="POST",
data=request_data,
params=params,
)
return True
6 changes: 6 additions & 0 deletions aiodocker/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
from yarl import URL

# Sub-API classes
from .configs import DockerConfigs
from .containers import DockerContainer, DockerContainers
from .events import DockerEvents
from .exceptions import DockerError
from .images import DockerImages
from .logs import DockerLog
from .networks import DockerNetwork, DockerNetworks
from .nodes import DockerSwarmNodes
from .secrets import DockerSecrets
from .services import DockerServices
from .swarm import DockerSwarm
from .system import DockerSystem
Expand All @@ -38,6 +40,8 @@
"DockerImages",
"DockerLog",
"DockerSwarm",
"DockerConfigs",
"DockerSecrets",
"DockerServices",
"DockerTasks",
"DockerVolumes",
Expand Down Expand Up @@ -132,6 +136,8 @@ def __init__(
self.containers = DockerContainers(self)
self.swarm = DockerSwarm(self)
self.services = DockerServices(self)
self.configs = DockerConfigs(self)
self.secrets = DockerSecrets(self)
self.tasks = DockerTasks(self)
self.images = DockerImages(self)
self.volumes = DockerVolumes(self)
Expand Down
163 changes: 163 additions & 0 deletions aiodocker/secrets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import json
from base64 import b64encode
from typing import Any, List, Mapping

from .utils import clean_filters, clean_map


class DockerSecrets(object):
def __init__(self, docker):
self.docker = docker

async def list(self, *, filters: Mapping = None) -> List[Mapping]:
"""
Return a list of secrets
Args:
filters: a dict with a list of filters
Available filters:
id=<secret id>
label=<key> or label=<key>=value
name=<secret name>
names=<secret name>
"""

params = {"filters": clean_filters(filters)}
response = await self.docker._query_json("secrets", method="GET", params=params)
return response

async def create(
self,
name: str,
data: str,
*,
b64: bool = False,
labels: List = None,
driver: Mapping = None,
templating: Mapping = None,
) -> Mapping[str, Any]:
"""
Create a secret
Args:
name: name of the secret
labels: user-defined key/value metadata
data: data to store as secret
b64: True if data is already Base64-url-safe-encoded
driver: Driver represents a driver (network, logging, secrets).
templating: Driver represents a driver (network, logging, secrets).
Returns:
a dict with info of the created secret
"""

b64_data = None
if data is not None:
b64_data = data if b64 else b64encode(data.encode()).decode()

headers = None
request = {
"Name": name,
"Labels": labels,
"Data": b64_data,
"Driver": driver,
"Templating": templating,
}

request_data = json.dumps(clean_map(request))
response = await self.docker._query_json(
"secrets/create", method="POST", data=request_data, headers=headers
)
return response

async def inspect(self, secret_id: str) -> Mapping[str, Any]:
"""
Inspect a secret
Args:
secret_id: ID of the secret
Returns:
a dict with info about a secret
"""

response = await self.docker._query_json(
"secrets/{secret_id}".format(secret_id=secret_id), method="GET"
)
return response

async def delete(self, secret_id: str) -> bool:
"""
Remove a secret
Args:
secret_id: ID of the secret
Returns:
True if successful
"""

async with self.docker._query(
"secrets/{secret_id}".format(secret_id=secret_id), method="DELETE"
):
return True

async def update(
self,
secret_id: str,
version: str,
*,
name: str = None,
data: str = None,
b64: bool = False,
labels: List = None,
driver: Mapping = None,
templating: Mapping = None,
) -> bool:
"""
Update a secret.
Args:
secret_id: ID of the secret.
name: name of the secret
labels: user-defined key/value metadata
data: data to store as secret
b64: True if data is already Base64-url-safe-encoded
driver: Driver represents a driver (network, logging, secrets).
templating: Driver represents a driver (network, logging, secrets).
Returns:
True if successful.
"""

inspect_secret = await self.inspect(secret_id)
spec = inspect_secret["Spec"]

b64_data = None
if data is not None:
b64_data = data if b64 else b64encode(data.encode()).decode()
spec["Data"] = b64_data

if name is not None:
spec["Name"] = name

if labels is not None:
spec["Labels"] = labels

if driver is not None:
spec["Driver"] = driver

if templating is not None:
spec["Templating"] = templating

params = {"version": version}
request_data = json.dumps(clean_map(spec))

await self.docker._query_json(
"secrets/{secret_id}/update".format(secret_id=secret_id),
method="POST",
data=request_data,
params=params,
)
return True

0 comments on commit 5dfa90e

Please sign in to comment.