devnomads 0.3.1__tar.gz → 0.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. {devnomads-0.3.1 → devnomads-0.4.1}/PKG-INFO +1 -1
  2. {devnomads-0.3.1 → devnomads-0.4.1}/openapi.json +140 -0
  3. {devnomads-0.3.1 → devnomads-0.4.1}/pyproject.toml +1 -1
  4. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/api/_services.py +37 -0
  5. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/api/client.py +15 -1
  6. {devnomads-0.3.1 → devnomads-0.4.1}/uv.lock +1213 -1203
  7. {devnomads-0.3.1 → devnomads-0.4.1}/.flake8 +0 -0
  8. {devnomads-0.3.1 → devnomads-0.4.1}/.gitignore +0 -0
  9. {devnomads-0.3.1 → devnomads-0.4.1}/.gitlab-ci.yml +0 -0
  10. {devnomads-0.3.1 → devnomads-0.4.1}/Makefile +0 -0
  11. {devnomads-0.3.1 → devnomads-0.4.1}/README.md +0 -0
  12. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/__init__.py +0 -0
  13. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/acme/__init__.py +0 -0
  14. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/acme/challenge_server.py +0 -0
  15. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/acme/client.py +0 -0
  16. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/acme/dns01.py +0 -0
  17. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/acme/errors.py +0 -0
  18. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/acme/http01.py +0 -0
  19. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/acme/keys.py +0 -0
  20. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/acme/verify.py +0 -0
  21. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/api/__init__.py +0 -0
  22. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/api/credentials.py +0 -0
  23. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/api/errors.py +0 -0
  24. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/dns/__init__.py +0 -0
  25. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/dns/errors.py +0 -0
  26. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/dns/names.py +0 -0
  27. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/dns/zones.py +0 -0
  28. {devnomads-0.3.1 → devnomads-0.4.1}/src/devnomads/py.typed +0 -0
  29. {devnomads-0.3.1 → devnomads-0.4.1}/tests/conftest.py +0 -0
  30. {devnomads-0.3.1 → devnomads-0.4.1}/tests/test_acme_challenges.py +0 -0
  31. {devnomads-0.3.1 → devnomads-0.4.1}/tests/test_acme_client.py +0 -0
  32. {devnomads-0.3.1 → devnomads-0.4.1}/tests/test_acme_keys.py +0 -0
  33. {devnomads-0.3.1 → devnomads-0.4.1}/tests/test_client.py +0 -0
  34. {devnomads-0.3.1 → devnomads-0.4.1}/tests/test_credentials.py +0 -0
  35. {devnomads-0.3.1 → devnomads-0.4.1}/tests/test_dns.py +0 -0
  36. {devnomads-0.3.1 → devnomads-0.4.1}/tests/test_names.py +0 -0
  37. {devnomads-0.3.1 → devnomads-0.4.1}/tests/test_services.py +0 -0
  38. {devnomads-0.3.1 → devnomads-0.4.1}/tools/bump_version.py +0 -0
  39. {devnomads-0.3.1 → devnomads-0.4.1}/tools/generate.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devnomads
3
- Version: 0.3.1
3
+ Version: 0.4.1
4
4
  Summary: Python client library for the DevNomads API (transport, DNS, ACME)
5
5
  Project-URL: Homepage, https://devnomads.nl
6
6
  Author-email: DevNomads <support@devnomads.nl>
@@ -2926,6 +2926,146 @@
2926
2926
  ]
2927
2927
  }
2928
2928
  },
