Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial (bare-bones) implementation of the infrastructure for end-to-end tests #2691

Merged
merged 8 commits into from
Oct 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added tests_e2e/__init__.py
Empty file.
21 changes: 21 additions & 0 deletions tests_e2e/azure-pipelines.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
variables:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Entry point for Azure Pipelines

- name: azureConnection
value: 'AzLinux DCR Public (8e037ad4-618f-4466-8bc8-5099d41ac15b)'
- name: subId
value: '8e037ad4-618f-4466-8bc8-5099d41ac15b'
- name: testsSourcesDirectory
value: "$(Build.SourcesDirectory)/tests_e2e"

trigger:
- develop

pr: none

pool:
vmImage: ubuntu-latest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this pool for orchestrator vms?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is the pool of Azure Pipelines VMs where we run the orchestrator (singular, now we have only 1 orchestrator)

Copy link
Contributor

@nagworld9 nagworld9 Oct 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mean you plan to keep only 1 for all scenarios or at this point we have one?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 at this point. the actual number will depend on how we organize the test runs and how much we can take advantage of LISA's capabilities.


stages:
- stage: "Execute"
jobs:
- template: 'templates/execute-tests.yml'

82 changes: 82 additions & 0 deletions tests_e2e/lisa/runbook/azure.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: azure
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, the interface with LISA is under the 'lisa' subdirectory (it will be moved one level up in a future PR). This YML file is the entry point to LISA.

extension:
- "../testsuites"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the directory all of the LISA tests need to be in? Or will LISA look for tests in the entire /lisa directory

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LISA runbook points to the test location

extension:
  - "../testsuites"

variable:
- name: location
value: "westus2"
- name: subscription_id
value: ""
- name: resource_group_name
value: ""
#
# Set the vm_name to run on an existing VM
#
- name: vm_name
value: ""
- name: marketplace_image
value: "Canonical UbuntuServer 18.04-LTS latest"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like this is not in urn format. Is this how we suppose to define images?
How can we pass multiple images? how each scenario override this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll define a combinator to pass multiple distros. The LISA documentation has some info on how to do that, but we can always work with them if we need more info or features.

- name: vhd
value: ""
- name: vm_size
value: ""
#
# Turn off deploy to run on an existing VM
#
- name: deploy
value: true
- name: keep_environment
value: "no"
- name: wait_delete
value: false
- name: user
value: "waagent"
- name: identity_file
value: ""
is_secret: true
- name: admin_password
value: ""
is_secret: true
- name: proxy_host
value: ""
- name: proxy_user
value: ""
- name: proxy_identity_file
value: ""
is_secret: true
notifier:
- type: html
- type: env_stats
platform:
- type: azure
admin_username: $(user)
admin_private_key_file: $(identity_file)
admin_password: $(admin_password)
keep_environment: $(keep_environment)
azure:
resource_group_name: $(resource_group_name)
deploy: $(deploy)
subscription_id: $(subscription_id)
wait_delete: $(wait_delete)
requirement:
core_count:
min: 2
azure:
marketplace: "$(marketplace_image)"
vhd: $(vhd)
location: $(location)
name: $(vm_name)
vm_size: $(vm_size)

testcase:
- criteria:
area: bvt

#
# Set to do SSH proxy jumps
#
#dev:
# mock_tcp_ping: True
# jump_boxes:
# - private_key_file: $(proxy_identity_file)
# address: $(proxy_host)
# username: $(proxy_user)
Empty file.
Empty file.
23 changes: 23 additions & 0 deletions tests_e2e/lisa/tests/agent_bvt/check_agent_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env python
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skeleton for the current scenarios\agent-bvt\01_check_waagent_version.py test in DCR


from __future__ import print_function

import subprocess
import sys


def main():
print("Executing waagent --version")

