codecraftai-provisioning 1.3.0__py3-none-any.whl
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.
- ccai/provisioning/__init__.py +0 -0
- ccai/provisioning/aspects/__init__.py +0 -0
- ccai/provisioning/aspects/provisioningaspects.py +46 -0
- ccai/provisioning/cloudinit/__init__.py +0 -0
- ccai/provisioning/cloudinit/bootstraprenderer.py +139 -0
- ccai/provisioning/cloudinit/bootstrapsecrets.py +128 -0
- ccai/provisioning/cloudinit/cloudinitmerge.py +68 -0
- ccai/provisioning/cloudinit/cloudinitrenderererror.py +18 -0
- ccai/provisioning/cloudinit/pythonenvcloudinitrenderer.py +420 -0
- ccai/provisioning/cloudinit/secretquoting.py +50 -0
- ccai/provisioning/cloudinit/vpncloudinitrenderer.py +375 -0
- ccai/provisioning/cloudprovisionerregistry.py +109 -0
- ccai/provisioning/dependencygraph.py +251 -0
- ccai/provisioning/landscape/__init__.py +0 -0
- ccai/provisioning/landscape/deviceaddressblock.py +58 -0
- ccai/provisioning/landscape/landscapeemitter.py +247 -0
- ccai/provisioning/model/__init__.py +0 -0
- ccai/provisioning/model/cloud/__init__.py +0 -0
- ccai/provisioning/model/cloud/_fake/__init__.py +0 -0
- ccai/provisioning/model/cloud/_fake/fakecloudprovisioner.py +273 -0
- ccai/provisioning/model/cloud/acceleratornotofferederror.py +43 -0
- ccai/provisioning/model/cloud/accelerators.yaml +128 -0
- ccai/provisioning/model/cloud/cloudacceleratorcatalog.py +398 -0
- ccai/provisioning/model/cloud/cloudacceleratorcatalogentry.py +98 -0
- ccai/provisioning/model/cloud/clouddevice.py +98 -0
- ccai/provisioning/model/cloud/clouddnsrecord.py +66 -0
- ccai/provisioning/model/cloud/cloudegressrule.py +86 -0
- ccai/provisioning/model/cloud/cloudgroup.py +55 -0
- ccai/provisioning/model/cloud/cloudimage.py +94 -0
- ccai/provisioning/model/cloud/cloudingressrule.py +113 -0
- ccai/provisioning/model/cloud/cloudinstance.py +304 -0
- ccai/provisioning/model/cloud/cloudinstancesizecatalog.py +435 -0
- ccai/provisioning/model/cloud/cloudinstancesizecatalogentry.py +100 -0
- ccai/provisioning/model/cloud/cloudinterconnect.py +75 -0
- ccai/provisioning/model/cloud/cloudkeypair.py +47 -0
- ccai/provisioning/model/cloud/cloudloadbalancer.py +73 -0
- ccai/provisioning/model/cloud/cloudloadbalancerlistener.py +97 -0
- ccai/provisioning/model/cloud/cloudnetwork.py +55 -0
- ccai/provisioning/model/cloud/cloudobjectbucket.py +54 -0
- ccai/provisioning/model/cloud/cloudprovisioner.py +361 -0
- ccai/provisioning/model/cloud/cloudresourcekind.py +30 -0
- ccai/provisioning/model/cloud/cloudresourceprofile.py +164 -0
- ccai/provisioning/model/cloud/cloudsecuritygroup.py +103 -0
- ccai/provisioning/model/cloud/cloudstoragevolume.py +99 -0
- ccai/provisioning/model/cloud/cloudsubnet.py +61 -0
- ccai/provisioning/model/cloud/cloudvenue.py +106 -0
- ccai/provisioning/model/cloud/deviceaddressset.py +59 -0
- ccai/provisioning/model/cloud/imagefamily.py +186 -0
- ccai/provisioning/model/cloud/imagefamilynotofferederror.py +36 -0
- ccai/provisioning/model/cloud/instancesizes.yaml +224 -0
- ccai/provisioning/model/cloud/networkprotocol.py +33 -0
- ccai/provisioning/model/cloud/notofferedonvenueerror.py +38 -0
- ccai/provisioning/model/cloud/plannedaction.py +88 -0
- ccai/provisioning/model/cloud/plannedactionintent.py +30 -0
- ccai/provisioning/model/cloud/preemptionpolicy.py +28 -0
- ccai/provisioning/model/cloud/provisionedresource.py +70 -0
- ccai/provisioning/model/cloud/provisioningplan.py +65 -0
- ccai/provisioning/model/cloud/provisioningresult.py +91 -0
- ccai/provisioning/model/cloud/storageclass.py +29 -0
- ccai/provisioning/model/cloud/validationresult.py +47 -0
- ccai/provisioning/model/cloud/venuecapability.py +134 -0
- ccai/provisioning/model/pythonenv/__init__.py +0 -0
- ccai/provisioning/model/pythonenv/indexcredentialresolver.py +155 -0
- ccai/provisioning/model/vpn/__init__.py +0 -0
- ccai/provisioning/model/vpn/hostnametemplate.py +141 -0
- ccai/provisioning/model/vpn/vpncredentialresolver.py +108 -0
- ccai/provisioning/model/workload/__init__.py +0 -0
- ccai/provisioning/model/workload/autoscalingspec.py +72 -0
- ccai/provisioning/model/workload/kubernetesworkloadprovisioner.py +449 -0
- ccai/provisioning/model/workload/nodepoolspec.py +75 -0
- ccai/provisioning/model/workload/nomadworkloadprovisioner.py +111 -0
- ccai/provisioning/model/workload/rayworkloadprovisioner.py +111 -0
- ccai/provisioning/model/workload/slurmworkloadprovisioner.py +112 -0
- ccai/provisioning/model/workload/workloadcluster.py +69 -0
- ccai/provisioning/model/workload/workloadjob.py +96 -0
- ccai/provisioning/model/workload/workloadprovisioner.py +434 -0
- ccai/provisioning/model/workload/workloadservice.py +97 -0
- ccai/provisioning/model/workload/workloadspec.py +61 -0
- ccai/provisioning/model/workload/workloadvenue.py +75 -0
- ccai/provisioning/pipelineplan.py +61 -0
- ccai/provisioning/pipelinestage.py +44 -0
- ccai/provisioning/preemption/__init__.py +12 -0
- ccai/provisioning/preemption/preemptionerrors.py +22 -0
- ccai/provisioning/preemption/preemptionevent.py +132 -0
- ccai/provisioning/preemption/preemptionhandler.py +294 -0
- ccai/provisioning/provisioningengine.py +858 -0
- ccai/provisioning/provisioningverifyerror.py +17 -0
- ccai/provisioning/py.typed +0 -0
- ccai/provisioning/stages/__init__.py +0 -0
- ccai/provisioning/state/__init__.py +0 -0
- ccai/provisioning/state/atomicwrite.py +31 -0
- ccai/provisioning/state/crossplatformlock.py +72 -0
- ccai/provisioning/state/provisioninglocktimeouterror.py +17 -0
- ccai/provisioning/state/provisioningstatestore.py +371 -0
- ccai/provisioning/state/redactforpersistence.py +115 -0
- ccai/provisioning/state/runindexentry.py +63 -0
- ccai/provisioning/state/runstate.py +67 -0
- ccai/provisioning/state/runstatus.py +25 -0
- ccai/provisioning/venues/__init__.py +0 -0
- ccai/provisioning/venues/aws/__init__.py +0 -0
- ccai/provisioning/venues/aws/awsboto3sessionfactory.py +119 -0
- ccai/provisioning/venues/aws/awscloudprovisioner.py +956 -0
- ccai/provisioning/venues/aws/awserrors.py +38 -0
- ccai/provisioning/venues/aws/awsidempotency.py +92 -0
- ccai/provisioning/venues/aws/awsregionconfig.py +78 -0
- ccai/provisioning/venues/aws/awsspec.py +103 -0
- ccai/provisioning/venues/aws/awstagging.py +144 -0
- ccai/provisioning/venues/aws/awstask.py +86 -0
- ccai/provisioning/venues/aws/resources/__init__.py +0 -0
- ccai/provisioning/venues/aws/resources/bucketmanager.py +227 -0
- ccai/provisioning/venues/aws/resources/dnsmanager.py +148 -0
- ccai/provisioning/venues/aws/resources/fsxmanager.py +114 -0
- ccai/provisioning/venues/aws/resources/imageresolver.py +227 -0
- ccai/provisioning/venues/aws/resources/instancemanager.py +501 -0
- ccai/provisioning/venues/aws/resources/keypairmanager.py +221 -0
- ccai/provisioning/venues/aws/resources/networkmanager.py +290 -0
- ccai/provisioning/venues/aws/resources/placementgroupmanager.py +143 -0
- ccai/provisioning/venues/aws/resources/securitygroupmanager.py +316 -0
- ccai/provisioning/venues/aws/resources/subnetmanager.py +361 -0
- ccai/provisioning/venues/aws/resources/volumemanager.py +266 -0
- ccai/provisioning/venues/azure/__init__.py +0 -0
- ccai/provisioning/venues/azure/azurecloudprovisioner.py +1124 -0
- ccai/provisioning/venues/azure/azureerrors.py +38 -0
- ccai/provisioning/venues/azure/azureidempotency.py +109 -0
- ccai/provisioning/venues/azure/azureregionconfig.py +99 -0
- ccai/provisioning/venues/azure/azuresessionfactory.py +247 -0
- ccai/provisioning/venues/azure/azurespec.py +108 -0
- ccai/provisioning/venues/azure/azuretagging.py +153 -0
- ccai/provisioning/venues/azure/azuretask.py +82 -0
- ccai/provisioning/venues/azure/resources/__init__.py +11 -0
- ccai/provisioning/venues/azure/resources/blobmanager.py +281 -0
- ccai/provisioning/venues/azure/resources/diskmanager.py +256 -0
- ccai/provisioning/venues/azure/resources/dnsmanager.py +146 -0
- ccai/provisioning/venues/azure/resources/imageresolver.py +129 -0
- ccai/provisioning/venues/azure/resources/lustremanager.py +106 -0
- ccai/provisioning/venues/azure/resources/nicmanager.py +248 -0
- ccai/provisioning/venues/azure/resources/nsgmanager.py +384 -0
- ccai/provisioning/venues/azure/resources/placement.py +212 -0
- ccai/provisioning/venues/azure/resources/resourcegroupmanager.py +195 -0
- ccai/provisioning/venues/azure/resources/subnetmanager.py +188 -0
- ccai/provisioning/venues/azure/resources/vmmanager.py +527 -0
- ccai/provisioning/venues/azure/resources/vnetmanager.py +243 -0
- ccai/provisioning/venues/coreweave/README.md +54 -0
- ccai/provisioning/venues/coreweave/__init__.py +3 -0
- ccai/provisioning/venues/coreweave/coreweaveworkloadprovisioner.py +848 -0
- ccai/provisioning/venues/coreweave/coreweaveworkloadspec.py +76 -0
- ccai/provisioning/venues/coreweave/cwerrors.py +39 -0
- ccai/provisioning/venues/coreweave/cwlabeltranslator.py +151 -0
- ccai/provisioning/venues/coreweave/cwmanifestrenderer.py +212 -0
- ccai/provisioning/venues/coreweave/cwnodepoolselector.py +173 -0
- ccai/provisioning/venues/coreweave/cwsunkrenderer.py +191 -0
- ccai/provisioning/venues/coreweave/cwvpnsidecar.py +161 -0
- ccai/provisioning/venues/crusoe/README.md +48 -0
- ccai/provisioning/venues/crusoe/__init__.py +3 -0
- ccai/provisioning/venues/crusoe/crusoecloudprovisioner.py +1021 -0
- ccai/provisioning/venues/crusoe/crusoeerrors.py +31 -0
- ccai/provisioning/venues/crusoe/crusoeibpartition.py +90 -0
- ccai/provisioning/venues/crusoe/crusoelabeltranslator.py +58 -0
- ccai/provisioning/venues/crusoe/crusoeprojectconfig.py +79 -0
- ccai/provisioning/venues/crusoe/crusoeresolver.py +181 -0
- ccai/provisioning/venues/crusoe/crusoespec.py +104 -0
- ccai/provisioning/venues/crusoe/crusoeuserdatarenderer.py +67 -0
- ccai/provisioning/venues/digitalocean/README.md +61 -0
- ccai/provisioning/venues/digitalocean/__init__.py +11 -0
- ccai/provisioning/venues/digitalocean/digitaloceancloudprovisioner.py +835 -0
- ccai/provisioning/venues/digitalocean/doclient.py +222 -0
- ccai/provisioning/venues/digitalocean/doerrors.py +39 -0
- ccai/provisioning/venues/digitalocean/doidempotency.py +89 -0
- ccai/provisioning/venues/digitalocean/dopagination.py +62 -0
- ccai/provisioning/venues/digitalocean/doregionconfig.py +92 -0
- ccai/provisioning/venues/digitalocean/doresolver.py +173 -0
- ccai/provisioning/venues/digitalocean/dospec.py +106 -0
- ccai/provisioning/venues/digitalocean/dotagtranslator.py +207 -0
- ccai/provisioning/venues/digitalocean/dotask.py +87 -0
- ccai/provisioning/venues/digitalocean/douserdatarenderer.py +64 -0
- ccai/provisioning/venues/digitalocean/resources/__init__.py +11 -0
- ccai/provisioning/venues/digitalocean/resources/dnsmanager.py +179 -0
- ccai/provisioning/venues/digitalocean/resources/dropletmanager.py +293 -0
- ccai/provisioning/venues/digitalocean/resources/firewallmanager.py +288 -0
- ccai/provisioning/venues/digitalocean/resources/networkmanager.py +234 -0
- ccai/provisioning/venues/digitalocean/resources/spacesmanager.py +199 -0
- ccai/provisioning/venues/digitalocean/resources/sshkeymanager.py +175 -0
- ccai/provisioning/venues/digitalocean/resources/volumemanager.py +207 -0
- ccai/provisioning/venues/equinix_metal/__init__.py +0 -0
- ccai/provisioning/venues/equinix_metal/equinixmetalcloudprovisioner.py +554 -0
- ccai/provisioning/venues/equinix_metal/metalapplystages.py +622 -0
- ccai/provisioning/venues/equinix_metal/metalclient.py +496 -0
- ccai/provisioning/venues/equinix_metal/metaldestroystages.py +124 -0
- ccai/provisioning/venues/equinix_metal/metalerrors.py +74 -0
- ccai/provisioning/venues/equinix_metal/metalinventory.py +163 -0
- ccai/provisioning/venues/equinix_metal/metalplanbuilder.py +202 -0
- ccai/provisioning/venues/equinix_metal/metalprojectconfig.py +79 -0
- ccai/provisioning/venues/equinix_metal/metalresolver.py +231 -0
- ccai/provisioning/venues/equinix_metal/metalspec.py +110 -0
- ccai/provisioning/venues/equinix_metal/metaltagtranslator.py +168 -0
- ccai/provisioning/venues/equinix_metal/metaluserdatarenderer.py +57 -0
- ccai/provisioning/venues/google/__init__.py +1 -0
- ccai/provisioning/venues/google/gcperrors.py +38 -0
- ccai/provisioning/venues/google/gcpidempotency.py +75 -0
- ccai/provisioning/venues/google/gcpoperations.py +87 -0
- ccai/provisioning/venues/google/gcpregionconfig.py +114 -0
- ccai/provisioning/venues/google/gcpsessionfactory.py +173 -0
- ccai/provisioning/venues/google/gcpspec.py +105 -0
- ccai/provisioning/venues/google/gcptagging.py +289 -0
- ccai/provisioning/venues/google/gcptask.py +86 -0
- ccai/provisioning/venues/google/googlecloudprovisioner.py +1091 -0
- ccai/provisioning/venues/google/resources/__init__.py +0 -0
- ccai/provisioning/venues/google/resources/bucketmanager.py +231 -0
- ccai/provisioning/venues/google/resources/diskmanager.py +260 -0
- ccai/provisioning/venues/google/resources/dnsmanager.py +131 -0
- ccai/provisioning/venues/google/resources/firewallmanager.py +271 -0
- ccai/provisioning/venues/google/resources/instancemanager.py +521 -0
- ccai/provisioning/venues/google/resources/networkmanager.py +251 -0
- ccai/provisioning/venues/google/resources/placement.py +151 -0
- ccai/provisioning/venues/google/resources/subnetmanager.py +273 -0
- ccai/provisioning/venues/google/resources/tpunodemanager.py +341 -0
- ccai/provisioning/venues/hetzner/README.md +40 -0
- ccai/provisioning/venues/hetzner/__init__.py +0 -0
- ccai/provisioning/venues/hetzner/hetznerapplystages.py +674 -0
- ccai/provisioning/venues/hetzner/hetznerclientfactory.py +58 -0
- ccai/provisioning/venues/hetzner/hetznercloudprovisioner.py +462 -0
- ccai/provisioning/venues/hetzner/hetznerdestroystages.py +142 -0
- ccai/provisioning/venues/hetzner/hetznererrors.py +38 -0
- ccai/provisioning/venues/hetzner/hetznerinventory.py +144 -0
- ccai/provisioning/venues/hetzner/hetznerlabeltranslator.py +271 -0
- ccai/provisioning/venues/hetzner/hetznerlocationconfig.py +73 -0
- ccai/provisioning/venues/hetzner/hetznerplanbuilder.py +298 -0
- ccai/provisioning/venues/hetzner/hetznerresolver.py +173 -0
- ccai/provisioning/venues/hetzner/hetznerspec.py +104 -0
- ccai/provisioning/venues/hetzner/hetzneruserdatarenderer.py +57 -0
- ccai/provisioning/venues/hyperv/README.md +58 -0
- ccai/provisioning/venues/hyperv/__init__.py +11 -0
- ccai/provisioning/venues/hyperv/hvapplystages.py +396 -0
- ccai/provisioning/venues/hyperv/hvcloudinitrenderer.py +220 -0
- ccai/provisioning/venues/hyperv/hvdestroystages.py +141 -0
- ccai/provisioning/venues/hyperv/hverrors.py +31 -0
- ccai/provisioning/venues/hyperv/hvhardware.py +34 -0
- ccai/provisioning/venues/hyperv/hvhostconfig.py +52 -0
- ccai/provisioning/venues/hyperv/hvinventory.py +112 -0
- ccai/provisioning/venues/hyperv/hvnotestranslator.py +140 -0
- ccai/provisioning/venues/hyperv/hvplanbuilder.py +173 -0
- ccai/provisioning/venues/hyperv/hvresolver.py +166 -0
- ccai/provisioning/venues/hyperv/hypervcloudprovisioner.py +532 -0
- ccai/provisioning/venues/hyperv/hypervspec.py +105 -0
- ccai/provisioning/venues/lambdalabs/__init__.py +0 -0
- ccai/provisioning/venues/lambdalabs/lambdalabscloudprovisioner.py +410 -0
- ccai/provisioning/venues/lambdalabs/lambdalabsspec.py +103 -0
- ccai/provisioning/venues/lambdalabs/llapplystages.py +368 -0
- ccai/provisioning/venues/lambdalabs/lldestroystages.py +127 -0
- ccai/provisioning/venues/lambdalabs/llerrors.py +33 -0
- ccai/provisioning/venues/lambdalabs/llinventory.py +126 -0
- ccai/provisioning/venues/lambdalabs/llnaming.py +47 -0
- ccai/provisioning/venues/lambdalabs/llplanbuilder.py +128 -0
- ccai/provisioning/venues/lambdalabs/llresolver.py +208 -0
- ccai/provisioning/venues/lambdalabs/llsidecartag.py +139 -0
- ccai/provisioning/venues/lambdalabs/lluserdatarenderer.py +54 -0
- ccai/provisioning/venues/libvirt/README.md +46 -0
- ccai/provisioning/venues/libvirt/__init__.py +0 -0
- ccai/provisioning/venues/libvirt/libvirtcloudprovisioner.py +414 -0
- ccai/provisioning/venues/libvirt/libvirtspec.py +117 -0
- ccai/provisioning/venues/libvirt/libvirtvenueconfig.py +115 -0
- ccai/provisioning/venues/libvirt/lvapplystages.py +491 -0
- ccai/provisioning/venues/libvirt/lvdestroystages.py +259 -0
- ccai/provisioning/venues/libvirt/lvdomainxmlbuilder.py +141 -0
- ccai/provisioning/venues/libvirt/lverrors.py +35 -0
- ccai/provisioning/venues/libvirt/lvinventory.py +176 -0
- ccai/provisioning/venues/libvirt/lvmetadatatranslator.py +149 -0
- ccai/provisioning/venues/libvirt/lvnaming.py +76 -0
- ccai/provisioning/venues/libvirt/lvplanbuilder.py +208 -0
- ccai/provisioning/venues/libvirt/lvseedisobuilder.py +244 -0
- ccai/provisioning/venues/linode/__init__.py +11 -0
- ccai/provisioning/venues/linode/linodeapplystages.py +553 -0
- ccai/provisioning/venues/linode/linodeclientfactory.py +68 -0
- ccai/provisioning/venues/linode/linodecloudprovisioner.py +425 -0
- ccai/provisioning/venues/linode/linodedestroystages.py +139 -0
- ccai/provisioning/venues/linode/linodeerrors.py +31 -0
- ccai/provisioning/venues/linode/linodeinventory.py +163 -0
- ccai/provisioning/venues/linode/linodeplanbuilder.py +225 -0
- ccai/provisioning/venues/linode/linodereader.py +326 -0
- ccai/provisioning/venues/linode/linoderegionconfig.py +81 -0
- ccai/provisioning/venues/linode/linoderesolver.py +196 -0
- ccai/provisioning/venues/linode/linodespec.py +103 -0
- ccai/provisioning/venues/linode/linodetagtranslator.py +182 -0
- ccai/provisioning/venues/linode/linodeuserdatarenderer.py +111 -0
- ccai/provisioning/venues/nebius/README.md +57 -0
- ccai/provisioning/venues/nebius/__init__.py +0 -0
- ccai/provisioning/venues/nebius/nebiusapplystages.py +456 -0
- ccai/provisioning/venues/nebius/nebiuscloudprovisioner.py +520 -0
- ccai/provisioning/venues/nebius/nebiusdestroystages.py +144 -0
- ccai/provisioning/venues/nebius/nebiuserrors.py +31 -0
- ccai/provisioning/venues/nebius/nebiusgpucluster.py +147 -0
- ccai/provisioning/venues/nebius/nebiusinventory.py +147 -0
- ccai/provisioning/venues/nebius/nebiuslabeltranslator.py +105 -0
- ccai/provisioning/venues/nebius/nebiusplanbuilder.py +243 -0
- ccai/provisioning/venues/nebius/nebiusresolver.py +181 -0
- ccai/provisioning/venues/nebius/nebiusspec.py +112 -0
- ccai/provisioning/venues/nebius/nebiususerdatarenderer.py +60 -0
- ccai/provisioning/venues/nutanix/README.md +47 -0
- ccai/provisioning/venues/nutanix/__init__.py +11 -0
- ccai/provisioning/venues/nutanix/ntxapplystages.py +579 -0
- ccai/provisioning/venues/nutanix/ntxcategorytranslator.py +138 -0
- ccai/provisioning/venues/nutanix/ntxcloudinitrenderer.py +122 -0
- ccai/provisioning/venues/nutanix/ntxdestroystages.py +306 -0
- ccai/provisioning/venues/nutanix/ntxerrors.py +35 -0
- ccai/provisioning/venues/nutanix/ntxinventory.py +141 -0
- ccai/provisioning/venues/nutanix/ntxnaming.py +52 -0
- ccai/provisioning/venues/nutanix/ntxplanbuilder.py +271 -0
- ccai/provisioning/venues/nutanix/ntxresolver.py +180 -0
- ccai/provisioning/venues/nutanix/nutanixcloudprovisioner.py +421 -0
- ccai/provisioning/venues/nutanix/nutanixspec.py +119 -0
- ccai/provisioning/venues/nutanix/nutanixvenueconfig.py +105 -0
- ccai/provisioning/venues/oracle/__init__.py +0 -0
- ccai/provisioning/venues/oracle/ocierrors.py +39 -0
- ccai/provisioning/venues/oracle/ociidempotency.py +106 -0
- ccai/provisioning/venues/oracle/ociregionconfig.py +103 -0
- ccai/provisioning/venues/oracle/ocisessionfactory.py +146 -0
- ccai/provisioning/venues/oracle/ocispec.py +107 -0
- ccai/provisioning/venues/oracle/ocitagging.py +153 -0
- ccai/provisioning/venues/oracle/ocitask.py +86 -0
- ccai/provisioning/venues/oracle/oraclecloudprovisioner.py +915 -0
- ccai/provisioning/venues/oracle/resources/__init__.py +0 -0
- ccai/provisioning/venues/oracle/resources/blockvolumemanager.py +284 -0
- ccai/provisioning/venues/oracle/resources/clusternetworkmanager.py +246 -0
- ccai/provisioning/venues/oracle/resources/computemanager.py +447 -0
- ccai/provisioning/venues/oracle/resources/dnsmanager.py +154 -0
- ccai/provisioning/venues/oracle/resources/filestoragemanager.py +136 -0
- ccai/provisioning/venues/oracle/resources/imageresolver.py +132 -0
- ccai/provisioning/venues/oracle/resources/internetgatewaymanager.py +137 -0
- ccai/provisioning/venues/oracle/resources/keypairmanager.py +66 -0
- ccai/provisioning/venues/oracle/resources/objectstoragemanager.py +267 -0
- ccai/provisioning/venues/oracle/resources/routetablemanager.py +141 -0
- ccai/provisioning/venues/oracle/resources/securitylistmanager.py +337 -0
- ccai/provisioning/venues/oracle/resources/subnetmanager.py +219 -0
- ccai/provisioning/venues/oracle/resources/vcnmanager.py +208 -0
- ccai/provisioning/venues/proxmox/__init__.py +11 -0
- ccai/provisioning/venues/proxmox/proxmoxcloudprovisioner.py +423 -0
- ccai/provisioning/venues/proxmox/proxmoxspec.py +112 -0
- ccai/provisioning/venues/proxmox/pveapplystages.py +548 -0
- ccai/provisioning/venues/proxmox/pvecloudinitrenderer.py +188 -0
- ccai/provisioning/venues/proxmox/pvedestroystages.py +99 -0
- ccai/provisioning/venues/proxmox/pveerrors.py +34 -0
- ccai/provisioning/venues/proxmox/pveinventory.py +136 -0
- ccai/provisioning/venues/proxmox/pvenaming.py +81 -0
- ccai/provisioning/venues/proxmox/pveplanbuilder.py +231 -0
- ccai/provisioning/venues/proxmox/pveresolver.py +254 -0
- ccai/provisioning/venues/proxmox/pvetagtranslator.py +69 -0
- ccai/provisioning/venues/runpod/README.md +73 -0
- ccai/provisioning/venues/runpod/__init__.py +0 -0
- ccai/provisioning/venues/runpod/rpapplystages.py +236 -0
- ccai/provisioning/venues/runpod/rpcontainerstartrenderer.py +134 -0
- ccai/provisioning/venues/runpod/rpdestroystages.py +91 -0
- ccai/provisioning/venues/runpod/rperrors.py +36 -0
- ccai/provisioning/venues/runpod/rpinventory.py +96 -0
- ccai/provisioning/venues/runpod/rpnaming.py +60 -0
- ccai/provisioning/venues/runpod/rpplanbuilder.py +141 -0
- ccai/provisioning/venues/runpod/rpresolver.py +146 -0
- ccai/provisioning/venues/runpod/rpsidecartag.py +145 -0
- ccai/provisioning/venues/runpod/runpodworkloadprovisioner.py +574 -0
- ccai/provisioning/venues/runpod/runpodworkloadspec.py +143 -0
- ccai/provisioning/venues/vpncleanup.py +132 -0
- ccai/provisioning/venues/vsphere/README.md +39 -0
- ccai/provisioning/venues/vsphere/__init__.py +0 -0
- ccai/provisioning/venues/vsphere/resources/__init__.py +0 -0
- ccai/provisioning/venues/vsphere/vsapplystages.py +329 -0
- ccai/provisioning/venues/vsphere/vsdestroystages.py +116 -0
- ccai/provisioning/venues/vsphere/vserrors.py +38 -0
- ccai/provisioning/venues/vsphere/vsguestcustomrenderer.py +179 -0
- ccai/provisioning/venues/vsphere/vsinventory.py +128 -0
- ccai/provisioning/venues/vsphere/vspherecloudprovisioner.py +439 -0
- ccai/provisioning/venues/vsphere/vsphereops.py +399 -0
- ccai/provisioning/venues/vsphere/vspherespec.py +107 -0
- ccai/provisioning/venues/vsphere/vspherevenueconfig.py +180 -0
- ccai/provisioning/venues/vsphere/vsplanbuilder.py +113 -0
- ccai/provisioning/venues/vsphere/vsresolver.py +231 -0
- ccai/provisioning/venues/vsphere/vstagtranslator.py +186 -0
- ccai/provisioning/venues/vultr/README.md +45 -0
- ccai/provisioning/venues/vultr/__init__.py +11 -0
- ccai/provisioning/venues/vultr/vultrapplystages.py +690 -0
- ccai/provisioning/venues/vultr/vultrclient.py +190 -0
- ccai/provisioning/venues/vultr/vultrcloudprovisioner.py +399 -0
- ccai/provisioning/venues/vultr/vultrdestroystages.py +166 -0
- ccai/provisioning/venues/vultr/vultrerrors.py +37 -0
- ccai/provisioning/venues/vultr/vultrinventory.py +130 -0
- ccai/provisioning/venues/vultr/vultrplanbuilder.py +138 -0
- ccai/provisioning/venues/vultr/vultrresolver.py +218 -0
- ccai/provisioning/venues/vultr/vultrresources.py +159 -0
- ccai/provisioning/venues/vultr/vultrspec.py +103 -0
- ccai/provisioning/venues/vultr/vultrtagtranslator.py +158 -0
- ccai/provisioning/venues/vultr/vultruserdatarenderer.py +76 -0
- ccai/provisioning/venues/xcpng/__init__.py +0 -0
- ccai/provisioning/venues/xcpng/xcpngcloudprovisioner.py +385 -0
- ccai/provisioning/venues/xcpng/xcpngspec.py +99 -0
- ccai/provisioning/venues/xcpng/xenapplystages.py +396 -0
- ccai/provisioning/venues/xcpng/xencloudinitrenderer.py +96 -0
- ccai/provisioning/venues/xcpng/xendestroystages.py +147 -0
- ccai/provisioning/venues/xcpng/xenerrors.py +37 -0
- ccai/provisioning/venues/xcpng/xeninventory.py +137 -0
- ccai/provisioning/venues/xcpng/xennaming.py +60 -0
- ccai/provisioning/venues/xcpng/xenplanbuilder.py +173 -0
- ccai/provisioning/venues/xcpng/xenresolver.py +218 -0
- ccai/provisioning/venues/xcpng/xentagtranslator.py +116 -0
- codecraftai_provisioning-1.3.0.dist-info/METADATA +106 -0
- codecraftai_provisioning-1.3.0.dist-info/RECORD +405 -0
- codecraftai_provisioning-1.3.0.dist-info/WHEEL +4 -0
- codecraftai_provisioning-1.3.0.dist-info/licenses/LICENSE.md +204 -0
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""
|
|
2
|
+
.. module:: provisioningaspects
|
|
3
|
+
:platform: Darwin, Linux, Unix, Windows
|
|
4
|
+
:synopsis: ProvisioningAspects — behaviour bundle for provisioning calls.
|
|
5
|
+
|
|
6
|
+
.. moduleauthor:: Myron Walker <myron.walker@gmail.com>
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__author__ = "Myron Walker"
|
|
10
|
+
__copyright__ = "Copyright 2026, Code Craft AI LLC"
|
|
11
|
+
__credits__ = []
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
from typing import Optional
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ProvisioningAspects:
|
|
18
|
+
"""
|
|
19
|
+
Aspect bundle controlling provisioning behaviour.
|
|
20
|
+
|
|
21
|
+
Following the project Aspects pattern: callers pass behaviour as a
|
|
22
|
+
single parameter rather than via decorators.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, *, dry_run: bool = False, confirm: bool = False,
|
|
26
|
+
runid: Optional[str] = None,
|
|
27
|
+
verify_timeout: float = 600.0,
|
|
28
|
+
verify_interval: float = 10.0,
|
|
29
|
+
lock_timeout_seconds: float = 30.0) -> None:
|
|
30
|
+
"""
|
|
31
|
+
Construct a ProvisioningAspects bundle.
|
|
32
|
+
|
|
33
|
+
:param dry_run: When True, the engine halts at the end of PLAN.
|
|
34
|
+
:param confirm: When True, destroy is permitted.
|
|
35
|
+
:param runid: Optional run identifier for state-persistence.
|
|
36
|
+
:param verify_timeout: Total timeout for the VERIFY stage.
|
|
37
|
+
:param verify_interval: Polling interval for VERIFY.
|
|
38
|
+
:param lock_timeout_seconds: Index-file lock wait timeout.
|
|
39
|
+
"""
|
|
40
|
+
self.dry_run: bool = dry_run
|
|
41
|
+
self.confirm: bool = confirm
|
|
42
|
+
self.runid: Optional[str] = runid
|
|
43
|
+
self.verify_timeout: float = verify_timeout
|
|
44
|
+
self.verify_interval: float = verify_interval
|
|
45
|
+
self.lock_timeout_seconds: float = lock_timeout_seconds
|
|
46
|
+
return
|
|
File without changes
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""
|
|
2
|
+
.. module:: bootstraprenderer
|
|
3
|
+
:platform: Darwin, Linux, Unix, Windows
|
|
4
|
+
:synopsis: Composes every first-boot fragment a CloudInstance declares
|
|
5
|
+
into one cloud-init document.
|
|
6
|
+
|
|
7
|
+
.. moduleauthor:: Myron Walker <myron.walker@gmail.com>
|
|
8
|
+
|
|
9
|
+
Venue renderers historically checked ``instance.vpn_join`` and called
|
|
10
|
+
:func:`render_cloud_init` directly. As more bootstrap concerns arrive
|
|
11
|
+
(Python environments today), that per-venue branching would have to be
|
|
12
|
+
repeated in every venue. This module is the single place that knows
|
|
13
|
+
which instance slots produce cloud-init fragments and in what order;
|
|
14
|
+
venues call :func:`render_instance_cloud_init` and only decide how to
|
|
15
|
+
ship the resulting document (base64, verbatim, seed ISO, ...).
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
__author__ = "Myron Walker"
|
|
19
|
+
__copyright__ = "Copyright 2026, Code Craft AI LLC"
|
|
20
|
+
__credits__ = []
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
from typing import Any, Dict, List, Optional
|
|
24
|
+
|
|
25
|
+
import yaml
|
|
26
|
+
|
|
27
|
+
from ccai.provisioning.cloudinit.bootstrapsecrets import BootstrapSecrets
|
|
28
|
+
from ccai.provisioning.cloudinit.cloudinitmerge import merge_cloud_init_fragments
|
|
29
|
+
from ccai.provisioning.cloudinit.pythonenvcloudinitrenderer import (
|
|
30
|
+
render_python_env_cloud_init
|
|
31
|
+
)
|
|
32
|
+
from ccai.provisioning.cloudinit.vpncloudinitrenderer import render_cloud_init
|
|
33
|
+
from ccai.provisioning.model.cloud.cloudinstance import CloudInstance
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
CLOUD_CONFIG_HEADER = "#cloud-config"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def render_instance_cloud_init(*, instance: CloudInstance,
|
|
40
|
+
authkey: Optional[str] = None,
|
|
41
|
+
rendered_hostname: Optional[str] = None,
|
|
42
|
+
secrets: Optional[BootstrapSecrets] = None
|
|
43
|
+
) -> Optional[Dict[str, Any]]:
|
|
44
|
+
"""
|
|
45
|
+
Render and merge every cloud-init fragment the instance declares.
|
|
46
|
+
|
|
47
|
+
Order: VPN join first (so the overlay is up before anything that
|
|
48
|
+
might need a private index), then Python environments. A raw
|
|
49
|
+
``user_data_script`` is appended as a final ``runcmd`` entry so it
|
|
50
|
+
runs after the managed bootstrap.
|
|
51
|
+
|
|
52
|
+
:param instance: The neutral CloudInstance.
|
|
53
|
+
:param authkey: Minted VPN auth-key; required when ``vpn_join`` is
|
|
54
|
+
set (an empty string is substituted otherwise).
|
|
55
|
+
:param rendered_hostname: Hostname rendered from the join spec
|
|
56
|
+
template; defaults to the instance name.
|
|
57
|
+
:param secrets: Optional resolved :class:`BootstrapSecrets`; when
|
|
58
|
+
``None`` the container bound by the engine for the
|
|
59
|
+
current apply is used.
|
|
60
|
+
|
|
61
|
+
:returns: The merged fragment, or ``None`` when the instance
|
|
62
|
+
declares no bootstrap content at all.
|
|
63
|
+
"""
|
|
64
|
+
fragments: List[Optional[Dict[str, Any]]] = []
|
|
65
|
+
|
|
66
|
+
if instance.vpn_join is not None:
|
|
67
|
+
effective_hostname = rendered_hostname
|
|
68
|
+
if effective_hostname is None or len(effective_hostname) == 0:
|
|
69
|
+
effective_hostname = instance.name
|
|
70
|
+
effective_authkey = authkey if authkey is not None else ""
|
|
71
|
+
fragments.append(render_cloud_init(
|
|
72
|
+
spec=instance.vpn_join,
|
|
73
|
+
authkey=effective_authkey,
|
|
74
|
+
rendered_hostname=effective_hostname,
|
|
75
|
+
image_family=instance.image.family,
|
|
76
|
+
))
|
|
77
|
+
|
|
78
|
+
python_environments = instance.python_environments
|
|
79
|
+
if python_environments is not None and len(python_environments) > 0:
|
|
80
|
+
fragments.append(render_python_env_cloud_init(
|
|
81
|
+
specs=python_environments,
|
|
82
|
+
image_family=instance.image.family,
|
|
83
|
+
secrets=secrets,
|
|
84
|
+
))
|
|
85
|
+
|
|
86
|
+
raw_script = instance.user_data_script
|
|
87
|
+
if len(fragments) == 0:
|
|
88
|
+
rtnval: Optional[Dict[str, Any]] = None
|
|
89
|
+
return rtnval
|
|
90
|
+
|
|
91
|
+
merged = merge_cloud_init_fragments(*fragments)
|
|
92
|
+
if raw_script is not None and len(raw_script) > 0:
|
|
93
|
+
runcmd: List[Any] = list(merged.get("runcmd", []))
|
|
94
|
+
runcmd.append(["sh", "-c", raw_script])
|
|
95
|
+
merged["runcmd"] = runcmd
|
|
96
|
+
|
|
97
|
+
rtnval = merged
|
|
98
|
+
return rtnval
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def render_instance_user_data(*, instance: CloudInstance,
|
|
102
|
+
authkey: Optional[str] = None,
|
|
103
|
+
rendered_hostname: Optional[str] = None,
|
|
104
|
+
secrets: Optional[BootstrapSecrets] = None
|
|
105
|
+
) -> Optional[str]:
|
|
106
|
+
"""
|
|
107
|
+
Render the complete ``#cloud-config`` document for an instance.
|
|
108
|
+
|
|
109
|
+
:param instance: The neutral CloudInstance.
|
|
110
|
+
:param authkey: Minted VPN auth-key when ``vpn_join`` is set.
|
|
111
|
+
:param rendered_hostname: Hostname for the join spec.
|
|
112
|
+
:param secrets: Optional resolved :class:`BootstrapSecrets`.
|
|
113
|
+
|
|
114
|
+
:returns: The YAML document with the ``#cloud-config`` header; the
|
|
115
|
+
raw ``user_data_script`` verbatim when that is the only
|
|
116
|
+
bootstrap content; ``None`` when there is none.
|
|
117
|
+
"""
|
|
118
|
+
fragment = render_instance_cloud_init(
|
|
119
|
+
instance=instance, authkey=authkey, rendered_hostname=rendered_hostname,
|
|
120
|
+
secrets=secrets,
|
|
121
|
+
)
|
|
122
|
+
if fragment is None:
|
|
123
|
+
raw_script = instance.user_data_script
|
|
124
|
+
if raw_script is None or len(raw_script) == 0:
|
|
125
|
+
rtnval: Optional[str] = None
|
|
126
|
+
return rtnval
|
|
127
|
+
rtnval = raw_script
|
|
128
|
+
return rtnval
|
|
129
|
+
|
|
130
|
+
body = yaml.safe_dump(fragment, default_flow_style=False, sort_keys=False)
|
|
131
|
+
rtnval = "{}\n{}".format(CLOUD_CONFIG_HEADER, body)
|
|
132
|
+
return rtnval
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
__all__ = [
|
|
136
|
+
"CLOUD_CONFIG_HEADER",
|
|
137
|
+
"render_instance_cloud_init",
|
|
138
|
+
"render_instance_user_data",
|
|
139
|
+
]
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""
|
|
2
|
+
.. module:: bootstrapsecrets
|
|
3
|
+
:platform: Darwin, Linux, Unix, Windows
|
|
4
|
+
:synopsis: Per-run container for secrets the first-boot renderers need,
|
|
5
|
+
resolved once by the engine and bound for the apply stages.
|
|
6
|
+
|
|
7
|
+
.. moduleauthor:: Myron Walker <myron.walker@gmail.com>
|
|
8
|
+
|
|
9
|
+
Specs never carry secrets. ``PythonEnvironmentSpec.index_credential``
|
|
10
|
+
names a credential-vault entry; the engine resolves every such name
|
|
11
|
+
during LOAD_VALIDATE into a :class:`BootstrapSecrets` and binds it for
|
|
12
|
+
the duration of the apply stages with :func:`bind_bootstrap_secrets`.
|
|
13
|
+
Renderers read :func:`current_bootstrap_secrets` when a caller does not
|
|
14
|
+
hand them a container explicitly, so the twenty venue user-data paths
|
|
15
|
+
need no new plumbing and no venue ever touches a credential vault.
|
|
16
|
+
|
|
17
|
+
The binding is a :class:`contextvars.ContextVar`, which is per-thread
|
|
18
|
+
and per-task, so two engines applying concurrently in one process do
|
|
19
|
+
not see each other's secrets.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
__author__ = "Myron Walker"
|
|
23
|
+
__copyright__ = "Copyright 2026, Code Craft AI LLC"
|
|
24
|
+
__credits__ = []
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
import contextlib
|
|
28
|
+
import contextvars
|
|
29
|
+
|
|
30
|
+
from dataclasses import dataclass, field
|
|
31
|
+
from typing import Any, Dict, Iterator, Optional
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass(frozen=True)
|
|
35
|
+
class IndexCredential:
|
|
36
|
+
"""
|
|
37
|
+
Credentials for a package index.
|
|
38
|
+
|
|
39
|
+
:param username: HTTP basic-auth username (``__token__`` for
|
|
40
|
+
token-style indexes such as PyPI and most private
|
|
41
|
+
mirrors).
|
|
42
|
+
:param secret: The password or token.
|
|
43
|
+
"""
|
|
44
|
+
username: str
|
|
45
|
+
secret: str
|
|
46
|
+
|
|
47
|
+
def __repr__(self) -> str:
|
|
48
|
+
"""
|
|
49
|
+
Never let the secret into a log line or an exception message.
|
|
50
|
+
"""
|
|
51
|
+
rtnval = "IndexCredential(username={!r}, secret='***')".format(self.username)
|
|
52
|
+
return rtnval
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass
|
|
56
|
+
class BootstrapSecrets:
|
|
57
|
+
"""
|
|
58
|
+
Resolved secrets for one provisioning run.
|
|
59
|
+
|
|
60
|
+
:param index_credentials: Map of credential-vault reference (the
|
|
61
|
+
value of ``PythonEnvironmentSpec.
|
|
62
|
+
index_credential``) to the resolved
|
|
63
|
+
:class:`IndexCredential`.
|
|
64
|
+
"""
|
|
65
|
+
index_credentials: Dict[str, IndexCredential] = field(default_factory=dict)
|
|
66
|
+
|
|
67
|
+
def credential_for(self, *, spec: Any) -> Optional[IndexCredential]:
|
|
68
|
+
"""
|
|
69
|
+
Look up the credential a spec names.
|
|
70
|
+
|
|
71
|
+
:param spec: A ``PythonEnvironmentSpec`` (anything with an
|
|
72
|
+
``index_credential`` attribute).
|
|
73
|
+
|
|
74
|
+
:returns: The :class:`IndexCredential`, or ``None`` when the spec
|
|
75
|
+
names no credential or the name is not resolved here.
|
|
76
|
+
"""
|
|
77
|
+
reference = getattr(spec, "index_credential", None)
|
|
78
|
+
if reference is None:
|
|
79
|
+
rtnval: Optional[IndexCredential] = None
|
|
80
|
+
return rtnval
|
|
81
|
+
rtnval = self.index_credentials.get(reference, None)
|
|
82
|
+
return rtnval
|
|
83
|
+
|
|
84
|
+
def __repr__(self) -> str:
|
|
85
|
+
rtnval = "BootstrapSecrets(index_credentials={})".format(
|
|
86
|
+
sorted(self.index_credentials.keys())
|
|
87
|
+
)
|
|
88
|
+
return rtnval
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
_CURRENT: contextvars.ContextVar = contextvars.ContextVar(
|
|
92
|
+
"ccai_provisioning_bootstrap_secrets", default=None
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def current_bootstrap_secrets() -> Optional[BootstrapSecrets]:
|
|
97
|
+
"""
|
|
98
|
+
The :class:`BootstrapSecrets` bound for the calling context, or
|
|
99
|
+
``None`` outside an engine apply.
|
|
100
|
+
|
|
101
|
+
:returns: The bound container or ``None``.
|
|
102
|
+
"""
|
|
103
|
+
rtnval = _CURRENT.get()
|
|
104
|
+
return rtnval
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@contextlib.contextmanager
|
|
108
|
+
def bind_bootstrap_secrets(secrets: Optional[BootstrapSecrets]) -> Iterator[None]:
|
|
109
|
+
"""
|
|
110
|
+
Bind ``secrets`` as the current container for the duration of the
|
|
111
|
+
``with`` block, restoring the previous binding afterwards.
|
|
112
|
+
|
|
113
|
+
:param secrets: The container to bind (``None`` clears the binding).
|
|
114
|
+
"""
|
|
115
|
+
token = _CURRENT.set(secrets)
|
|
116
|
+
try:
|
|
117
|
+
yield
|
|
118
|
+
finally:
|
|
119
|
+
_CURRENT.reset(token)
|
|
120
|
+
return
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
__all__ = [
|
|
124
|
+
"BootstrapSecrets",
|
|
125
|
+
"IndexCredential",
|
|
126
|
+
"bind_bootstrap_secrets",
|
|
127
|
+
"current_bootstrap_secrets",
|
|
128
|
+
]
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""
|
|
2
|
+
.. module:: cloudinitmerge
|
|
3
|
+
:platform: Darwin, Linux, Unix, Windows
|
|
4
|
+
:synopsis: Merge helper for venue-neutral cloud-init fragments.
|
|
5
|
+
|
|
6
|
+
.. moduleauthor:: Myron Walker <myron.walker@gmail.com>
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__author__ = "Myron Walker"
|
|
10
|
+
__copyright__ = "Copyright 2026, Code Craft AI LLC"
|
|
11
|
+
__credits__ = []
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
import copy
|
|
15
|
+
import os
|
|
16
|
+
|
|
17
|
+
from typing import Any, Dict, Optional
|
|
18
|
+
|
|
19
|
+
from ccai.provisioning.cloudinit.cloudinitrenderererror import (
|
|
20
|
+
CloudInitRendererError
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def merge_cloud_init_fragments(*fragments: Optional[Dict[str, Any]]) -> Dict[str, Any]:
|
|
25
|
+
"""
|
|
26
|
+
Merge cloud-init fragments produced by the shared renderers.
|
|
27
|
+
|
|
28
|
+
List-valued keys (``write_files``, ``runcmd``, ``packages``, ...)
|
|
29
|
+
are concatenated in argument order, so bootstrap ordering follows
|
|
30
|
+
the order the fragments are passed. Scalar keys must agree
|
|
31
|
+
across fragments; a conflict raises rather than silently picking
|
|
32
|
+
a winner. ``None`` fragments are skipped.
|
|
33
|
+
|
|
34
|
+
:param fragments: Fragment dicts (or ``None``).
|
|
35
|
+
|
|
36
|
+
:returns: A new merged dict; inputs are not mutated.
|
|
37
|
+
|
|
38
|
+
:raises: CloudInitRendererError
|
|
39
|
+
"""
|
|
40
|
+
rtnval: Dict[str, Any] = {}
|
|
41
|
+
|
|
42
|
+
for fragment in fragments:
|
|
43
|
+
if fragment is None:
|
|
44
|
+
continue
|
|
45
|
+
for key, value in fragment.items():
|
|
46
|
+
if key not in rtnval:
|
|
47
|
+
rtnval[key] = copy.deepcopy(value)
|
|
48
|
+
continue
|
|
49
|
+
|
|
50
|
+
existing = rtnval[key]
|
|
51
|
+
if isinstance(existing, list) and isinstance(value, list):
|
|
52
|
+
existing.extend(copy.deepcopy(value))
|
|
53
|
+
continue
|
|
54
|
+
|
|
55
|
+
if existing == value:
|
|
56
|
+
continue
|
|
57
|
+
|
|
58
|
+
err_msg_lines = ["Conflicting scalar value while merging cloud-init fragments."]
|
|
59
|
+
err_msg_lines.append("KEY: {!r}".format(key))
|
|
60
|
+
err_msg_lines.append("EXISTING: {!r}".format(existing))
|
|
61
|
+
err_msg_lines.append("INCOMING: {!r}".format(value))
|
|
62
|
+
err_msg = os.linesep.join(err_msg_lines)
|
|
63
|
+
raise CloudInitRendererError(err_msg)
|
|
64
|
+
|
|
65
|
+
return rtnval
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
__all__ = ["merge_cloud_init_fragments"]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
.. module:: cloudinitrenderererror
|
|
3
|
+
:platform: Darwin, Linux, Unix, Windows
|
|
4
|
+
:synopsis: Exception type for cloud-init renderer failures.
|
|
5
|
+
|
|
6
|
+
.. moduleauthor:: Myron Walker <myron.walker@gmail.com>
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__author__ = "Myron Walker"
|
|
10
|
+
__copyright__ = "Copyright 2026, Code Craft AI LLC"
|
|
11
|
+
__credits__ = []
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class CloudInitRendererError(ValueError):
|
|
15
|
+
"""
|
|
16
|
+
Raised when an unsupported image family is requested or the renderer
|
|
17
|
+
cannot produce a valid payload.
|
|
18
|
+
"""
|