)
import json
+from deepmerge import Merger
"""
API views.
except ObjectDoesNotExist:
return HttpResponseNotFound("Could not find a matching resource by id " + str(resource_id))
- return HttpResponse(cifile.text, status=200)
+ text = cifile.text
+
+ prepended_text = "#cloud-config\n"
+ #mstrat = CloudInitFile.merge_strategy()
+ #prepended_text = prepended_text + yaml.dump({"merge_strategy": mstrat}) + "\n"
+ #print("in cloudinitfile create")
+ text = prepended_text + text
+ cloud_dict = {
+ "datasource": {
+ "None": {
+ "metadata": {
+ "instance-id": str(uuid.uuid4())
+ },
+ "userdata_raw": text,
+ },
+ },
+ "datasource_list": ["None"],
+ }
+
+ return HttpResponse(yaml.dump(cloud_dict), status=200)
@csrf_exempt
def resource_ci_metadata(request, lab_name="", job_id="", resource_id="", file_id=0):
files = resource.config.cloud_init_files
files = [{"id": file.id, "priority": file.priority} for file in files.order_by("priority").all()]
- return HttpResponse(json.dumps(files), status=200)
+ d = {
+ 'merge_failures': []
+ }
+
+ merger = Merger(
+ [
+ (list, ["append"]),
+ (dict, ["merge"]),
+ ],
+ ["override"], # fallback
+ ["override"], # if types conflict (shouldn't happen in CI, but handle case)
+ )
+
+ for file in files.order_by("priority").all():
+ try:
+ other_dict = yaml.load(file.text)
+ if not (type(d) is dict):
+ raise Exception("CI file was valid yaml but was not a dict")
+
+ merger.merge(d, other_dict)
+ except Exception as e:
+ # if fail to merge, then just skip
+ print("Failed to merge file in, as it had invalid content:", file.id)
+ print("File text was:")
+ print(file.text)
+ d['merge_failures'].append({file.id: str(e)})
+
+ file = CloudInitFile.create(text=yaml.dump(d), priority=0)
+
+ return HttpResponse(json.dumps([{"id": file.id, "priority": file.priority}]), status=200)
def new_jobs(request, lab_name=""):
global_cloud_config = None if not form.cleaned_data['global_cloud_config'] else form.cleaned_data['global_cloud_config']
if global_cloud_config:
+ try:
+ d = yaml.load(global_cloud_config)
+ if not (type(d) is dict):
+ raise Exception("CI file was valid yaml but was not a dict")
+ except Exception as e:
+ raise ValidationError("The provided Cloud Config is not valid yaml, please refer to the Cloud Init documentation for expected structure")
print("about to create global cloud config")
global_cloud_config = CloudInitFile.create(text=global_cloud_config, priority=CloudInitFile.objects.count())
print("made global cloud config")
@classmethod
def create(cls, text="", priority=0):
- prepended_text = "#cloud-config\n"
- mstrat = CloudInitFile.merge_strategy()
- prepended_text = prepended_text + yaml.dump({"merge_strategy": mstrat}) + "\n"
- print("in cloudinitfile create")
- text = prepended_text + text
- cloud_dict = {
- "datasource": {
- "None": {
- "metadata": {
- "instance-id": str(uuid.uuid4())
- },
- "userdata_raw": text,
- },
- },
- "datasource_list": ["None"],
- }
- return CloudInitFile.objects.create(priority=priority, text=yaml.dump(cloud_dict))
+ #prepended_text = "#cloud-config\n"
+ #mstrat = CloudInitFile.merge_strategy()
+ #prepended_text = prepended_text + yaml.dump({"merge_strategy": mstrat}) + "\n"
+ #print("in cloudinitfile create")
+ #text = prepended_text + text
+ #cloud_dict = {
+ # "datasource": {
+ # "None": {
+ # "metadata": {
+ # "instance-id": str(uuid.uuid4())
+ # },
+ # "userdata_raw": text,
+ # },
+ # },
+ # "datasource_list": ["None"],
+ # }
+ return CloudInitFile.objects.create(priority=priority, text=text)
class ResourceTemplate(models.Model):
"""