Skip to content

Commit

Permalink
add environment tests (#1371)
Browse files Browse the repository at this point in the history
### Feature or Bugfix
Feature

### Detail
* add list_environment tests
* add test for updating an environment (via update_stack)
* generalise the polling functions for stacks

### Relates
#1220 

### Security
Please answer the questions below briefly where applicable, or write
`N/A`. Based on
[OWASP 10](https://owasp.org/Top10/en/).

- Does this PR introduce or modify any input fields or queries - this
includes
fetching data from storage outside the application (e.g. a database, an
S3 bucket)?
  - Is the input sanitized?
- What precautions are you taking before deserializing the data you
consume?
  - Is injection prevented by parametrizing queries?
  - Have you ensured no `eval` or similar functions are used?
- Does this PR introduce any functionality or component that requires
authorization?
- How have you ensured it respects the existing AuthN/AuthZ mechanisms?
  - Are you logging failed auth attempts?
- Are you using or adding any cryptographic features?
  - Do you use a standard proven implementations?
  - Are the used keys controlled by the customer? Where are they stored?
- Are you introducing any new policies/roles/users?
  - Have you used the least-privilege principle? How?


By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license.
  • Loading branch information
petrkalos authored Jun 28, 2024
1 parent e913d48 commit c3c58bd
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 123 deletions.
69 changes: 42 additions & 27 deletions tests_new/integration_tests/core/environment/global_conftest.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
import logging
import re

import pytest

from integration_tests.client import GqlError
from integration_tests.core.environment.queries import create_environment, get_environment, delete_environment
from integration_tests.utils import poller
from integration_tests.core.environment.queries import (
create_environment,
get_environment,
delete_environment,
list_environments,
)
from integration_tests.core.organizations.queries import create_organization
from integration_tests.core.stack.utils import check_stack_ready

log = logging.getLogger(__name__)


@poller(check_success=lambda env: not re.match(r'.*IN_PROGRESS|PENDING', env.stack.status, re.IGNORECASE), timeout=600)
def check_env_ready(client, env_uri):
env = get_environment(client, env_uri)
log.info(f'polling {env_uri=}, new {env.stack.status=}')
return env
def create_env(client, group, org_uri, account_id, region, tags=[]):
env = create_environment(
client, name='testEnvA', group=group, organizationUri=org_uri, awsAccountId=account_id, region=region, tags=tags
)
check_stack_ready(client, env.environmentUri, env.stack.stackUri)
return get_environment(client, env.environmentUri)


def create_env(client, group, org_uri, account_id, region):
new_env_uri = create_environment(
client, name='testEnvA', group=group, organizationUri=org_uri, awsAccountId=account_id, region=region
)['environmentUri']
return check_env_ready(client, new_env_uri)


def delete_env(client, env_uri):
check_env_ready(client, env_uri)
def delete_env(client, env):
check_stack_ready(client, env.environmentUri, env.stack.stackUri)
try:
return delete_environment(client, env_uri)
return delete_environment(client, env.environmentUri)
except GqlError:
log.exception('unexpected error when deleting environment')
return False
Expand All @@ -40,27 +39,27 @@ def delete_env(client, env_uri):


@pytest.fixture(scope='session')
def session_env1(client1, group1, org1, testdata):
def session_env1(client1, group1, org1, session_id, testdata):
envdata = testdata.envs['session_env1']
env = None
try:
env = create_env(client1, group1, org1['organizationUri'], envdata.accountId, envdata.region)
env = create_env(client1, group1, org1['organizationUri'], envdata.accountId, envdata.region, tags=[session_id])
yield env
finally:
if env:
delete_env(client1, env['environmentUri'])
delete_env(client1, env)


@pytest.fixture(scope='session')
def session_env2(client1, group1, org1, testdata):
def session_env2(client1, group1, org1, session_id, testdata):
envdata = testdata.envs['session_env2']
env = None
try:
env = create_env(client1, group1, org1['organizationUri'], envdata.accountId, envdata.region)
env = create_env(client1, group1, org1['organizationUri'], envdata.accountId, envdata.region, tags=[session_id])
yield env
finally:
if env:
delete_env(client1, env['environmentUri'])
delete_env(client1, env)


"""
Expand All @@ -78,7 +77,7 @@ def temp_env1(client1, group1, org1, testdata):
yield env
finally:
if env:
delete_env(client1, env['environmentUri'])
delete_env(client1, env)


"""
Expand All @@ -87,5 +86,21 @@ def temp_env1(client1, group1, org1, testdata):
"""


@pytest.fixture(scope='function')
def persistent_env1(client1, group1, org1, testdata): ... # TODO
def get_or_create_persistent_env(env_name, client, group, testdata):
envs = list_environments(client, term=env_name).nodes
if envs:
return envs[0]
else:
envdata = testdata.envs[env_name]
org = create_organization(client, f'org_{env_name}', group)
env = create_env(client, group, org['organizationUri'], envdata.accountId, envdata.region, tags=[env_name])
if env.stack.status in ['CREATE_COMPLETE', 'UPDATE_COMPLETE']:
return env
else:
delete_env(client, env['environmentUri'])
raise RuntimeError(f'failed to create {env_name=} {env=}')


@pytest.fixture(scope='session')
def persistent_env1(client1, group1, testdata):
return get_or_create_persistent_env('persistent_env1', client1, group1, testdata)
181 changes: 96 additions & 85 deletions tests_new/integration_tests/core/environment/queries.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,55 @@
def create_environment(client, name, group, organizationUri, awsAccountId, region):
ENV_TYPE = """
environmentUri
created
userRoleInEnvironment
description
name
label
AwsAccountId
region
owner
tags
SamlGroupName
EnvironmentDefaultBucketName
EnvironmentDefaultIAMRoleArn
EnvironmentDefaultIAMRoleName
EnvironmentDefaultIAMRoleImported
resourcePrefix
subscriptionsEnabled
subscriptionsProducersTopicImported
subscriptionsConsumersTopicImported
subscriptionsConsumersTopicName
subscriptionsProducersTopicName
organization {
organizationUri
label
name
}
stack {
stack
status
stackUri
targetUri
accountid
region
stackid
link
outputs
resources
}
networks {
VpcId
privateSubnetIds
publicSubnetIds
}
parameters {
key
value
}
"""


def create_environment(client, name, group, organizationUri, awsAccountId, region, tags):
query = {
'operationName': 'CreateEnvironment',
'variables': {
Expand All @@ -9,24 +60,15 @@ def create_environment(client, name, group, organizationUri, awsAccountId, regio
'AwsAccountId': awsAccountId,
'region': region,
'description': 'Created for integration testing',
'tags': [],
'tags': tags,
}
},
'query': """
mutation CreateEnvironment($input: NewEnvironmentInput!) {
createEnvironment(input: $input) {
environmentUri
label
userRoleInEnvironment
SamlGroupName
AwsAccountId
created
parameters {
key
value
}
}
}
'query': f"""
mutation CreateEnvironment($input: NewEnvironmentInput!) {{
createEnvironment(input: $input) {{
{ENV_TYPE}
}}
}}
""",
}
response = client.query(query=query)
Expand All @@ -37,58 +79,12 @@ def get_environment(client, environmentUri):
query = {
'operationName': 'GetEnvironment',
'variables': {'environmentUri': environmentUri},
'query': """
query GetEnvironment($environmentUri: String!) {
getEnvironment(environmentUri: $environmentUri) {
environmentUri
created
userRoleInEnvironment
description
name
label
AwsAccountId
region
owner
tags
SamlGroupName
EnvironmentDefaultBucketName
EnvironmentDefaultIAMRoleArn
EnvironmentDefaultIAMRoleName
EnvironmentDefaultIAMRoleImported
resourcePrefix
subscriptionsEnabled
subscriptionsProducersTopicImported
subscriptionsConsumersTopicImported
subscriptionsConsumersTopicName
subscriptionsProducersTopicName
organization {
organizationUri
label
name
}
stack {
stack
status
stackUri
targetUri
accountid
region
stackid
link
outputs
resources
}
networks {
VpcId
privateSubnetIds
publicSubnetIds
}
parameters {
key
value
}
}
}
'query': f"""
query GetEnvironment($environmentUri: String!) {{
getEnvironment(environmentUri: $environmentUri) {{
{ENV_TYPE}
}}
}}
""",
}
response = client.query(query=query)
Expand Down Expand Up @@ -125,26 +121,41 @@ def update_environment(client, environmentUri, input: dict):
'environmentUri': environmentUri,
'input': input,
},
'query': """
'query': f"""
mutation UpdateEnvironment(
$environmentUri: String!
$input: ModifyEnvironmentInput!
) {
updateEnvironment(environmentUri: $environmentUri, input: $input) {
environmentUri
label
userRoleInEnvironment
SamlGroupName
AwsAccountId
description
created
parameters {
key
value
}
}
}
) {{
updateEnvironment(environmentUri: $environmentUri, input: $input) {{
{ENV_TYPE}
}}
}}
""",
}
response = client.query(query=query)
return response.data.updateEnvironment


def list_environments(client, term=''):
query = {
'operationName': 'ListEnvironments',
'variables': {
'filter': {'term': term},
},
'query': f"""
query ListEnvironments($filter: EnvironmentFilter) {{
listEnvironments(filter: $filter) {{
count
page
pages
hasNext
hasPrevious
nodes {{
{ENV_TYPE}
}}
}}
}}
""",
}
response = client.query(query=query)
return response.data.listEnvironments
37 changes: 30 additions & 7 deletions tests_new/integration_tests/core/environment/test_environment.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
import logging
from datetime import datetime

from assertpy import assert_that

from integration_tests.core.environment.queries import update_environment, get_environment
from integration_tests.core.environment.queries import get_environment, update_environment, list_environments
from integration_tests.core.stack.queries import update_stack
from integration_tests.core.stack.utils import check_stack_in_progress, check_stack_ready
from integration_tests.errors import GqlError

log = logging.getLogger(__name__)


def test_create_env(session_env1):
assert_that(session_env1.stack.status).is_equal_to('CREATE_COMPLETE')
assert_that(session_env1.stack.status).is_in('CREATE_COMPLETE', 'UPDATE_COMPLETE')


def test_modify_env(client1, session_env1):
test_description = f'a test description {datetime.utcnow().isoformat()}'
env_uri = session_env1.environmentUri
updated_env = update_environment(client1, env_uri, {'description': test_description})
assert_that(updated_env).contains_entry({'environmentUri': env_uri}, {'description': test_description})
assert_that(updated_env).contains_entry(environmentUri=env_uri, description=test_description)
env = get_environment(client1, env_uri)
assert_that(env).contains_entry({'environmentUri': env_uri}, {'description': test_description})
assert_that(env).contains_entry(environmentUri=env_uri, description=test_description)


def test_modify_env_unauthorized(client1, client2, session_env1):
Expand All @@ -26,6 +31,24 @@ def test_modify_env_unauthorized(client1, client2, session_env1):
client2, env_uri, {'description': test_description}
).contains('UnauthorizedOperation', env_uri)
env = get_environment(client1, env_uri)
assert_that(env).contains_entry({'environmentUri': env_uri}).does_not_contain_entry(
{'description': test_description}
)
assert_that(env).contains_entry(environmentUri=env_uri).does_not_contain_entry(description=test_description)


def test_list_envs_authorized(client1, session_env1, session_env2, session_id):
assert_that(list_environments(client1, term=session_id).nodes).is_length(2)


def test_list_envs_unauthorized(client2, session_env1, session_env2, session_id):
assert_that(list_environments(client2, term=session_id).nodes).is_length(0)


def test_persistent_env_update(client1, persistent_env1):
# wait for stack to get to a final state before triggering an update
stack_uri = persistent_env1.stack.stackUri
env_uri = persistent_env1.environmentUri
check_stack_ready(client1, env_uri, stack_uri)
update_stack(client1, env_uri, 'environment')
# wait for stack to move to "in_progress" state
check_stack_in_progress(client1, env_uri, stack_uri)
stack = check_stack_ready(client1, env_uri, stack_uri)
assert_that(stack.status).is_equal_to('UPDATE_COMPLETE')
Loading

0 comments on commit c3c58bd

Please sign in to comment.