pipe = subprocess.Popen(['waagent', '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout_lines = list(map(lambda s: s.decode('utf-8'), pipe.stdout.readlines()))
exit_code = pipe.wait()

for line in stdout_lines:
print(line)

return exit_code


if __name__ == "__main__":
sys.exit(main())
45 changes: 45 additions & 0 deletions tests_e2e/lisa/tests/agent_bvt/custom_script.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import argparse
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skeleton for the current scenarios\agent-bvt\06_customscript_20.py test in DCR

import os
import uuid
import sys

from tests_e2e.scenario_utils.extensions.CustomScriptExtension import CustomScriptExtension


def main(subscription_id, resource_group_name, vm_name):
os.environ["VMNAME"] = vm_name
os.environ['RGNAME'] = resource_group_name
os.environ["SUBID"] = subscription_id
os.environ["SCENARIONAME"] = "BVT"
os.environ["LOCATION"] = "westus2"
os.environ["ADMINUSERNAME"] = "somebody"
os.environ["BUILD_SOURCESDIRECTORY"] = "/somewhere"

cse = CustomScriptExtension(extension_name="testCSE")

ext_props = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we rewrite here? it already there in add_cse() function in Customerscript extension. Can we reuse that to run it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add_cse() does more than I need for this prototype (slowing the execution down), and, in any case, we will need to do a major rewrite of the BaseExtensionTest class we brought from DCR. In my oipinion the abstraction it presents is not appropriate and, more importantly, it handles errors poorly and does not output enough diagnostic info to debug failures.

cse.get_ext_props(settings={'commandToExecute': f"echo \'Hello World! {uuid.uuid4()} \'"}),
cse.get_ext_props(settings={'commandToExecute': "echo \'Hello again\'"})
]

cse.run(ext_props=ext_props)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed all of the logging from cse.run is being logged as lisa.stderr. Why is lisa capturing these as stderr instead of stdout?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The output is coming from BaseExtensionTestClass (in the scenatio_utils directory). This code comes straight from the current DCR and will need a lot of improvements, for example writing to the log file instead of stdout/stderr.



if __name__ == "__main__":
try:
parser = argparse.ArgumentParser()
parser.add_argument('--subscription')
parser.add_argument('--group')
parser.add_argument('--vm')

args = parser.parse_args()

main(args.subscription, args.group, args.vm)

except Exception as exception:
print(str(exception))
sys.exit(1)

sys.exit(0)


41 changes: 41 additions & 0 deletions tests_e2e/lisa/testsuites/agent-bvt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from assertpy import assert_that
Copy link
Member Author

@narrieta narrieta Oct 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skeleton to define the 2 basic patterns for the end-to-end tests. Currently hardcoded to specific tests, but will be abstracted in future PRs.

from pathlib import Path
from tests_e2e.lisa.tests.agent_bvt import custom_script

from lisa import (
CustomScriptBuilder,
Logger,
Node,
simple_requirement,
TestCaseMetadata,
TestSuite,
TestSuiteMetadata,
)
from lisa.sut_orchestrator.azure.common import get_node_context


@TestSuiteMetadata(
area="bvt",
category="functional",
description="""
A POC test suite for the waagent BVTs.
""",
requirement=simple_requirement(unsupported_os=[]),
)
class AgentBvt(TestSuite):
@TestCaseMetadata(description="", priority=0)
def check_agent_version(self, node: Node, log: Logger) -> None:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pattern 1: Execute a test remotely over SSH

script_path = CustomScriptBuilder(Path(__file__).parent.parent.joinpath("tests", "agent_bvt"), ["check_agent_version.py"])
script = node.tools[script_path]
result = script.run()
log.info(result.stdout)
log.error(result.stderr)
assert_that(result.exit_code).is_equal_to(0)

@TestCaseMetadata(description="", priority=0)
def custom_script(self, node: Node) -> None:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pattern 2: Execute a test locally (local to the orchestrator) to trigger extensions on the remote test VM

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At what point is the remote test VM created?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LISA does that. In the output of the task you will see something similar to

2022-10-25 15:13:49.326[140692391196416][INFO] lisa.[azure].deploy[generated_0] vm setting: AzureNodeSchema(name='lisa-azure-20221025-151340-053-e0-n0', short_name='lisa--053-e0-n0', vm_size='Standard_DS2_v2', maximize_capability=False, location='westus2', subscription_id='8e037ad4-****-****-****-********c15b', marketplace_raw={'publisher': 'canonical', 'offer': 'ubuntuserver', 'sku': '18.04-lts', 'version': '18.04.202210180'}, shared_gallery_raw=None, vhd='', hyperv_generation=1, purchase_plan=None, is_linux=True)
2022-10-25 15:13:53.044[140692391196416][INFO] lisa.[azure].deploy[generated_0] resource group 'lisa-azure-20221025-151340-053-e0' deployment is in progress...
2022-10-25 15:15:26.749[140692391196416][INFO] lisa.[azure].deploy[generated_0] deployed in 99.972 sec
2022-10-25 15:15:26.754[140692483270400][INFO] lisa.env[generated_0].node[0] initializing node 'lisa-azure-20221025-151340-053-e0-n0' w****t@20.230.174.145:22

node_context = get_node_context(node)
subscription_id = node.features._platform.subscription_id
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently reaching into the internal "_platform" object to get the Subscription ID. This should be done by implementing a LISA feature that exposes subscription ID/resource group name/vm name.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once we are creating multiple test VMs with different images, how will LISA know which nodes this test should be ran with? Will that be specified in the runbook?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we will create a combinator to execute each test on each distro and add it to the runbook

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the node details that it's trying to fetch for the actual test vm not the orchestrator vm right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, the Node represents the VM created by LISA

resource_group_name = node_context.resource_group_name
vm_name = node_context.vm_name
custom_script.main(subscription_id, resource_group_name, vm_name)
13 changes: 13 additions & 0 deletions tests_e2e/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# This is a list of pip packages that will be installed on both the orchestrator and the test VM
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requirements for the orchestrator/test VM. Comes directly from the 'dcr' POC, but should be splitted in 2 (one for orchestrator, one for test VM)

# Only add the common packages here, for more specific modules, add them to the scenario itself
azure-identity
azure-keyvault-keys
azure-mgmt-compute>=22.1.0
azure-mgmt-keyvault>=7.0.0
azure-mgmt-network>=16.0.0
azure-mgmt-resource>=15.0.0
cryptography
distro
junitparser
msrestazure
python-dotenv
Empty file.
Loading