eryph-compute 0.1.1

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 (222) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +47 -0
  3. data/LICENSE +21 -0
  4. data/README.md +144 -0
  5. data/eryph-clientruntime.gemspec +42 -0
  6. data/eryph-compute.gemspec +44 -0
  7. data/lib/eryph/clientruntime/client_credentials_lookup.rb +295 -0
  8. data/lib/eryph/clientruntime/config_store.rb +206 -0
  9. data/lib/eryph/clientruntime/config_stores_reader.rb +211 -0
  10. data/lib/eryph/clientruntime/endpoint_lookup.rb +226 -0
  11. data/lib/eryph/clientruntime/environment.rb +440 -0
  12. data/lib/eryph/clientruntime/local_identity_provider_info.rb +153 -0
  13. data/lib/eryph/clientruntime/token_provider.rb +275 -0
  14. data/lib/eryph/clientruntime/version.rb +6 -0
  15. data/lib/eryph/clientruntime.rb +79 -0
  16. data/lib/eryph/compute/client.rb +442 -0
  17. data/lib/eryph/compute/generated/Gemfile +9 -0
  18. data/lib/eryph/compute/generated/README.md +206 -0
  19. data/lib/eryph/compute/generated/Rakefile +10 -0
  20. data/lib/eryph/compute/generated/compute_client.gemspec +41 -0
  21. data/lib/eryph/compute/generated/docs/ApiVersion.md +20 -0
  22. data/lib/eryph/compute/generated/docs/ApiVersionResponse.md +18 -0
  23. data/lib/eryph/compute/generated/docs/Catlet.md +32 -0
  24. data/lib/eryph/compute/generated/docs/CatletConfigOperationResult.md +18 -0
  25. data/lib/eryph/compute/generated/docs/CatletConfigValidationResult.md +20 -0
  26. data/lib/eryph/compute/generated/docs/CatletConfiguration.md +18 -0
  27. data/lib/eryph/compute/generated/docs/CatletDrive.md +20 -0
  28. data/lib/eryph/compute/generated/docs/CatletDriveType.md +15 -0
  29. data/lib/eryph/compute/generated/docs/CatletList.md +18 -0
  30. data/lib/eryph/compute/generated/docs/CatletNetwork.md +30 -0
  31. data/lib/eryph/compute/generated/docs/CatletNetworkAdapter.md +20 -0
  32. data/lib/eryph/compute/generated/docs/CatletStatus.md +15 -0
  33. data/lib/eryph/compute/generated/docs/CatletStopMode.md +15 -0
  34. data/lib/eryph/compute/generated/docs/CatletsApi.md +863 -0
  35. data/lib/eryph/compute/generated/docs/DiskStatus.md +15 -0
  36. data/lib/eryph/compute/generated/docs/ExpandCatletConfigRequestBody.md +22 -0
  37. data/lib/eryph/compute/generated/docs/ExpandNewCatletConfigRequest.md +22 -0
  38. data/lib/eryph/compute/generated/docs/FloatingNetworkPort.md +26 -0
  39. data/lib/eryph/compute/generated/docs/Gene.md +30 -0
  40. data/lib/eryph/compute/generated/docs/GeneList.md +18 -0
  41. data/lib/eryph/compute/generated/docs/GeneType.md +15 -0
  42. data/lib/eryph/compute/generated/docs/GeneWithUsage.md +34 -0
  43. data/lib/eryph/compute/generated/docs/GenesApi.md +281 -0
  44. data/lib/eryph/compute/generated/docs/NewCatletRequest.md +20 -0
  45. data/lib/eryph/compute/generated/docs/NewProjectMemberBody.md +22 -0
  46. data/lib/eryph/compute/generated/docs/NewProjectRequest.md +20 -0
  47. data/lib/eryph/compute/generated/docs/NewVirtualDiskRequest.md +30 -0
  48. data/lib/eryph/compute/generated/docs/Operation.md +32 -0
  49. data/lib/eryph/compute/generated/docs/OperationList.md +18 -0
  50. data/lib/eryph/compute/generated/docs/OperationLogEntry.md +24 -0
  51. data/lib/eryph/compute/generated/docs/OperationResource.md +22 -0
  52. data/lib/eryph/compute/generated/docs/OperationResult.md +18 -0
  53. data/lib/eryph/compute/generated/docs/OperationStatus.md +15 -0
  54. data/lib/eryph/compute/generated/docs/OperationTask.md +30 -0
  55. data/lib/eryph/compute/generated/docs/OperationTaskReference.md +22 -0
  56. data/lib/eryph/compute/generated/docs/OperationTaskStatus.md +15 -0
  57. data/lib/eryph/compute/generated/docs/OperationsApi.md +157 -0
  58. data/lib/eryph/compute/generated/docs/PopulateCatletConfigVariablesRequest.md +20 -0
  59. data/lib/eryph/compute/generated/docs/ProblemDetails.md +26 -0
  60. data/lib/eryph/compute/generated/docs/Project.md +22 -0
  61. data/lib/eryph/compute/generated/docs/ProjectList.md +18 -0
  62. data/lib/eryph/compute/generated/docs/ProjectMemberRole.md +26 -0
  63. data/lib/eryph/compute/generated/docs/ProjectMemberRoleList.md +18 -0
  64. data/lib/eryph/compute/generated/docs/ProjectMembersApi.md +293 -0
  65. data/lib/eryph/compute/generated/docs/ProjectsApi.md +286 -0
  66. data/lib/eryph/compute/generated/docs/ResourceType.md +15 -0
  67. data/lib/eryph/compute/generated/docs/StopCatletRequestBody.md +18 -0
  68. data/lib/eryph/compute/generated/docs/TaskReferenceType.md +15 -0
  69. data/lib/eryph/compute/generated/docs/UpdateCatletRequestBody.md +20 -0
  70. data/lib/eryph/compute/generated/docs/UpdateProjectNetworksRequestBody.md +20 -0
  71. data/lib/eryph/compute/generated/docs/ValidateConfigRequest.md +18 -0
  72. data/lib/eryph/compute/generated/docs/ValidationIssue.md +20 -0
  73. data/lib/eryph/compute/generated/docs/VersionApi.md +69 -0
  74. data/lib/eryph/compute/generated/docs/VirtualDisk.md +42 -0
  75. data/lib/eryph/compute/generated/docs/VirtualDiskAttachedCatlet.md +20 -0
  76. data/lib/eryph/compute/generated/docs/VirtualDiskGeneInfo.md +22 -0
  77. data/lib/eryph/compute/generated/docs/VirtualDiskList.md +18 -0
  78. data/lib/eryph/compute/generated/docs/VirtualDisksApi.md +291 -0
  79. data/lib/eryph/compute/generated/docs/VirtualNetwork.md +28 -0
  80. data/lib/eryph/compute/generated/docs/VirtualNetworkConfiguration.md +18 -0
  81. data/lib/eryph/compute/generated/docs/VirtualNetworkList.md +18 -0
  82. data/lib/eryph/compute/generated/docs/VirtualNetworksApi.md +291 -0
  83. data/lib/eryph/compute/generated/git_push.sh +57 -0
  84. data/lib/eryph/compute/generated/lib/compute_client/api/catlets_api.rb +812 -0
  85. data/lib/eryph/compute/generated/lib/compute_client/api/genes_api.rb +262 -0
  86. data/lib/eryph/compute/generated/lib/compute_client/api/operations_api.rb +154 -0
  87. data/lib/eryph/compute/generated/lib/compute_client/api/project_members_api.rb +297 -0
  88. data/lib/eryph/compute/generated/lib/compute_client/api/projects_api.rb +269 -0
  89. data/lib/eryph/compute/generated/lib/compute_client/api/version_api.rb +79 -0
  90. data/lib/eryph/compute/generated/lib/compute_client/api/virtual_disks_api.rb +272 -0
  91. data/lib/eryph/compute/generated/lib/compute_client/api/virtual_networks_api.rb +282 -0
  92. data/lib/eryph/compute/generated/lib/compute_client/api_client.rb +437 -0
  93. data/lib/eryph/compute/generated/lib/compute_client/api_error.rb +58 -0
  94. data/lib/eryph/compute/generated/lib/compute_client/configuration.rb +392 -0
  95. data/lib/eryph/compute/generated/lib/compute_client/models/api_version.rb +263 -0
  96. data/lib/eryph/compute/generated/lib/compute_client/models/api_version_response.rb +237 -0
  97. data/lib/eryph/compute/generated/lib/compute_client/models/catlet.rb +400 -0
  98. data/lib/eryph/compute/generated/lib/compute_client/models/catlet_config_operation_result.rb +234 -0
  99. data/lib/eryph/compute/generated/lib/compute_client/models/catlet_config_validation_result.rb +251 -0
  100. data/lib/eryph/compute/generated/lib/compute_client/models/catlet_configuration.rb +223 -0
  101. data/lib/eryph/compute/generated/lib/compute_client/models/catlet_drive.rb +270 -0
  102. data/lib/eryph/compute/generated/lib/compute_client/models/catlet_drive_type.rb +43 -0
  103. data/lib/eryph/compute/generated/lib/compute_client/models/catlet_list.rb +239 -0
  104. data/lib/eryph/compute/generated/lib/compute_client/models/catlet_network.rb +318 -0
  105. data/lib/eryph/compute/generated/lib/compute_client/models/catlet_network_adapter.rb +247 -0
  106. data/lib/eryph/compute/generated/lib/compute_client/models/catlet_status.rb +43 -0
  107. data/lib/eryph/compute/generated/lib/compute_client/models/catlet_stop_mode.rb +41 -0
  108. data/lib/eryph/compute/generated/lib/compute_client/models/disk_status.rb +40 -0
  109. data/lib/eryph/compute/generated/lib/compute_client/models/expand_catlet_config_request_body.rb +243 -0
  110. data/lib/eryph/compute/generated/lib/compute_client/models/expand_new_catlet_config_request.rb +243 -0
  111. data/lib/eryph/compute/generated/lib/compute_client/models/floating_network_port.rb +313 -0
  112. data/lib/eryph/compute/generated/lib/compute_client/models/gene.rb +415 -0
  113. data/lib/eryph/compute/generated/lib/compute_client/models/gene_list.rb +239 -0
  114. data/lib/eryph/compute/generated/lib/compute_client/models/gene_type.rb +41 -0
  115. data/lib/eryph/compute/generated/lib/compute_client/models/gene_with_usage.rb +439 -0
  116. data/lib/eryph/compute/generated/lib/compute_client/models/new_catlet_request.rb +233 -0
  117. data/lib/eryph/compute/generated/lib/compute_client/models/new_project_member_body.rb +273 -0
  118. data/lib/eryph/compute/generated/lib/compute_client/models/new_project_request.rb +247 -0
  119. data/lib/eryph/compute/generated/lib/compute_client/models/new_virtual_disk_request.rb +345 -0
  120. data/lib/eryph/compute/generated/lib/compute_client/models/operation.rb +352 -0
  121. data/lib/eryph/compute/generated/lib/compute_client/models/operation_list.rb +239 -0
  122. data/lib/eryph/compute/generated/lib/compute_client/models/operation_log_entry.rb +299 -0
  123. data/lib/eryph/compute/generated/lib/compute_client/models/operation_resource.rb +311 -0
  124. data/lib/eryph/compute/generated/lib/compute_client/models/operation_result.rb +242 -0
  125. data/lib/eryph/compute/generated/lib/compute_client/models/operation_status.rb +42 -0
  126. data/lib/eryph/compute/generated/lib/compute_client/models/operation_task.rb +366 -0
  127. data/lib/eryph/compute/generated/lib/compute_client/models/operation_task_reference.rb +311 -0
  128. data/lib/eryph/compute/generated/lib/compute_client/models/operation_task_status.rb +42 -0
  129. data/lib/eryph/compute/generated/lib/compute_client/models/populate_catlet_config_variables_request.rb +233 -0
  130. data/lib/eryph/compute/generated/lib/compute_client/models/problem_details.rb +261 -0
  131. data/lib/eryph/compute/generated/lib/compute_client/models/project.rb +289 -0
  132. data/lib/eryph/compute/generated/lib/compute_client/models/project_list.rb +239 -0
  133. data/lib/eryph/compute/generated/lib/compute_client/models/project_member_role.rb +341 -0
  134. data/lib/eryph/compute/generated/lib/compute_client/models/project_member_role_list.rb +239 -0
  135. data/lib/eryph/compute/generated/lib/compute_client/models/resource_type.rb +42 -0
  136. data/lib/eryph/compute/generated/lib/compute_client/models/stop_catlet_request_body.rb +259 -0
  137. data/lib/eryph/compute/generated/lib/compute_client/models/task_reference_type.rb +40 -0
  138. data/lib/eryph/compute/generated/lib/compute_client/models/update_catlet_request_body.rb +233 -0
  139. data/lib/eryph/compute/generated/lib/compute_client/models/update_project_networks_request_body.rb +233 -0
  140. data/lib/eryph/compute/generated/lib/compute_client/models/validate_config_request.rb +223 -0
  141. data/lib/eryph/compute/generated/lib/compute_client/models/validation_issue.rb +249 -0
  142. data/lib/eryph/compute/generated/lib/compute_client/models/virtual_disk.rb +479 -0
  143. data/lib/eryph/compute/generated/lib/compute_client/models/virtual_disk_attached_catlet.rb +285 -0
  144. data/lib/eryph/compute/generated/lib/compute_client/models/virtual_disk_gene_info.rb +289 -0
  145. data/lib/eryph/compute/generated/lib/compute_client/models/virtual_disk_list.rb +239 -0
  146. data/lib/eryph/compute/generated/lib/compute_client/models/virtual_network.rb +351 -0
  147. data/lib/eryph/compute/generated/lib/compute_client/models/virtual_network_configuration.rb +223 -0
  148. data/lib/eryph/compute/generated/lib/compute_client/models/virtual_network_list.rb +239 -0
  149. data/lib/eryph/compute/generated/lib/compute_client/version.rb +15 -0
  150. data/lib/eryph/compute/generated/lib/compute_client.rb +101 -0
  151. data/lib/eryph/compute/generated/spec/api/catlets_api_spec.rb +182 -0
  152. data/lib/eryph/compute/generated/spec/api/genes_api_spec.rb +81 -0
  153. data/lib/eryph/compute/generated/spec/api/operations_api_spec.rb +62 -0
  154. data/lib/eryph/compute/generated/spec/api/project_members_api_spec.rb +86 -0
  155. data/lib/eryph/compute/generated/spec/api/projects_api_spec.rb +82 -0
  156. data/lib/eryph/compute/generated/spec/api/version_api_spec.rb +46 -0
  157. data/lib/eryph/compute/generated/spec/api/virtual_disks_api_spec.rb +83 -0
  158. data/lib/eryph/compute/generated/spec/api/virtual_networks_api_spec.rb +84 -0
  159. data/lib/eryph/compute/generated/spec/models/api_version_response_spec.rb +36 -0
  160. data/lib/eryph/compute/generated/spec/models/api_version_spec.rb +42 -0
  161. data/lib/eryph/compute/generated/spec/models/catlet_config_operation_result_spec.rb +36 -0
  162. data/lib/eryph/compute/generated/spec/models/catlet_config_validation_result_spec.rb +42 -0
  163. data/lib/eryph/compute/generated/spec/models/catlet_configuration_spec.rb +36 -0
  164. data/lib/eryph/compute/generated/spec/models/catlet_drive_spec.rb +42 -0
  165. data/lib/eryph/compute/generated/spec/models/catlet_drive_type_spec.rb +30 -0
  166. data/lib/eryph/compute/generated/spec/models/catlet_list_spec.rb +36 -0
  167. data/lib/eryph/compute/generated/spec/models/catlet_network_adapter_spec.rb +42 -0
  168. data/lib/eryph/compute/generated/spec/models/catlet_network_spec.rb +72 -0
  169. data/lib/eryph/compute/generated/spec/models/catlet_spec.rb +78 -0
  170. data/lib/eryph/compute/generated/spec/models/catlet_status_spec.rb +30 -0
  171. data/lib/eryph/compute/generated/spec/models/catlet_stop_mode_spec.rb +30 -0
  172. data/lib/eryph/compute/generated/spec/models/disk_status_spec.rb +30 -0
  173. data/lib/eryph/compute/generated/spec/models/expand_catlet_config_request_body_spec.rb +48 -0
  174. data/lib/eryph/compute/generated/spec/models/expand_new_catlet_config_request_spec.rb +48 -0
  175. data/lib/eryph/compute/generated/spec/models/floating_network_port_spec.rb +60 -0
  176. data/lib/eryph/compute/generated/spec/models/gene_list_spec.rb +36 -0
  177. data/lib/eryph/compute/generated/spec/models/gene_spec.rb +72 -0
  178. data/lib/eryph/compute/generated/spec/models/gene_type_spec.rb +30 -0
  179. data/lib/eryph/compute/generated/spec/models/gene_with_usage_spec.rb +84 -0
  180. data/lib/eryph/compute/generated/spec/models/new_catlet_request_spec.rb +42 -0
  181. data/lib/eryph/compute/generated/spec/models/new_project_member_body_spec.rb +48 -0
  182. data/lib/eryph/compute/generated/spec/models/new_project_request_spec.rb +42 -0
  183. data/lib/eryph/compute/generated/spec/models/new_virtual_disk_request_spec.rb +72 -0
  184. data/lib/eryph/compute/generated/spec/models/operation_list_spec.rb +36 -0
  185. data/lib/eryph/compute/generated/spec/models/operation_log_entry_spec.rb +54 -0
  186. data/lib/eryph/compute/generated/spec/models/operation_resource_spec.rb +48 -0
  187. data/lib/eryph/compute/generated/spec/models/operation_result_spec.rb +36 -0
  188. data/lib/eryph/compute/generated/spec/models/operation_spec.rb +78 -0
  189. data/lib/eryph/compute/generated/spec/models/operation_status_spec.rb +30 -0
  190. data/lib/eryph/compute/generated/spec/models/operation_task_reference_spec.rb +48 -0
  191. data/lib/eryph/compute/generated/spec/models/operation_task_spec.rb +72 -0
  192. data/lib/eryph/compute/generated/spec/models/operation_task_status_spec.rb +30 -0
  193. data/lib/eryph/compute/generated/spec/models/populate_catlet_config_variables_request_spec.rb +42 -0
  194. data/lib/eryph/compute/generated/spec/models/problem_details_spec.rb +60 -0
  195. data/lib/eryph/compute/generated/spec/models/project_list_spec.rb +36 -0
  196. data/lib/eryph/compute/generated/spec/models/project_member_role_list_spec.rb +36 -0
  197. data/lib/eryph/compute/generated/spec/models/project_member_role_spec.rb +60 -0
  198. data/lib/eryph/compute/generated/spec/models/project_spec.rb +48 -0
  199. data/lib/eryph/compute/generated/spec/models/resource_type_spec.rb +30 -0
  200. data/lib/eryph/compute/generated/spec/models/stop_catlet_request_body_spec.rb +36 -0
  201. data/lib/eryph/compute/generated/spec/models/task_reference_type_spec.rb +30 -0
  202. data/lib/eryph/compute/generated/spec/models/update_catlet_request_body_spec.rb +42 -0
  203. data/lib/eryph/compute/generated/spec/models/update_project_networks_request_body_spec.rb +42 -0
  204. data/lib/eryph/compute/generated/spec/models/validate_config_request_spec.rb +36 -0
  205. data/lib/eryph/compute/generated/spec/models/validation_issue_spec.rb +42 -0
  206. data/lib/eryph/compute/generated/spec/models/virtual_disk_attached_catlet_spec.rb +42 -0
  207. data/lib/eryph/compute/generated/spec/models/virtual_disk_gene_info_spec.rb +48 -0
  208. data/lib/eryph/compute/generated/spec/models/virtual_disk_list_spec.rb +36 -0
  209. data/lib/eryph/compute/generated/spec/models/virtual_disk_spec.rb +108 -0
  210. data/lib/eryph/compute/generated/spec/models/virtual_network_configuration_spec.rb +36 -0
  211. data/lib/eryph/compute/generated/spec/models/virtual_network_list_spec.rb +36 -0
  212. data/lib/eryph/compute/generated/spec/models/virtual_network_spec.rb +66 -0
  213. data/lib/eryph/compute/generated/spec/spec_helper.rb +111 -0
  214. data/lib/eryph/compute/generated.rb +137 -0
  215. data/lib/eryph/compute/operation_result.rb +255 -0
  216. data/lib/eryph/compute/operation_tracker.rb +247 -0
  217. data/lib/eryph/compute/problem_details_error.rb +139 -0
  218. data/lib/eryph/compute/version.rb +6 -0
  219. data/lib/eryph/compute.rb +40 -0
  220. data/lib/eryph/version.rb +4 -0
  221. data/lib/eryph.rb +68 -0
  222. metadata +329 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b325ab23bab7159f9739f2ca245c2c9610643d5cd80aeba5471b0a9ddda30596