2929
+ "/services/servers/{serviceId}/snapshots": {
2930
+ "get": {
2931
+ "tags": [
2932
+ "Server"
2933
+ ],
2934
+ "summary": "Get list of server snapshots",
2935
+ "description": "Get list of snapshots for a server service",
2936
+ "operationId": "services.servers.snapshots.index",
2937
+ "parameters": [
2938
+ {
2939
+ "name": "serviceId",
2940
+ "in": "path",
2941
+ "description": "Service ID",
2942
+ "required": true,
2943
+ "schema": {
2944
+ "type": "integer"
2945
+ }
2946
+ }
2947
+ ],
2948
+ "responses": {
2949
+ "200": {
2950
+ "description": "Success"
2951
+ }
2952
+ },
2953
+ "security": [
2954
+ {
2955
+ "bearerToken": []
2956
+ }
2957
+ ]
2958
+ },
2959
+ "post": {
2960
+ "tags": [
2961
+ "Server"
2962
+ ],
2963
+ "summary": "Create server snapshot",
2964
+ "description": "Create a new snapshot for a server service",
2965
+ "operationId": "services.servers.snapshots.create",
2966
+ "parameters": [
2967
+ {
2968
+ "name": "serviceId",
2969
+ "in": "path",
2970
+ "description": "Service ID",
2971
+ "required": true,
2972
+ "schema": {
2973
+ "type": "integer"
2974
+ }
2975
+ }
2976
+ ],
2977
+ "responses": {
2978
+ "202": {
2979
+ "description": "Accepted"
2980
+ }
2981
+ },
2982
+ "security": [
2983
+ {
2984
+ "bearerToken": []
2985
+ }
2986
+ ]
2987
+ }
2988
+ },
2989
+ "/services/servers/{serviceId}/snapshots/{snapshotUuid}/restore": {
2990
+ "get": {
2991
+ "tags": [
2992
+ "Server"
2993
+ ],
2994
+ "summary": "Restore server snapshot",
2995
+ "description": "Restore a snapshot for a server service",
2996
+ "operationId": "services.servers.snapshots.restore",
2997
+ "parameters": [
2998
+ {
2999
+ "name": "serviceId",
3000
+ "in": "path",
3001
+ "description": "Service ID",
3002
+ "required": true,
3003
+ "schema": {
3004
+ "type": "integer"
3005
+ }
3006
+ },
3007
+ {
3008
+ "name": "snapshotUuid",
3009
+ "in": "path",
3010
+ "description": "Snapshot UUID",
3011
+ "required": true,
3012
+ "schema": {
3013
+ "type": "string"
3014
+ }
3015
+ }
3016
+ ],
3017
+ "responses": {
3018
+ "202": {
3019
+ "description": "Accepted"
3020
+ }
3021
+ },
3022
+ "security": [
3023
+ {
3024
+ "bearerToken": []
3025
+ }
3026
+ ]
3027
+ }
3028
+ },
3029
+ "/services/servers/{serviceId}/snapshots/{snapshotUuid}": {
3030
+ "delete": {
3031
+ "tags": [
3032
+ "Server"
3033
+ ],
3034
+ "summary": "Delete server snapshot",
3035
+ "description": "Delete a snapshot for a server service",
3036
+ "operationId": "services.servers.snapshots.delete",
3037
+ "parameters": [
3038
+ {
3039
+ "name": "serviceId",
3040
+ "in": "path",
3041
+ "description": "Service ID",
3042
+ "required": true,
3043
+ "schema": {
3044
+ "type": "integer"
3045
+ }
3046
+ },
3047
+ {
3048
+ "name": "snapshotUuid",
3049
+ "in": "path",
3050
+ "description": "Snapshot UUID",
3051
+ "required": true,
3052
+ "schema": {
3053
+ "type": "string"
3054
+ }
3055
+ }
3056
+ ],
3057
+ "responses": {
3058
+ "202": {
3059
+ "description": "Accepted"
3060
+ }
3061
+ },
3062
+ "security": [
3063
+ {
3064
+ "bearerToken": []
3065
+ }
3066
+ ]
3067
+ }
3068
+ },
2929
3069
  "/services": {
2930
3070
  "get": {
2931
3071
  "tags": [
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "devnomads"
7
- version = "0.3.1"
7
+ version = "0.4.1"
8
8
  description = "Python client library for the DevNomads API (transport, DNS, ACME)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -717,6 +717,43 @@ class ServersResource:
717
717
  path = f"/services/servers/{service_id}/state/{state}"
718
718
  return self._client.request("GET", path, params=params)
719
719
 
720
+ @property
721
+ def snapshots(self) -> ServersSnapshotsResource:
722
+ return ServersSnapshotsResource(self._client)
723
+
724
+
725
+ class ServersSnapshotsResource:
726
+ """Generated resource accessor."""
727
+
728
+ def __init__(self, client: Client) -> None:
729
+ self._client = client
730
+
731
+ def create(
732
+ self, service_id: str, params: dict | None = None, body: Any = None
733
+ ) -> Any:
734
+ """Create server snapshot"""
735
+ path = f"/services/servers/{service_id}/snapshots"
736
+ return self._client.request("POST", path, params=params, json_body=body)
737
+
738
+ def delete(
739
+ self, service_id: str, snapshot_uuid: str, params: dict | None = None
740
+ ) -> Any:
741
+ """Delete server snapshot"""
742
+ path = f"/services/servers/{service_id}/snapshots/{snapshot_uuid}"
743
+ return self._client.request("DELETE", path, params=params)
744
+
745
+ def list(self, service_id: str, params: dict | None = None) -> Any:
746
+ """Get list of server snapshots"""
747
+ path = f"/services/servers/{service_id}/snapshots"
748
+ return self._client.request("GET", path, params=params)
749
+
750
+ def restore(
751
+ self, service_id: str, snapshot_uuid: str, params: dict | None = None
752
+ ) -> Any:
753
+ """Restore server snapshot"""
754
+ path = f"/services/servers/{service_id}/snapshots/{snapshot_uuid}/restore"
755
+ return self._client.request("GET", path, params=params)
756
+
720
757
 
721
758
  class SitesResource:
722
759
  """Generated resource accessor."""
@@ -124,12 +124,26 @@ class Client(ResourcesMixin):
124
124
  status=status,
125
125
  detail=_error_detail(response),
126
126
  )
127
+ if 300 <= status < 400:
128
+ location = response.headers.get("location", "")
129
+ raise ApiError(
130
+ f"API returned an unexpected HTTP {status} redirect"
131
+ + (f" to {location}" if location else "")
132
+ + " - the endpoint or credentials may be misrouted",
133
+ status=status,
134
+ detail=location,
135
+ )
127
136
  if status == 204 or not response.content:
128
137
  return None
129
138
  try:
130
139
  return _unwrap(response.json())
131
140
  except ValueError as exc:
132
- raise ApiError(f"API returned invalid JSON: {exc}", status=status) from exc
141
+ snippet = response.text[:200].strip()
142
+ raise ApiError(
143
+ f"API returned invalid JSON (HTTP {status}): {exc}; "
144
+ f"body starts with: {snippet!r}",
145
+ status=status,
146
+ ) from exc
133
147
 
134
148
  def _send(
135
149
  self,