def test_k8sConfig(self): os.environ["TEST_SECRET"] = "a secret" manifest = YamlManifest(manifestScript) job = Runner(manifest).run(JobOptions(add=True, startTime=1)) assert not job.unexpectedAbort assert job.status == Status.ok, job.summary() # print(job.summary()) # print(job.out.getvalue()) # verify secret contents isn't saved in config self.assertNotIn("a secret", job.out.getvalue()) self.assertNotIn("YSBzZWNyZXQ", job.out.getvalue()) # base64 of "a secret" # print (job.out.getvalue()) self.assertIn("<<REDACTED>>", job.out.getvalue()) assert not job.unexpectedAbort assert job.status == Status.ok, job.summary() manifest = YamlManifest(job.out.getvalue()) job2 = Runner(manifest).run( JobOptions(workflow="undeploy", startTime=2)) results = job2.jsonSummary() assert not job2.unexpectedAbort assert job2.status == Status.ok, job2.summary() assert len(results["tasks"]) == 1, results
def test_manifest(self): path = __file__ + "/../examples/helm-manifest.yaml" manifest = YamlManifest(path=path) runner = Runner(manifest) assert not manifest.lastJob, "expected new manifest" output = six.StringIO() # so we don't save the file job = runner.run(JobOptions(add=True, out=output, startTime="test")) assert not job.unexpectedAbort, job.unexpectedAbort.getStackTrace() # manifest shouldn't have changed # print("1", output.getvalue()) manifest2 = YamlManifest(output.getvalue()) # manifest2.statusSummary() output2 = six.StringIO() job2 = Runner(manifest2).run( JobOptions(add=True, out=output2, startTime=1)) # print("2", output2.getvalue()) # print(job2.summary()) assert not job2.unexpectedAbort, job2.unexpectedAbort.getStackTrace() # should not have found any tasks to run: assert len(job2.workDone) == 0, job2.workDone self.maxDiff = None # self.assertEqual(output.getvalue(), output2.getvalue()) output3 = six.StringIO() manifest3 = YamlManifest(output2.getvalue()) job3 = Runner(manifest3).run( JobOptions(workflow="undeploy", out=output3, startTime=2)) # print(output3.getvalue()) # only the chart delete task should have ran as it owns the resources it created # print(job3.jsonSummary()) assert len(job3.workDone) == 1, job3.jsonSummary() tasks = list(job3.workDone.values()) assert tasks[0].target.status.name == "absent", tasks[0].target.status
def test_terraform(self): """ test that runner figures out the proper tasks to run """ runner = CliRunner() with runner.isolated_filesystem(): with open("unfurl.yaml", "w") as f: f.write(projectConfig) with open("ensemble.yaml", "w") as f: f.write(ensembleConfig) manifest = LocalEnv().getManifest() assert manifest.manifest.vault and manifest.manifest.vault.secrets assert not manifest.lastJob job = Runner(manifest).run(JobOptions(startTime=1, verbose=-1)) # print(job.out.getvalue()) # print(job.jsonSummary(True)) assert not job.unexpectedAbort, job.unexpectedAbort.getStackTrace() assert job.status == Status.ok, job.summary() example = job.rootResource.findResource("example") self.assertEqual(example.attributes["tags"], {"Name": "test"}) self.assertEqual(example.attributes["availability_zone"], "us-east-1a") self.assertEqual(type(example.attributes["availability_zone"]), sensitive_str) self.assertEqual( job.jsonSummary(), { "job": { "id": "A01110000000", "status": "ok", "total": 1, "ok": 1, "error": 0, "unknown": 0, "skipped": 0, "changed": 1, }, "outputs": {}, "tasks": [{ "status": "ok", "target": "example", "operation": "create", "template": "example", "type": "unfurl.nodes.Installer.Terraform", "targetStatus": "ok", "changed": True, "configurator": "unfurl.configurators.terraform.TerraformConfigurator", "priority": "required", "reason": "add", }], }, ) # reload and check manifest2 = LocalEnv().getManifest() assert manifest2.lastJob manifest2.rootResource.findResource("example") self.assertEqual(type(example.attributes["availability_zone"]), sensitive_str) job = Runner(manifest2).run( JobOptions(workflow="check", verbose=-1, startTime=2)) assert not job.unexpectedAbort, job.unexpectedAbort.getStackTrace() assert job.status == Status.ok, job.summary() self.assertEqual( job.jsonSummary(), { "job": { "id": "A01120000000", "status": "ok", "total": 1, "ok": 1, "error": 0, "unknown": 0, "skipped": 0, "changed": 0, }, "outputs": {}, "tasks": [{ "status": "ok", "target": "example", "operation": "check", "template": "example", "type": "unfurl.nodes.Installer.Terraform", "targetStatus": "ok", "changed": False, "configurator": "unfurl.configurators.terraform.TerraformConfigurator", "priority": "required", "reason": "check", }], }, ) # reload and undeploy: manifest3 = LocalEnv().getManifest() assert manifest3.lastJob manifest3.rootResource.findResource("example") self.assertEqual(type(example.attributes["availability_zone"]), sensitive_str) job = Runner(manifest2).run( JobOptions(workflow="undeploy", verbose=-1, startTime=3)) assert not job.unexpectedAbort, job.unexpectedAbort.getStackTrace() assert job.status == Status.ok, job.summary() self.assertEqual( job.jsonSummary(), { "job": { "id": "A01130000000", "status": "ok", "total": 1, "ok": 1, "error": 0, "unknown": 0, "skipped": 0, "changed": 1, }, "outputs": {}, "tasks": [{ "status": "ok", "target": "example", "operation": "delete", "template": "example", "type": "unfurl.nodes.Installer.Terraform", "targetStatus": "absent", "changed": True, "configurator": "unfurl.configurators.terraform.TerraformConfigurator", "priority": "required", "reason": "undeploy", }], }, )
def test_import(self): foreign = ( """ apiVersion: %s kind: Manifest spec: service_template: node_types: test.nodes.AbstractTest: derived_from: tosca.nodes.Root properties: private_address: type: string required: false metadata: sensitive: true interfaces: Install: operations: check: implementation: SetAttribute instances: anInstance: type: test.nodes.AbstractTest """ % API_VERSION ) localConfig = """ apiVersion: unfurl/v1alpha1 kind: Project contexts: defaults: secrets: attributes: vault_default_password: a_password external: foreign: manifest: file: foreignmanifest.yaml instance: "*" # this is the default """ # import a node from a external manifest and have an abstract node template select it # check will be run on it each time mainManifest = ( """ apiVersion: %s kind: Manifest spec: service_template: imports: - foreignmanifest.yaml#/spec/service_template topology_template: outputs: server_ip: value: {eval: "::foreign:anInstance::private_address"} node_templates: anInstance: type: test.nodes.AbstractTest directives: - select """ % API_VERSION ) runner = CliRunner() # delete UNFURL_HOME try: UNFURL_HOME = os.environ.get("UNFURL_HOME") with runner.isolated_filesystem(): os.environ["UNFURL_HOME"] = "" with open("foreignmanifest.yaml", "w") as f: f.write(foreign) with open("unfurl.yaml", "w") as f: f.write(localConfig) with open("manifest.yaml", "w") as f: f.write(mainManifest) manifest = LocalEnv("manifest.yaml").getManifest() assert manifest.manifest.vault and manifest.manifest.vault.secrets job = Runner(manifest).run( JobOptions(add=True, startTime="time-to-test") ) # print(job.out.getvalue()) # print(job.jsonSummary(True)) assert job.status == Status.ok, job.summary() self.assertEqual( [ { "operation": "check", "configurator": "test_tosca.SetAttributeConfigurator", "changed": True, "priority": "required", "reason": "check", "status": "ok", "target": "foreign:anInstance", "targetStatus": "ok", "template": "anInstance", "type": "test.nodes.AbstractTest", } ], job.jsonSummary()["tasks"], ) job.getOutputs() self.assertEqual(job.getOutputs()["server_ip"], "10.0.0.1") self.assertEqual( len(manifest.localEnv._manifests), 2, manifest.localEnv._manifests ) # print("output", job.out.getvalue()) assert "10.0.0.1" not in job.out.getvalue(), job.out.getvalue() vaultString1 = "server_ip: !vault |\n $ANSIBLE_VAULT;1.1;AES256" assert vaultString1 in job.out.getvalue() vaultString2 = ( "private_address: !vault |\n $ANSIBLE_VAULT;1.1;AES256" ) assert vaultString2 in job.out.getvalue() # reload: manifest2 = LocalEnv("manifest.yaml").getManifest() assert manifest2.lastJob # test that restored manifest create a shadow instance for the foreign instance imported = manifest2.imports["foreign"].resource assert imported imported2 = manifest2.imports.findImport("foreign:anInstance") assert imported2 assert imported2.shadow self.assertIs(imported2.root, manifest2.getRootResource()) self.assertEqual(imported2.attributes["private_address"], "10.0.0.1") self.assertIsNot(imported2.shadow.root, manifest2.getRootResource()) finally: if UNFURL_HOME is not None: os.environ["UNFURL_HOME"] = UNFURL_HOME
def test_check(self): manifest = YamlManifest(manifestContent) runner = Runner(manifest) job = runner.run(JobOptions(startTime=1)) # deploy assert not job.unexpectedAbort, job.unexpectedAbort.getStackTrace() summary = job.jsonSummary() # print(json.dumps(summary, indent=2)) # print(job.out.getvalue()) self.assertEqual( { "id": "A01110000000", "status": "ok", "total": 5, "ok": 5, "error": 0, "unknown": 0, "skipped": 0, "changed": 4, }, summary["job"], ) targets = [t["target"] for t in summary["tasks"]] self.assertNotIn( "discovered", targets, "template with dependent directive should not create an instance", ) self.assertNotIn("managed", targets, "managed should not create deploy tasks") self.assertIn("unmanaged", targets, "unmanaged should create deploy tasks") self.assertEqual( job.rootResource.findResource("managed").created, "::installerNode") self.assertIs(job.rootResource.findResource("unmanaged").created, True) self.assertIs( job.rootResource.findResource("preexisting").created, False) self.assertNotIn("external", targets, "missing external instances should not be created") # print(job.out.getvalue()) manifest2 = YamlManifest(job.out.getvalue()) # don't delete installerNode instances = [n for n in job.rootResource.all if n != "installerNode"] job = Runner(manifest2).run( JobOptions(workflow="undeploy", instances=instances, startTime=2)) assert not job.unexpectedAbort, job.unexpectedAbort.getStackTrace() summary = job.jsonSummary() # print(json.dumps(summary, indent=2)) self.assertEqual( { "id": "A01120000000", "status": "ok", "total": 2, "ok": 2, "error": 0, "unknown": 0, "skipped": 0, "changed": 2, }, summary["job"], ) targets = [t["target"] for t in summary["tasks"]] self.assertNotIn("preexisting", targets, "discovered instances should not be deleted") self.assertIn("unmanaged", targets, "unmanaged should be deleted") self.assertNotIn("managed", targets, "managed should not be deleted") # print(job.out.getvalue()) # now undeploy installerNode manifest3 = YamlManifest(job.out.getvalue()) job = Runner(manifest3).run( JobOptions(workflow="undeploy", startTime=3)) assert not job.unexpectedAbort, job.unexpectedAbort.getStackTrace() summary = job.jsonSummary() # print(json.dumps(summary, indent=2)) # installerNode gets deleted, orphaning "managed" self.assertEqual( { "id": "A01130000000", "status": "ok", "total": 1, "ok": 1, "error": 0, "unknown": 0, "skipped": 0, "changed": 1, }, summary["job"], ) targets = [t["target"] for t in summary["tasks"]] self.assertNotIn("preexisting", targets, "discovered instances should not be deleted") self.assertIn("installerNode", targets, "installerNode should be deleted")
def test_stop(self): manifest = YamlManifest(manifest2Content) runner = Runner(manifest) job = runner.run(JobOptions(startTime=1)) # deploy assert not job.unexpectedAbort, job.unexpectedAbort.getStackTrace() summary = job.jsonSummary() # print(json.dumps(summary, indent=2)) # print(job.out.getvalue()) self.assertEqual( { "id": "A01110000000", "status": "ok", "total": 2, "ok": 2, "error": 0, "unknown": 0, "skipped": 0, "changed": 1, }, summary["job"], ) manifest2 = YamlManifest(job.out.getvalue()) job = Runner(manifest2).run(JobOptions(workflow="stop", startTime=2)) assert not job.unexpectedAbort, job.unexpectedAbort.getStackTrace() summary = job.jsonSummary() # print(json.dumps(summary, indent=2)) # print(job.out.getvalue()) self.assertEqual( [{ "status": "ok", "target": "simple", "operation": "stop", "template": "simple", "type": "test.nodes.simple", "targetStatus": "pending", "changed": True, "configurator": "unfurl.configurators.TemplateConfigurator", "priority": "required", "reason": "stop", }], summary["tasks"], ) # start again manifest3 = YamlManifest(job.out.getvalue()) job = Runner(manifest3).run(JobOptions(startTime=3)) assert not job.unexpectedAbort, job.unexpectedAbort.getStackTrace() summary = job.jsonSummary() # print(json.dumps(summary, indent=2)) # print(job.out.getvalue()) self.assertEqual( { "id": "A01130000000", "status": "ok", "total": 1, "ok": 1, "error": 0, "unknown": 0, "skipped": 0, "changed": 1, }, summary["job"], ) manifest4 = YamlManifest(job.out.getvalue()) job = Runner(manifest4).run( JobOptions(workflow="undeploy", startTime=4)) assert not job.unexpectedAbort, job.unexpectedAbort.getStackTrace() summary = job.jsonSummary() # print(json.dumps(summary, indent=2)) # print(job.out.getvalue()) self.assertEqual( { "id": "A01140000000", "status": "ok", "total": 1, "ok": 1, "error": 0, "unknown": 0, "skipped": 0, "changed": 1, }, summary["job"], ) self.assertEqual( [ { "status": "ok", "target": "simple", "operation": "delete", "template": "simple", "type": "test.nodes.simple", "targetStatus": "absent", "changed": True, "configurator": "unfurl.configurators.TemplateConfigurator", "priority": "required", "reason": "undeploy", }, ], summary["tasks"], )