4
+ data.tar.gz: 532c3c97b205016b2135d539950e74b2889ee8cd5b6dd1e362a7ef77cc26b036
5
+ SHA512:
6
+ metadata.gz: 631697c5902ab1f3c954b31d9b3ee9c12615b63b0373e54386b3236d018fdbebc08d28c2ee2e36058a250f858c6b9eb6f67ccc8ce60082126dd857dbf8e721ea
7
+ data.tar.gz: 04e0985c3d88904066af5a635338bc40a2a3405b6f9ed9e73b03457000a4566c8456a5beab01396ed03b7fe9436afbc26bf4be1ebcddbebf6526f5d0487c965e
data/CHANGELOG.md ADDED
@@ -0,0 +1,47 @@
1
+ # Changelog
2
+
3
+ All notable changes to the Eryph Ruby client libraries will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+ - Initial release of Eryph Ruby compute client
12
+ - OAuth2 authentication with JWT support
13
+ - **Automatic credential discovery** - Tries multiple configurations (default → zero → local) without requiring explicit config name
14
+ - **Client ID-based discovery** - Find specific client across all configurations
15
+ - **Enhanced Client constructor** - Support for `client_id` parameter and automatic discovery
16
+ - System client credential detection for eryph-zero
17
+ - Complete Compute API coverage via OpenAPI generation
18
+ - Configuration-based endpoint management
19
+ - SSL/TLS configuration support
20
+ - Comprehensive error handling and logging
21
+ - **Cross-platform admin privilege detection** - Windows Administrator and Linux root support
22
+
23
+ ### Changed
24
+
25
+ ### Deprecated
26
+
27
+ ### Removed
28
+
29
+ ### Fixed
30
+
31
+ ### Security
32
+
33
+ ## [0.1.0] - 2025-01-24
34
+
35
+ ### Added
36
+ - Initial release of `eryph-clientruntime` gem with authentication and configuration management
37
+ - Initial release of `eryph-compute` gem with complete Compute API coverage
38
+ - Support for Windows DPAPI credential decryption
39
+ - Automatic endpoint discovery from running eryph-zero instances
40
+ - Generated API client with proper authentication
41
+ - Monorepo structure with separate versioning for runtime and compute client using changesets
42
+ - Examples and documentation for common usage patterns
43
+ - Integration with @changesets/cli for version management
44
+ - Automated version synchronization between NPM packages and Ruby gems
45
+
46
+ [Unreleased]: https://github.com/eryph-org/ruby-client/compare/v0.1.0...HEAD
47
+ [0.1.0]: https://github.com/eryph-org/ruby-client/releases/tag/v0.1.0
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Eryph Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # Eryph Ruby Client Libraries
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/eryph-compute.svg)](https://badge.fury.io/rb/eryph-compute)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ Official Ruby client libraries for Eryph APIs with seamless OAuth2 authentication, automatic configuration discovery, and cross-platform support.
7
+
8
+ ## 🚀 Quick Start
9
+
10
+ ```ruby
11
+ require 'eryph'
12
+
13
+ # Automatic credential discovery - tries multiple configs in priority order
14
+ client = Eryph.compute_client # Auto-discovers: default → zero → local
15
+
16
+ # Or specify configuration/client explicitly
17
+ # client = Eryph.compute_client('production') # Specific config
18
+ # client = Eryph.compute_client(client_id: 'my-app') # Find client across all configs
19
+ # client = Eryph.compute_client('zero', client_id: 'admin') # Specific client in config
20
+
21
+ # List your catlets
22
+ catlets = client.catlets.catlets_list
23
+ puts "Found #{catlets.value.length} catlets"
24
+
25
+ # Validate a configuration
26
+ config = { name: 'my-app', parent: 'dbosoft/ubuntu-22.04/starter' }
27
+ result = client.validate_catlet_config(config)
28
+ puts result.is_valid ? '✅ Valid' : '❌ Invalid'
29
+ ```
30
+
31
+ ## 📦 Installation
32
+
33
+ Add to your Gemfile:
34
+ ```ruby
35
+ gem 'eryph-compute'
36
+ ```
37
+
38
+ Or install directly:
39
+ ```bash
40
+ gem install eryph-compute
41
+ ```
42
+
43
+ ## ✨ Features
44
+
45
+ - **🔐 Zero-Config Authentication** - Automatic credential discovery from multiple sources
46
+ - **🎯 eryph-zero Integration** - Auto-detects local development environments
47
+ - **🌍 Cross-Platform** - Windows, Linux, and macOS support
48
+ - **🔄 Operation Tracking** - Real-time monitoring of long-running operations
49
+
50
+ ## 🏗️ Architecture
51
+
52
+ This is a **monorepo** containing multiple Ruby client libraries:
53
+
54
+ | Gem | Description | Use Case |
55
+ |-----|-------------|----------|
56
+ | **`eryph-compute`** | Compute API client | Managing catlets, projects, resources |
57
+ | **`eryph-clientruntime`** | Shared authentication runtime | Used by all Eryph clients |
58
+ | **`eryph-identity`** | *Coming Soon* | User and role management |
59
+
60
+ ## 📚 Documentation
61
+
62
+ ### Getting Started
63
+ - **[Installation & Setup](docs/guides/getting-started.md)** - Complete installation guide
64
+ - **[Authentication](docs/guides/authentication.md)** - OAuth2 setup and configuration
65
+ - **[Configuration](docs/guides/configuration.md)** - Managing multiple environments
66
+
67
+ ### API Reference
68
+ - **[Ruby API Reference](docs/ruby-api/)** - High-level Ruby client documentation
69
+ - **[REST API Reference](docs/api/)** - Complete OpenAPI specification
70
+ - **[Code Examples](docs/examples/)** - Common usage patterns
71
+
72
+ For detailed API endpoint documentation, see **[API Reference](docs/api/)** - complete REST API documentation with all endpoints, models, and examples.
73
+
74
+ ## 🔧 Configuration
75
+
76
+ The client uses a hierarchical configuration system with automatic discovery:
77
+
78
+ ```bash
79
+ # Priority order (highest to lowest):
80
+ 1. ./.eryph/{config}.config # Project directory
81
+ 2. ~/.config/.eryph/{config}.config # User directory (Unix)
82
+ %APPDATA%\.eryph\{config}.config # User directory (Windows)
83
+ 3. /etc/.eryph/{config}.config # System directory (Unix)
84
+ %PROGRAMDATA%\.eryph\{config}.config # System directory (Windows)
85
+ ```
86
+
87
+ **Configuration file example** (`.eryph/default.config`):
88
+ ```json
89
+ {
90
+ "endpoints": {
91
+ "identity": "https://identity.mycompany.com",
92
+ "compute": "https://compute.mycompany.com"
93
+ },
94
+ "clients": [{
95
+ "id": "my-app-client",
96
+ "name": "My Application"
97
+ }],
98
+ "defaultClient": "my-app-client"
99
+ }
100
+ ```
101
+
102
+ ## 🎯 Multiple Environments & Discovery
103
+
104
+ ```ruby
105
+ # Automatic discovery (recommended - tries multiple configs)
106
+ client = Eryph.compute_client # Auto-discovers best available credentials
107
+
108
+ # Specific configurations
109
+ prod_client = Eryph.compute_client('production') # Production environment
110
+ dev_client = Eryph.compute_client('zero') # Local eryph-zero instance
111
+
112
+ # Client ID-based discovery (searches across all configurations)
113
+ admin_client = Eryph.compute_client(client_id: 'admin-client')
114
+ app_client = Eryph.compute_client(client_id: 'my-app-client')
115
+
116
+ # Combined - specific client in specific config
117
+ specific_client = Eryph.compute_client('production', client_id: 'backup-service')
118
+ ```
119
+
120
+ ## 🤝 Contributing
121
+
122
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details on:
123
+
124
+ - Development setup with changeset management
125
+ - Code style and testing requirements
126
+ - Pull request process
127
+ - Release workflow
128
+
129
+ ## 📄 License
130
+
131
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
132
+
133
+ ## 🆘 Support & Community
134
+
135
+ - **[📖 Documentation](https://https://www.eryph.io/docs)** - Complete guides and API reference
136
+ - **[🐛 Issue Tracker](https://github.com/eryph-org/ruby-client/issues)** - Bug reports and feature requests
137
+ - **[💬 Discussions](https://github.com/eryph-org/eryph/discussions)** - Community support and questions
138
+ - **[🌐 Website](https://eryph.io)** - Learn more about Eryph
139
+
140
+ ---
141
+
142
+ <div align="center">
143
+ <strong>Built with ❤️ by the Eryph Team</strong>
144
+ </div>
@@ -0,0 +1,42 @@
1
+ $LOAD_PATH.push File.expand_path('lib', __dir__)
2
+ require 'eryph/clientruntime/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'eryph-clientruntime'
6
+ s.version = Eryph::ClientRuntime::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ['Eryph Team']
9
+ s.email = ['support@eryph.io']
10
+ s.homepage = 'https://github.com/eryph-org/ruby-client'
11
+ s.summary = 'Eryph Client Runtime for Ruby'
12
+ s.description = 'Authentication, configuration, and credential lookup runtime for Eryph Ruby client libraries'
13
+ s.license = 'MIT'
14
+ s.required_ruby_version = '>= 2.7'
15
+
16
+ s.metadata = {
17
+ 'bug_tracker_uri' => 'https://github.com/eryph-org/ruby-client/issues',
18
+ 'changelog_uri' => 'https://github.com/eryph-org/ruby-client/blob/main/CHANGELOG.md',
19
+ 'source_code_uri' => 'https://github.com/eryph-org/ruby-client',
20
+ 'homepage_uri' => 'https://eryph.io',
21
+ 'documentation_uri' => 'https://www.eryph.io/docs',
22
+ 'rubygems_mfa_required' => 'true',
23
+ }
24
+
25
+ # Runtime dependencies
26
+ s.add_dependency 'jwt', '>= 2.0', '< 4.0'
27
+
28
+ # Development dependencies moved to Gemfile for better version management
29
+
30
+ # Specify files to include (only clientruntime files)
31
+ s.files = Dir[
32
+ 'lib/eryph/clientruntime.rb',
33
+ 'lib/eryph/clientruntime/**/*',
34
+ 'README.md',
35
+ 'CHANGELOG.md',
36
+ 'LICENSE',
37
+ '*.gemspec'
38
+ ].select { |f| File.file?(f) }
39
+
40
+ s.executables = []
41
+ s.require_paths = ['lib']
42
+ end
@@ -0,0 +1,44 @@
1
+ $LOAD_PATH.push File.expand_path('lib', __dir__)
2
+ require 'eryph/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'eryph-compute'
6
+ s.version = Eryph::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ['Eryph Team']
9
+ s.email = ['support@eryph.io']
10
+ s.homepage = 'https://github.com/eryph-org/ruby-client'
11
+ s.summary = 'Ruby client for Eryph Compute API'
12
+ s.description = 'Official Ruby client library for the Eryph Compute API with OAuth2 authentication support'
13
+ s.license = 'MIT'
14
+ s.required_ruby_version = '>= 2.7'
15
+
16
+ s.metadata = {
17
+ 'bug_tracker_uri' => 'https://github.com/eryph-org/ruby-client/issues',
18
+ 'changelog_uri' => 'https://github.com/eryph-org/ruby-client/blob/main/CHANGELOG.md',
19
+ 'source_code_uri' => 'https://github.com/eryph-org/ruby-client',
20
+ 'homepage_uri' => 'https://eryph.io',
21
+ 'documentation_uri' => 'https://www.eryph.io/docs',
22
+ 'rubygems_mfa_required' => 'true',
23
+ }
24
+
25
+ # Runtime dependencies
26
+ s.add_dependency 'eryph-clientruntime', '~> 0.1'
27
+ s.add_dependency 'faraday', '>= 1.0.1', '< 3.0'
28
+ s.add_dependency 'faraday-multipart', '~> 1.0'
29
+ s.add_dependency 'marcel', '~> 1.0'
30
+
31
+ # Development dependencies moved to Gemfile for better version management
32
+
33
+ # Specify files to include
34
+ s.files = Dir[
35
+ 'lib/**/*',
36
+ 'README.md',
37
+ 'CHANGELOG.md',
38
+ 'LICENSE',
39
+ '*.gemspec'
40
+ ].select { |f| File.file?(f) }
41
+
42
+ s.executables = []
43
+ s.require_paths = ['lib']
44
+ end
@@ -0,0 +1,295 @@
1
+ require 'openssl'
2
+ require 'logger'
3
+
4
+ module Eryph
5
+ module ClientRuntime
6
+ # Client credentials structure
7
+ # Holds the information needed for OAuth2 client credentials flow
8
+ class ClientCredentials
9
+ # @return [String] OAuth client ID
10
+ attr_reader :client_id
11
+
12
+ # @return [String] client name
13
+ attr_reader :client_name
14
+
15
+ # @return [OpenSSL::PKey::RSA] RSA private key for JWT signing
16
+ attr_reader :private_key
17
+
18
+ # @return [String] OAuth token endpoint URL
19
+ attr_reader :token_endpoint
20
+
21
+ # @return [String, nil] configuration name this client belongs to
22
+ attr_reader :configuration
23
+
24
+ # Initialize client credentials
25
+ # @param client_id [String] OAuth client ID
26
+ # @param client_name [String] client name
27
+ # @param private_key [OpenSSL::PKey::RSA, String] RSA private key
28
+ # @param token_endpoint [String] OAuth token endpoint URL
29
+ # @param configuration [String, nil] configuration name
30
+ def initialize(client_id:, client_name:, private_key:, token_endpoint:, configuration: nil)
31
+ raise ArgumentError, 'client_id cannot be nil or empty' if client_id.nil? || client_id.empty?
32
+ raise ArgumentError, 'token_endpoint cannot be nil or empty' if token_endpoint.nil? || token_endpoint.empty?
33
+
34
+ @client_id = client_id
35
+ @client_name = client_name
36
+ @private_key = parse_private_key(private_key)
37
+ @token_endpoint = token_endpoint
38
+ @configuration = configuration
39
+ end
40
+
41
+ private
42
+
43
+ def parse_private_key(key)
44
+ raise ArgumentError, 'private_key cannot be nil' if key.nil?
45
+
46
+ case key
47
+ when OpenSSL::PKey::RSA
48
+ key
49
+ when String
50
+ raise ArgumentError, 'private_key cannot be empty' if key.empty?
51
+
52
+ OpenSSL::PKey::RSA.new(key)
53
+ else
54
+ raise ArgumentError, 'private_key must be an RSA key or PEM string'
55
+ end
56
+ rescue OpenSSL::PKey::RSAError => e
57
+ raise ArgumentError, "Invalid RSA private key: #{e.message}"
58
+ end
59
+ end
60
+
61
+ # Looks up client credentials from configuration stores
62
+ # Supports automatic discovery across multiple configurations like .NET implementation
63
+ class ClientCredentialsLookup
64
+ # @return [ConfigStoresReader] configuration stores reader
65
+ attr_reader :reader
66
+
67
+ # @return [String, nil] configuration name for specific lookups
68
+ attr_reader :config_name
69
+
70
+ # @return [Logger] logger instance
71
+ attr_reader :logger
72
+
73
+ # Initialize the credentials lookup
74
+ # @param reader [ConfigStoresReader] configuration stores reader
75
+ # @param config_name [String, nil] configuration name for specific lookup, nil for automatic discovery
76
+ # @param logger [Logger, nil] logger instance
77
+ def initialize(reader, config_name = nil, logger: nil)
78
+ @reader = reader
79
+ @config_name = config_name
80
+ @logger = logger || Logger.new($stdout).tap { |l| l.level = Logger::WARN }
81
+ end
82
+
83
+ # Find and return client credentials
84
+ # Uses automatic discovery if no config_name specified, otherwise looks in specific config
85
+ # @return [ClientCredentials] the discovered credentials
86
+ # @raise [CredentialsNotFoundError, NoUserCredentialsError] if credentials cannot be found
87
+ def find_credentials
88
+ @logger.debug("find_credentials: config=#{@config_name || 'auto'}")
89
+
90
+ if @config_name
91
+ # Find default client in specific config
92
+ creds = get_default_credentials(@config_name)
93
+ @logger.debug("find_credentials: default_client=#{creds ? 'found' : 'nil'}")
94
+
95
+ # For zero/local config, try system client as fallback
96
+ if !creds && %w[zero local].include?(@config_name)
97
+ @logger.debug('find_credentials: trying system_client fallback')
98
+ creds = get_system_client_credentials(@config_name)
99
+ @logger.debug("find_credentials: system_client=#{creds ? 'found' : 'nil'}")
100
+ end
101
+
102
+ @logger.debug("find_credentials: result=#{creds ? creds.client_id : 'nil'}")
103
+ raise CredentialsNotFoundError, "No default client found in configuration '#{@config_name}'" unless creds
104
+
105
+ creds
106
+ else
107
+ # Automatic discovery across multiple configs
108
+ configs = @reader.environment.windows? ? %w[default zero local] : %w[default local]
109
+ @logger.debug("find_credentials: auto_discovery configs=#{configs.join(',')}")
110
+ find_credentials_in_configs(*configs)
111
+ end
112
+ end
113
+
114
+ # Try multiple configurations in order
115
+ # @param config_names [Array<String>] configuration names to try
116
+ # @return [ClientCredentials] first credentials found
117
+ # @raise [NoUserCredentialsError] if no credentials found in any config
118
+ def find_credentials_in_configs(*config_names)
119
+ @logger.debug("find_credentials_in_configs: trying #{config_names.join(',')}")
120
+
121
+ config_names.each do |config_name|
122
+ @logger.debug("find_credentials_in_configs: checking config=#{config_name}")
123
+
124
+ # Try default client first
125
+ creds = get_default_credentials(config_name)
126
+ if creds
127
+ @logger.debug("find_credentials_in_configs: found default in #{config_name}")
128
+ return creds
129
+ end
130
+
131
+ # Try system client for zero/local configs
132
+ next unless %w[zero local].include?(config_name)
133
+
134
+ @logger.debug("find_credentials_in_configs: trying system client for #{config_name}")
135
+ creds = get_system_client_credentials(config_name)
136
+ if creds
137
+ @logger.debug("find_credentials_in_configs: found system client in #{config_name}")
138
+ return creds
139
+ end
140
+ end
141
+
142
+ @logger.debug('find_credentials_in_configs: no credentials found in any config')
143
+ raise NoUserCredentialsError, 'No credentials found. Please configure an eryph client.'
144
+ end
145
+
146
+ # Get default client credentials from specific configuration
147
+ # @param config_name [String] configuration name
148
+ # @return [ClientCredentials, nil] credentials if found, nil otherwise
149
+ def get_default_credentials(config_name)
150
+ @logger.debug("get_default_credentials: config=#{config_name}")
151
+
152
+ client = @reader.get_default_client(config_name)
153
+ @logger.debug("get_default_credentials: client=#{client ? client['id'] : 'nil'}")
154
+ return nil unless client
155
+
156
+ creds = build_credentials(client, config_name)
157
+ @logger.debug("get_default_credentials: build_result=#{creds ? 'success' : 'failed'}")
158
+ creds
159
+ end
160
+
161
+ # Get credentials by client ID from specific configuration
162
+ # @param client_id [String] client ID to find
163
+ # @param config_name [String] configuration name to search in
164
+ # @return [ClientCredentials, nil] credentials if found, nil otherwise
165
+ def get_credentials_by_client_id(client_id, config_name = 'default')
166
+ # Handle system-client specially
167
+ if client_id == 'system-client'
168
+ return get_system_client_credentials(config_name)
169
+ end
170
+
171
+ client = @reader.get_client(config_name, client_id)
172
+ return nil unless client
173
+
174
+ build_credentials(client, config_name)
175
+ end
176
+
177
+ # Get credentials by client name from specific configuration
178
+ # @param client_name [String] client name to find
179
+ # @param config_name [String] configuration name to search in
180
+ # @return [ClientCredentials, nil] credentials if found, nil otherwise
181
+ def get_credentials_by_client_name(client_name, config_name = 'default')
182
+ # Search through all clients to find by name
183
+ all_clients = @reader.get_all_clients(config_name)
184
+ client = all_clients.find { |c| c['name'] == client_name }
185
+ return nil unless client
186
+
187
+ build_credentials(client, config_name)
188
+ end
189
+
190
+ # Get system client credentials for zero/local configurations
191
+ # @param config_name [String] configuration name ('zero' or 'local')
192
+ # @return [ClientCredentials, nil] system credentials if available, nil otherwise
193
+ # @raise [NoUserCredentialsError] if system client available but requires admin privileges
194
+ def get_system_client_credentials(config_name = 'local')
195
+ @logger.debug("get_system_client_credentials: config=#{config_name}")
196
+
197
+ unless %w[zero local].include?(config_name)
198
+ @logger.debug('get_system_client_credentials: invalid config')
199
+ return nil
200
+ end
201
+
202
+ unless @reader.environment.windows? || @reader.environment.linux?
203
+ @logger.debug('get_system_client_credentials: unsupported platform')
204
+ return nil
205
+ end
206
+
207
+ # Zero config only supported on Windows
208
+ if config_name == 'zero' && !@reader.environment.windows?
209
+ @logger.debug('get_system_client_credentials: zero config not supported on non-Windows')
210
+ return nil
211
+ end
212
+
213
+ # Check admin privileges on Windows
214
+ if @reader.environment.windows? && !@reader.environment.admin_user?
215
+ @logger.debug('get_system_client_credentials: Windows admin required')
216
+ raise NoUserCredentialsError,
217
+ 'No user credentials found. System client is available but requires Administrator privileges. ' \
218
+ 'Please run as Administrator (Windows) or root (Linux) to use system client.'
219
+ end
220
+
221
+ # Check root privileges on Linux
222
+ if @reader.environment.linux? && !@reader.environment.admin_user?
223
+ @logger.debug('get_system_client_credentials: Linux root required')
224
+ raise NoUserCredentialsError,
225
+ 'No user credentials found. System client is available but requires root privileges. ' \
226
+ 'Please run as root to use system client.'
227
+ end
228
+
229
+ provider_info = LocalIdentityProviderInfo.new(@reader.environment, config_name, logger: @logger)
230
+ provider_running = provider_info.running?
231
+ @logger.debug("get_system_client_credentials: provider_running=#{provider_running}")
232
+
233
+ return nil unless provider_running
234
+
235
+ system_creds = provider_info.system_client_credentials
236
+ @logger.debug("get_system_client_credentials: system_creds=#{system_creds ? 'found' : 'nil'}")
237
+ return nil unless system_creds
238
+
239
+ @logger.debug("get_system_client_credentials: creating credentials for #{system_creds['id']}")
240
+
241
+ ClientCredentials.new(
242
+ client_id: system_creds['id'],
243
+ client_name: 'system-client',
244
+ private_key: system_creds['private_key'],
245
+ token_endpoint: "#{system_creds['identity_endpoint']}/connect/token",
246
+ configuration: config_name
247
+ )
248
+ end
249
+
250
+ # Test if credentials are available
251
+ # @return [Boolean] true if credentials can be found
252
+ def credentials_available?
253
+ find_credentials
254
+ true
255
+ rescue CredentialsNotFoundError, NoUserCredentialsError
256
+ false
257
+ end
258
+
259
+ private
260
+
261
+ # Build credentials object from client data and config
262
+ # @param client [Hash] client data from configuration
263
+ # @param config_name [String] configuration name
264
+ # @return [ClientCredentials, nil] built credentials or nil if invalid
265
+ def build_credentials(client, config_name)
266
+ private_key = @reader.get_client_private_key(client)
267
+ return nil unless private_key
268
+
269
+ token_endpoint = get_token_endpoint(config_name)
270
+ return nil unless token_endpoint
271
+
272
+ ClientCredentials.new(
273
+ client_id: client['id'],
274
+ client_name: client['name'] || client['id'],
275
+ private_key: private_key,
276
+ token_endpoint: token_endpoint,
277
+ configuration: config_name
278
+ )
279
+ rescue ArgumentError
280
+ nil
281
+ end
282
+
283
+ # Get token endpoint for configuration
284
+ # @param config_name [String] configuration name
285
+ # @return [String, nil] token endpoint URL or nil if not found
286
+ def get_token_endpoint(config_name)
287
+ endpoint_lookup = EndpointLookup.new(@reader, config_name, logger: @logger)
288
+ identity_url = endpoint_lookup.endpoint('identity')
289
+ return nil unless identity_url
290
+
291
+ "#{identity_url.chomp('/')}/connect/token"
292
+ end
293
+ end
294
+ end
295
+ end